blob: 1db20c0be075f4b007e580a85904782a5e8d4a4c [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);
40// clang-format on
41// When choosing dataspaces below, whether the match the destination or not determined whether
42// a color correction effect is added to the shader. There may be other additional shader details
43// for particular color spaces.
44// TODO(b/184842383) figure out which color related shaders are necessary
45constexpr auto kDestDataSpace = ui::Dataspace::SRGB;
46} // namespace
47
Nathaniel Nifong4fc750d2021-03-19 11:37:36 -040048static void drawShadowLayers(SkiaRenderEngine* renderengine, const DisplaySettings& display,
49 sp<GraphicBuffer> dstBuffer) {
Leon Scroggins IIIb9216dc2021-03-08 17:19:01 -050050 // Somewhat arbitrary dimensions, but on screen and slightly shorter, based
51 // on actual use.
52 FloatRect rect(0, 0, display.physicalDisplay.width(), display.physicalDisplay.height() - 30);
53 LayerSettings layer{
54 .geometry =
55 Geometry{
56 .boundaries = rect,
57 .roundedCornersCrop = rect,
58 },
Nathaniel Nifong4fc750d2021-03-19 11:37:36 -040059 // drawShadow ignores alpha
Leon Scroggins IIIb9216dc2021-03-08 17:19:01 -050060 .shadow =
61 ShadowSettings{
62 .ambientColor = vec4(0, 0, 0, 0.00935997f),
63 .spotColor = vec4(0, 0, 0, 0.0455841f),
64 .lightPos = vec3(370.508f, -1527.03f, 1650.f),
65 .lightRadius = 2200.0f,
66 .length = 0.955342f,
67 },
Nathaniel Nifongb9f27ef2021-04-01 16:44:12 -040068 // important that this matches dest so the general shadow fragment shader doesn't
69 // have color correction added, and important that it be srgb, so the *vertex* shader
70 // doesn't have color correction added.
71 .sourceDataspace = kDestDataSpace,
Leon Scroggins IIIb9216dc2021-03-08 17:19:01 -050072 };
73
74 auto layers = std::vector<const LayerSettings*>{&layer};
Nathaniel Nifongb9f27ef2021-04-01 16:44:12 -040075 // The identity matrix will generate the fast shader
76 renderengine->drawLayers(display, layers, dstBuffer, kUseFrameBufferCache, base::unique_fd(),
77 nullptr);
78 // This matrix, which has different scales for x and y, will
79 // generate the slower (more general case) version, which has variants for translucent
80 // casters and rounded rects.
81 // clang-format off
82 layer.geometry.positionTransform = mat4(0.7f, 0.f, 0.f, 0.f,
83 0.f, 0.8f, 0.f, 0.f,
84 0.f, 0.f, 1.f, 0.f,
85 0.f, 0.f, 0.f, 1.f);
86 // clang-format on
87 for (auto translucent : {false, true}) {
88 layer.shadow.casterIsTranslucent = translucent;
Nathaniel Nifong4fc750d2021-03-19 11:37:36 -040089 renderengine->drawLayers(display, layers, dstBuffer, kUseFrameBufferCache,
Leon Scroggins IIIb9216dc2021-03-08 17:19:01 -050090 base::unique_fd(), nullptr);
91 }
92}
93
94static void drawImageLayers(SkiaRenderEngine* renderengine, const DisplaySettings& display,
95 sp<GraphicBuffer> dstBuffer, sp<GraphicBuffer> srcBuffer) {
96 const Rect& displayRect = display.physicalDisplay;
97 FloatRect rect(0, 0, displayRect.width(), displayRect.height());
98 LayerSettings layer{
99 .geometry =
100 Geometry{
101 .boundaries = rect,
Leon Scroggins IIIb9216dc2021-03-08 17:19:01 -0500102 .roundedCornersCrop = rect,
103 },
104 .source = PixelSource{.buffer =
105 Buffer{
106 .buffer = srcBuffer,
107 .maxMasteringLuminance = 1000.f,
108 .maxContentLuminance = 1000.f,
109 }},
110 };
111
Nathaniel Nifongb9f27ef2021-04-01 16:44:12 -0400112 auto threeCornerRadii = {0.0f, 0.05f, 50.f};
113 auto oneCornerRadius = {50.f};
Nathaniel Nifong4fc750d2021-03-19 11:37:36 -0400114
Leon Scroggins IIIb9216dc2021-03-08 17:19:01 -0500115 // Test both drawRect and drawRRect
116 auto layers = std::vector<const LayerSettings*>{&layer};
Nathaniel Nifongb9f27ef2021-04-01 16:44:12 -0400117 for (bool identity : {true, false}) {
118 layer.geometry.positionTransform = identity ? mat4() : kScaleAndTranslate;
119 // Corner radii less than 0.5 creates a special shader. This likely occurs in real usage
120 // due to animating corner radius.
121 // For the non-idenity matrix, only the large corner radius will create a new shader.
122 for (float roundedCornersRadius : identity ? threeCornerRadii : oneCornerRadius) {
Nathaniel Nifong4fc750d2021-03-19 11:37:36 -0400123 // roundedCornersCrop is always set, but it is this radius that triggers the behavior
124 layer.geometry.roundedCornersRadius = roundedCornersRadius;
Nathaniel Nifongb9f27ef2021-04-01 16:44:12 -0400125 for (bool isOpaque : {true, false}) {
126 layer.source.buffer.isOpaque = isOpaque;
127 for (auto alpha : {half(.23999f), half(1.0f)}) {
128 layer.alpha = alpha;
129 renderengine->drawLayers(display, layers, dstBuffer, kUseFrameBufferCache,
130 base::unique_fd(), nullptr);
Leon Scroggins IIIb9216dc2021-03-08 17:19:01 -0500131 }
132 }
133 }
134 }
135}
136
Nathaniel Nifong4fc750d2021-03-19 11:37:36 -0400137static void drawSolidLayers(SkiaRenderEngine* renderengine, const DisplaySettings& display,
138 sp<GraphicBuffer> dstBuffer) {
139 const Rect& displayRect = display.physicalDisplay;
140 FloatRect rect(0, 0, displayRect.width(), displayRect.height());
141 LayerSettings layer{
142 .geometry =
143 Geometry{
144 .boundaries = rect,
145 },
146 .alpha = 1,
147 .source =
148 PixelSource{
149 .solidColor = half3(0.1f, 0.2f, 0.3f),
150 },
151 };
152
153 auto layers = std::vector<const LayerSettings*>{&layer};
Nathaniel Nifongb9f27ef2021-04-01 16:44:12 -0400154 for (auto transform : {mat4(), kScaleAndTranslate}) {
155 layer.geometry.positionTransform = transform;
156 for (float roundedCornersRadius : {0.0f, 0.05f, 50.f}) {
157 layer.geometry.roundedCornersRadius = roundedCornersRadius;
158 renderengine->drawLayers(display, layers, dstBuffer, kUseFrameBufferCache,
159 base::unique_fd(), nullptr);
160 }
161 }
Nathaniel Nifong4fc750d2021-03-19 11:37:36 -0400162}
163
Nathaniel Nifongb9f27ef2021-04-01 16:44:12 -0400164static void drawBlurLayers(SkiaRenderEngine* renderengine, const DisplaySettings& display,
165 sp<GraphicBuffer> dstBuffer) {
166 const Rect& displayRect = display.physicalDisplay;
167 FloatRect rect(0, 0, displayRect.width(), displayRect.height());
168 LayerSettings layer{
169 .geometry =
170 Geometry{
171 .boundaries = rect,
172 },
173 .alpha = 1,
174 };
175
176 auto layers = std::vector<const LayerSettings*>{&layer};
177 for (int radius : {9, 60}) {
178 layer.backgroundBlurRadius = radius;
179 renderengine->drawLayers(display, layers, dstBuffer, kUseFrameBufferCache,
180 base::unique_fd(), nullptr);
181 }
182}
183
Nathaniel Nifongb9f27ef2021-04-01 16:44:12 -0400184//
185// The collection of shaders cached here were found by using perfetto to record shader compiles
186// during actions that involve RenderEngine, logging the layer settings, and the shader code
187// and reproducing those settings here.
188//
189// It is helpful when debugging this to turn on
190// in SkGLRenderEngine.cpp:
191// kPrintLayerSettings = true
192// kFlushAfterEveryLayer = true
193// in external/skia/src/gpu/gl/builders/GrGLShaderStringBuilder.cpp
194// gPrintSKSL = true
195//
196// TODO(b/184631553) cache the shader involved in youtube pip return.
Leon Scroggins IIIb9216dc2021-03-08 17:19:01 -0500197void Cache::primeShaderCache(SkiaRenderEngine* renderengine) {
Nathaniel Nifongb9f27ef2021-04-01 16:44:12 -0400198 const int previousCount = renderengine->reportShadersCompiled();
199 if (previousCount) {
200 ALOGD("%d Shaders already compiled before Cache::primeShaderCache ran\n", previousCount);
201 }
Leon Scroggins IIIb9216dc2021-03-08 17:19:01 -0500202 const nsecs_t timeBefore = systemTime();
203 // The dimensions should not matter, so long as we draw inside them.
204 const Rect displayRect(0, 0, 1080, 2340);
205 DisplaySettings display{
206 .physicalDisplay = displayRect,
207 .clip = displayRect,
208 .maxLuminance = 500,
Nathaniel Nifongb9f27ef2021-04-01 16:44:12 -0400209 .outputDataspace = kDestDataSpace,
Leon Scroggins IIIb9216dc2021-03-08 17:19:01 -0500210 };
211
212 const int64_t usage = GRALLOC_USAGE_HW_RENDER | GRALLOC_USAGE_HW_TEXTURE;
213
214 sp<GraphicBuffer> dstBuffer =
215 new GraphicBuffer(displayRect.width(), displayRect.height(), PIXEL_FORMAT_RGBA_8888, 1,
216 usage, "primeShaderCache_dst");
217 // This buffer will be the source for the call to drawImageLayers. Draw
218 // something to it as a placeholder for what an app draws. We should draw
Nathaniel Nifong4fc750d2021-03-19 11:37:36 -0400219 // something, but the details are not important. Make use of the shadow layer drawing step
220 // to populate it.
Leon Scroggins IIIb9216dc2021-03-08 17:19:01 -0500221 sp<GraphicBuffer> srcBuffer =
222 new GraphicBuffer(displayRect.width(), displayRect.height(), PIXEL_FORMAT_RGBA_8888, 1,
223 usage, "drawImageLayer_src");
Nathaniel Nifongb9f27ef2021-04-01 16:44:12 -0400224
Nathaniel Nifong4fc750d2021-03-19 11:37:36 -0400225 drawSolidLayers(renderengine, display, dstBuffer);
226 drawShadowLayers(renderengine, display, srcBuffer);
Nathaniel Nifongb9f27ef2021-04-01 16:44:12 -0400227 drawBlurLayers(renderengine, display, dstBuffer);
228 // The majority of shaders are related to sampling images.
Leon Scroggins IIIb9216dc2021-03-08 17:19:01 -0500229 drawImageLayers(renderengine, display, dstBuffer, srcBuffer);
Nathaniel Nifongb9f27ef2021-04-01 16:44:12 -0400230
Nathaniel Nifongf4362402021-04-12 11:41:05 -0400231 // should be the same as AHARDWAREBUFFER_USAGE_GPU_SAMPLED_IMAGE;
232 const int64_t usageExternal = GRALLOC_USAGE_HW_TEXTURE;
233
234 sp<GraphicBuffer> externalBuffer =
235 new GraphicBuffer(displayRect.width(), displayRect.height(), PIXEL_FORMAT_RGBA_8888, 1,
236 usageExternal, "primeShaderCache_external");
237 // TODO(b/184665179) doubles number of image shader compilations, but only somewhere
238 // between 6 and 8 will occur in real uses.
239 drawImageLayers(renderengine, display, dstBuffer, externalBuffer);
240 renderengine->unbindExternalTextureBuffer(externalBuffer->getId());
Nathaniel Nifongb9f27ef2021-04-01 16:44:12 -0400241
242 renderengine->unbindExternalTextureBuffer(srcBuffer->getId());
243
Leon Scroggins IIIb9216dc2021-03-08 17:19:01 -0500244 const nsecs_t timeAfter = systemTime();
245 const float compileTimeMs = static_cast<float>(timeAfter - timeBefore) / 1.0E6;
Nathaniel Nifongb9f27ef2021-04-01 16:44:12 -0400246 const int shadersCompiled = renderengine->reportShadersCompiled();
247 ALOGD("Shader cache generated %d shaders in %f ms\n", shadersCompiled, compileTimeMs);
Leon Scroggins IIIb9216dc2021-03-08 17:19:01 -0500248}
249
250} // namespace android::renderengine::skia