blob: 4de42fd142de37101aa5ff2760e094cbff77d055 [file] [log] [blame]
Leon Scroggins IIIb9216dc2021-03-08 17:19:01 -05001/*
2 * Copyright 2021 The Android Open Source Project
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
Leon Scroggins IIIb9216dc2021-03-08 17:19:01 -050016#include "Cache.h"
17#include "AutoBackendTexture.h"
18#include "SkiaRenderEngine.h"
19#include "android-base/unique_fd.h"
20#include "renderengine/DisplaySettings.h"
21#include "renderengine/LayerSettings.h"
Vishnu Nairdbbe3852022-01-12 20:22:11 -080022#include "renderengine/impl/ExternalTexture.h"
Leon Scroggins IIIb9216dc2021-03-08 17:19:01 -050023#include "ui/GraphicBuffer.h"
24#include "ui/GraphicTypes.h"
25#include "ui/PixelFormat.h"
26#include "ui/Rect.h"
27#include "utils/Timers.h"
28
29namespace android::renderengine::skia {
30
Nathaniel Nifongb9f27ef2021-04-01 16:44:12 -040031namespace {
Nathaniel Nifong4fc750d2021-03-19 11:37:36 -040032
Nathaniel Nifongb9f27ef2021-04-01 16:44:12 -040033// clang-format off
34// Any non-identity matrix will do.
35const auto kScaleAndTranslate = mat4(0.7f, 0.f, 0.f, 0.f,
36 0.f, 0.7f, 0.f, 0.f,
37 0.f, 0.f, 1.f, 0.f,
38 67.3f, 52.2f, 0.f, 1.f);
Nathaniel Nifongafeac5b2021-05-27 10:52:30 -040039const auto kScaleAsymmetric = mat4(0.8f, 0.f, 0.f, 0.f,
40 0.f, 1.1f, 0.f, 0.f,
41 0.f, 0.f, 1.f, 0.f,
42 0.f, 0.f, 0.f, 1.f);
Nathaniel Nifong13491502021-06-30 17:28:29 -040043const auto kFlip = mat4(1.1f, -0.1f, 0.f, 0.f,
44 0.1f, 1.1f, 0.f, 0.f,
45 0.f, 0.f, 1.f, 0.f,
46 2.f, 2.f, 0.f, 1.f);
Nathaniel Nifongb9f27ef2021-04-01 16:44:12 -040047// clang-format on
Nathaniel Nifongbf6f7542021-04-27 12:05:16 -040048// When setting layer.sourceDataspace, whether it matches the destination or not determines whether
49// a color correction effect is added to the shader.
Nathaniel Nifongb9f27ef2021-04-01 16:44:12 -040050constexpr auto kDestDataSpace = ui::Dataspace::SRGB;
Nathaniel Nifong21e021f2021-04-21 13:15:46 -040051constexpr auto kOtherDataSpace = ui::Dataspace::DISPLAY_P3;
Mattias Simonsson65746132023-08-15 13:26:16 +000052// Dimming is needed to trigger linear effects for some dataspace pairs
53const std::array<float, 3> kLayerWhitePoints = {
54 1000.0f, 500.0f,
55 100.0f, // trigger dithering by dimming below 20%
56};
Nathaniel Nifongb9f27ef2021-04-01 16:44:12 -040057} // namespace
58
Nathaniel Nifong4fc750d2021-03-19 11:37:36 -040059static void drawShadowLayers(SkiaRenderEngine* renderengine, const DisplaySettings& display,
Alec Mouria90a5702021-04-16 16:36:21 +000060 const std::shared_ptr<ExternalTexture>& dstTexture) {
Leon Scroggins IIIb9216dc2021-03-08 17:19:01 -050061 // Somewhat arbitrary dimensions, but on screen and slightly shorter, based
62 // on actual use.
Nathaniel Nifonga6b54232021-07-02 13:24:32 -040063 const Rect& displayRect = display.physicalDisplay;
64 FloatRect rect(0, 0, displayRect.width(), displayRect.height());
65 FloatRect smallerRect(20, 20, displayRect.width()-20, displayRect.height()-20);
66
Leon Scroggins IIIb9216dc2021-03-08 17:19:01 -050067 LayerSettings layer{
68 .geometry =
69 Geometry{
70 .boundaries = rect,
Vishnu Nair50c0afe2022-07-11 15:04:07 -070071 .roundedCornersRadius = {50.f, 50.f},
Leon Scroggins III894c5f82023-08-25 14:43:54 -040072 .roundedCornersCrop = rect,
Leon Scroggins IIIb9216dc2021-03-08 17:19:01 -050073 },
Leon Scroggins III894c5f82023-08-25 14:43:54 -040074 .alpha = 1,
75 // setting this is mandatory for shadows and blurs
76 .skipContentDraw = true,
Nathaniel Nifong4fc750d2021-03-19 11:37:36 -040077 // drawShadow ignores alpha
Leon Scroggins IIIb9216dc2021-03-08 17:19:01 -050078 .shadow =
79 ShadowSettings{
Nathaniel Nifonga6b54232021-07-02 13:24:32 -040080 .boundaries = rect,
Leon Scroggins IIIb9216dc2021-03-08 17:19:01 -050081 .ambientColor = vec4(0, 0, 0, 0.00935997f),
82 .spotColor = vec4(0, 0, 0, 0.0455841f),
Nathaniel Nifonga6b54232021-07-02 13:24:32 -040083 .lightPos = vec3(500.f, -1500.f, 1500.f),
84 .lightRadius = 2500.0f,
85 .length = 15.f,
Leon Scroggins IIIb9216dc2021-03-08 17:19:01 -050086 },
Nathaniel Nifonga6b54232021-07-02 13:24:32 -040087 };
88 LayerSettings caster{
89 .geometry =
90 Geometry{
91 .boundaries = smallerRect,
Vishnu Nair50c0afe2022-07-11 15:04:07 -070092 .roundedCornersRadius = {50.f, 50.f},
Leon Scroggins III894c5f82023-08-25 14:43:54 -040093 .roundedCornersCrop = rect,
Nathaniel Nifonga6b54232021-07-02 13:24:32 -040094 },
95 .source =
96 PixelSource{
97 .solidColor = half3(0.f, 0.f, 0.f),
98 },
99 .alpha = 1,
Leon Scroggins IIIb9216dc2021-03-08 17:19:01 -0500100 };
101
Nathaniel Nifong49a59582021-07-26 19:49:47 -0400102 // Four combinations of settings are used (two transforms here, and drawShadowLayers is
103 // called with two different destination data spaces) They're all rounded rect.
104 // Three of these are cache misses that generate new shaders.
105 // The first combination generates a short and simple shadow shader.
106 // The second combination, flip transform, generates two shaders. The first appears to involve
107 // gaussian_fp. The second is a long and general purpose shadow shader with a device space
108 // transformation stage.
109 // The third combination is a cache hit, nothing new.
110 // The fourth combination, flip transform with a non-SRGB destination dataspace, is new.
111 // It is unique in that nearly everything is done in the vertex shader, and that vertex shader
112 // requires color correction. This is triggered differently from every other instance of color
113 // correction. All other instances are triggered when src and dst dataspaces differ, while
114 // this one is triggered by the destination being non-srgb. Apparently since the third
115 // combination is a cache hit, this color correction is only added when the vertex shader is
116 // doing something non-trivial.
117 for (auto transform : {mat4(), kFlip}) {
118 layer.geometry.positionTransform = transform;
119 caster.geometry.positionTransform = transform;
Leon Scroggins IIIae07fe52022-04-26 15:23:55 -0400120
121 auto layers = std::vector<LayerSettings>{layer, caster};
Alec Mourif29700f2023-08-17 21:53:31 +0000122 renderengine->drawLayers(display, layers, dstTexture, base::unique_fd());
Leon Scroggins IIIb9216dc2021-03-08 17:19:01 -0500123 }
124}
125
126static void drawImageLayers(SkiaRenderEngine* renderengine, const DisplaySettings& display,
Alec Mouria90a5702021-04-16 16:36:21 +0000127 const std::shared_ptr<ExternalTexture>& dstTexture,
128 const std::shared_ptr<ExternalTexture>& srcTexture) {
Leon Scroggins IIIb9216dc2021-03-08 17:19:01 -0500129 const Rect& displayRect = display.physicalDisplay;
130 FloatRect rect(0, 0, displayRect.width(), displayRect.height());
131 LayerSettings layer{
132 .geometry =
133 Geometry{
Leon Scroggins III894c5f82023-08-25 14:43:54 -0400134 .boundaries = rect,
Nathaniel Nifongf06a45b2021-06-25 17:24:26 -0400135 // The position transform doesn't matter when the reduced shader mode
136 // in in effect. A matrix transform stage is always included.
137 .positionTransform = mat4(),
Leon Scroggins IIIb9216dc2021-03-08 17:19:01 -0500138 .roundedCornersCrop = rect,
139 },
140 .source = PixelSource{.buffer =
141 Buffer{
Alec Mouria90a5702021-04-16 16:36:21 +0000142 .buffer = srcTexture,
John Reckac09e452021-04-07 16:35:37 -0400143 .maxLuminanceNits = 1000.f,
Leon Scroggins IIIb9216dc2021-03-08 17:19:01 -0500144 }},
145 };
146
Nathaniel Nifongbf6f7542021-04-27 12:05:16 -0400147 for (auto dataspace : {kDestDataSpace, kOtherDataSpace}) {
148 layer.sourceDataspace = dataspace;
Nathaniel Nifong13491502021-06-30 17:28:29 -0400149 // Cache shaders for both rects and round rects.
150 // In reduced shader mode, all non-zero round rect radii get the same code path.
Nathaniel Nifongf06a45b2021-06-25 17:24:26 -0400151 for (float roundedCornersRadius : {0.0f, 50.0f}) {
152 // roundedCornersCrop is always set, but the radius triggers the behavior
Vishnu Nair50c0afe2022-07-11 15:04:07 -0700153 layer.geometry.roundedCornersRadius = {roundedCornersRadius, roundedCornersRadius};
Nathaniel Nifongf06a45b2021-06-25 17:24:26 -0400154 for (bool isOpaque : {true, false}) {
155 layer.source.buffer.isOpaque = isOpaque;
156 for (auto alpha : {half(.2f), half(1.0f)}) {
157 layer.alpha = alpha;
Leon Scroggins IIIae07fe52022-04-26 15:23:55 -0400158 auto layers = std::vector<LayerSettings>{layer};
Alec Mourif29700f2023-08-17 21:53:31 +0000159 renderengine->drawLayers(display, layers, dstTexture, base::unique_fd());
Leon Scroggins IIIb9216dc2021-03-08 17:19:01 -0500160 }
161 }
162 }
163 }
164}
165
Nathaniel Nifong4fc750d2021-03-19 11:37:36 -0400166static void drawSolidLayers(SkiaRenderEngine* renderengine, const DisplaySettings& display,
Alec Mouria90a5702021-04-16 16:36:21 +0000167 const std::shared_ptr<ExternalTexture>& dstTexture) {
Nathaniel Nifong4fc750d2021-03-19 11:37:36 -0400168 const Rect& displayRect = display.physicalDisplay;
169 FloatRect rect(0, 0, displayRect.width(), displayRect.height());
170 LayerSettings layer{
171 .geometry =
172 Geometry{
173 .boundaries = rect,
174 },
Nathaniel Nifong4fc750d2021-03-19 11:37:36 -0400175 .source =
176 PixelSource{
177 .solidColor = half3(0.1f, 0.2f, 0.3f),
178 },
Nathaniel Nifong768693f2021-06-08 14:33:47 -0400179 .alpha = 0.5,
Nathaniel Nifong4fc750d2021-03-19 11:37:36 -0400180 };
181
Nathaniel Nifongb9f27ef2021-04-01 16:44:12 -0400182 for (auto transform : {mat4(), kScaleAndTranslate}) {
183 layer.geometry.positionTransform = transform;
Nathaniel Nifongf06a45b2021-06-25 17:24:26 -0400184 for (float roundedCornersRadius : {0.0f, 50.f}) {
Vishnu Nair50c0afe2022-07-11 15:04:07 -0700185 layer.geometry.roundedCornersRadius = {roundedCornersRadius, roundedCornersRadius};
Leon Scroggins IIIae07fe52022-04-26 15:23:55 -0400186 auto layers = std::vector<LayerSettings>{layer};
Alec Mourif29700f2023-08-17 21:53:31 +0000187 renderengine->drawLayers(display, layers, dstTexture, base::unique_fd());
Nathaniel Nifongb9f27ef2021-04-01 16:44:12 -0400188 }
189 }
Nathaniel Nifong4fc750d2021-03-19 11:37:36 -0400190}
191
Nathaniel Nifongb9f27ef2021-04-01 16:44:12 -0400192static void drawBlurLayers(SkiaRenderEngine* renderengine, const DisplaySettings& display,
Alec Mouria90a5702021-04-16 16:36:21 +0000193 const std::shared_ptr<ExternalTexture>& dstTexture) {
Nathaniel Nifongb9f27ef2021-04-01 16:44:12 -0400194 const Rect& displayRect = display.physicalDisplay;
195 FloatRect rect(0, 0, displayRect.width(), displayRect.height());
196 LayerSettings layer{
197 .geometry =
198 Geometry{
199 .boundaries = rect,
200 },
201 .alpha = 1,
Nathaniel Nifong490a9472021-06-23 16:44:19 -0400202 // setting this is mandatory for shadows and blurs
203 .skipContentDraw = true,
Nathaniel Nifongb9f27ef2021-04-01 16:44:12 -0400204 };
205
Nathaniel Nifong490a9472021-06-23 16:44:19 -0400206 // Different blur code is invoked for radii less and greater than 30 pixels
Nathaniel Nifongb9f27ef2021-04-01 16:44:12 -0400207 for (int radius : {9, 60}) {
208 layer.backgroundBlurRadius = radius;
Leon Scroggins IIIae07fe52022-04-26 15:23:55 -0400209 auto layers = std::vector<LayerSettings>{layer};
Alec Mourif29700f2023-08-17 21:53:31 +0000210 renderengine->drawLayers(display, layers, dstTexture, base::unique_fd());
Nathaniel Nifongb9f27ef2021-04-01 16:44:12 -0400211 }
212}
213
Nathaniel Nifong2d91c5e2021-05-13 17:14:00 -0400214// The unique feature of these layers is that the boundary is slightly smaller than the rounded
215// rect crop, so the rounded edges intersect that boundary and require a different clipping method.
Nathaniel Nifongafeac5b2021-05-27 10:52:30 -0400216// For buffers, this is done with a stage that computes coverage and it will differ for round and
217// elliptical corners.
Nathaniel Nifong2d91c5e2021-05-13 17:14:00 -0400218static void drawClippedLayers(SkiaRenderEngine* renderengine, const DisplaySettings& display,
219 const std::shared_ptr<ExternalTexture>& dstTexture,
220 const std::shared_ptr<ExternalTexture>& srcTexture) {
Nathaniel Nifong21e021f2021-04-21 13:15:46 -0400221 const Rect& displayRect = display.physicalDisplay;
Nathaniel Nifong2d91c5e2021-05-13 17:14:00 -0400222 FloatRect rect(0, 0, displayRect.width(), displayRect.height() - 20); // boundary is smaller
223
Nathaniel Nifongafeac5b2021-05-27 10:52:30 -0400224 PixelSource bufferSource{.buffer = Buffer{
225 .buffer = srcTexture,
226 .isOpaque = 0,
227 .maxLuminanceNits = 1000.f,
228 }};
229 PixelSource bufferOpaque{.buffer = Buffer{
230 .buffer = srcTexture,
231 .isOpaque = 1,
232 .maxLuminanceNits = 1000.f,
233 }};
234 PixelSource colorSource{.solidColor = half3(0.1f, 0.2f, 0.3f)};
Nathaniel Nifong2d91c5e2021-05-13 17:14:00 -0400235
Nathaniel Nifong21e021f2021-04-21 13:15:46 -0400236 LayerSettings layer{
237 .geometry =
238 Geometry{
239 .boundaries = rect,
Vishnu Nair50c0afe2022-07-11 15:04:07 -0700240 .roundedCornersRadius = {27.f, 27.f},
Nathaniel Nifong2d91c5e2021-05-13 17:14:00 -0400241 .roundedCornersCrop =
242 FloatRect(0, 0, displayRect.width(), displayRect.height()),
Nathaniel Nifong21e021f2021-04-21 13:15:46 -0400243 },
Nathaniel Nifong21e021f2021-04-21 13:15:46 -0400244 };
245
Nathaniel Nifongafeac5b2021-05-27 10:52:30 -0400246 for (auto pixelSource : {bufferSource, bufferOpaque, colorSource}) {
247 layer.source = pixelSource;
248 for (auto dataspace : {kDestDataSpace, kOtherDataSpace}) {
249 layer.sourceDataspace = dataspace;
Nathaniel Nifong13491502021-06-30 17:28:29 -0400250 // Produce a CircularRRect clip and an EllipticalRRect clip.
Nathaniel Nifongafeac5b2021-05-27 10:52:30 -0400251 for (auto transform : {kScaleAndTranslate, kScaleAsymmetric}) {
252 layer.geometry.positionTransform = transform;
Nathaniel Nifongafeac5b2021-05-27 10:52:30 -0400253 for (float alpha : {0.5f, 1.f}) {
Leon Scroggins IIIae07fe52022-04-26 15:23:55 -0400254 layer.alpha = alpha;
255 auto layers = std::vector<LayerSettings>{layer};
Alec Mourif29700f2023-08-17 21:53:31 +0000256 renderengine->drawLayers(display, layers, dstTexture, base::unique_fd());
Nathaniel Nifongafeac5b2021-05-27 10:52:30 -0400257 }
258 }
Nathaniel Nifong2d91c5e2021-05-13 17:14:00 -0400259 }
Nathaniel Nifong21e021f2021-04-21 13:15:46 -0400260 }
261}
262
Nathaniel Nifong13491502021-06-30 17:28:29 -0400263static void drawPIPImageLayer(SkiaRenderEngine* renderengine, const DisplaySettings& display,
264 const std::shared_ptr<ExternalTexture>& dstTexture,
265 const std::shared_ptr<ExternalTexture>& srcTexture) {
266 const Rect& displayRect = display.physicalDisplay;
267 FloatRect rect(0, 0, displayRect.width(), displayRect.height());
268 LayerSettings layer{
269 .geometry =
270 Geometry{
Leon Scroggins III894c5f82023-08-25 14:43:54 -0400271 .boundaries = rect,
Nathaniel Nifong13491502021-06-30 17:28:29 -0400272 // Note that this flip matrix only makes a difference when clipping,
273 // which happens in this layer because the roundrect crop is just a bit
274 // larger than the layer bounds.
275 .positionTransform = kFlip,
Vishnu Nair50c0afe2022-07-11 15:04:07 -0700276 .roundedCornersRadius = {94.2551f, 94.2551f},
277 .roundedCornersCrop = FloatRect(-93.75, 0, displayRect.width() + 93.75,
278 displayRect.height()),
Nathaniel Nifong13491502021-06-30 17:28:29 -0400279 },
280 .source = PixelSource{.buffer =
281 Buffer{
282 .buffer = srcTexture,
Nathaniel Nifong13491502021-06-30 17:28:29 -0400283 .usePremultipliedAlpha = 1,
Leon Scroggins III894c5f82023-08-25 14:43:54 -0400284 .isOpaque = 0,
285 .maxLuminanceNits = 1000.f,
Nathaniel Nifong13491502021-06-30 17:28:29 -0400286 }},
Nathaniel Nifong13491502021-06-30 17:28:29 -0400287 .alpha = 1,
Leon Scroggins III894c5f82023-08-25 14:43:54 -0400288 .sourceDataspace = kOtherDataSpace,
Nathaniel Nifong13491502021-06-30 17:28:29 -0400289
290 };
291
Sally Qi59a9f502021-10-12 18:53:23 +0000292 auto layers = std::vector<LayerSettings>{layer};
Alec Mourif29700f2023-08-17 21:53:31 +0000293 renderengine->drawLayers(display, layers, dstTexture, base::unique_fd());
Nathaniel Nifong13491502021-06-30 17:28:29 -0400294}
295
296static void drawHolePunchLayer(SkiaRenderEngine* renderengine, const DisplaySettings& display,
297 const std::shared_ptr<ExternalTexture>& dstTexture) {
298 const Rect& displayRect = display.physicalDisplay;
299 FloatRect rect(0, 0, displayRect.width(), displayRect.height());
300 FloatRect small(0, 0, displayRect.width()-20, displayRect.height()+20);
301 LayerSettings layer{
302 .geometry =
303 Geometry{
Nathaniel Nifong13491502021-06-30 17:28:29 -0400304 // the boundaries have to be smaller than the rounded crop so that
305 // clipRRect is used instead of drawRRect
306 .boundaries = small,
Leon Scroggins III894c5f82023-08-25 14:43:54 -0400307 .positionTransform = kScaleAndTranslate,
Vishnu Nair50c0afe2022-07-11 15:04:07 -0700308 .roundedCornersRadius = {50.f, 50.f},
Nathaniel Nifong13491502021-06-30 17:28:29 -0400309 .roundedCornersCrop = rect,
310 },
Vishnu Nair50c0afe2022-07-11 15:04:07 -0700311 .source =
312 PixelSource{
Nathaniel Nifong13491502021-06-30 17:28:29 -0400313 .solidColor = half3(0.f, 0.f, 0.f),
314 },
Nathaniel Nifong13491502021-06-30 17:28:29 -0400315 .alpha = 0,
Leon Scroggins III894c5f82023-08-25 14:43:54 -0400316 .sourceDataspace = kDestDataSpace,
Nathaniel Nifong13491502021-06-30 17:28:29 -0400317 .disableBlending = true,
318
319 };
320
Sally Qi59a9f502021-10-12 18:53:23 +0000321 auto layers = std::vector<LayerSettings>{layer};
Alec Mourif29700f2023-08-17 21:53:31 +0000322 renderengine->drawLayers(display, layers, dstTexture, base::unique_fd());
Nathaniel Nifong13491502021-06-30 17:28:29 -0400323}
324
Mattias Simonsson65746132023-08-15 13:26:16 +0000325static void drawImageDimmedLayers(SkiaRenderEngine* renderengine, const DisplaySettings& display,
326 const std::shared_ptr<ExternalTexture>& dstTexture,
327 const std::shared_ptr<ExternalTexture>& srcTexture) {
328 const Rect& displayRect = display.physicalDisplay;
329 FloatRect rect(0, 0, displayRect.width(), displayRect.height());
330 LayerSettings layer{
331 .geometry =
332 Geometry{
333 // The position transform doesn't matter when the reduced shader mode
334 // in in effect. A matrix transform stage is always included.
335 .positionTransform = mat4(),
336 .boundaries = rect,
337 .roundedCornersCrop = rect,
338 .roundedCornersRadius = {0.f, 0.f},
339 },
340 .source = PixelSource{.buffer = Buffer{.buffer = srcTexture,
341 .maxLuminanceNits = 1000.f,
342 .usePremultipliedAlpha = true,
343 .isOpaque = true}},
344 .alpha = 1.f,
345 .sourceDataspace = kDestDataSpace,
346 };
347
348 std::vector<LayerSettings> layers;
349
350 for (auto layerWhitePoint : kLayerWhitePoints) {
351 layer.whitePointNits = layerWhitePoint;
352 layers.push_back(layer);
353 }
354 renderengine->drawLayers(display, layers, dstTexture, base::unique_fd());
355}
356
357static void drawTransparentImageDimmedLayers(SkiaRenderEngine* renderengine,
358 const DisplaySettings& display,
359 const std::shared_ptr<ExternalTexture>& dstTexture,
360 const std::shared_ptr<ExternalTexture>& srcTexture) {
361 const Rect& displayRect = display.physicalDisplay;
362 FloatRect rect(0, 0, displayRect.width(), displayRect.height());
363 LayerSettings layer{
364 .geometry =
365 Geometry{
366 .positionTransform = mat4(),
367 .boundaries = rect,
368 .roundedCornersCrop = rect,
369 },
370 .source = PixelSource{.buffer =
371 Buffer{
372 .buffer = srcTexture,
373 .maxLuminanceNits = 1000.f,
374 .usePremultipliedAlpha = true,
375 .isOpaque = false,
376 }},
377 .sourceDataspace = kDestDataSpace,
378 };
379
380 for (auto roundedCornerRadius : {0.f, 50.f}) {
381 layer.geometry.roundedCornersRadius = {roundedCornerRadius, roundedCornerRadius};
382 for (auto alpha : {0.5f, 1.0f}) {
383 layer.alpha = alpha;
384 std::vector<LayerSettings> layers;
385
386 for (auto layerWhitePoint : kLayerWhitePoints) {
387 layer.whitePointNits = layerWhitePoint;
388 layers.push_back(layer);
389 }
390 renderengine->drawLayers(display, layers, dstTexture, base::unique_fd());
391 }
392 }
393}
394
395static void drawClippedDimmedImageLayers(SkiaRenderEngine* renderengine,
396 const DisplaySettings& display,
397 const std::shared_ptr<ExternalTexture>& dstTexture,
398 const std::shared_ptr<ExternalTexture>& srcTexture) {
399 const Rect& displayRect = display.physicalDisplay;
400
401 // If rect and boundary is too small compared to roundedCornersRadius, Skia will switch to
402 // blending instead of EllipticalRRect, so enlarge them a bit.
403 FloatRect rect(0, 0, displayRect.width(), displayRect.height());
404 FloatRect boundary(0, 0, displayRect.width(),
405 displayRect.height() - 20); // boundary is smaller
406 LayerSettings layer{
407 .geometry =
408 Geometry{
409 .positionTransform = mat4(),
410 .boundaries = boundary,
411 .roundedCornersCrop = rect,
412 .roundedCornersRadius = {27.f, 27.f},
413 },
414 .source = PixelSource{.buffer =
415 Buffer{
416 .buffer = srcTexture,
417 .maxLuminanceNits = 1000.f,
418 .usePremultipliedAlpha = true,
419 .isOpaque = false,
420 }},
421 .alpha = 1.f,
422 .sourceDataspace = kDestDataSpace,
423 };
424
425 std::array<mat4, 2> transforms = {kScaleAndTranslate, kScaleAsymmetric};
426
427 constexpr float radius = 27.f;
428
429 for (size_t i = 0; i < transforms.size(); i++) {
430 layer.geometry.positionTransform = transforms[i];
431 layer.geometry.roundedCornersRadius = {radius, radius};
432
433 std::vector<LayerSettings> layers;
434
435 for (auto layerWhitePoint : kLayerWhitePoints) {
436 layer.whitePointNits = layerWhitePoint;
437 layers.push_back(layer);
438 }
439 renderengine->drawLayers(display, layers, dstTexture, base::unique_fd());
440 }
441}
442
443static void drawSolidDimmedLayers(SkiaRenderEngine* renderengine, const DisplaySettings& display,
444 const std::shared_ptr<ExternalTexture>& dstTexture) {
445 const Rect& displayRect = display.physicalDisplay;
446 FloatRect rect(0, 0, displayRect.width(), displayRect.height());
447 LayerSettings layer{
448 .geometry =
449 Geometry{
450 .boundaries = rect,
451 .roundedCornersCrop = rect,
452 },
453 .source =
454 PixelSource{
455 .solidColor = half3(0.1f, 0.2f, 0.3f),
456 },
457 .alpha = 1.f,
458 };
459
460 std::vector<LayerSettings> layers;
461
462 for (auto layerWhitePoint : kLayerWhitePoints) {
463 layer.whitePointNits = layerWhitePoint;
464 layers.push_back(layer);
465 }
466 renderengine->drawLayers(display, layers, dstTexture, base::unique_fd());
467}
468
Nathaniel Nifongb9f27ef2021-04-01 16:44:12 -0400469//
470// The collection of shaders cached here were found by using perfetto to record shader compiles
471// during actions that involve RenderEngine, logging the layer settings, and the shader code
472// and reproducing those settings here.
473//
474// It is helpful when debugging this to turn on
475// in SkGLRenderEngine.cpp:
476// kPrintLayerSettings = true
477// kFlushAfterEveryLayer = true
478// in external/skia/src/gpu/gl/builders/GrGLShaderStringBuilder.cpp
479// gPrintSKSL = true
Leon Scroggins IIIb9216dc2021-03-08 17:19:01 -0500480void Cache::primeShaderCache(SkiaRenderEngine* renderengine) {
Nathaniel Nifongb9f27ef2021-04-01 16:44:12 -0400481 const int previousCount = renderengine->reportShadersCompiled();
482 if (previousCount) {
483 ALOGD("%d Shaders already compiled before Cache::primeShaderCache ran\n", previousCount);
484 }
Leon Scroggins IIIb9216dc2021-03-08 17:19:01 -0500485
Derek Sollenbergere9a51082021-05-06 14:01:38 -0400486 // The loop is beneficial for debugging and should otherwise be optimized out by the compiler.
487 // Adding additional bounds to the loop is useful for verifying that the size of the dst buffer
488 // does not impact the shader compilation counts by triggering different behaviors in RE/Skia.
489 for (SkSize bounds : {SkSize::Make(128, 128), /*SkSize::Make(1080, 2340)*/}) {
490 const nsecs_t timeBefore = systemTime();
491 // The dimensions should not matter, so long as we draw inside them.
492 const Rect displayRect(0, 0, bounds.fWidth, bounds.fHeight);
493 DisplaySettings display{
494 .physicalDisplay = displayRect,
495 .clip = displayRect,
496 .maxLuminance = 500,
497 .outputDataspace = kDestDataSpace,
498 };
Nathaniel Nifonga6b54232021-07-02 13:24:32 -0400499 DisplaySettings p3Display{
500 .physicalDisplay = displayRect,
501 .clip = displayRect,
502 .maxLuminance = 500,
503 .outputDataspace = kOtherDataSpace,
504 };
Mattias Simonsson65746132023-08-15 13:26:16 +0000505 DisplaySettings bt2020Display{.physicalDisplay = displayRect,
506 .clip = displayRect,
507 .maxLuminance = 500,
508 .outputDataspace = ui::Dataspace::BT2020,
509 .deviceHandlesColorTransform = true,
510 .dimmingStage = aidl::android::hardware::graphics::composer3::
511 DimmingStage::GAMMA_OETF,
512 .renderIntent = aidl::android::hardware::graphics::composer3::
513 RenderIntent::TONE_MAP_ENHANCE};
Leon Scroggins IIIb9216dc2021-03-08 17:19:01 -0500514
Derek Sollenbergere9a51082021-05-06 14:01:38 -0400515 const int64_t usage = GRALLOC_USAGE_HW_RENDER | GRALLOC_USAGE_HW_TEXTURE;
Alec Mouria90a5702021-04-16 16:36:21 +0000516
Derek Sollenbergere9a51082021-05-06 14:01:38 -0400517 sp<GraphicBuffer> dstBuffer =
Ady Abrahamd11bade2022-08-01 16:18:03 -0700518 sp<GraphicBuffer>::make(displayRect.width(), displayRect.height(),
519 PIXEL_FORMAT_RGBA_8888, 1, usage, "primeShaderCache_dst");
Nathaniel Nifongb9f27ef2021-04-01 16:44:12 -0400520
Derek Sollenbergere9a51082021-05-06 14:01:38 -0400521 const auto dstTexture =
Vishnu Nairdbbe3852022-01-12 20:22:11 -0800522 std::make_shared<impl::ExternalTexture>(dstBuffer, *renderengine,
523 impl::ExternalTexture::Usage::WRITEABLE);
Derek Sollenbergere9a51082021-05-06 14:01:38 -0400524 // This buffer will be the source for the call to drawImageLayers. Draw
525 // something to it as a placeholder for what an app draws. We should draw
526 // something, but the details are not important. Make use of the shadow layer drawing step
527 // to populate it.
528 sp<GraphicBuffer> srcBuffer =
Ady Abrahamd11bade2022-08-01 16:18:03 -0700529 sp<GraphicBuffer>::make(displayRect.width(), displayRect.height(),
530 PIXEL_FORMAT_RGBA_8888, 1, usage, "drawImageLayer_src");
Alec Mouria90a5702021-04-16 16:36:21 +0000531
Vishnu Nairdbbe3852022-01-12 20:22:11 -0800532 const auto srcTexture = std::make_shared<
533 impl::ExternalTexture>(srcBuffer, *renderengine,
534 impl::ExternalTexture::Usage::READABLE |
535 impl::ExternalTexture::Usage::WRITEABLE);
Nathaniel Nifong13491502021-06-30 17:28:29 -0400536 drawHolePunchLayer(renderengine, display, dstTexture);
Derek Sollenbergere9a51082021-05-06 14:01:38 -0400537 drawSolidLayers(renderengine, display, dstTexture);
Mattias Simonsson65746132023-08-15 13:26:16 +0000538 drawSolidDimmedLayers(renderengine, display, dstTexture);
Nathaniel Nifong49a59582021-07-26 19:49:47 -0400539
Derek Sollenbergere9a51082021-05-06 14:01:38 -0400540 drawShadowLayers(renderengine, display, srcTexture);
Nathaniel Nifonga6b54232021-07-02 13:24:32 -0400541 drawShadowLayers(renderengine, p3Display, srcTexture);
Nathaniel Nifongcda45e92021-06-10 15:01:42 -0400542
543 if (renderengine->supportsBackgroundBlur()) {
544 drawBlurLayers(renderengine, display, dstTexture);
545 }
546
Nathaniel Nifong73537a32021-08-06 15:07:26 -0400547 // The majority of skia shaders needed by RenderEngine are related to sampling images.
548 // These need to be generated with various source textures.
549 // Make a list of applicable sources.
550 // GRALLOC_USAGE_HW_TEXTURE should be the same as AHARDWAREBUFFER_USAGE_GPU_SAMPLED_IMAGE.
Derek Sollenbergere9a51082021-05-06 14:01:38 -0400551 const int64_t usageExternal = GRALLOC_USAGE_HW_TEXTURE;
Derek Sollenbergere9a51082021-05-06 14:01:38 -0400552 sp<GraphicBuffer> externalBuffer =
Ady Abrahamd11bade2022-08-01 16:18:03 -0700553 sp<GraphicBuffer>::make(displayRect.width(), displayRect.height(),
554 PIXEL_FORMAT_RGBA_8888, 1, usageExternal,
555 "primeShaderCache_external");
Derek Sollenbergere9a51082021-05-06 14:01:38 -0400556 const auto externalTexture =
Vishnu Nairdbbe3852022-01-12 20:22:11 -0800557 std::make_shared<impl::ExternalTexture>(externalBuffer, *renderengine,
558 impl::ExternalTexture::Usage::READABLE);
Nathaniel Nifong73537a32021-08-06 15:07:26 -0400559 std::vector<const std::shared_ptr<ExternalTexture>> textures =
560 {srcTexture, externalTexture};
Nathaniel Nifong21e021f2021-04-21 13:15:46 -0400561
Nathaniel Nifong73537a32021-08-06 15:07:26 -0400562 // Another external texture with a different pixel format triggers useIsOpaqueWorkaround.
563 // It doesn't have to be f16, but it can't be the usual 8888.
Nathaniel Nifongf06a45b2021-06-25 17:24:26 -0400564 sp<GraphicBuffer> f16ExternalBuffer =
Ady Abrahamd11bade2022-08-01 16:18:03 -0700565 sp<GraphicBuffer>::make(displayRect.width(), displayRect.height(),
566 PIXEL_FORMAT_RGBA_FP16, 1, usageExternal,
567 "primeShaderCache_external_f16");
Nathaniel Nifong73537a32021-08-06 15:07:26 -0400568 // The F16 texture may not be usable on all devices, so check first that it was created.
569 status_t error = f16ExternalBuffer->initCheck();
570 if (!error) {
571 const auto f16ExternalTexture =
Vishnu Nairdbbe3852022-01-12 20:22:11 -0800572 std::make_shared<impl::ExternalTexture>(f16ExternalBuffer, *renderengine,
573 impl::ExternalTexture::Usage::READABLE);
Nathaniel Nifong73537a32021-08-06 15:07:26 -0400574 textures.push_back(f16ExternalTexture);
575 }
Nathaniel Nifongf06a45b2021-06-25 17:24:26 -0400576
Nathaniel Nifong73537a32021-08-06 15:07:26 -0400577 for (auto texture : textures) {
Nathaniel Nifongf06a45b2021-06-25 17:24:26 -0400578 drawImageLayers(renderengine, display, dstTexture, texture);
Mattias Simonsson65746132023-08-15 13:26:16 +0000579 drawImageDimmedLayers(renderengine, display, dstTexture, texture);
580 drawImageDimmedLayers(renderengine, p3Display, dstTexture, texture);
581 drawImageDimmedLayers(renderengine, bt2020Display, dstTexture, texture);
Nathaniel Nifongf06a45b2021-06-25 17:24:26 -0400582 // Draw layers for b/185569240.
583 drawClippedLayers(renderengine, display, dstTexture, texture);
584 }
Derek Sollenbergere9a51082021-05-06 14:01:38 -0400585
Nathaniel Nifong13491502021-06-30 17:28:29 -0400586 drawPIPImageLayer(renderengine, display, dstTexture, externalTexture);
587
Mattias Simonsson65746132023-08-15 13:26:16 +0000588 drawTransparentImageDimmedLayers(renderengine, bt2020Display, dstTexture, externalTexture);
589 drawTransparentImageDimmedLayers(renderengine, display, dstTexture, externalTexture);
590 drawTransparentImageDimmedLayers(renderengine, p3Display, dstTexture, externalTexture);
591
592 drawClippedDimmedImageLayers(renderengine, bt2020Display, dstTexture, externalTexture);
593
Nathaniel Nifong2d2f4322021-07-22 15:17:36 -0400594 // draw one final layer synchronously to force GL submit
595 LayerSettings layer{
596 .source = PixelSource{.solidColor = half3(0.f, 0.f, 0.f)},
597 };
Sally Qi59a9f502021-10-12 18:53:23 +0000598 auto layers = std::vector<LayerSettings>{layer};
Sally Qi4cabdd02021-08-05 16:45:57 -0700599 // call get() to make it synchronous
Alec Mourif29700f2023-08-17 21:53:31 +0000600 renderengine->drawLayers(display, layers, dstTexture, base::unique_fd()).get();
Nathaniel Nifong2d2f4322021-07-22 15:17:36 -0400601
Derek Sollenbergere9a51082021-05-06 14:01:38 -0400602 const nsecs_t timeAfter = systemTime();
603 const float compileTimeMs = static_cast<float>(timeAfter - timeBefore) / 1.0E6;
Leon Scroggins III45be9182022-04-27 10:37:11 -0400604 const int shadersCompiled = renderengine->reportShadersCompiled() - previousCount;
Derek Sollenbergere9a51082021-05-06 14:01:38 -0400605 ALOGD("Shader cache generated %d shaders in %f ms\n", shadersCompiled, compileTimeMs);
606 }
Leon Scroggins IIIb9216dc2021-03-08 17:19:01 -0500607}
608
609} // namespace android::renderengine::skia