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