blob: 69ad1897652194841d3b9f457eb806cc0d145e60 [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>
John Reck67b1e2b2020-08-26 13:17:24 -070026#include <GrContextOptions.h>
John Reck67b1e2b2020-08-26 13:17:24 -070027#include <SkCanvas.h>
Alec Mourib34f0b72020-10-02 13:18:34 -070028#include <SkColorFilter.h>
29#include <SkColorMatrix.h>
Alec Mourib5777452020-09-28 11:32:42 -070030#include <SkColorSpace.h>
John Reck67b1e2b2020-08-26 13:17:24 -070031#include <SkImage.h>
Lucas Dupinf4cb4a02020-09-22 14:19:26 -070032#include <SkImageFilters.h>
Lucas Dupin3f11e922020-09-22 17:31:04 -070033#include <SkShadowUtils.h>
John Reck67b1e2b2020-08-26 13:17:24 -070034#include <SkSurface.h>
Alec Mourib5777452020-09-28 11:32:42 -070035#include <gl/GrGLInterface.h>
36#include <sync/sync.h>
37#include <ui/GraphicBuffer.h>
38#include <utils/Trace.h>
39
40#include <cmath>
41
42#include "../gl/GLExtensions.h"
Alec Mourib34f0b72020-10-02 13:18:34 -070043#include "SkiaGLRenderEngine.h"
Alec Mourib5777452020-09-28 11:32:42 -070044#include "filters/BlurFilter.h"
John Reck67b1e2b2020-08-26 13:17:24 -070045
46extern "C" EGLAPI const char* eglQueryStringImplementationANDROID(EGLDisplay dpy, EGLint name);
47
48bool checkGlError(const char* op, int lineNumber);
49
50namespace android {
51namespace renderengine {
52namespace skia {
53
54static status_t selectConfigForAttribute(EGLDisplay dpy, EGLint const* attrs, EGLint attribute,
55 EGLint wanted, EGLConfig* outConfig) {
56 EGLint numConfigs = -1, n = 0;
57 eglGetConfigs(dpy, nullptr, 0, &numConfigs);
58 std::vector<EGLConfig> configs(numConfigs, EGL_NO_CONFIG_KHR);
59 eglChooseConfig(dpy, attrs, configs.data(), configs.size(), &n);
60 configs.resize(n);
61
62 if (!configs.empty()) {
63 if (attribute != EGL_NONE) {
64 for (EGLConfig config : configs) {
65 EGLint value = 0;
66 eglGetConfigAttrib(dpy, config, attribute, &value);
67 if (wanted == value) {
68 *outConfig = config;
69 return NO_ERROR;
70 }
71 }
72 } else {
73 // just pick the first one
74 *outConfig = configs[0];
75 return NO_ERROR;
76 }
77 }
78
79 return NAME_NOT_FOUND;
80}
81
82static status_t selectEGLConfig(EGLDisplay display, EGLint format, EGLint renderableType,
83 EGLConfig* config) {
84 // select our EGLConfig. It must support EGL_RECORDABLE_ANDROID if
85 // it is to be used with WIFI displays
86 status_t err;
87 EGLint wantedAttribute;
88 EGLint wantedAttributeValue;
89
90 std::vector<EGLint> attribs;
91 if (renderableType) {
92 const ui::PixelFormat pixelFormat = static_cast<ui::PixelFormat>(format);
93 const bool is1010102 = pixelFormat == ui::PixelFormat::RGBA_1010102;
94
95 // Default to 8 bits per channel.
96 const EGLint tmpAttribs[] = {
97 EGL_RENDERABLE_TYPE,
98 renderableType,
99 EGL_RECORDABLE_ANDROID,
100 EGL_TRUE,
101 EGL_SURFACE_TYPE,
102 EGL_WINDOW_BIT | EGL_PBUFFER_BIT,
103 EGL_FRAMEBUFFER_TARGET_ANDROID,
104 EGL_TRUE,
105 EGL_RED_SIZE,
106 is1010102 ? 10 : 8,
107 EGL_GREEN_SIZE,
108 is1010102 ? 10 : 8,
109 EGL_BLUE_SIZE,
110 is1010102 ? 10 : 8,
111 EGL_ALPHA_SIZE,
112 is1010102 ? 2 : 8,
113 EGL_NONE,
114 };
115 std::copy(tmpAttribs, tmpAttribs + (sizeof(tmpAttribs) / sizeof(EGLint)),
116 std::back_inserter(attribs));
117 wantedAttribute = EGL_NONE;
118 wantedAttributeValue = EGL_NONE;
119 } else {
120 // if no renderable type specified, fallback to a simplified query
121 wantedAttribute = EGL_NATIVE_VISUAL_ID;
122 wantedAttributeValue = format;
123 }
124
125 err = selectConfigForAttribute(display, attribs.data(), wantedAttribute, wantedAttributeValue,
126 config);
127 if (err == NO_ERROR) {
128 EGLint caveat;
129 if (eglGetConfigAttrib(display, *config, EGL_CONFIG_CAVEAT, &caveat))
130 ALOGW_IF(caveat == EGL_SLOW_CONFIG, "EGL_SLOW_CONFIG selected!");
131 }
132
133 return err;
134}
135
Alec Mourib5777452020-09-28 11:32:42 -0700136// Converts an android dataspace to a supported SkColorSpace
137// Supported dataspaces are
138// 1. sRGB
139// 2. Display P3
140// 3. BT2020 PQ
141// 4. BT2020 HLG
142// Unknown primaries are mapped to BT709, and unknown transfer functions
143// are mapped to sRGB.
144static sk_sp<SkColorSpace> toColorSpace(ui::Dataspace dataspace) {
145 skcms_Matrix3x3 gamut;
146 switch (dataspace & HAL_DATASPACE_STANDARD_MASK) {
147 case HAL_DATASPACE_STANDARD_BT709:
148 gamut = SkNamedGamut::kSRGB;
149 break;
150 case HAL_DATASPACE_STANDARD_BT2020:
151 gamut = SkNamedGamut::kRec2020;
152 break;
153 case HAL_DATASPACE_STANDARD_DCI_P3:
154 gamut = SkNamedGamut::kDisplayP3;
155 break;
156 default:
157 ALOGV("Unsupported Gamut: %d, defaulting to sRGB", dataspace);
158 gamut = SkNamedGamut::kSRGB;
159 break;
160 }
161
162 switch (dataspace & HAL_DATASPACE_TRANSFER_MASK) {
163 case HAL_DATASPACE_TRANSFER_LINEAR:
164 return SkColorSpace::MakeRGB(SkNamedTransferFn::kLinear, gamut);
165 case HAL_DATASPACE_TRANSFER_SRGB:
166 return SkColorSpace::MakeRGB(SkNamedTransferFn::kSRGB, gamut);
167 case HAL_DATASPACE_TRANSFER_ST2084:
168 return SkColorSpace::MakeRGB(SkNamedTransferFn::kPQ, gamut);
169 case HAL_DATASPACE_TRANSFER_HLG:
170 return SkColorSpace::MakeRGB(SkNamedTransferFn::kHLG, gamut);
171 default:
172 ALOGV("Unsupported Gamma: %d, defaulting to sRGB transfer", dataspace);
173 return SkColorSpace::MakeRGB(SkNamedTransferFn::kSRGB, gamut);
174 }
175}
176
John Reck67b1e2b2020-08-26 13:17:24 -0700177std::unique_ptr<SkiaGLRenderEngine> SkiaGLRenderEngine::create(
178 const RenderEngineCreationArgs& args) {
179 // initialize EGL for the default display
180 EGLDisplay display = eglGetDisplay(EGL_DEFAULT_DISPLAY);
181 if (!eglInitialize(display, nullptr, nullptr)) {
182 LOG_ALWAYS_FATAL("failed to initialize EGL");
183 }
184
185 const auto eglVersion = eglQueryStringImplementationANDROID(display, EGL_VERSION);
186 if (!eglVersion) {
187 checkGlError(__FUNCTION__, __LINE__);
188 LOG_ALWAYS_FATAL("eglQueryStringImplementationANDROID(EGL_VERSION) failed");
189 }
190
191 const auto eglExtensions = eglQueryStringImplementationANDROID(display, EGL_EXTENSIONS);
192 if (!eglExtensions) {
193 checkGlError(__FUNCTION__, __LINE__);
194 LOG_ALWAYS_FATAL("eglQueryStringImplementationANDROID(EGL_EXTENSIONS) failed");
195 }
196
197 auto& extensions = gl::GLExtensions::getInstance();
198 extensions.initWithEGLStrings(eglVersion, eglExtensions);
199
200 // The code assumes that ES2 or later is available if this extension is
201 // supported.
202 EGLConfig config = EGL_NO_CONFIG_KHR;
203 if (!extensions.hasNoConfigContext()) {
204 config = chooseEglConfig(display, args.pixelFormat, /*logConfig*/ true);
205 }
206
207 bool useContextPriority =
208 extensions.hasContextPriority() && args.contextPriority == ContextPriority::HIGH;
209 EGLContext protectedContext = EGL_NO_CONTEXT;
210 if (args.enableProtectedContext && extensions.hasProtectedContent()) {
211 protectedContext = createEglContext(display, config, nullptr, useContextPriority,
212 Protection::PROTECTED);
213 ALOGE_IF(protectedContext == EGL_NO_CONTEXT, "Can't create protected context");
214 }
215
216 EGLContext ctxt = createEglContext(display, config, protectedContext, useContextPriority,
217 Protection::UNPROTECTED);
218
219 // if can't create a GL context, we can only abort.
220 LOG_ALWAYS_FATAL_IF(ctxt == EGL_NO_CONTEXT, "EGLContext creation failed");
221
222 EGLSurface placeholder = EGL_NO_SURFACE;
223 if (!extensions.hasSurfacelessContext()) {
224 placeholder = createPlaceholderEglPbufferSurface(display, config, args.pixelFormat,
225 Protection::UNPROTECTED);
226 LOG_ALWAYS_FATAL_IF(placeholder == EGL_NO_SURFACE, "can't create placeholder pbuffer");
227 }
228 EGLBoolean success = eglMakeCurrent(display, placeholder, placeholder, ctxt);
229 LOG_ALWAYS_FATAL_IF(!success, "can't make placeholder pbuffer current");
230 extensions.initWithGLStrings(glGetString(GL_VENDOR), glGetString(GL_RENDERER),
231 glGetString(GL_VERSION), glGetString(GL_EXTENSIONS));
232
233 EGLSurface protectedPlaceholder = EGL_NO_SURFACE;
234 if (protectedContext != EGL_NO_CONTEXT && !extensions.hasSurfacelessContext()) {
235 protectedPlaceholder = createPlaceholderEglPbufferSurface(display, config, args.pixelFormat,
236 Protection::PROTECTED);
237 ALOGE_IF(protectedPlaceholder == EGL_NO_SURFACE,
238 "can't create protected placeholder pbuffer");
239 }
240
241 // initialize the renderer while GL is current
242 std::unique_ptr<SkiaGLRenderEngine> engine =
Lucas Dupinf4cb4a02020-09-22 14:19:26 -0700243 std::make_unique<SkiaGLRenderEngine>(args, display, config, ctxt, placeholder,
John Reck67b1e2b2020-08-26 13:17:24 -0700244 protectedContext, protectedPlaceholder);
245
246 ALOGI("OpenGL ES informations:");
247 ALOGI("vendor : %s", extensions.getVendor());
248 ALOGI("renderer : %s", extensions.getRenderer());
249 ALOGI("version : %s", extensions.getVersion());
250 ALOGI("extensions: %s", extensions.getExtensions());
251 ALOGI("GL_MAX_TEXTURE_SIZE = %zu", engine->getMaxTextureSize());
252 ALOGI("GL_MAX_VIEWPORT_DIMS = %zu", engine->getMaxViewportDims());
253
254 return engine;
255}
256
257EGLConfig SkiaGLRenderEngine::chooseEglConfig(EGLDisplay display, int format, bool logConfig) {
258 status_t err;
259 EGLConfig config;
260
261 // First try to get an ES3 config
262 err = selectEGLConfig(display, format, EGL_OPENGL_ES3_BIT, &config);
263 if (err != NO_ERROR) {
264 // If ES3 fails, try to get an ES2 config
265 err = selectEGLConfig(display, format, EGL_OPENGL_ES2_BIT, &config);
266 if (err != NO_ERROR) {
267 // If ES2 still doesn't work, probably because we're on the emulator.
268 // try a simplified query
269 ALOGW("no suitable EGLConfig found, trying a simpler query");
270 err = selectEGLConfig(display, format, 0, &config);
271 if (err != NO_ERROR) {
272 // this EGL is too lame for android
273 LOG_ALWAYS_FATAL("no suitable EGLConfig found, giving up");
274 }
275 }
276 }
277
278 if (logConfig) {
279 // print some debugging info
280 EGLint r, g, b, a;
281 eglGetConfigAttrib(display, config, EGL_RED_SIZE, &r);
282 eglGetConfigAttrib(display, config, EGL_GREEN_SIZE, &g);
283 eglGetConfigAttrib(display, config, EGL_BLUE_SIZE, &b);
284 eglGetConfigAttrib(display, config, EGL_ALPHA_SIZE, &a);
285 ALOGI("EGL information:");
286 ALOGI("vendor : %s", eglQueryString(display, EGL_VENDOR));
287 ALOGI("version : %s", eglQueryString(display, EGL_VERSION));
288 ALOGI("extensions: %s", eglQueryString(display, EGL_EXTENSIONS));
289 ALOGI("Client API: %s", eglQueryString(display, EGL_CLIENT_APIS) ?: "Not Supported");
290 ALOGI("EGLSurface: %d-%d-%d-%d, config=%p", r, g, b, a, config);
291 }
292
293 return config;
294}
295
Lucas Dupinf4cb4a02020-09-22 14:19:26 -0700296SkiaGLRenderEngine::SkiaGLRenderEngine(const RenderEngineCreationArgs& args, EGLDisplay display,
297 EGLConfig config, EGLContext ctxt, EGLSurface placeholder,
298 EGLContext protectedContext, EGLSurface protectedPlaceholder)
Alec Mouri081be4c2020-09-16 10:24:47 -0700299 : mEGLDisplay(display),
John Reck67b1e2b2020-08-26 13:17:24 -0700300 mEGLConfig(config),
301 mEGLContext(ctxt),
302 mPlaceholderSurface(placeholder),
303 mProtectedEGLContext(protectedContext),
Alec Mourib5777452020-09-28 11:32:42 -0700304 mProtectedPlaceholderSurface(protectedPlaceholder),
305 mUseColorManagement(args.useColorManagement) {
John Reck67b1e2b2020-08-26 13:17:24 -0700306 // Suppress unused field warnings for things we definitely will need/use
307 // These EGL fields will all be needed for toggling between protected & unprotected contexts
308 // Or we need different RE instances for that
309 (void)mEGLDisplay;
310 (void)mEGLConfig;
311 (void)mEGLContext;
312 (void)mPlaceholderSurface;
313 (void)mProtectedEGLContext;
314 (void)mProtectedPlaceholderSurface;
315
316 sk_sp<const GrGLInterface> glInterface(GrGLCreateNativeInterface());
317 LOG_ALWAYS_FATAL_IF(!glInterface.get());
318
319 GrContextOptions options;
320 options.fPreferExternalImagesOverES3 = true;
321 options.fDisableDistanceFieldPaths = true;
322 mGrContext = GrDirectContext::MakeGL(std::move(glInterface), options);
Lucas Dupinf4cb4a02020-09-22 14:19:26 -0700323
324 if (args.supportsBackgroundBlur) {
325 mBlurFilter = new BlurFilter();
326 }
John Reck67b1e2b2020-08-26 13:17:24 -0700327}
328
329base::unique_fd SkiaGLRenderEngine::flush() {
330 ATRACE_CALL();
331 if (!gl::GLExtensions::getInstance().hasNativeFenceSync()) {
332 return base::unique_fd();
333 }
334
335 EGLSyncKHR sync = eglCreateSyncKHR(mEGLDisplay, EGL_SYNC_NATIVE_FENCE_ANDROID, nullptr);
336 if (sync == EGL_NO_SYNC_KHR) {
337 ALOGW("failed to create EGL native fence sync: %#x", eglGetError());
338 return base::unique_fd();
339 }
340
341 // native fence fd will not be populated until flush() is done.
342 glFlush();
343
344 // get the fence fd
345 base::unique_fd fenceFd(eglDupNativeFenceFDANDROID(mEGLDisplay, sync));
346 eglDestroySyncKHR(mEGLDisplay, sync);
347 if (fenceFd == EGL_NO_NATIVE_FENCE_FD_ANDROID) {
348 ALOGW("failed to dup EGL native fence sync: %#x", eglGetError());
349 }
350
351 return fenceFd;
352}
353
354bool SkiaGLRenderEngine::waitFence(base::unique_fd fenceFd) {
355 if (!gl::GLExtensions::getInstance().hasNativeFenceSync() ||
356 !gl::GLExtensions::getInstance().hasWaitSync()) {
357 return false;
358 }
359
360 // release the fd and transfer the ownership to EGLSync
361 EGLint attribs[] = {EGL_SYNC_NATIVE_FENCE_FD_ANDROID, fenceFd.release(), EGL_NONE};
362 EGLSyncKHR sync = eglCreateSyncKHR(mEGLDisplay, EGL_SYNC_NATIVE_FENCE_ANDROID, attribs);
363 if (sync == EGL_NO_SYNC_KHR) {
364 ALOGE("failed to create EGL native fence sync: %#x", eglGetError());
365 return false;
366 }
367
368 // XXX: The spec draft is inconsistent as to whether this should return an
369 // EGLint or void. Ignore the return value for now, as it's not strictly
370 // needed.
371 eglWaitSyncKHR(mEGLDisplay, sync, 0);
372 EGLint error = eglGetError();
373 eglDestroySyncKHR(mEGLDisplay, sync);
374 if (error != EGL_SUCCESS) {
375 ALOGE("failed to wait for EGL native fence sync: %#x", error);
376 return false;
377 }
378
379 return true;
380}
381
382static bool hasUsage(const AHardwareBuffer_Desc& desc, uint64_t usage) {
383 return !!(desc.usage & usage);
384}
385
Alec Mouri678245d2020-09-30 16:58:23 -0700386static float toDegrees(uint32_t transform) {
387 switch (transform) {
388 case ui::Transform::ROT_90:
389 return 90.0;
390 case ui::Transform::ROT_180:
391 return 180.0;
392 case ui::Transform::ROT_270:
393 return 270.0;
394 default:
395 return 0.0;
396 }
397}
398
Alec Mourib34f0b72020-10-02 13:18:34 -0700399static SkColorMatrix toSkColorMatrix(const mat4& matrix) {
400 return SkColorMatrix(matrix[0][0], matrix[1][0], matrix[2][0], matrix[3][0], 0, matrix[0][1],
401 matrix[1][1], matrix[2][1], matrix[3][1], 0, matrix[0][2], matrix[1][2],
402 matrix[2][2], matrix[3][2], 0, matrix[0][3], matrix[1][3], matrix[2][3],
403 matrix[3][3], 0);
404}
405
John Reck67b1e2b2020-08-26 13:17:24 -0700406void SkiaGLRenderEngine::unbindExternalTextureBuffer(uint64_t bufferId) {
407 std::lock_guard<std::mutex> lock(mRenderingMutex);
408 mImageCache.erase(bufferId);
409}
410
411status_t SkiaGLRenderEngine::drawLayers(const DisplaySettings& display,
412 const std::vector<const LayerSettings*>& layers,
413 const sp<GraphicBuffer>& buffer,
414 const bool useFramebufferCache,
415 base::unique_fd&& bufferFence, base::unique_fd* drawFence) {
416 ATRACE_NAME("SkiaGL::drawLayers");
417 std::lock_guard<std::mutex> lock(mRenderingMutex);
418 if (layers.empty()) {
419 ALOGV("Drawing empty layer stack");
420 return NO_ERROR;
421 }
422
423 if (bufferFence.get() >= 0) {
424 // Duplicate the fence for passing to waitFence.
425 base::unique_fd bufferFenceDup(dup(bufferFence.get()));
426 if (bufferFenceDup < 0 || !waitFence(std::move(bufferFenceDup))) {
427 ATRACE_NAME("Waiting before draw");
428 sync_wait(bufferFence.get(), -1);
429 }
430 }
431 if (buffer == nullptr) {
432 ALOGE("No output buffer provided. Aborting GPU composition.");
433 return BAD_VALUE;
434 }
435
436 AHardwareBuffer_Desc bufferDesc;
437 AHardwareBuffer_describe(buffer->toAHardwareBuffer(), &bufferDesc);
438
439 LOG_ALWAYS_FATAL_IF(!hasUsage(bufferDesc, AHARDWAREBUFFER_USAGE_GPU_SAMPLED_IMAGE),
440 "missing usage");
441
442 sk_sp<SkSurface> surface;
443 if (useFramebufferCache) {
444 auto iter = mSurfaceCache.find(buffer->getId());
445 if (iter != mSurfaceCache.end()) {
446 ALOGV("Cache hit!");
447 surface = iter->second;
448 }
449 }
450 if (!surface) {
451 surface = SkSurface::MakeFromAHardwareBuffer(mGrContext.get(), buffer->toAHardwareBuffer(),
452 GrSurfaceOrigin::kTopLeft_GrSurfaceOrigin,
Alec Mourib5777452020-09-28 11:32:42 -0700453 mUseColorManagement
454 ? toColorSpace(display.outputDataspace)
455 : SkColorSpace::MakeSRGB(),
456 nullptr);
John Reck67b1e2b2020-08-26 13:17:24 -0700457 if (useFramebufferCache && surface) {
458 ALOGD("Adding to cache");
459 mSurfaceCache.insert({buffer->getId(), surface});
460 }
461 }
462 if (!surface) {
463 ALOGE("Failed to make surface");
464 return BAD_VALUE;
465 }
Alec Mouri678245d2020-09-30 16:58:23 -0700466
John Reck67b1e2b2020-08-26 13:17:24 -0700467 auto canvas = surface->getCanvas();
Alec Mouri678245d2020-09-30 16:58:23 -0700468 // Clear the entire canvas with a transparent black to prevent ghost images.
469 canvas->clear(SK_ColorTRANSPARENT);
Lucas Dupinbb1a1d42020-09-18 15:17:02 -0700470 canvas->save();
John Reck67b1e2b2020-08-26 13:17:24 -0700471
Lucas Dupinbb1a1d42020-09-18 15:17:02 -0700472 // Before doing any drawing, let's make sure that we'll start at the origin of the display.
473 // Some displays don't start at 0,0 for example when we're mirroring the screen. Also, virtual
474 // displays might have different scaling when compared to the physical screen.
Alec Mouri678245d2020-09-30 16:58:23 -0700475
476 canvas->clipRect(getSkRect(display.physicalDisplay));
Lucas Dupinbb1a1d42020-09-18 15:17:02 -0700477 canvas->translate(display.physicalDisplay.left, display.physicalDisplay.top);
Alec Mouri678245d2020-09-30 16:58:23 -0700478
479 const auto clipWidth = display.clip.width();
480 const auto clipHeight = display.clip.height();
481 auto rotatedClipWidth = clipWidth;
482 auto rotatedClipHeight = clipHeight;
483 // Scale is contingent on the rotation result.
484 if (display.orientation & ui::Transform::ROT_90) {
485 std::swap(rotatedClipWidth, rotatedClipHeight);
486 }
Lucas Dupinbb1a1d42020-09-18 15:17:02 -0700487 const auto scaleX = static_cast<SkScalar>(display.physicalDisplay.width()) /
Alec Mouri678245d2020-09-30 16:58:23 -0700488 static_cast<SkScalar>(rotatedClipWidth);
Lucas Dupinbb1a1d42020-09-18 15:17:02 -0700489 const auto scaleY = static_cast<SkScalar>(display.physicalDisplay.height()) /
Alec Mouri678245d2020-09-30 16:58:23 -0700490 static_cast<SkScalar>(rotatedClipHeight);
Lucas Dupinbb1a1d42020-09-18 15:17:02 -0700491 canvas->scale(scaleX, scaleY);
Alec Mouri678245d2020-09-30 16:58:23 -0700492
493 // Canvas rotation is done by centering the clip window at the origin, rotating, translating
494 // back so that the top left corner of the clip is at (0, 0).
495 canvas->translate(rotatedClipWidth / 2, rotatedClipHeight / 2);
496 canvas->rotate(toDegrees(display.orientation));
497 canvas->translate(-clipWidth / 2, -clipHeight / 2);
498 canvas->translate(-display.clip.left, -display.clip.top);
John Reck67b1e2b2020-08-26 13:17:24 -0700499 for (const auto& layer : layers) {
Lucas Dupin21f348e2020-09-16 17:31:26 -0700500 SkPaint paint;
501 const auto& bounds = layer->geometry.boundaries;
Lucas Dupin3f11e922020-09-22 17:31:04 -0700502 const auto dest = getSkRect(bounds);
Lucas Dupin21f348e2020-09-16 17:31:26 -0700503
Lucas Dupinf4cb4a02020-09-22 14:19:26 -0700504 if (layer->backgroundBlurRadius > 0) {
505 ATRACE_NAME("BackgroundBlur");
506 mBlurFilter->draw(canvas, surface, layer->backgroundBlurRadius);
507 }
508
John Reck67b1e2b2020-08-26 13:17:24 -0700509 if (layer->source.buffer.buffer) {
510 ATRACE_NAME("DrawImage");
511 const auto& item = layer->source.buffer;
Alec Mouri678245d2020-09-30 16:58:23 -0700512 const auto bufferWidth = item.buffer->getBounds().width();
513 const auto bufferHeight = item.buffer->getBounds().height();
John Reck67b1e2b2020-08-26 13:17:24 -0700514 sk_sp<SkImage> image;
515 auto iter = mImageCache.find(item.buffer->getId());
516 if (iter != mImageCache.end()) {
517 image = iter->second;
518 } else {
519 image = SkImage::MakeFromAHardwareBuffer(item.buffer->toAHardwareBuffer(),
520 item.usePremultipliedAlpha
521 ? kPremul_SkAlphaType
Alec Mourib5777452020-09-28 11:32:42 -0700522 : kUnpremul_SkAlphaType,
523 mUseColorManagement
524 ? toColorSpace(
525 layer->sourceDataspace)
526 : SkColorSpace::MakeSRGB());
John Reck67b1e2b2020-08-26 13:17:24 -0700527 mImageCache.insert({item.buffer->getId(), image});
528 }
Lucas Dupin21f348e2020-09-16 17:31:26 -0700529
530 SkMatrix matrix;
531 if (layer->geometry.roundedCornersRadius > 0) {
532 const auto roundedRect = getRoundedRect(layer);
533 matrix.setTranslate(roundedRect.getBounds().left() - dest.left(),
534 roundedRect.getBounds().top() - dest.top());
535 } else {
536 matrix.setIdentity();
537 }
Alec Mouri678245d2020-09-30 16:58:23 -0700538
539 auto texMatrix = getSkM44(item.textureTransform).asM33();
540 // textureTansform was intended to be passed directly into a shader, so when
541 // building the total matrix with the textureTransform we need to first
542 // normalize it, then apply the textureTransform, then scale back up.
543 matrix.postScale(1.0f / bufferWidth, 1.0f / bufferHeight);
544
545 auto rotatedBufferWidth = bufferWidth;
546 auto rotatedBufferHeight = bufferHeight;
547
548 // Swap the buffer width and height if we're rotating, so that we
549 // scale back up by the correct factors post-rotation.
550 if (texMatrix.getSkewX() <= -0.5f || texMatrix.getSkewX() >= 0.5f) {
551 std::swap(rotatedBufferWidth, rotatedBufferHeight);
552 // TODO: clean this up.
553 // GLESRenderEngine specifies its texture coordinates in
554 // CW orientation under OpenGL conventions, when they probably should have
555 // been CCW instead. The net result is that orientation
556 // transforms are applied in the reverse
557 // direction to render the correct result, because SurfaceFlinger uses the inverse
558 // of the display transform to correct for that. But this means that
559 // the tex transform passed by SkiaGLRenderEngine will rotate
560 // individual layers in the reverse orientation. Hack around it
561 // by injected a 180 degree rotation, but ultimately this is
562 // a bug in how SurfaceFlinger invokes the RenderEngine
563 // interface, so the proper fix should live there, and GLESRenderEngine
564 // should be fixed accordingly.
565 matrix.postRotate(180, 0.5, 0.5);
566 }
567
568 matrix.postConcat(texMatrix);
569 matrix.postScale(rotatedBufferWidth, rotatedBufferHeight);
Lucas Dupin21f348e2020-09-16 17:31:26 -0700570 paint.setShader(image->makeShader(matrix));
John Reck67b1e2b2020-08-26 13:17:24 -0700571 } else {
572 ATRACE_NAME("DrawColor");
John Reck67b1e2b2020-08-26 13:17:24 -0700573 const auto color = layer->source.solidColor;
574 paint.setColor(SkColor4f{.fR = color.r, .fG = color.g, .fB = color.b, layer->alpha});
575 }
Lucas Dupin21f348e2020-09-16 17:31:26 -0700576
Alec Mourib34f0b72020-10-02 13:18:34 -0700577 paint.setColorFilter(SkColorFilters::Matrix(toSkColorMatrix(display.colorTransform)));
578
Lucas Dupinbb1a1d42020-09-18 15:17:02 -0700579 // Layers have a local transform matrix that should be applied to them.
580 canvas->save();
581 canvas->concat(getSkM44(layer->geometry.positionTransform));
582
Lucas Dupin3f11e922020-09-22 17:31:04 -0700583 if (layer->shadow.length > 0) {
584 const auto rect = layer->geometry.roundedCornersRadius > 0
585 ? getSkRect(layer->geometry.roundedCornersCrop)
586 : dest;
587 drawShadow(canvas, rect, layer->geometry.roundedCornersRadius, layer->shadow);
588 }
589
Lucas Dupin21f348e2020-09-16 17:31:26 -0700590 if (layer->geometry.roundedCornersRadius > 0) {
591 canvas->drawRRect(getRoundedRect(layer), paint);
592 } else {
593 canvas->drawRect(dest, paint);
594 }
Lucas Dupinbb1a1d42020-09-18 15:17:02 -0700595 canvas->restore();
John Reck67b1e2b2020-08-26 13:17:24 -0700596 }
597 {
598 ATRACE_NAME("flush surface");
599 surface->flush();
600 }
Lucas Dupinbb1a1d42020-09-18 15:17:02 -0700601 canvas->restore();
John Reck67b1e2b2020-08-26 13:17:24 -0700602
603 if (drawFence != nullptr) {
604 *drawFence = flush();
605 }
606
607 // If flush failed or we don't support native fences, we need to force the
608 // gl command stream to be executed.
609 bool requireSync = drawFence == nullptr || drawFence->get() < 0;
610 if (requireSync) {
611 ATRACE_BEGIN("Submit(sync=true)");
612 } else {
613 ATRACE_BEGIN("Submit(sync=false)");
614 }
615 bool success = mGrContext->submit(requireSync);
616 ATRACE_END();
617 if (!success) {
618 ALOGE("Failed to flush RenderEngine commands");
619 // Chances are, something illegal happened (either the caller passed
620 // us bad parameters, or we messed up our shader generation).
621 return INVALID_OPERATION;
622 }
623
624 // checkErrors();
625 return NO_ERROR;
626}
627
Lucas Dupin3f11e922020-09-22 17:31:04 -0700628inline SkRect SkiaGLRenderEngine::getSkRect(const FloatRect& rect) {
629 return SkRect::MakeLTRB(rect.left, rect.top, rect.right, rect.bottom);
630}
631
632inline SkRect SkiaGLRenderEngine::getSkRect(const Rect& rect) {
633 return SkRect::MakeLTRB(rect.left, rect.top, rect.right, rect.bottom);
634}
635
Lucas Dupin21f348e2020-09-16 17:31:26 -0700636inline SkRRect SkiaGLRenderEngine::getRoundedRect(const LayerSettings* layer) {
Lucas Dupin3f11e922020-09-22 17:31:04 -0700637 const auto rect = getSkRect(layer->geometry.roundedCornersCrop);
Lucas Dupin21f348e2020-09-16 17:31:26 -0700638 const auto cornerRadius = layer->geometry.roundedCornersRadius;
639 return SkRRect::MakeRectXY(rect, cornerRadius, cornerRadius);
640}
641
Lucas Dupin3f11e922020-09-22 17:31:04 -0700642inline SkColor SkiaGLRenderEngine::getSkColor(const vec4& color) {
643 return SkColorSetARGB(color.a * 255, color.r * 255, color.g * 255, color.b * 255);
644}
645
Lucas Dupinbb1a1d42020-09-18 15:17:02 -0700646inline SkM44 SkiaGLRenderEngine::getSkM44(const mat4& matrix) {
647 return SkM44(matrix[0][0], matrix[1][0], matrix[2][0], matrix[3][0],
648 matrix[0][1], matrix[1][1], matrix[2][1], matrix[3][1],
649 matrix[0][2], matrix[1][2], matrix[2][2], matrix[3][2],
650 matrix[0][3], matrix[1][3], matrix[2][3], matrix[3][3]);
651}
652
Lucas Dupin3f11e922020-09-22 17:31:04 -0700653inline SkPoint3 SkiaGLRenderEngine::getSkPoint3(const vec3& vector) {
654 return SkPoint3::Make(vector.x, vector.y, vector.z);
655}
656
John Reck67b1e2b2020-08-26 13:17:24 -0700657size_t SkiaGLRenderEngine::getMaxTextureSize() const {
658 return mGrContext->maxTextureSize();
659}
660
661size_t SkiaGLRenderEngine::getMaxViewportDims() const {
662 return mGrContext->maxRenderTargetSize();
663}
664
Lucas Dupin3f11e922020-09-22 17:31:04 -0700665void SkiaGLRenderEngine::drawShadow(SkCanvas* canvas, const SkRect& casterRect, float cornerRadius,
666 const ShadowSettings& settings) {
667 ATRACE_CALL();
668 const float casterZ = settings.length / 2.0f;
669 const auto shadowShape = cornerRadius > 0
670 ? SkPath::RRect(SkRRect::MakeRectXY(casterRect, cornerRadius, cornerRadius))
671 : SkPath::Rect(casterRect);
672 const auto flags =
673 settings.casterIsTranslucent ? kTransparentOccluder_ShadowFlag : kNone_ShadowFlag;
674
675 SkShadowUtils::DrawShadow(canvas, shadowShape, SkPoint3::Make(0, 0, casterZ),
676 getSkPoint3(settings.lightPos), settings.lightRadius,
677 getSkColor(settings.ambientColor), getSkColor(settings.spotColor),
678 flags);
679}
680
John Reck67b1e2b2020-08-26 13:17:24 -0700681EGLContext SkiaGLRenderEngine::createEglContext(EGLDisplay display, EGLConfig config,
682 EGLContext shareContext, bool useContextPriority,
683 Protection protection) {
684 EGLint renderableType = 0;
685 if (config == EGL_NO_CONFIG_KHR) {
686 renderableType = EGL_OPENGL_ES3_BIT;
687 } else if (!eglGetConfigAttrib(display, config, EGL_RENDERABLE_TYPE, &renderableType)) {
688 LOG_ALWAYS_FATAL("can't query EGLConfig RENDERABLE_TYPE");
689 }
690 EGLint contextClientVersion = 0;
691 if (renderableType & EGL_OPENGL_ES3_BIT) {
692 contextClientVersion = 3;
693 } else if (renderableType & EGL_OPENGL_ES2_BIT) {
694 contextClientVersion = 2;
695 } else if (renderableType & EGL_OPENGL_ES_BIT) {
696 contextClientVersion = 1;
697 } else {
698 LOG_ALWAYS_FATAL("no supported EGL_RENDERABLE_TYPEs");
699 }
700
701 std::vector<EGLint> contextAttributes;
702 contextAttributes.reserve(7);
703 contextAttributes.push_back(EGL_CONTEXT_CLIENT_VERSION);
704 contextAttributes.push_back(contextClientVersion);
705 if (useContextPriority) {
706 contextAttributes.push_back(EGL_CONTEXT_PRIORITY_LEVEL_IMG);
707 contextAttributes.push_back(EGL_CONTEXT_PRIORITY_HIGH_IMG);
708 }
709 if (protection == Protection::PROTECTED) {
710 contextAttributes.push_back(EGL_PROTECTED_CONTENT_EXT);
711 contextAttributes.push_back(EGL_TRUE);
712 }
713 contextAttributes.push_back(EGL_NONE);
714
715 EGLContext context = eglCreateContext(display, config, shareContext, contextAttributes.data());
716
717 if (contextClientVersion == 3 && context == EGL_NO_CONTEXT) {
718 // eglGetConfigAttrib indicated we can create GLES 3 context, but we failed, thus
719 // EGL_NO_CONTEXT so that we can abort.
720 if (config != EGL_NO_CONFIG_KHR) {
721 return context;
722 }
723 // If |config| is EGL_NO_CONFIG_KHR, we speculatively try to create GLES 3 context, so we
724 // should try to fall back to GLES 2.
725 contextAttributes[1] = 2;
726 context = eglCreateContext(display, config, shareContext, contextAttributes.data());
727 }
728
729 return context;
730}
731
732EGLSurface SkiaGLRenderEngine::createPlaceholderEglPbufferSurface(EGLDisplay display,
733 EGLConfig config, int hwcFormat,
734 Protection protection) {
735 EGLConfig placeholderConfig = config;
736 if (placeholderConfig == EGL_NO_CONFIG_KHR) {
737 placeholderConfig = chooseEglConfig(display, hwcFormat, /*logConfig*/ true);
738 }
739 std::vector<EGLint> attributes;
740 attributes.reserve(7);
741 attributes.push_back(EGL_WIDTH);
742 attributes.push_back(1);
743 attributes.push_back(EGL_HEIGHT);
744 attributes.push_back(1);
745 if (protection == Protection::PROTECTED) {
746 attributes.push_back(EGL_PROTECTED_CONTENT_EXT);
747 attributes.push_back(EGL_TRUE);
748 }
749 attributes.push_back(EGL_NONE);
750
751 return eglCreatePbufferSurface(display, placeholderConfig, attributes.data());
752}
753
754void SkiaGLRenderEngine::cleanFramebufferCache() {
755 mSurfaceCache.clear();
756}
757
758} // namespace skia
759} // namespace renderengine
760} // namespace android