blob: 6ab93dfb4dcf21e5c1d2c07ca5573fa5100b6af6 [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"
22#include "ui/GraphicBuffer.h"
23#include "ui/GraphicTypes.h"
24#include "ui/PixelFormat.h"
25#include "ui/Rect.h"
26#include "utils/Timers.h"
27
28namespace android::renderengine::skia {
29
Nathaniel Nifongb9f27ef2021-04-01 16:44:12 -040030namespace {
Nathaniel Nifong4fc750d2021-03-19 11:37:36 -040031// Warming shader cache, not framebuffer cache.
32constexpr bool kUseFrameBufferCache = false;
33
Nathaniel Nifongb9f27ef2021-04-01 16:44:12 -040034// clang-format off
35// Any non-identity matrix will do.
36const auto kScaleAndTranslate = mat4(0.7f, 0.f, 0.f, 0.f,
37 0.f, 0.7f, 0.f, 0.f,
38 0.f, 0.f, 1.f, 0.f,
39 67.3f, 52.2f, 0.f, 1.f);
Nathaniel Nifong21e021f2021-04-21 13:15:46 -040040const auto kScaleYOnly = mat4(1.f, 0.f, 0.f, 0.f,
41 0.f, 0.7f, 0.f, 0.f,
42 0.f, 0.f, 1.f, 0.f,
43 0.f, 0.f, 0.f, 1.f);
Nathaniel Nifongb9f27ef2021-04-01 16:44:12 -040044// clang-format on
Nathaniel Nifongbf6f7542021-04-27 12:05:16 -040045// When setting layer.sourceDataspace, whether it matches the destination or not determines whether
46// a color correction effect is added to the shader.
Nathaniel Nifongb9f27ef2021-04-01 16:44:12 -040047constexpr auto kDestDataSpace = ui::Dataspace::SRGB;
Nathaniel Nifong21e021f2021-04-21 13:15:46 -040048constexpr auto kOtherDataSpace = ui::Dataspace::DISPLAY_P3;
Nathaniel Nifongb9f27ef2021-04-01 16:44:12 -040049} // namespace
50
Nathaniel Nifong4fc750d2021-03-19 11:37:36 -040051static void drawShadowLayers(SkiaRenderEngine* renderengine, const DisplaySettings& display,
Alec Mouria90a5702021-04-16 16:36:21 +000052 const std::shared_ptr<ExternalTexture>& dstTexture) {
Leon Scroggins IIIb9216dc2021-03-08 17:19:01 -050053 // Somewhat arbitrary dimensions, but on screen and slightly shorter, based
54 // on actual use.
55 FloatRect rect(0, 0, display.physicalDisplay.width(), display.physicalDisplay.height() - 30);
56 LayerSettings layer{
57 .geometry =
58 Geometry{
59 .boundaries = rect,
60 .roundedCornersCrop = rect,
61 },
Nathaniel Nifong4fc750d2021-03-19 11:37:36 -040062 // drawShadow ignores alpha
Leon Scroggins IIIb9216dc2021-03-08 17:19:01 -050063 .shadow =
64 ShadowSettings{
65 .ambientColor = vec4(0, 0, 0, 0.00935997f),
66 .spotColor = vec4(0, 0, 0, 0.0455841f),
67 .lightPos = vec3(370.508f, -1527.03f, 1650.f),
68 .lightRadius = 2200.0f,
69 .length = 0.955342f,
70 },
Nathaniel Nifongb9f27ef2021-04-01 16:44:12 -040071 // important that this matches dest so the general shadow fragment shader doesn't
72 // have color correction added, and important that it be srgb, so the *vertex* shader
73 // doesn't have color correction added.
74 .sourceDataspace = kDestDataSpace,
Leon Scroggins IIIb9216dc2021-03-08 17:19:01 -050075 };
76
77 auto layers = std::vector<const LayerSettings*>{&layer};
Nathaniel Nifongb9f27ef2021-04-01 16:44:12 -040078 // The identity matrix will generate the fast shader
Alec Mouria90a5702021-04-16 16:36:21 +000079 renderengine->drawLayers(display, layers, dstTexture, kUseFrameBufferCache, base::unique_fd(),
Nathaniel Nifongb9f27ef2021-04-01 16:44:12 -040080 nullptr);
81 // This matrix, which has different scales for x and y, will
82 // generate the slower (more general case) version, which has variants for translucent
83 // casters and rounded rects.
84 // clang-format off
85 layer.geometry.positionTransform = mat4(0.7f, 0.f, 0.f, 0.f,
86 0.f, 0.8f, 0.f, 0.f,
87 0.f, 0.f, 1.f, 0.f,
88 0.f, 0.f, 0.f, 1.f);
89 // clang-format on
90 for (auto translucent : {false, true}) {
91 layer.shadow.casterIsTranslucent = translucent;
Alec Mouria90a5702021-04-16 16:36:21 +000092 renderengine->drawLayers(display, layers, dstTexture, kUseFrameBufferCache,
Leon Scroggins IIIb9216dc2021-03-08 17:19:01 -050093 base::unique_fd(), nullptr);
94 }
95}
96
97static void drawImageLayers(SkiaRenderEngine* renderengine, const DisplaySettings& display,
Alec Mouria90a5702021-04-16 16:36:21 +000098 const std::shared_ptr<ExternalTexture>& dstTexture,
99 const std::shared_ptr<ExternalTexture>& srcTexture) {
Leon Scroggins IIIb9216dc2021-03-08 17:19:01 -0500100 const Rect& displayRect = display.physicalDisplay;
101 FloatRect rect(0, 0, displayRect.width(), displayRect.height());
102 LayerSettings layer{
103 .geometry =
104 Geometry{
105 .boundaries = rect,
Leon Scroggins IIIb9216dc2021-03-08 17:19:01 -0500106 .roundedCornersCrop = rect,
107 },
108 .source = PixelSource{.buffer =
109 Buffer{
Alec Mouria90a5702021-04-16 16:36:21 +0000110 .buffer = srcTexture,
Leon Scroggins IIIb9216dc2021-03-08 17:19:01 -0500111 .maxMasteringLuminance = 1000.f,
112 .maxContentLuminance = 1000.f,
113 }},
114 };
115
Nathaniel Nifongb9f27ef2021-04-01 16:44:12 -0400116 auto threeCornerRadii = {0.0f, 0.05f, 50.f};
117 auto oneCornerRadius = {50.f};
Nathaniel Nifong4fc750d2021-03-19 11:37:36 -0400118
Leon Scroggins IIIb9216dc2021-03-08 17:19:01 -0500119 // Test both drawRect and drawRRect
120 auto layers = std::vector<const LayerSettings*>{&layer};
Nathaniel Nifongbf6f7542021-04-27 12:05:16 -0400121 for (auto dataspace : {kDestDataSpace, kOtherDataSpace}) {
122 layer.sourceDataspace = dataspace;
123 for (bool identity : {true, false}) {
124 layer.geometry.positionTransform = identity ? mat4() : kScaleAndTranslate;
125 // Corner radii less than 0.5 creates a special shader. This likely occurs in real usage
126 // due to animating corner radius.
127 // For the non-idenity matrix, only the large corner radius will create a new shader.
128 for (float roundedCornersRadius : identity ? threeCornerRadii : oneCornerRadius) {
129 // roundedCornersCrop is always set, but it is this radius that triggers the
130 // behavior
131 layer.geometry.roundedCornersRadius = roundedCornersRadius;
132 for (bool isOpaque : {true, false}) {
133 layer.source.buffer.isOpaque = isOpaque;
134 for (auto alpha : {half(.23999f), half(1.0f)}) {
135 layer.alpha = alpha;
136 renderengine->drawLayers(display, layers, dstTexture, kUseFrameBufferCache,
137 base::unique_fd(), nullptr);
138 }
Leon Scroggins IIIb9216dc2021-03-08 17:19:01 -0500139 }
140 }
141 }
142 }
143}
144
Nathaniel Nifong4fc750d2021-03-19 11:37:36 -0400145static void drawSolidLayers(SkiaRenderEngine* renderengine, const DisplaySettings& display,
Alec Mouria90a5702021-04-16 16:36:21 +0000146 const std::shared_ptr<ExternalTexture>& dstTexture) {
Nathaniel Nifong4fc750d2021-03-19 11:37:36 -0400147 const Rect& displayRect = display.physicalDisplay;
148 FloatRect rect(0, 0, displayRect.width(), displayRect.height());
149 LayerSettings layer{
150 .geometry =
151 Geometry{
152 .boundaries = rect,
153 },
Nathaniel Nifong4fc750d2021-03-19 11:37:36 -0400154 .source =
155 PixelSource{
156 .solidColor = half3(0.1f, 0.2f, 0.3f),
157 },
Alec Mouria90a5702021-04-16 16:36:21 +0000158 .alpha = 1,
Nathaniel Nifong4fc750d2021-03-19 11:37:36 -0400159 };
160
161 auto layers = std::vector<const LayerSettings*>{&layer};
Nathaniel Nifongb9f27ef2021-04-01 16:44:12 -0400162 for (auto transform : {mat4(), kScaleAndTranslate}) {
163 layer.geometry.positionTransform = transform;
164 for (float roundedCornersRadius : {0.0f, 0.05f, 50.f}) {
165 layer.geometry.roundedCornersRadius = roundedCornersRadius;
Alec Mouria90a5702021-04-16 16:36:21 +0000166 renderengine->drawLayers(display, layers, dstTexture, kUseFrameBufferCache,
Nathaniel Nifongb9f27ef2021-04-01 16:44:12 -0400167 base::unique_fd(), nullptr);
168 }
169 }
Nathaniel Nifong4fc750d2021-03-19 11:37:36 -0400170}
171
Nathaniel Nifongb9f27ef2021-04-01 16:44:12 -0400172static void drawBlurLayers(SkiaRenderEngine* renderengine, const DisplaySettings& display,
Alec Mouria90a5702021-04-16 16:36:21 +0000173 const std::shared_ptr<ExternalTexture>& dstTexture) {
Nathaniel Nifongb9f27ef2021-04-01 16:44:12 -0400174 const Rect& displayRect = display.physicalDisplay;
175 FloatRect rect(0, 0, displayRect.width(), displayRect.height());
176 LayerSettings layer{
177 .geometry =
178 Geometry{
179 .boundaries = rect,
180 },
181 .alpha = 1,
182 };
183
184 auto layers = std::vector<const LayerSettings*>{&layer};
185 for (int radius : {9, 60}) {
186 layer.backgroundBlurRadius = radius;
Alec Mouria90a5702021-04-16 16:36:21 +0000187 renderengine->drawLayers(display, layers, dstTexture, kUseFrameBufferCache,
Nathaniel Nifongb9f27ef2021-04-01 16:44:12 -0400188 base::unique_fd(), nullptr);
189 }
190}
191
Nathaniel Nifong21e021f2021-04-21 13:15:46 -0400192static void drawTextureScaleLayers(SkiaRenderEngine* renderengine, const DisplaySettings& display,
193 const std::shared_ptr<ExternalTexture>& dstTexture,
194 const std::shared_ptr<ExternalTexture>& srcTexture) {
195 const Rect& displayRect = display.physicalDisplay;
196 FloatRect rect(0, 0, displayRect.width(), displayRect.height());
197 LayerSettings layer{
198 .geometry =
199 Geometry{
200 .boundaries = rect,
201 .roundedCornersCrop = rect,
202 .positionTransform = kScaleAndTranslate,
203 .roundedCornersRadius = 300,
204 },
205 .source = PixelSource{.buffer =
206 Buffer{
207 .buffer = srcTexture,
208 .maxMasteringLuminance = 1000.f,
209 .maxContentLuminance = 1000.f,
210 .textureTransform = kScaleYOnly,
211 }},
212 .sourceDataspace = kOtherDataSpace,
213 };
214
215 auto layers = std::vector<const LayerSettings*>{&layer};
216 for (float alpha : {0.5f, 1.f}) {
217 layer.alpha = alpha,
218 renderengine->drawLayers(display, layers, dstTexture, kUseFrameBufferCache,
219 base::unique_fd(), nullptr);
220 }
221}
222
Nathaniel Nifongb9f27ef2021-04-01 16:44:12 -0400223//
224// The collection of shaders cached here were found by using perfetto to record shader compiles
225// during actions that involve RenderEngine, logging the layer settings, and the shader code
226// and reproducing those settings here.
227//
228// It is helpful when debugging this to turn on
229// in SkGLRenderEngine.cpp:
230// kPrintLayerSettings = true
231// kFlushAfterEveryLayer = true
232// in external/skia/src/gpu/gl/builders/GrGLShaderStringBuilder.cpp
233// gPrintSKSL = true
234//
235// TODO(b/184631553) cache the shader involved in youtube pip return.
Leon Scroggins IIIb9216dc2021-03-08 17:19:01 -0500236void Cache::primeShaderCache(SkiaRenderEngine* renderengine) {
Nathaniel Nifongb9f27ef2021-04-01 16:44:12 -0400237 const int previousCount = renderengine->reportShadersCompiled();
238 if (previousCount) {
239 ALOGD("%d Shaders already compiled before Cache::primeShaderCache ran\n", previousCount);
240 }
Leon Scroggins IIIb9216dc2021-03-08 17:19:01 -0500241 const nsecs_t timeBefore = systemTime();
242 // The dimensions should not matter, so long as we draw inside them.
243 const Rect displayRect(0, 0, 1080, 2340);
244 DisplaySettings display{
245 .physicalDisplay = displayRect,
246 .clip = displayRect,
247 .maxLuminance = 500,
Nathaniel Nifongb9f27ef2021-04-01 16:44:12 -0400248 .outputDataspace = kDestDataSpace,
Leon Scroggins IIIb9216dc2021-03-08 17:19:01 -0500249 };
250
251 const int64_t usage = GRALLOC_USAGE_HW_RENDER | GRALLOC_USAGE_HW_TEXTURE;
252
253 sp<GraphicBuffer> dstBuffer =
254 new GraphicBuffer(displayRect.width(), displayRect.height(), PIXEL_FORMAT_RGBA_8888, 1,
255 usage, "primeShaderCache_dst");
Alec Mouria90a5702021-04-16 16:36:21 +0000256
257 const auto dstTexture = std::make_shared<ExternalTexture>(dstBuffer, *renderengine,
258 ExternalTexture::Usage::WRITEABLE);
Leon Scroggins IIIb9216dc2021-03-08 17:19:01 -0500259 // This buffer will be the source for the call to drawImageLayers. Draw
260 // something to it as a placeholder for what an app draws. We should draw
Nathaniel Nifong4fc750d2021-03-19 11:37:36 -0400261 // something, but the details are not important. Make use of the shadow layer drawing step
262 // to populate it.
Leon Scroggins IIIb9216dc2021-03-08 17:19:01 -0500263 sp<GraphicBuffer> srcBuffer =
264 new GraphicBuffer(displayRect.width(), displayRect.height(), PIXEL_FORMAT_RGBA_8888, 1,
265 usage, "drawImageLayer_src");
Nathaniel Nifongb9f27ef2021-04-01 16:44:12 -0400266
Alec Mouria90a5702021-04-16 16:36:21 +0000267 const auto srcTexture =
268 std::make_shared<ExternalTexture>(srcBuffer, *renderengine,
269 ExternalTexture::Usage::READABLE |
270 ExternalTexture::Usage::WRITEABLE);
271
272 drawSolidLayers(renderengine, display, dstTexture);
273 drawShadowLayers(renderengine, display, srcTexture);
274 drawBlurLayers(renderengine, display, dstTexture);
Nathaniel Nifongb9f27ef2021-04-01 16:44:12 -0400275 // The majority of shaders are related to sampling images.
Alec Mouria90a5702021-04-16 16:36:21 +0000276 drawImageLayers(renderengine, display, dstTexture, srcTexture);
Nathaniel Nifongb9f27ef2021-04-01 16:44:12 -0400277
Nathaniel Nifongf4362402021-04-12 11:41:05 -0400278 // should be the same as AHARDWAREBUFFER_USAGE_GPU_SAMPLED_IMAGE;
279 const int64_t usageExternal = GRALLOC_USAGE_HW_TEXTURE;
280
281 sp<GraphicBuffer> externalBuffer =
282 new GraphicBuffer(displayRect.width(), displayRect.height(), PIXEL_FORMAT_RGBA_8888, 1,
283 usageExternal, "primeShaderCache_external");
Alec Mouria90a5702021-04-16 16:36:21 +0000284 const auto externalTexture =
285 std::make_shared<ExternalTexture>(externalBuffer, *renderengine,
286 ExternalTexture::Usage::READABLE);
Nathaniel Nifongf4362402021-04-12 11:41:05 -0400287 // TODO(b/184665179) doubles number of image shader compilations, but only somewhere
288 // between 6 and 8 will occur in real uses.
Alec Mouria90a5702021-04-16 16:36:21 +0000289 drawImageLayers(renderengine, display, dstTexture, externalTexture);
Nathaniel Nifongb9f27ef2021-04-01 16:44:12 -0400290
Nathaniel Nifong21e021f2021-04-21 13:15:46 -0400291 // Draw layers for b/185569240.
292 drawTextureScaleLayers(renderengine, display, dstTexture, externalTexture);
293
Leon Scroggins IIIb9216dc2021-03-08 17:19:01 -0500294 const nsecs_t timeAfter = systemTime();
295 const float compileTimeMs = static_cast<float>(timeAfter - timeBefore) / 1.0E6;
Nathaniel Nifongb9f27ef2021-04-01 16:44:12 -0400296 const int shadersCompiled = renderengine->reportShadersCompiled();
297 ALOGD("Shader cache generated %d shaders in %f ms\n", shadersCompiled, compileTimeMs);
Leon Scroggins IIIb9216dc2021-03-08 17:19:01 -0500298}
299
300} // namespace android::renderengine::skia