blob: 03c8e80d045eaa9212383d5b49118268caeb6ffa [file] [log] [blame]
John Reck67b1e2b2020-08-26 13:17:24 -07001/*
2 * Copyright 2020 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//#define LOG_NDEBUG 0
Alec Mouri678245d2020-09-30 16:58:23 -070018#include <cstdint>
John Reck67b1e2b2020-08-26 13:17:24 -070019#undef LOG_TAG
20#define LOG_TAG "RenderEngine"
21#define ATRACE_TAG ATRACE_TAG_GRAPHICS
22
John Reck67b1e2b2020-08-26 13:17:24 -070023#include <EGL/egl.h>
24#include <EGL/eglext.h>
25#include <GLES2/gl2.h>
Lucas Dupinc3800b82020-10-02 16:24:48 -070026#include <sync/sync.h>
27#include <ui/BlurRegion.h>
28#include <ui/GraphicBuffer.h>
29#include <utils/Trace.h>
30#include "../gl/GLExtensions.h"
31#include "SkiaGLRenderEngine.h"
32#include "filters/BlurFilter.h"
33
John Reck67b1e2b2020-08-26 13:17:24 -070034#include <GrContextOptions.h>
John Reck67b1e2b2020-08-26 13:17:24 -070035#include <SkCanvas.h>
Alec Mourib34f0b72020-10-02 13:18:34 -070036#include <SkColorFilter.h>
37#include <SkColorMatrix.h>
Alec Mourib5777452020-09-28 11:32:42 -070038#include <SkColorSpace.h>
John Reck67b1e2b2020-08-26 13:17:24 -070039#include <SkImage.h>
Lucas Dupinf4cb4a02020-09-22 14:19:26 -070040#include <SkImageFilters.h>
Lucas Dupin3f11e922020-09-22 17:31:04 -070041#include <SkShadowUtils.h>
John Reck67b1e2b2020-08-26 13:17:24 -070042#include <SkSurface.h>
Alec Mourib5777452020-09-28 11:32:42 -070043#include <gl/GrGLInterface.h>
44#include <sync/sync.h>
45#include <ui/GraphicBuffer.h>
46#include <utils/Trace.h>
47
48#include <cmath>
49
50#include "../gl/GLExtensions.h"
Alec Mourib34f0b72020-10-02 13:18:34 -070051#include "SkiaGLRenderEngine.h"
Alec Mourib5777452020-09-28 11:32:42 -070052#include "filters/BlurFilter.h"
John Reck67b1e2b2020-08-26 13:17:24 -070053
54extern "C" EGLAPI const char* eglQueryStringImplementationANDROID(EGLDisplay dpy, EGLint name);
55
56bool checkGlError(const char* op, int lineNumber);
57
58namespace android {
59namespace renderengine {
60namespace skia {
61
62static status_t selectConfigForAttribute(EGLDisplay dpy, EGLint const* attrs, EGLint attribute,
63 EGLint wanted, EGLConfig* outConfig) {
64 EGLint numConfigs = -1, n = 0;
65 eglGetConfigs(dpy, nullptr, 0, &numConfigs);
66 std::vector<EGLConfig> configs(numConfigs, EGL_NO_CONFIG_KHR);
67 eglChooseConfig(dpy, attrs, configs.data(), configs.size(), &n);
68 configs.resize(n);
69
70 if (!configs.empty()) {
71 if (attribute != EGL_NONE) {
72 for (EGLConfig config : configs) {
73 EGLint value = 0;
74 eglGetConfigAttrib(dpy, config, attribute, &value);
75 if (wanted == value) {
76 *outConfig = config;
77 return NO_ERROR;
78 }
79 }
80 } else {
81 // just pick the first one
82 *outConfig = configs[0];
83 return NO_ERROR;
84 }
85 }
86
87 return NAME_NOT_FOUND;
88}
89
90static status_t selectEGLConfig(EGLDisplay display, EGLint format, EGLint renderableType,
91 EGLConfig* config) {
92 // select our EGLConfig. It must support EGL_RECORDABLE_ANDROID if
93 // it is to be used with WIFI displays
94 status_t err;
95 EGLint wantedAttribute;
96 EGLint wantedAttributeValue;
97
98 std::vector<EGLint> attribs;
99 if (renderableType) {
100 const ui::PixelFormat pixelFormat = static_cast<ui::PixelFormat>(format);
101 const bool is1010102 = pixelFormat == ui::PixelFormat::RGBA_1010102;
102
103 // Default to 8 bits per channel.
104 const EGLint tmpAttribs[] = {
105 EGL_RENDERABLE_TYPE,
106 renderableType,
107 EGL_RECORDABLE_ANDROID,
108 EGL_TRUE,
109 EGL_SURFACE_TYPE,
110 EGL_WINDOW_BIT | EGL_PBUFFER_BIT,
111 EGL_FRAMEBUFFER_TARGET_ANDROID,
112 EGL_TRUE,
113 EGL_RED_SIZE,
114 is1010102 ? 10 : 8,
115 EGL_GREEN_SIZE,
116 is1010102 ? 10 : 8,
117 EGL_BLUE_SIZE,
118 is1010102 ? 10 : 8,
119 EGL_ALPHA_SIZE,
120 is1010102 ? 2 : 8,
121 EGL_NONE,
122 };
123 std::copy(tmpAttribs, tmpAttribs + (sizeof(tmpAttribs) / sizeof(EGLint)),
124 std::back_inserter(attribs));
125 wantedAttribute = EGL_NONE;
126 wantedAttributeValue = EGL_NONE;
127 } else {
128 // if no renderable type specified, fallback to a simplified query
129 wantedAttribute = EGL_NATIVE_VISUAL_ID;
130 wantedAttributeValue = format;
131 }
132
133 err = selectConfigForAttribute(display, attribs.data(), wantedAttribute, wantedAttributeValue,
134 config);
135 if (err == NO_ERROR) {
136 EGLint caveat;
137 if (eglGetConfigAttrib(display, *config, EGL_CONFIG_CAVEAT, &caveat))
138 ALOGW_IF(caveat == EGL_SLOW_CONFIG, "EGL_SLOW_CONFIG selected!");
139 }
140
141 return err;
142}
143
Alec Mourib5777452020-09-28 11:32:42 -0700144// Converts an android dataspace to a supported SkColorSpace
145// Supported dataspaces are
146// 1. sRGB
147// 2. Display P3
148// 3. BT2020 PQ
149// 4. BT2020 HLG
150// Unknown primaries are mapped to BT709, and unknown transfer functions
151// are mapped to sRGB.
152static sk_sp<SkColorSpace> toColorSpace(ui::Dataspace dataspace) {
153 skcms_Matrix3x3 gamut;
154 switch (dataspace & HAL_DATASPACE_STANDARD_MASK) {
155 case HAL_DATASPACE_STANDARD_BT709:
156 gamut = SkNamedGamut::kSRGB;
157 break;
158 case HAL_DATASPACE_STANDARD_BT2020:
159 gamut = SkNamedGamut::kRec2020;
160 break;
161 case HAL_DATASPACE_STANDARD_DCI_P3:
162 gamut = SkNamedGamut::kDisplayP3;
163 break;
164 default:
165 ALOGV("Unsupported Gamut: %d, defaulting to sRGB", dataspace);
166 gamut = SkNamedGamut::kSRGB;
167 break;
168 }
169
170 switch (dataspace & HAL_DATASPACE_TRANSFER_MASK) {
171 case HAL_DATASPACE_TRANSFER_LINEAR:
172 return SkColorSpace::MakeRGB(SkNamedTransferFn::kLinear, gamut);
173 case HAL_DATASPACE_TRANSFER_SRGB:
174 return SkColorSpace::MakeRGB(SkNamedTransferFn::kSRGB, gamut);
175 case HAL_DATASPACE_TRANSFER_ST2084:
176 return SkColorSpace::MakeRGB(SkNamedTransferFn::kPQ, gamut);
177 case HAL_DATASPACE_TRANSFER_HLG:
178 return SkColorSpace::MakeRGB(SkNamedTransferFn::kHLG, gamut);
179 default:
180 ALOGV("Unsupported Gamma: %d, defaulting to sRGB transfer", dataspace);
181 return SkColorSpace::MakeRGB(SkNamedTransferFn::kSRGB, gamut);
182 }
183}
184
John Reck67b1e2b2020-08-26 13:17:24 -0700185std::unique_ptr<SkiaGLRenderEngine> SkiaGLRenderEngine::create(
186 const RenderEngineCreationArgs& args) {
187 // initialize EGL for the default display
188 EGLDisplay display = eglGetDisplay(EGL_DEFAULT_DISPLAY);
189 if (!eglInitialize(display, nullptr, nullptr)) {
190 LOG_ALWAYS_FATAL("failed to initialize EGL");
191 }
192
193 const auto eglVersion = eglQueryStringImplementationANDROID(display, EGL_VERSION);
194 if (!eglVersion) {
195 checkGlError(__FUNCTION__, __LINE__);
196 LOG_ALWAYS_FATAL("eglQueryStringImplementationANDROID(EGL_VERSION) failed");
197 }
198
199 const auto eglExtensions = eglQueryStringImplementationANDROID(display, EGL_EXTENSIONS);
200 if (!eglExtensions) {
201 checkGlError(__FUNCTION__, __LINE__);
202 LOG_ALWAYS_FATAL("eglQueryStringImplementationANDROID(EGL_EXTENSIONS) failed");
203 }
204
205 auto& extensions = gl::GLExtensions::getInstance();
206 extensions.initWithEGLStrings(eglVersion, eglExtensions);
207
208 // The code assumes that ES2 or later is available if this extension is
209 // supported.
210 EGLConfig config = EGL_NO_CONFIG_KHR;
211 if (!extensions.hasNoConfigContext()) {
212 config = chooseEglConfig(display, args.pixelFormat, /*logConfig*/ true);
213 }
214
215 bool useContextPriority =
216 extensions.hasContextPriority() && args.contextPriority == ContextPriority::HIGH;
217 EGLContext protectedContext = EGL_NO_CONTEXT;
218 if (args.enableProtectedContext && extensions.hasProtectedContent()) {
219 protectedContext = createEglContext(display, config, nullptr, useContextPriority,
220 Protection::PROTECTED);
221 ALOGE_IF(protectedContext == EGL_NO_CONTEXT, "Can't create protected context");
222 }
223
224 EGLContext ctxt = createEglContext(display, config, protectedContext, useContextPriority,
225 Protection::UNPROTECTED);
226
227 // if can't create a GL context, we can only abort.
228 LOG_ALWAYS_FATAL_IF(ctxt == EGL_NO_CONTEXT, "EGLContext creation failed");
229
230 EGLSurface placeholder = EGL_NO_SURFACE;
231 if (!extensions.hasSurfacelessContext()) {
232 placeholder = createPlaceholderEglPbufferSurface(display, config, args.pixelFormat,
233 Protection::UNPROTECTED);
234 LOG_ALWAYS_FATAL_IF(placeholder == EGL_NO_SURFACE, "can't create placeholder pbuffer");
235 }
236 EGLBoolean success = eglMakeCurrent(display, placeholder, placeholder, ctxt);
237 LOG_ALWAYS_FATAL_IF(!success, "can't make placeholder pbuffer current");
238 extensions.initWithGLStrings(glGetString(GL_VENDOR), glGetString(GL_RENDERER),
239 glGetString(GL_VERSION), glGetString(GL_EXTENSIONS));
240
241 EGLSurface protectedPlaceholder = EGL_NO_SURFACE;
242 if (protectedContext != EGL_NO_CONTEXT && !extensions.hasSurfacelessContext()) {
243 protectedPlaceholder = createPlaceholderEglPbufferSurface(display, config, args.pixelFormat,
244 Protection::PROTECTED);
245 ALOGE_IF(protectedPlaceholder == EGL_NO_SURFACE,
246 "can't create protected placeholder pbuffer");
247 }
248
249 // initialize the renderer while GL is current
250 std::unique_ptr<SkiaGLRenderEngine> engine =
Lucas Dupinf4cb4a02020-09-22 14:19:26 -0700251 std::make_unique<SkiaGLRenderEngine>(args, display, config, ctxt, placeholder,
John Reck67b1e2b2020-08-26 13:17:24 -0700252 protectedContext, protectedPlaceholder);
253
254 ALOGI("OpenGL ES informations:");
255 ALOGI("vendor : %s", extensions.getVendor());
256 ALOGI("renderer : %s", extensions.getRenderer());
257 ALOGI("version : %s", extensions.getVersion());
258 ALOGI("extensions: %s", extensions.getExtensions());
259 ALOGI("GL_MAX_TEXTURE_SIZE = %zu", engine->getMaxTextureSize());
260 ALOGI("GL_MAX_VIEWPORT_DIMS = %zu", engine->getMaxViewportDims());
261
262 return engine;
263}
264
265EGLConfig SkiaGLRenderEngine::chooseEglConfig(EGLDisplay display, int format, bool logConfig) {
266 status_t err;
267 EGLConfig config;
268
269 // First try to get an ES3 config
270 err = selectEGLConfig(display, format, EGL_OPENGL_ES3_BIT, &config);
271 if (err != NO_ERROR) {
272 // If ES3 fails, try to get an ES2 config
273 err = selectEGLConfig(display, format, EGL_OPENGL_ES2_BIT, &config);
274 if (err != NO_ERROR) {
275 // If ES2 still doesn't work, probably because we're on the emulator.
276 // try a simplified query
277 ALOGW("no suitable EGLConfig found, trying a simpler query");
278 err = selectEGLConfig(display, format, 0, &config);
279 if (err != NO_ERROR) {
280 // this EGL is too lame for android
281 LOG_ALWAYS_FATAL("no suitable EGLConfig found, giving up");
282 }
283 }
284 }
285
286 if (logConfig) {
287 // print some debugging info
288 EGLint r, g, b, a;
289 eglGetConfigAttrib(display, config, EGL_RED_SIZE, &r);
290 eglGetConfigAttrib(display, config, EGL_GREEN_SIZE, &g);
291 eglGetConfigAttrib(display, config, EGL_BLUE_SIZE, &b);
292 eglGetConfigAttrib(display, config, EGL_ALPHA_SIZE, &a);
293 ALOGI("EGL information:");
294 ALOGI("vendor : %s", eglQueryString(display, EGL_VENDOR));
295 ALOGI("version : %s", eglQueryString(display, EGL_VERSION));
296 ALOGI("extensions: %s", eglQueryString(display, EGL_EXTENSIONS));
297 ALOGI("Client API: %s", eglQueryString(display, EGL_CLIENT_APIS) ?: "Not Supported");
298 ALOGI("EGLSurface: %d-%d-%d-%d, config=%p", r, g, b, a, config);
299 }
300
301 return config;
302}
303
Lucas Dupinf4cb4a02020-09-22 14:19:26 -0700304SkiaGLRenderEngine::SkiaGLRenderEngine(const RenderEngineCreationArgs& args, EGLDisplay display,
305 EGLConfig config, EGLContext ctxt, EGLSurface placeholder,
306 EGLContext protectedContext, EGLSurface protectedPlaceholder)
Alec Mouri081be4c2020-09-16 10:24:47 -0700307 : mEGLDisplay(display),
John Reck67b1e2b2020-08-26 13:17:24 -0700308 mEGLConfig(config),
309 mEGLContext(ctxt),
310 mPlaceholderSurface(placeholder),
311 mProtectedEGLContext(protectedContext),
Alec Mourib5777452020-09-28 11:32:42 -0700312 mProtectedPlaceholderSurface(protectedPlaceholder),
313 mUseColorManagement(args.useColorManagement) {
John Reck67b1e2b2020-08-26 13:17:24 -0700314 // Suppress unused field warnings for things we definitely will need/use
315 // These EGL fields will all be needed for toggling between protected & unprotected contexts
316 // Or we need different RE instances for that
317 (void)mEGLDisplay;
318 (void)mEGLConfig;
319 (void)mEGLContext;
320 (void)mPlaceholderSurface;
321 (void)mProtectedEGLContext;
322 (void)mProtectedPlaceholderSurface;
323
324 sk_sp<const GrGLInterface> glInterface(GrGLCreateNativeInterface());
325 LOG_ALWAYS_FATAL_IF(!glInterface.get());
326
327 GrContextOptions options;
328 options.fPreferExternalImagesOverES3 = true;
329 options.fDisableDistanceFieldPaths = true;
330 mGrContext = GrDirectContext::MakeGL(std::move(glInterface), options);
Lucas Dupinf4cb4a02020-09-22 14:19:26 -0700331
332 if (args.supportsBackgroundBlur) {
333 mBlurFilter = new BlurFilter();
334 }
John Reck67b1e2b2020-08-26 13:17:24 -0700335}
336
337base::unique_fd SkiaGLRenderEngine::flush() {
338 ATRACE_CALL();
339 if (!gl::GLExtensions::getInstance().hasNativeFenceSync()) {
340 return base::unique_fd();
341 }
342
343 EGLSyncKHR sync = eglCreateSyncKHR(mEGLDisplay, EGL_SYNC_NATIVE_FENCE_ANDROID, nullptr);
344 if (sync == EGL_NO_SYNC_KHR) {
345 ALOGW("failed to create EGL native fence sync: %#x", eglGetError());
346 return base::unique_fd();
347 }
348
349 // native fence fd will not be populated until flush() is done.
350 glFlush();
351
352 // get the fence fd
353 base::unique_fd fenceFd(eglDupNativeFenceFDANDROID(mEGLDisplay, sync));
354 eglDestroySyncKHR(mEGLDisplay, sync);
355 if (fenceFd == EGL_NO_NATIVE_FENCE_FD_ANDROID) {
356 ALOGW("failed to dup EGL native fence sync: %#x", eglGetError());
357 }
358
359 return fenceFd;
360}
361
362bool SkiaGLRenderEngine::waitFence(base::unique_fd fenceFd) {
363 if (!gl::GLExtensions::getInstance().hasNativeFenceSync() ||
364 !gl::GLExtensions::getInstance().hasWaitSync()) {
365 return false;
366 }
367
368 // release the fd and transfer the ownership to EGLSync
369 EGLint attribs[] = {EGL_SYNC_NATIVE_FENCE_FD_ANDROID, fenceFd.release(), EGL_NONE};
370 EGLSyncKHR sync = eglCreateSyncKHR(mEGLDisplay, EGL_SYNC_NATIVE_FENCE_ANDROID, attribs);
371 if (sync == EGL_NO_SYNC_KHR) {
372 ALOGE("failed to create EGL native fence sync: %#x", eglGetError());
373 return false;
374 }
375
376 // XXX: The spec draft is inconsistent as to whether this should return an
377 // EGLint or void. Ignore the return value for now, as it's not strictly
378 // needed.
379 eglWaitSyncKHR(mEGLDisplay, sync, 0);
380 EGLint error = eglGetError();
381 eglDestroySyncKHR(mEGLDisplay, sync);
382 if (error != EGL_SUCCESS) {
383 ALOGE("failed to wait for EGL native fence sync: %#x", error);
384 return false;
385 }
386
387 return true;
388}
389
390static bool hasUsage(const AHardwareBuffer_Desc& desc, uint64_t usage) {
391 return !!(desc.usage & usage);
392}
393
Alec Mouri678245d2020-09-30 16:58:23 -0700394static float toDegrees(uint32_t transform) {
395 switch (transform) {
396 case ui::Transform::ROT_90:
397 return 90.0;
398 case ui::Transform::ROT_180:
399 return 180.0;
400 case ui::Transform::ROT_270:
401 return 270.0;
402 default:
403 return 0.0;
404 }
405}
406
Alec Mourib34f0b72020-10-02 13:18:34 -0700407static SkColorMatrix toSkColorMatrix(const mat4& matrix) {
408 return SkColorMatrix(matrix[0][0], matrix[1][0], matrix[2][0], matrix[3][0], 0, matrix[0][1],
409 matrix[1][1], matrix[2][1], matrix[3][1], 0, matrix[0][2], matrix[1][2],
410 matrix[2][2], matrix[3][2], 0, matrix[0][3], matrix[1][3], matrix[2][3],
411 matrix[3][3], 0);
412}
413
John Reck67b1e2b2020-08-26 13:17:24 -0700414void SkiaGLRenderEngine::unbindExternalTextureBuffer(uint64_t bufferId) {
415 std::lock_guard<std::mutex> lock(mRenderingMutex);
416 mImageCache.erase(bufferId);
417}
418
419status_t SkiaGLRenderEngine::drawLayers(const DisplaySettings& display,
420 const std::vector<const LayerSettings*>& layers,
421 const sp<GraphicBuffer>& buffer,
422 const bool useFramebufferCache,
423 base::unique_fd&& bufferFence, base::unique_fd* drawFence) {
424 ATRACE_NAME("SkiaGL::drawLayers");
425 std::lock_guard<std::mutex> lock(mRenderingMutex);
426 if (layers.empty()) {
427 ALOGV("Drawing empty layer stack");
428 return NO_ERROR;
429 }
430
431 if (bufferFence.get() >= 0) {
432 // Duplicate the fence for passing to waitFence.
433 base::unique_fd bufferFenceDup(dup(bufferFence.get()));
434 if (bufferFenceDup < 0 || !waitFence(std::move(bufferFenceDup))) {
435 ATRACE_NAME("Waiting before draw");
436 sync_wait(bufferFence.get(), -1);
437 }
438 }
439 if (buffer == nullptr) {
440 ALOGE("No output buffer provided. Aborting GPU composition.");
441 return BAD_VALUE;
442 }
443
444 AHardwareBuffer_Desc bufferDesc;
445 AHardwareBuffer_describe(buffer->toAHardwareBuffer(), &bufferDesc);
446
447 LOG_ALWAYS_FATAL_IF(!hasUsage(bufferDesc, AHARDWAREBUFFER_USAGE_GPU_SAMPLED_IMAGE),
448 "missing usage");
449
450 sk_sp<SkSurface> surface;
451 if (useFramebufferCache) {
452 auto iter = mSurfaceCache.find(buffer->getId());
453 if (iter != mSurfaceCache.end()) {
454 ALOGV("Cache hit!");
455 surface = iter->second;
456 }
457 }
458 if (!surface) {
459 surface = SkSurface::MakeFromAHardwareBuffer(mGrContext.get(), buffer->toAHardwareBuffer(),
460 GrSurfaceOrigin::kTopLeft_GrSurfaceOrigin,
Alec Mourib5777452020-09-28 11:32:42 -0700461 mUseColorManagement
462 ? toColorSpace(display.outputDataspace)
463 : SkColorSpace::MakeSRGB(),
464 nullptr);
John Reck67b1e2b2020-08-26 13:17:24 -0700465 if (useFramebufferCache && surface) {
466 ALOGD("Adding to cache");
467 mSurfaceCache.insert({buffer->getId(), surface});
468 }
469 }
470 if (!surface) {
471 ALOGE("Failed to make surface");
472 return BAD_VALUE;
473 }
Alec Mouri678245d2020-09-30 16:58:23 -0700474
John Reck67b1e2b2020-08-26 13:17:24 -0700475 auto canvas = surface->getCanvas();
Alec Mouri678245d2020-09-30 16:58:23 -0700476 // Clear the entire canvas with a transparent black to prevent ghost images.
477 canvas->clear(SK_ColorTRANSPARENT);
Lucas Dupinbb1a1d42020-09-18 15:17:02 -0700478 canvas->save();
John Reck67b1e2b2020-08-26 13:17:24 -0700479
Lucas Dupinbb1a1d42020-09-18 15:17:02 -0700480 // Before doing any drawing, let's make sure that we'll start at the origin of the display.
481 // Some displays don't start at 0,0 for example when we're mirroring the screen. Also, virtual
482 // displays might have different scaling when compared to the physical screen.
Alec Mouri678245d2020-09-30 16:58:23 -0700483
484 canvas->clipRect(getSkRect(display.physicalDisplay));
Lucas Dupinbb1a1d42020-09-18 15:17:02 -0700485 canvas->translate(display.physicalDisplay.left, display.physicalDisplay.top);
Alec Mouri678245d2020-09-30 16:58:23 -0700486
487 const auto clipWidth = display.clip.width();
488 const auto clipHeight = display.clip.height();
489 auto rotatedClipWidth = clipWidth;
490 auto rotatedClipHeight = clipHeight;
491 // Scale is contingent on the rotation result.
492 if (display.orientation & ui::Transform::ROT_90) {
493 std::swap(rotatedClipWidth, rotatedClipHeight);
494 }
Lucas Dupinbb1a1d42020-09-18 15:17:02 -0700495 const auto scaleX = static_cast<SkScalar>(display.physicalDisplay.width()) /
Alec Mouri678245d2020-09-30 16:58:23 -0700496 static_cast<SkScalar>(rotatedClipWidth);
Lucas Dupinbb1a1d42020-09-18 15:17:02 -0700497 const auto scaleY = static_cast<SkScalar>(display.physicalDisplay.height()) /
Alec Mouri678245d2020-09-30 16:58:23 -0700498 static_cast<SkScalar>(rotatedClipHeight);
Lucas Dupinbb1a1d42020-09-18 15:17:02 -0700499 canvas->scale(scaleX, scaleY);
Alec Mouri678245d2020-09-30 16:58:23 -0700500
501 // Canvas rotation is done by centering the clip window at the origin, rotating, translating
502 // back so that the top left corner of the clip is at (0, 0).
503 canvas->translate(rotatedClipWidth / 2, rotatedClipHeight / 2);
504 canvas->rotate(toDegrees(display.orientation));
505 canvas->translate(-clipWidth / 2, -clipHeight / 2);
506 canvas->translate(-display.clip.left, -display.clip.top);
John Reck67b1e2b2020-08-26 13:17:24 -0700507 for (const auto& layer : layers) {
Lucas Dupin21f348e2020-09-16 17:31:26 -0700508 SkPaint paint;
509 const auto& bounds = layer->geometry.boundaries;
Lucas Dupin3f11e922020-09-22 17:31:04 -0700510 const auto dest = getSkRect(bounds);
Lucas Dupinc3800b82020-10-02 16:24:48 -0700511 std::unordered_map<uint32_t, sk_sp<SkSurface>> cachedBlurs;
Lucas Dupin21f348e2020-09-16 17:31:26 -0700512
Lucas Dupinc3800b82020-10-02 16:24:48 -0700513 if (mBlurFilter) {
514 if (layer->backgroundBlurRadius > 0) {
515 ATRACE_NAME("BackgroundBlur");
516 auto blurredSurface =
517 mBlurFilter->draw(canvas, surface, layer->backgroundBlurRadius);
518 cachedBlurs[layer->backgroundBlurRadius] = blurredSurface;
519 }
520 if (layer->blurRegions.size() > 0) {
521 for (auto region : layer->blurRegions) {
522 if (cachedBlurs[region.blurRadius]) {
523 continue;
524 }
525 ATRACE_NAME("BlurRegion");
526 auto blurredSurface = mBlurFilter->generate(canvas, surface, region.blurRadius);
527 cachedBlurs[region.blurRadius] = blurredSurface;
528 }
529 }
Lucas Dupinf4cb4a02020-09-22 14:19:26 -0700530 }
531
John Reck67b1e2b2020-08-26 13:17:24 -0700532 if (layer->source.buffer.buffer) {
533 ATRACE_NAME("DrawImage");
534 const auto& item = layer->source.buffer;
Alec Mouri678245d2020-09-30 16:58:23 -0700535 const auto bufferWidth = item.buffer->getBounds().width();
536 const auto bufferHeight = item.buffer->getBounds().height();
John Reck67b1e2b2020-08-26 13:17:24 -0700537 sk_sp<SkImage> image;
538 auto iter = mImageCache.find(item.buffer->getId());
539 if (iter != mImageCache.end()) {
540 image = iter->second;
541 } else {
542 image = SkImage::MakeFromAHardwareBuffer(item.buffer->toAHardwareBuffer(),
543 item.usePremultipliedAlpha
544 ? kPremul_SkAlphaType
Alec Mourib5777452020-09-28 11:32:42 -0700545 : kUnpremul_SkAlphaType,
546 mUseColorManagement
547 ? toColorSpace(
548 layer->sourceDataspace)
549 : SkColorSpace::MakeSRGB());
John Reck67b1e2b2020-08-26 13:17:24 -0700550 mImageCache.insert({item.buffer->getId(), image});
551 }
Lucas Dupin21f348e2020-09-16 17:31:26 -0700552
553 SkMatrix matrix;
554 if (layer->geometry.roundedCornersRadius > 0) {
555 const auto roundedRect = getRoundedRect(layer);
556 matrix.setTranslate(roundedRect.getBounds().left() - dest.left(),
557 roundedRect.getBounds().top() - dest.top());
558 } else {
559 matrix.setIdentity();
560 }
Alec Mouri678245d2020-09-30 16:58:23 -0700561
562 auto texMatrix = getSkM44(item.textureTransform).asM33();
563 // textureTansform was intended to be passed directly into a shader, so when
564 // building the total matrix with the textureTransform we need to first
565 // normalize it, then apply the textureTransform, then scale back up.
566 matrix.postScale(1.0f / bufferWidth, 1.0f / bufferHeight);
567
568 auto rotatedBufferWidth = bufferWidth;
569 auto rotatedBufferHeight = bufferHeight;
570
571 // Swap the buffer width and height if we're rotating, so that we
572 // scale back up by the correct factors post-rotation.
573 if (texMatrix.getSkewX() <= -0.5f || texMatrix.getSkewX() >= 0.5f) {
574 std::swap(rotatedBufferWidth, rotatedBufferHeight);
575 // TODO: clean this up.
576 // GLESRenderEngine specifies its texture coordinates in
577 // CW orientation under OpenGL conventions, when they probably should have
578 // been CCW instead. The net result is that orientation
579 // transforms are applied in the reverse
580 // direction to render the correct result, because SurfaceFlinger uses the inverse
581 // of the display transform to correct for that. But this means that
582 // the tex transform passed by SkiaGLRenderEngine will rotate
583 // individual layers in the reverse orientation. Hack around it
584 // by injected a 180 degree rotation, but ultimately this is
585 // a bug in how SurfaceFlinger invokes the RenderEngine
586 // interface, so the proper fix should live there, and GLESRenderEngine
587 // should be fixed accordingly.
588 matrix.postRotate(180, 0.5, 0.5);
589 }
590
591 matrix.postConcat(texMatrix);
592 matrix.postScale(rotatedBufferWidth, rotatedBufferHeight);
Lucas Dupin21f348e2020-09-16 17:31:26 -0700593 paint.setShader(image->makeShader(matrix));
John Reck67b1e2b2020-08-26 13:17:24 -0700594 } else {
595 ATRACE_NAME("DrawColor");
John Reck67b1e2b2020-08-26 13:17:24 -0700596 const auto color = layer->source.solidColor;
Lucas Dupinc3800b82020-10-02 16:24:48 -0700597 paint.setShader(SkShaders::Color(SkColor4f{.fR = color.r,
598 .fG = color.g,
599 .fB = color.b,
600 layer->alpha},
601 nullptr));
John Reck67b1e2b2020-08-26 13:17:24 -0700602 }
Lucas Dupin21f348e2020-09-16 17:31:26 -0700603
Alec Mourib34f0b72020-10-02 13:18:34 -0700604 paint.setColorFilter(SkColorFilters::Matrix(toSkColorMatrix(display.colorTransform)));
605
Lucas Dupinbb1a1d42020-09-18 15:17:02 -0700606 // Layers have a local transform matrix that should be applied to them.
607 canvas->save();
608 canvas->concat(getSkM44(layer->geometry.positionTransform));
609
Lucas Dupinc3800b82020-10-02 16:24:48 -0700610 for (const auto effectRegion : layer->blurRegions) {
611 drawBlurRegion(canvas, effectRegion, dest, cachedBlurs[effectRegion.blurRadius]);
612 }
613
Lucas Dupin3f11e922020-09-22 17:31:04 -0700614 if (layer->shadow.length > 0) {
615 const auto rect = layer->geometry.roundedCornersRadius > 0
616 ? getSkRect(layer->geometry.roundedCornersCrop)
617 : dest;
618 drawShadow(canvas, rect, layer->geometry.roundedCornersRadius, layer->shadow);
619 }
620
Lucas Dupin21f348e2020-09-16 17:31:26 -0700621 if (layer->geometry.roundedCornersRadius > 0) {
622 canvas->drawRRect(getRoundedRect(layer), paint);
623 } else {
624 canvas->drawRect(dest, paint);
625 }
Lucas Dupinc3800b82020-10-02 16:24:48 -0700626
Lucas Dupinbb1a1d42020-09-18 15:17:02 -0700627 canvas->restore();
John Reck67b1e2b2020-08-26 13:17:24 -0700628 }
629 {
630 ATRACE_NAME("flush surface");
631 surface->flush();
632 }
Lucas Dupinbb1a1d42020-09-18 15:17:02 -0700633 canvas->restore();
John Reck67b1e2b2020-08-26 13:17:24 -0700634
635 if (drawFence != nullptr) {
636 *drawFence = flush();
637 }
638
639 // If flush failed or we don't support native fences, we need to force the
640 // gl command stream to be executed.
641 bool requireSync = drawFence == nullptr || drawFence->get() < 0;
642 if (requireSync) {
643 ATRACE_BEGIN("Submit(sync=true)");
644 } else {
645 ATRACE_BEGIN("Submit(sync=false)");
646 }
647 bool success = mGrContext->submit(requireSync);
648 ATRACE_END();
649 if (!success) {
650 ALOGE("Failed to flush RenderEngine commands");
651 // Chances are, something illegal happened (either the caller passed
652 // us bad parameters, or we messed up our shader generation).
653 return INVALID_OPERATION;
654 }
655
656 // checkErrors();
657 return NO_ERROR;
658}
659
Lucas Dupin3f11e922020-09-22 17:31:04 -0700660inline SkRect SkiaGLRenderEngine::getSkRect(const FloatRect& rect) {
661 return SkRect::MakeLTRB(rect.left, rect.top, rect.right, rect.bottom);
662}
663
664inline SkRect SkiaGLRenderEngine::getSkRect(const Rect& rect) {
665 return SkRect::MakeLTRB(rect.left, rect.top, rect.right, rect.bottom);
666}
667
Lucas Dupin21f348e2020-09-16 17:31:26 -0700668inline SkRRect SkiaGLRenderEngine::getRoundedRect(const LayerSettings* layer) {
Lucas Dupin3f11e922020-09-22 17:31:04 -0700669 const auto rect = getSkRect(layer->geometry.roundedCornersCrop);
Lucas Dupin21f348e2020-09-16 17:31:26 -0700670 const auto cornerRadius = layer->geometry.roundedCornersRadius;
671 return SkRRect::MakeRectXY(rect, cornerRadius, cornerRadius);
672}
673
Lucas Dupin3f11e922020-09-22 17:31:04 -0700674inline SkColor SkiaGLRenderEngine::getSkColor(const vec4& color) {
675 return SkColorSetARGB(color.a * 255, color.r * 255, color.g * 255, color.b * 255);
676}
677
Lucas Dupinbb1a1d42020-09-18 15:17:02 -0700678inline SkM44 SkiaGLRenderEngine::getSkM44(const mat4& matrix) {
679 return SkM44(matrix[0][0], matrix[1][0], matrix[2][0], matrix[3][0],
680 matrix[0][1], matrix[1][1], matrix[2][1], matrix[3][1],
681 matrix[0][2], matrix[1][2], matrix[2][2], matrix[3][2],
682 matrix[0][3], matrix[1][3], matrix[2][3], matrix[3][3]);
683}
684
Lucas Dupin3f11e922020-09-22 17:31:04 -0700685inline SkPoint3 SkiaGLRenderEngine::getSkPoint3(const vec3& vector) {
686 return SkPoint3::Make(vector.x, vector.y, vector.z);
687}
688
John Reck67b1e2b2020-08-26 13:17:24 -0700689size_t SkiaGLRenderEngine::getMaxTextureSize() const {
690 return mGrContext->maxTextureSize();
691}
692
693size_t SkiaGLRenderEngine::getMaxViewportDims() const {
694 return mGrContext->maxRenderTargetSize();
695}
696
Lucas Dupin3f11e922020-09-22 17:31:04 -0700697void SkiaGLRenderEngine::drawShadow(SkCanvas* canvas, const SkRect& casterRect, float cornerRadius,
698 const ShadowSettings& settings) {
699 ATRACE_CALL();
700 const float casterZ = settings.length / 2.0f;
701 const auto shadowShape = cornerRadius > 0
702 ? SkPath::RRect(SkRRect::MakeRectXY(casterRect, cornerRadius, cornerRadius))
703 : SkPath::Rect(casterRect);
704 const auto flags =
705 settings.casterIsTranslucent ? kTransparentOccluder_ShadowFlag : kNone_ShadowFlag;
706
707 SkShadowUtils::DrawShadow(canvas, shadowShape, SkPoint3::Make(0, 0, casterZ),
708 getSkPoint3(settings.lightPos), settings.lightRadius,
709 getSkColor(settings.ambientColor), getSkColor(settings.spotColor),
710 flags);
711}
712
Lucas Dupinc3800b82020-10-02 16:24:48 -0700713void SkiaGLRenderEngine::drawBlurRegion(SkCanvas* canvas, const BlurRegion& effectRegion,
714 const SkRect& layerBoundaries,
715 sk_sp<SkSurface> blurredSurface) {
716 ATRACE_CALL();
717 SkPaint paint;
718 paint.setAlpha(static_cast<int>(effectRegion.alpha * 255));
719 const auto rect = SkRect::MakeLTRB(effectRegion.left, effectRegion.top, effectRegion.right,
720 effectRegion.bottom);
721
722 const auto matrix = mBlurFilter->getShaderMatrix(
723 SkMatrix::MakeTrans(layerBoundaries.left(), layerBoundaries.top()));
724 paint.setShader(blurredSurface->makeImageSnapshot()->makeShader(matrix));
725
726 if (effectRegion.cornerRadiusTL > 0 || effectRegion.cornerRadiusTR > 0 ||
727 effectRegion.cornerRadiusBL > 0 || effectRegion.cornerRadiusBR > 0) {
728 const SkVector radii[4] =
729 {SkVector::Make(effectRegion.cornerRadiusTL, effectRegion.cornerRadiusTL),
730 SkVector::Make(effectRegion.cornerRadiusTR, effectRegion.cornerRadiusTR),
731 SkVector::Make(effectRegion.cornerRadiusBL, effectRegion.cornerRadiusBL),
732 SkVector::Make(effectRegion.cornerRadiusBR, effectRegion.cornerRadiusBR)};
733 SkRRect roundedRect;
734 roundedRect.setRectRadii(rect, radii);
735 canvas->drawRRect(roundedRect, paint);
736 } else {
737 canvas->drawRect(rect, paint);
738 }
739}
740
John Reck67b1e2b2020-08-26 13:17:24 -0700741EGLContext SkiaGLRenderEngine::createEglContext(EGLDisplay display, EGLConfig config,
742 EGLContext shareContext, bool useContextPriority,
743 Protection protection) {
744 EGLint renderableType = 0;
745 if (config == EGL_NO_CONFIG_KHR) {
746 renderableType = EGL_OPENGL_ES3_BIT;
747 } else if (!eglGetConfigAttrib(display, config, EGL_RENDERABLE_TYPE, &renderableType)) {
748 LOG_ALWAYS_FATAL("can't query EGLConfig RENDERABLE_TYPE");
749 }
750 EGLint contextClientVersion = 0;
751 if (renderableType & EGL_OPENGL_ES3_BIT) {
752 contextClientVersion = 3;
753 } else if (renderableType & EGL_OPENGL_ES2_BIT) {
754 contextClientVersion = 2;
755 } else if (renderableType & EGL_OPENGL_ES_BIT) {
756 contextClientVersion = 1;
757 } else {
758 LOG_ALWAYS_FATAL("no supported EGL_RENDERABLE_TYPEs");
759 }
760
761 std::vector<EGLint> contextAttributes;
762 contextAttributes.reserve(7);
763 contextAttributes.push_back(EGL_CONTEXT_CLIENT_VERSION);
764 contextAttributes.push_back(contextClientVersion);
765 if (useContextPriority) {
766 contextAttributes.push_back(EGL_CONTEXT_PRIORITY_LEVEL_IMG);
767 contextAttributes.push_back(EGL_CONTEXT_PRIORITY_HIGH_IMG);
768 }
769 if (protection == Protection::PROTECTED) {
770 contextAttributes.push_back(EGL_PROTECTED_CONTENT_EXT);
771 contextAttributes.push_back(EGL_TRUE);
772 }
773 contextAttributes.push_back(EGL_NONE);
774
775 EGLContext context = eglCreateContext(display, config, shareContext, contextAttributes.data());
776
777 if (contextClientVersion == 3 && context == EGL_NO_CONTEXT) {
778 // eglGetConfigAttrib indicated we can create GLES 3 context, but we failed, thus
779 // EGL_NO_CONTEXT so that we can abort.
780 if (config != EGL_NO_CONFIG_KHR) {
781 return context;
782 }
783 // If |config| is EGL_NO_CONFIG_KHR, we speculatively try to create GLES 3 context, so we
784 // should try to fall back to GLES 2.
785 contextAttributes[1] = 2;
786 context = eglCreateContext(display, config, shareContext, contextAttributes.data());
787 }
788
789 return context;
790}
791
792EGLSurface SkiaGLRenderEngine::createPlaceholderEglPbufferSurface(EGLDisplay display,
793 EGLConfig config, int hwcFormat,
794 Protection protection) {
795 EGLConfig placeholderConfig = config;
796 if (placeholderConfig == EGL_NO_CONFIG_KHR) {
797 placeholderConfig = chooseEglConfig(display, hwcFormat, /*logConfig*/ true);
798 }
799 std::vector<EGLint> attributes;
800 attributes.reserve(7);
801 attributes.push_back(EGL_WIDTH);
802 attributes.push_back(1);
803 attributes.push_back(EGL_HEIGHT);
804 attributes.push_back(1);
805 if (protection == Protection::PROTECTED) {
806 attributes.push_back(EGL_PROTECTED_CONTENT_EXT);
807 attributes.push_back(EGL_TRUE);
808 }
809 attributes.push_back(EGL_NONE);
810
811 return eglCreatePbufferSurface(display, placeholderConfig, attributes.data());
812}
813
814void SkiaGLRenderEngine::cleanFramebufferCache() {
815 mSurfaceCache.clear();
816}
817
818} // namespace skia
819} // namespace renderengine
820} // namespace android