blob: 0cd3b622fa868b79973af8b4a4681182faa31801 [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
Nathaniel Nifongb9f27ef2021-04-01 16:44:12 -040028#include <android/hardware_buffer.h>
29
Leon Scroggins IIIb9216dc2021-03-08 17:19:01 -050030namespace android::renderengine::skia {
31
Nathaniel Nifongb9f27ef2021-04-01 16:44:12 -040032namespace {
Nathaniel Nifong4fc750d2021-03-19 11:37:36 -040033// Warming shader cache, not framebuffer cache.
34constexpr bool kUseFrameBufferCache = false;
35
Nathaniel Nifongb9f27ef2021-04-01 16:44:12 -040036// clang-format off
37// Any non-identity matrix will do.
38const auto kScaleAndTranslate = mat4(0.7f, 0.f, 0.f, 0.f,
39 0.f, 0.7f, 0.f, 0.f,
40 0.f, 0.f, 1.f, 0.f,
41 67.3f, 52.2f, 0.f, 1.f);
42// clang-format on
43// When choosing dataspaces below, whether the match the destination or not determined whether
44// a color correction effect is added to the shader. There may be other additional shader details
45// for particular color spaces.
46// TODO(b/184842383) figure out which color related shaders are necessary
47constexpr auto kDestDataSpace = ui::Dataspace::SRGB;
48} // namespace
49
Nathaniel Nifong4fc750d2021-03-19 11:37:36 -040050static void drawShadowLayers(SkiaRenderEngine* renderengine, const DisplaySettings& display,
51 sp<GraphicBuffer> dstBuffer) {
Leon Scroggins IIIb9216dc2021-03-08 17:19:01 -050052 // Somewhat arbitrary dimensions, but on screen and slightly shorter, based
53 // on actual use.
54 FloatRect rect(0, 0, display.physicalDisplay.width(), display.physicalDisplay.height() - 30);
55 LayerSettings layer{
56 .geometry =
57 Geometry{
58 .boundaries = rect,
59 .roundedCornersCrop = rect,
60 },
Nathaniel Nifong4fc750d2021-03-19 11:37:36 -040061 // drawShadow ignores alpha
Leon Scroggins IIIb9216dc2021-03-08 17:19:01 -050062 .shadow =
63 ShadowSettings{
64 .ambientColor = vec4(0, 0, 0, 0.00935997f),
65 .spotColor = vec4(0, 0, 0, 0.0455841f),
66 .lightPos = vec3(370.508f, -1527.03f, 1650.f),
67 .lightRadius = 2200.0f,
68 .length = 0.955342f,
69 },
Nathaniel Nifongb9f27ef2021-04-01 16:44:12 -040070 // important that this matches dest so the general shadow fragment shader doesn't
71 // have color correction added, and important that it be srgb, so the *vertex* shader
72 // doesn't have color correction added.
73 .sourceDataspace = kDestDataSpace,
Leon Scroggins IIIb9216dc2021-03-08 17:19:01 -050074 };
75
76 auto layers = std::vector<const LayerSettings*>{&layer};
Nathaniel Nifongb9f27ef2021-04-01 16:44:12 -040077 // The identity matrix will generate the fast shader
78 renderengine->drawLayers(display, layers, dstBuffer, kUseFrameBufferCache, base::unique_fd(),
79 nullptr);
80 // This matrix, which has different scales for x and y, will
81 // generate the slower (more general case) version, which has variants for translucent
82 // casters and rounded rects.
83 // clang-format off
84 layer.geometry.positionTransform = mat4(0.7f, 0.f, 0.f, 0.f,
85 0.f, 0.8f, 0.f, 0.f,
86 0.f, 0.f, 1.f, 0.f,
87 0.f, 0.f, 0.f, 1.f);
88 // clang-format on
89 for (auto translucent : {false, true}) {
90 layer.shadow.casterIsTranslucent = translucent;
Nathaniel Nifong4fc750d2021-03-19 11:37:36 -040091 renderengine->drawLayers(display, layers, dstBuffer, kUseFrameBufferCache,
Leon Scroggins IIIb9216dc2021-03-08 17:19:01 -050092 base::unique_fd(), nullptr);
93 }
94}
95
96static void drawImageLayers(SkiaRenderEngine* renderengine, const DisplaySettings& display,
97 sp<GraphicBuffer> dstBuffer, sp<GraphicBuffer> srcBuffer) {
98 const Rect& displayRect = display.physicalDisplay;
99 FloatRect rect(0, 0, displayRect.width(), displayRect.height());
100 LayerSettings layer{
101 .geometry =
102 Geometry{
103 .boundaries = rect,
Leon Scroggins IIIb9216dc2021-03-08 17:19:01 -0500104 .roundedCornersCrop = rect,
105 },
106 .source = PixelSource{.buffer =
107 Buffer{
108 .buffer = srcBuffer,
109 .maxMasteringLuminance = 1000.f,
110 .maxContentLuminance = 1000.f,
111 }},
112 };
113
Nathaniel Nifongb9f27ef2021-04-01 16:44:12 -0400114 auto threeCornerRadii = {0.0f, 0.05f, 50.f};
115 auto oneCornerRadius = {50.f};
Nathaniel Nifong4fc750d2021-03-19 11:37:36 -0400116
Leon Scroggins IIIb9216dc2021-03-08 17:19:01 -0500117 // Test both drawRect and drawRRect
118 auto layers = std::vector<const LayerSettings*>{&layer};
Nathaniel Nifongb9f27ef2021-04-01 16:44:12 -0400119 for (bool identity : {true, false}) {
120 layer.geometry.positionTransform = identity ? mat4() : kScaleAndTranslate;
121 // Corner radii less than 0.5 creates a special shader. This likely occurs in real usage
122 // due to animating corner radius.
123 // For the non-idenity matrix, only the large corner radius will create a new shader.
124 for (float roundedCornersRadius : identity ? threeCornerRadii : oneCornerRadius) {
Nathaniel Nifong4fc750d2021-03-19 11:37:36 -0400125 // roundedCornersCrop is always set, but it is this radius that triggers the behavior
126 layer.geometry.roundedCornersRadius = roundedCornersRadius;
Nathaniel Nifongb9f27ef2021-04-01 16:44:12 -0400127 for (bool isOpaque : {true, false}) {
128 layer.source.buffer.isOpaque = isOpaque;
129 for (auto alpha : {half(.23999f), half(1.0f)}) {
130 layer.alpha = alpha;
131 renderengine->drawLayers(display, layers, dstBuffer, kUseFrameBufferCache,
132 base::unique_fd(), nullptr);
Leon Scroggins IIIb9216dc2021-03-08 17:19:01 -0500133 }
134 }
135 }
136 }
137}
138
Nathaniel Nifong4fc750d2021-03-19 11:37:36 -0400139static void drawSolidLayers(SkiaRenderEngine* renderengine, const DisplaySettings& display,
140 sp<GraphicBuffer> dstBuffer) {
141 const Rect& displayRect = display.physicalDisplay;
142 FloatRect rect(0, 0, displayRect.width(), displayRect.height());
143 LayerSettings layer{
144 .geometry =
145 Geometry{
146 .boundaries = rect,
147 },
148 .alpha = 1,
149 .source =
150 PixelSource{
151 .solidColor = half3(0.1f, 0.2f, 0.3f),
152 },
153 };
154
155 auto layers = std::vector<const LayerSettings*>{&layer};
Nathaniel Nifongb9f27ef2021-04-01 16:44:12 -0400156 for (auto transform : {mat4(), kScaleAndTranslate}) {
157 layer.geometry.positionTransform = transform;
158 for (float roundedCornersRadius : {0.0f, 0.05f, 50.f}) {
159 layer.geometry.roundedCornersRadius = roundedCornersRadius;
160 renderengine->drawLayers(display, layers, dstBuffer, kUseFrameBufferCache,
161 base::unique_fd(), nullptr);
162 }
163 }
Nathaniel Nifong4fc750d2021-03-19 11:37:36 -0400164}
165
Nathaniel Nifongb9f27ef2021-04-01 16:44:12 -0400166static void drawBlurLayers(SkiaRenderEngine* renderengine, const DisplaySettings& display,
167 sp<GraphicBuffer> dstBuffer) {
168 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 },
175 .alpha = 1,
176 };
177
178 auto layers = std::vector<const LayerSettings*>{&layer};
179 for (int radius : {9, 60}) {
180 layer.backgroundBlurRadius = radius;
181 renderengine->drawLayers(display, layers, dstBuffer, kUseFrameBufferCache,
182 base::unique_fd(), nullptr);
183 }
184}
185
186namespace {
187
188struct AHardwareBuffer_deleter {
189 void operator()(AHardwareBuffer* ahb) const { AHardwareBuffer_release(ahb); }
190};
191
192std::unique_ptr<AHardwareBuffer, AHardwareBuffer_deleter> makeAHardwareBuffer() {
193 AHardwareBuffer* buffer = nullptr;
194
195 int w = 32;
196 int h = 32;
197
198 AHardwareBuffer_Desc hwbDesc;
199 hwbDesc.width = w;
200 hwbDesc.height = h;
201 hwbDesc.layers = 1;
202 hwbDesc.usage = AHARDWAREBUFFER_USAGE_CPU_READ_NEVER | AHARDWAREBUFFER_USAGE_CPU_WRITE_NEVER |
203 AHARDWAREBUFFER_USAGE_GPU_SAMPLED_IMAGE;
204 hwbDesc.format = AHARDWAREBUFFER_FORMAT_R8G8B8A8_UNORM;
205 // The following three are not used in the allocate
206 hwbDesc.stride = 0;
207 hwbDesc.rfu0 = 0;
208 hwbDesc.rfu1 = 0;
209
210 if (int error = AHardwareBuffer_allocate(&hwbDesc, &buffer)) {
211 ALOGE("Failed to allocated hardware buffer, error: %d", error);
212 if (buffer) {
213 AHardwareBuffer_release(buffer);
214 }
215 return nullptr;
216 }
217 return std::unique_ptr<AHardwareBuffer, AHardwareBuffer_deleter>(buffer);
218}
219} // namespace
220
221//
222// The collection of shaders cached here were found by using perfetto to record shader compiles
223// during actions that involve RenderEngine, logging the layer settings, and the shader code
224// and reproducing those settings here.
225//
226// It is helpful when debugging this to turn on
227// in SkGLRenderEngine.cpp:
228// kPrintLayerSettings = true
229// kFlushAfterEveryLayer = true
230// in external/skia/src/gpu/gl/builders/GrGLShaderStringBuilder.cpp
231// gPrintSKSL = true
232//
233// TODO(b/184631553) cache the shader involved in youtube pip return.
Leon Scroggins IIIb9216dc2021-03-08 17:19:01 -0500234void Cache::primeShaderCache(SkiaRenderEngine* renderengine) {
Nathaniel Nifongb9f27ef2021-04-01 16:44:12 -0400235 const int previousCount = renderengine->reportShadersCompiled();
236 if (previousCount) {
237 ALOGD("%d Shaders already compiled before Cache::primeShaderCache ran\n", previousCount);
238 }
Leon Scroggins IIIb9216dc2021-03-08 17:19:01 -0500239 const nsecs_t timeBefore = systemTime();
240 // The dimensions should not matter, so long as we draw inside them.
241 const Rect displayRect(0, 0, 1080, 2340);
242 DisplaySettings display{
243 .physicalDisplay = displayRect,
244 .clip = displayRect,
245 .maxLuminance = 500,
Nathaniel Nifongb9f27ef2021-04-01 16:44:12 -0400246 .outputDataspace = kDestDataSpace,
Leon Scroggins IIIb9216dc2021-03-08 17:19:01 -0500247 };
248
249 const int64_t usage = GRALLOC_USAGE_HW_RENDER | GRALLOC_USAGE_HW_TEXTURE;
250
251 sp<GraphicBuffer> dstBuffer =
252 new GraphicBuffer(displayRect.width(), displayRect.height(), PIXEL_FORMAT_RGBA_8888, 1,
253 usage, "primeShaderCache_dst");
254 // This buffer will be the source for the call to drawImageLayers. Draw
255 // something to it as a placeholder for what an app draws. We should draw
Nathaniel Nifong4fc750d2021-03-19 11:37:36 -0400256 // something, but the details are not important. Make use of the shadow layer drawing step
257 // to populate it.
Leon Scroggins IIIb9216dc2021-03-08 17:19:01 -0500258 sp<GraphicBuffer> srcBuffer =
259 new GraphicBuffer(displayRect.width(), displayRect.height(), PIXEL_FORMAT_RGBA_8888, 1,
260 usage, "drawImageLayer_src");
Nathaniel Nifongb9f27ef2021-04-01 16:44:12 -0400261
Nathaniel Nifong4fc750d2021-03-19 11:37:36 -0400262 drawSolidLayers(renderengine, display, dstBuffer);
263 drawShadowLayers(renderengine, display, srcBuffer);
Nathaniel Nifongb9f27ef2021-04-01 16:44:12 -0400264 drawBlurLayers(renderengine, display, dstBuffer);
265 // The majority of shaders are related to sampling images.
Leon Scroggins IIIb9216dc2021-03-08 17:19:01 -0500266 drawImageLayers(renderengine, display, dstBuffer, srcBuffer);
Nathaniel Nifongb9f27ef2021-04-01 16:44:12 -0400267
268 // Draw image layers again sampling from an AHardwareBuffer if it is possible to create one.
269 if (auto ahb = makeAHardwareBuffer()) {
270 sp<GraphicBuffer> externalBuffer = GraphicBuffer::fromAHardwareBuffer(ahb.get());
271 // TODO(b/184665179) doubles number of image shader compilations, but only somewhere
272 // between 6 and 8 will occur in real uses.
273 drawImageLayers(renderengine, display, dstBuffer, externalBuffer);
274 renderengine->unbindExternalTextureBuffer(externalBuffer->getId());
275 }
276
277 renderengine->unbindExternalTextureBuffer(srcBuffer->getId());
278
Leon Scroggins IIIb9216dc2021-03-08 17:19:01 -0500279 const nsecs_t timeAfter = systemTime();
280 const float compileTimeMs = static_cast<float>(timeAfter - timeBefore) / 1.0E6;
Nathaniel Nifongb9f27ef2021-04-01 16:44:12 -0400281 const int shadersCompiled = renderengine->reportShadersCompiled();
282 ALOGD("Shader cache generated %d shaders in %f ms\n", shadersCompiled, compileTimeMs);
Leon Scroggins IIIb9216dc2021-03-08 17:19:01 -0500283}
284
285} // namespace android::renderengine::skia