blob: a9bacb7ec2f611c1051ee444838ae90bbedf57c8 [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));
Galia Peycheva6c460652020-11-03 19:42:42 +0100485 SkMatrix screenTransform;
486 screenTransform.setTranslate(display.physicalDisplay.left, display.physicalDisplay.top);
Alec Mouri678245d2020-09-30 16:58:23 -0700487
488 const auto clipWidth = display.clip.width();
489 const auto clipHeight = display.clip.height();
490 auto rotatedClipWidth = clipWidth;
491 auto rotatedClipHeight = clipHeight;
492 // Scale is contingent on the rotation result.
493 if (display.orientation & ui::Transform::ROT_90) {
494 std::swap(rotatedClipWidth, rotatedClipHeight);
495 }
Lucas Dupinbb1a1d42020-09-18 15:17:02 -0700496 const auto scaleX = static_cast<SkScalar>(display.physicalDisplay.width()) /
Alec Mouri678245d2020-09-30 16:58:23 -0700497 static_cast<SkScalar>(rotatedClipWidth);
Lucas Dupinbb1a1d42020-09-18 15:17:02 -0700498 const auto scaleY = static_cast<SkScalar>(display.physicalDisplay.height()) /
Alec Mouri678245d2020-09-30 16:58:23 -0700499 static_cast<SkScalar>(rotatedClipHeight);
Galia Peycheva6c460652020-11-03 19:42:42 +0100500 screenTransform.preScale(scaleX, scaleY);
Alec Mouri678245d2020-09-30 16:58:23 -0700501
502 // Canvas rotation is done by centering the clip window at the origin, rotating, translating
503 // back so that the top left corner of the clip is at (0, 0).
Galia Peycheva6c460652020-11-03 19:42:42 +0100504 screenTransform.preTranslate(rotatedClipWidth / 2, rotatedClipHeight / 2);
505 screenTransform.preRotate(toDegrees(display.orientation));
506 screenTransform.preTranslate(-clipWidth / 2, -clipHeight / 2);
507 screenTransform.preTranslate(-display.clip.left, -display.clip.top);
John Reck67b1e2b2020-08-26 13:17:24 -0700508 for (const auto& layer : layers) {
Galia Peycheva6c460652020-11-03 19:42:42 +0100509 const SkMatrix drawTransform = getDrawTransform(layer, screenTransform);
510
Lucas Dupin21f348e2020-09-16 17:31:26 -0700511 SkPaint paint;
512 const auto& bounds = layer->geometry.boundaries;
Lucas Dupin3f11e922020-09-22 17:31:04 -0700513 const auto dest = getSkRect(bounds);
Lucas Dupinc3800b82020-10-02 16:24:48 -0700514 std::unordered_map<uint32_t, sk_sp<SkSurface>> cachedBlurs;
Lucas Dupin21f348e2020-09-16 17:31:26 -0700515
Lucas Dupinc3800b82020-10-02 16:24:48 -0700516 if (mBlurFilter) {
Galia Peycheva6c460652020-11-03 19:42:42 +0100517 const auto layerRect = drawTransform.mapRect(dest);
Lucas Dupinc3800b82020-10-02 16:24:48 -0700518 if (layer->backgroundBlurRadius > 0) {
519 ATRACE_NAME("BackgroundBlur");
520 auto blurredSurface =
Galia Peycheva6c460652020-11-03 19:42:42 +0100521 mBlurFilter->draw(canvas, surface, layer->backgroundBlurRadius, layerRect);
Lucas Dupinc3800b82020-10-02 16:24:48 -0700522 cachedBlurs[layer->backgroundBlurRadius] = blurredSurface;
523 }
524 if (layer->blurRegions.size() > 0) {
525 for (auto region : layer->blurRegions) {
526 if (cachedBlurs[region.blurRadius]) {
527 continue;
528 }
529 ATRACE_NAME("BlurRegion");
Galia Peycheva6c460652020-11-03 19:42:42 +0100530 auto blurredSurface =
531 mBlurFilter->generate(canvas, surface, region.blurRadius, layerRect);
Lucas Dupinc3800b82020-10-02 16:24:48 -0700532 cachedBlurs[region.blurRadius] = blurredSurface;
533 }
534 }
Lucas Dupinf4cb4a02020-09-22 14:19:26 -0700535 }
536
John Reck67b1e2b2020-08-26 13:17:24 -0700537 if (layer->source.buffer.buffer) {
538 ATRACE_NAME("DrawImage");
539 const auto& item = layer->source.buffer;
Alec Mouri678245d2020-09-30 16:58:23 -0700540 const auto bufferWidth = item.buffer->getBounds().width();
541 const auto bufferHeight = item.buffer->getBounds().height();
John Reck67b1e2b2020-08-26 13:17:24 -0700542 sk_sp<SkImage> image;
543 auto iter = mImageCache.find(item.buffer->getId());
544 if (iter != mImageCache.end()) {
545 image = iter->second;
546 } else {
547 image = SkImage::MakeFromAHardwareBuffer(item.buffer->toAHardwareBuffer(),
548 item.usePremultipliedAlpha
549 ? kPremul_SkAlphaType
Alec Mourib5777452020-09-28 11:32:42 -0700550 : kUnpremul_SkAlphaType,
551 mUseColorManagement
552 ? toColorSpace(
553 layer->sourceDataspace)
554 : SkColorSpace::MakeSRGB());
John Reck67b1e2b2020-08-26 13:17:24 -0700555 mImageCache.insert({item.buffer->getId(), image});
556 }
Lucas Dupin21f348e2020-09-16 17:31:26 -0700557
558 SkMatrix matrix;
559 if (layer->geometry.roundedCornersRadius > 0) {
560 const auto roundedRect = getRoundedRect(layer);
561 matrix.setTranslate(roundedRect.getBounds().left() - dest.left(),
562 roundedRect.getBounds().top() - dest.top());
563 } else {
564 matrix.setIdentity();
565 }
Alec Mouri678245d2020-09-30 16:58:23 -0700566
567 auto texMatrix = getSkM44(item.textureTransform).asM33();
568 // textureTansform was intended to be passed directly into a shader, so when
569 // building the total matrix with the textureTransform we need to first
570 // normalize it, then apply the textureTransform, then scale back up.
571 matrix.postScale(1.0f / bufferWidth, 1.0f / bufferHeight);
572
573 auto rotatedBufferWidth = bufferWidth;
574 auto rotatedBufferHeight = bufferHeight;
575
576 // Swap the buffer width and height if we're rotating, so that we
577 // scale back up by the correct factors post-rotation.
578 if (texMatrix.getSkewX() <= -0.5f || texMatrix.getSkewX() >= 0.5f) {
579 std::swap(rotatedBufferWidth, rotatedBufferHeight);
580 // TODO: clean this up.
581 // GLESRenderEngine specifies its texture coordinates in
582 // CW orientation under OpenGL conventions, when they probably should have
583 // been CCW instead. The net result is that orientation
584 // transforms are applied in the reverse
585 // direction to render the correct result, because SurfaceFlinger uses the inverse
586 // of the display transform to correct for that. But this means that
587 // the tex transform passed by SkiaGLRenderEngine will rotate
588 // individual layers in the reverse orientation. Hack around it
589 // by injected a 180 degree rotation, but ultimately this is
590 // a bug in how SurfaceFlinger invokes the RenderEngine
591 // interface, so the proper fix should live there, and GLESRenderEngine
592 // should be fixed accordingly.
593 matrix.postRotate(180, 0.5, 0.5);
594 }
595
596 matrix.postConcat(texMatrix);
597 matrix.postScale(rotatedBufferWidth, rotatedBufferHeight);
Lucas Dupin21f348e2020-09-16 17:31:26 -0700598 paint.setShader(image->makeShader(matrix));
John Reck67b1e2b2020-08-26 13:17:24 -0700599 } else {
600 ATRACE_NAME("DrawColor");
John Reck67b1e2b2020-08-26 13:17:24 -0700601 const auto color = layer->source.solidColor;
Lucas Dupinc3800b82020-10-02 16:24:48 -0700602 paint.setShader(SkShaders::Color(SkColor4f{.fR = color.r,
603 .fG = color.g,
604 .fB = color.b,
605 layer->alpha},
606 nullptr));
John Reck67b1e2b2020-08-26 13:17:24 -0700607 }
Lucas Dupin21f348e2020-09-16 17:31:26 -0700608
Alec Mourib34f0b72020-10-02 13:18:34 -0700609 paint.setColorFilter(SkColorFilters::Matrix(toSkColorMatrix(display.colorTransform)));
610
Lucas Dupinbb1a1d42020-09-18 15:17:02 -0700611 canvas->save();
Galia Peycheva6c460652020-11-03 19:42:42 +0100612 canvas->concat(drawTransform);
Lucas Dupinbb1a1d42020-09-18 15:17:02 -0700613
Lucas Dupinc3800b82020-10-02 16:24:48 -0700614 for (const auto effectRegion : layer->blurRegions) {
615 drawBlurRegion(canvas, effectRegion, dest, cachedBlurs[effectRegion.blurRadius]);
616 }
617
Lucas Dupin3f11e922020-09-22 17:31:04 -0700618 if (layer->shadow.length > 0) {
619 const auto rect = layer->geometry.roundedCornersRadius > 0
620 ? getSkRect(layer->geometry.roundedCornersCrop)
621 : dest;
622 drawShadow(canvas, rect, layer->geometry.roundedCornersRadius, layer->shadow);
623 }
624
Lucas Dupin21f348e2020-09-16 17:31:26 -0700625 if (layer->geometry.roundedCornersRadius > 0) {
626 canvas->drawRRect(getRoundedRect(layer), paint);
627 } else {
628 canvas->drawRect(dest, paint);
629 }
Lucas Dupinc3800b82020-10-02 16:24:48 -0700630
Lucas Dupinbb1a1d42020-09-18 15:17:02 -0700631 canvas->restore();
John Reck67b1e2b2020-08-26 13:17:24 -0700632 }
633 {
634 ATRACE_NAME("flush surface");
635 surface->flush();
636 }
Lucas Dupinbb1a1d42020-09-18 15:17:02 -0700637 canvas->restore();
John Reck67b1e2b2020-08-26 13:17:24 -0700638
639 if (drawFence != nullptr) {
640 *drawFence = flush();
641 }
642
643 // If flush failed or we don't support native fences, we need to force the
644 // gl command stream to be executed.
645 bool requireSync = drawFence == nullptr || drawFence->get() < 0;
646 if (requireSync) {
647 ATRACE_BEGIN("Submit(sync=true)");
648 } else {
649 ATRACE_BEGIN("Submit(sync=false)");
650 }
651 bool success = mGrContext->submit(requireSync);
652 ATRACE_END();
653 if (!success) {
654 ALOGE("Failed to flush RenderEngine commands");
655 // Chances are, something illegal happened (either the caller passed
656 // us bad parameters, or we messed up our shader generation).
657 return INVALID_OPERATION;
658 }
659
660 // checkErrors();
661 return NO_ERROR;
662}
663
Lucas Dupin3f11e922020-09-22 17:31:04 -0700664inline SkRect SkiaGLRenderEngine::getSkRect(const FloatRect& rect) {
665 return SkRect::MakeLTRB(rect.left, rect.top, rect.right, rect.bottom);
666}
667
668inline SkRect SkiaGLRenderEngine::getSkRect(const Rect& rect) {
669 return SkRect::MakeLTRB(rect.left, rect.top, rect.right, rect.bottom);
670}
671
Lucas Dupin21f348e2020-09-16 17:31:26 -0700672inline SkRRect SkiaGLRenderEngine::getRoundedRect(const LayerSettings* layer) {
Lucas Dupin3f11e922020-09-22 17:31:04 -0700673 const auto rect = getSkRect(layer->geometry.roundedCornersCrop);
Lucas Dupin21f348e2020-09-16 17:31:26 -0700674 const auto cornerRadius = layer->geometry.roundedCornersRadius;
675 return SkRRect::MakeRectXY(rect, cornerRadius, cornerRadius);
676}
677
Lucas Dupin3f11e922020-09-22 17:31:04 -0700678inline SkColor SkiaGLRenderEngine::getSkColor(const vec4& color) {
679 return SkColorSetARGB(color.a * 255, color.r * 255, color.g * 255, color.b * 255);
680}
681
Lucas Dupinbb1a1d42020-09-18 15:17:02 -0700682inline SkM44 SkiaGLRenderEngine::getSkM44(const mat4& matrix) {
683 return SkM44(matrix[0][0], matrix[1][0], matrix[2][0], matrix[3][0],
684 matrix[0][1], matrix[1][1], matrix[2][1], matrix[3][1],
685 matrix[0][2], matrix[1][2], matrix[2][2], matrix[3][2],
686 matrix[0][3], matrix[1][3], matrix[2][3], matrix[3][3]);
687}
688
Galia Peycheva6c460652020-11-03 19:42:42 +0100689inline SkMatrix SkiaGLRenderEngine::getDrawTransform(const LayerSettings* layer,
690 const SkMatrix& screenTransform) {
691 // Layers have a local transform matrix that should be applied to them.
692 const auto layerTransform = getSkM44(layer->geometry.positionTransform).asM33();
693 return SkMatrix::Concat(screenTransform, layerTransform);
694}
695
Lucas Dupin3f11e922020-09-22 17:31:04 -0700696inline SkPoint3 SkiaGLRenderEngine::getSkPoint3(const vec3& vector) {
697 return SkPoint3::Make(vector.x, vector.y, vector.z);
698}
699
John Reck67b1e2b2020-08-26 13:17:24 -0700700size_t SkiaGLRenderEngine::getMaxTextureSize() const {
701 return mGrContext->maxTextureSize();
702}
703
704size_t SkiaGLRenderEngine::getMaxViewportDims() const {
705 return mGrContext->maxRenderTargetSize();
706}
707
Lucas Dupin3f11e922020-09-22 17:31:04 -0700708void SkiaGLRenderEngine::drawShadow(SkCanvas* canvas, const SkRect& casterRect, float cornerRadius,
709 const ShadowSettings& settings) {
710 ATRACE_CALL();
711 const float casterZ = settings.length / 2.0f;
712 const auto shadowShape = cornerRadius > 0
713 ? SkPath::RRect(SkRRect::MakeRectXY(casterRect, cornerRadius, cornerRadius))
714 : SkPath::Rect(casterRect);
715 const auto flags =
716 settings.casterIsTranslucent ? kTransparentOccluder_ShadowFlag : kNone_ShadowFlag;
717
718 SkShadowUtils::DrawShadow(canvas, shadowShape, SkPoint3::Make(0, 0, casterZ),
719 getSkPoint3(settings.lightPos), settings.lightRadius,
720 getSkColor(settings.ambientColor), getSkColor(settings.spotColor),
721 flags);
722}
723
Lucas Dupinc3800b82020-10-02 16:24:48 -0700724void SkiaGLRenderEngine::drawBlurRegion(SkCanvas* canvas, const BlurRegion& effectRegion,
725 const SkRect& layerBoundaries,
726 sk_sp<SkSurface> blurredSurface) {
727 ATRACE_CALL();
728 SkPaint paint;
729 paint.setAlpha(static_cast<int>(effectRegion.alpha * 255));
730 const auto rect = SkRect::MakeLTRB(effectRegion.left, effectRegion.top, effectRegion.right,
731 effectRegion.bottom);
732
733 const auto matrix = mBlurFilter->getShaderMatrix(
734 SkMatrix::MakeTrans(layerBoundaries.left(), layerBoundaries.top()));
735 paint.setShader(blurredSurface->makeImageSnapshot()->makeShader(matrix));
736
737 if (effectRegion.cornerRadiusTL > 0 || effectRegion.cornerRadiusTR > 0 ||
738 effectRegion.cornerRadiusBL > 0 || effectRegion.cornerRadiusBR > 0) {
739 const SkVector radii[4] =
740 {SkVector::Make(effectRegion.cornerRadiusTL, effectRegion.cornerRadiusTL),
741 SkVector::Make(effectRegion.cornerRadiusTR, effectRegion.cornerRadiusTR),
742 SkVector::Make(effectRegion.cornerRadiusBL, effectRegion.cornerRadiusBL),
743 SkVector::Make(effectRegion.cornerRadiusBR, effectRegion.cornerRadiusBR)};
744 SkRRect roundedRect;
745 roundedRect.setRectRadii(rect, radii);
746 canvas->drawRRect(roundedRect, paint);
747 } else {
748 canvas->drawRect(rect, paint);
749 }
750}
751
John Reck67b1e2b2020-08-26 13:17:24 -0700752EGLContext SkiaGLRenderEngine::createEglContext(EGLDisplay display, EGLConfig config,
753 EGLContext shareContext, bool useContextPriority,
754 Protection protection) {
755 EGLint renderableType = 0;
756 if (config == EGL_NO_CONFIG_KHR) {
757 renderableType = EGL_OPENGL_ES3_BIT;
758 } else if (!eglGetConfigAttrib(display, config, EGL_RENDERABLE_TYPE, &renderableType)) {
759 LOG_ALWAYS_FATAL("can't query EGLConfig RENDERABLE_TYPE");
760 }
761 EGLint contextClientVersion = 0;
762 if (renderableType & EGL_OPENGL_ES3_BIT) {
763 contextClientVersion = 3;
764 } else if (renderableType & EGL_OPENGL_ES2_BIT) {
765 contextClientVersion = 2;
766 } else if (renderableType & EGL_OPENGL_ES_BIT) {
767 contextClientVersion = 1;
768 } else {
769 LOG_ALWAYS_FATAL("no supported EGL_RENDERABLE_TYPEs");
770 }
771
772 std::vector<EGLint> contextAttributes;
773 contextAttributes.reserve(7);
774 contextAttributes.push_back(EGL_CONTEXT_CLIENT_VERSION);
775 contextAttributes.push_back(contextClientVersion);
776 if (useContextPriority) {
777 contextAttributes.push_back(EGL_CONTEXT_PRIORITY_LEVEL_IMG);
778 contextAttributes.push_back(EGL_CONTEXT_PRIORITY_HIGH_IMG);
779 }
780 if (protection == Protection::PROTECTED) {
781 contextAttributes.push_back(EGL_PROTECTED_CONTENT_EXT);
782 contextAttributes.push_back(EGL_TRUE);
783 }
784 contextAttributes.push_back(EGL_NONE);
785
786 EGLContext context = eglCreateContext(display, config, shareContext, contextAttributes.data());
787
788 if (contextClientVersion == 3 && context == EGL_NO_CONTEXT) {
789 // eglGetConfigAttrib indicated we can create GLES 3 context, but we failed, thus
790 // EGL_NO_CONTEXT so that we can abort.
791 if (config != EGL_NO_CONFIG_KHR) {
792 return context;
793 }
794 // If |config| is EGL_NO_CONFIG_KHR, we speculatively try to create GLES 3 context, so we
795 // should try to fall back to GLES 2.
796 contextAttributes[1] = 2;
797 context = eglCreateContext(display, config, shareContext, contextAttributes.data());
798 }
799
800 return context;
801}
802
803EGLSurface SkiaGLRenderEngine::createPlaceholderEglPbufferSurface(EGLDisplay display,
804 EGLConfig config, int hwcFormat,
805 Protection protection) {
806 EGLConfig placeholderConfig = config;
807 if (placeholderConfig == EGL_NO_CONFIG_KHR) {
808 placeholderConfig = chooseEglConfig(display, hwcFormat, /*logConfig*/ true);
809 }
810 std::vector<EGLint> attributes;
811 attributes.reserve(7);
812 attributes.push_back(EGL_WIDTH);
813 attributes.push_back(1);
814 attributes.push_back(EGL_HEIGHT);
815 attributes.push_back(1);
816 if (protection == Protection::PROTECTED) {
817 attributes.push_back(EGL_PROTECTED_CONTENT_EXT);
818 attributes.push_back(EGL_TRUE);
819 }
820 attributes.push_back(EGL_NONE);
821
822 return eglCreatePbufferSurface(display, placeholderConfig, attributes.data());
823}
824
825void SkiaGLRenderEngine::cleanFramebufferCache() {
826 mSurfaceCache.clear();
827}
828
829} // namespace skia
830} // namespace renderengine
Galia Peycheva6c460652020-11-03 19:42:42 +0100831} // namespace android