blob: 69c6a090768ae8e6cab4090828062cdcacfe9499 [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 */
16
17#include "Cache.h"
18#include "AutoBackendTexture.h"
19#include "SkiaRenderEngine.h"
20#include "android-base/unique_fd.h"
21#include "renderengine/DisplaySettings.h"
22#include "renderengine/LayerSettings.h"
23#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 Nifong4fc750d2021-03-19 11:37:36 -040031// Warming shader cache, not framebuffer cache.
32constexpr bool kUseFrameBufferCache = false;
33
34static void drawShadowLayers(SkiaRenderEngine* renderengine, const DisplaySettings& display,
35 sp<GraphicBuffer> dstBuffer) {
Leon Scroggins IIIb9216dc2021-03-08 17:19:01 -050036 // Somewhat arbitrary dimensions, but on screen and slightly shorter, based
37 // on actual use.
38 FloatRect rect(0, 0, display.physicalDisplay.width(), display.physicalDisplay.height() - 30);
39 LayerSettings layer{
40 .geometry =
41 Geometry{
42 .boundaries = rect,
43 .roundedCornersCrop = rect,
44 },
Nathaniel Nifong4fc750d2021-03-19 11:37:36 -040045 // drawShadow ignores alpha
Leon Scroggins IIIb9216dc2021-03-08 17:19:01 -050046 .shadow =
47 ShadowSettings{
48 .ambientColor = vec4(0, 0, 0, 0.00935997f),
49 .spotColor = vec4(0, 0, 0, 0.0455841f),
50 .lightPos = vec3(370.508f, -1527.03f, 1650.f),
51 .lightRadius = 2200.0f,
52 .length = 0.955342f,
53 },
54 };
55
56 auto layers = std::vector<const LayerSettings*>{&layer};
57 // The identity matrix will generate the fast shaders, and the second matrix
58 // (based on one seen while going from dialer to the home screen) will
59 // generate the slower (more general case) version. If we also need a
60 // slow version without color correction, we should use this matrix with
61 // display.outputDataspace set to SRGB.
Leon Scroggins III9f3072c2021-03-22 10:42:47 -040062 bool identity = true;
Leon Scroggins IIIb9216dc2021-03-08 17:19:01 -050063 for (const mat4 transform : { mat4(), mat4(0.728872f, 0.f, 0.f, 0.f,
64 0.f, 0.727627f, 0.f, 0.f,
65 0.f, 0.f, 1.f, 0.f,
66 167.355743f, 1852.257812f, 0.f, 1.f) }) {
67 layer.geometry.positionTransform = transform;
Nathaniel Nifong4fc750d2021-03-19 11:37:36 -040068 renderengine->drawLayers(display, layers, dstBuffer, kUseFrameBufferCache,
Leon Scroggins IIIb9216dc2021-03-08 17:19:01 -050069 base::unique_fd(), nullptr);
Leon Scroggins III9f3072c2021-03-22 10:42:47 -040070 identity = false;
Leon Scroggins IIIb9216dc2021-03-08 17:19:01 -050071 }
72}
73
74static void drawImageLayers(SkiaRenderEngine* renderengine, const DisplaySettings& display,
75 sp<GraphicBuffer> dstBuffer, sp<GraphicBuffer> srcBuffer) {
76 const Rect& displayRect = display.physicalDisplay;
77 FloatRect rect(0, 0, displayRect.width(), displayRect.height());
78 LayerSettings layer{
79 .geometry =
80 Geometry{
81 .boundaries = rect,
Leon Scroggins IIIb9216dc2021-03-08 17:19:01 -050082 .roundedCornersCrop = rect,
83 },
84 .source = PixelSource{.buffer =
85 Buffer{
86 .buffer = srcBuffer,
87 .maxMasteringLuminance = 1000.f,
88 .maxContentLuminance = 1000.f,
89 }},
90 };
91
Nathaniel Nifong4fc750d2021-03-19 11:37:36 -040092 // This matrix is based on actual data seen when opening the dialer.
93 // translate and scale creates new shaders when combined with rounded corners
94 // clang-format off
95 auto scale_and_translate = mat4(.19f, .0f, .0f, .0f,
96 .0f, .19f, .0f, .0f,
97 .0f, .0f, 1.f, .0f,
98 169.f, 1527.f, .0f, 1.f);
99 // clang-format on
100
Leon Scroggins IIIb9216dc2021-03-08 17:19:01 -0500101 // Test both drawRect and drawRRect
102 auto layers = std::vector<const LayerSettings*>{&layer};
Nathaniel Nifong4fc750d2021-03-19 11:37:36 -0400103 for (auto transform : {mat4(), scale_and_translate}) {
104 layer.geometry.positionTransform = transform;
105 // fractional corner radius creates a shader that is used during home button swipe
106 for (float roundedCornersRadius : {0.0f, 0.05f, 500.f}) {
107 // roundedCornersCrop is always set, but it is this radius that triggers the behavior
108 layer.geometry.roundedCornersRadius = roundedCornersRadius;
109 // No need to check UNKNOWN, which is treated as SRGB.
110 for (auto dataspace : {ui::Dataspace::SRGB, ui::Dataspace::DISPLAY_P3}) {
111 layer.sourceDataspace = dataspace;
112 for (bool isOpaque : {true, false}) {
113 layer.source.buffer.isOpaque = isOpaque;
114 for (auto alpha : {half(.23999f), half(1.0f)}) {
115 layer.alpha = alpha;
116 renderengine->drawLayers(display, layers, dstBuffer, kUseFrameBufferCache,
117 base::unique_fd(), nullptr);
118 }
Leon Scroggins IIIb9216dc2021-03-08 17:19:01 -0500119 }
120 }
121 }
122 }
123}
124
Nathaniel Nifong4fc750d2021-03-19 11:37:36 -0400125static void drawSolidLayers(SkiaRenderEngine* renderengine, const DisplaySettings& display,
126 sp<GraphicBuffer> dstBuffer) {
127 const Rect& displayRect = display.physicalDisplay;
128 FloatRect rect(0, 0, displayRect.width(), displayRect.height());
129 LayerSettings layer{
130 .geometry =
131 Geometry{
132 .boundaries = rect,
133 },
134 .alpha = 1,
135 .source =
136 PixelSource{
137 .solidColor = half3(0.1f, 0.2f, 0.3f),
138 },
139 };
140
141 auto layers = std::vector<const LayerSettings*>{&layer};
142 renderengine->drawLayers(display, layers, dstBuffer, kUseFrameBufferCache, base::unique_fd(),
143 nullptr);
144}
145
Leon Scroggins IIIb9216dc2021-03-08 17:19:01 -0500146void Cache::primeShaderCache(SkiaRenderEngine* renderengine) {
147 const nsecs_t timeBefore = systemTime();
148 // The dimensions should not matter, so long as we draw inside them.
149 const Rect displayRect(0, 0, 1080, 2340);
150 DisplaySettings display{
151 .physicalDisplay = displayRect,
152 .clip = displayRect,
153 .maxLuminance = 500,
154 .outputDataspace = ui::Dataspace::DISPLAY_P3,
155 };
156
157 const int64_t usage = GRALLOC_USAGE_HW_RENDER | GRALLOC_USAGE_HW_TEXTURE;
158
159 sp<GraphicBuffer> dstBuffer =
160 new GraphicBuffer(displayRect.width(), displayRect.height(), PIXEL_FORMAT_RGBA_8888, 1,
161 usage, "primeShaderCache_dst");
162 // This buffer will be the source for the call to drawImageLayers. Draw
163 // something to it as a placeholder for what an app draws. We should draw
Nathaniel Nifong4fc750d2021-03-19 11:37:36 -0400164 // something, but the details are not important. Make use of the shadow layer drawing step
165 // to populate it.
Leon Scroggins IIIb9216dc2021-03-08 17:19:01 -0500166 sp<GraphicBuffer> srcBuffer =
167 new GraphicBuffer(displayRect.width(), displayRect.height(), PIXEL_FORMAT_RGBA_8888, 1,
168 usage, "drawImageLayer_src");
Nathaniel Nifong4fc750d2021-03-19 11:37:36 -0400169 drawSolidLayers(renderengine, display, dstBuffer);
170 drawShadowLayers(renderengine, display, srcBuffer);
Leon Scroggins IIIb9216dc2021-03-08 17:19:01 -0500171 drawImageLayers(renderengine, display, dstBuffer, srcBuffer);
172 const nsecs_t timeAfter = systemTime();
173 const float compileTimeMs = static_cast<float>(timeAfter - timeBefore) / 1.0E6;
174 ALOGD("shader cache generated in %f ms\n", compileTimeMs);
175}
176
177} // namespace android::renderengine::skia