blob: 0fed08b61f9d809c0fb698c13f3365bc4ab9d531 [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
18#undef LOG_TAG
19#define LOG_TAG "RenderEngine"
20#define ATRACE_TAG ATRACE_TAG_GRAPHICS
21
22#include <cmath>
23
24#include <EGL/egl.h>
25#include <EGL/eglext.h>
26#include <GLES2/gl2.h>
27#include <sync/sync.h>
28#include <ui/GraphicBuffer.h>
29#include <utils/Trace.h>
30#include "../gl/GLExtensions.h"
31#include "SkiaGLRenderEngine.h"
Lucas Dupinf4cb4a02020-09-22 14:19:26 -070032#include "filters/BlurFilter.h"
John Reck67b1e2b2020-08-26 13:17:24 -070033
34#include <GrContextOptions.h>
35#include <gl/GrGLInterface.h>
36
37#include <SkCanvas.h>
38#include <SkImage.h>
Lucas Dupinf4cb4a02020-09-22 14:19:26 -070039#include <SkImageFilters.h>
Lucas Dupin3f11e922020-09-22 17:31:04 -070040#include <SkShadowUtils.h>
John Reck67b1e2b2020-08-26 13:17:24 -070041#include <SkSurface.h>
42
43extern "C" EGLAPI const char* eglQueryStringImplementationANDROID(EGLDisplay dpy, EGLint name);
44
45bool checkGlError(const char* op, int lineNumber);
46
47namespace android {
48namespace renderengine {
49namespace skia {
50
51static status_t selectConfigForAttribute(EGLDisplay dpy, EGLint const* attrs, EGLint attribute,
52 EGLint wanted, EGLConfig* outConfig) {
53 EGLint numConfigs = -1, n = 0;
54 eglGetConfigs(dpy, nullptr, 0, &numConfigs);
55 std::vector<EGLConfig> configs(numConfigs, EGL_NO_CONFIG_KHR);
56 eglChooseConfig(dpy, attrs, configs.data(), configs.size(), &n);
57 configs.resize(n);
58
59 if (!configs.empty()) {
60 if (attribute != EGL_NONE) {
61 for (EGLConfig config : configs) {
62 EGLint value = 0;
63 eglGetConfigAttrib(dpy, config, attribute, &value);
64 if (wanted == value) {
65 *outConfig = config;
66 return NO_ERROR;
67 }
68 }
69 } else {
70 // just pick the first one
71 *outConfig = configs[0];
72 return NO_ERROR;
73 }
74 }
75
76 return NAME_NOT_FOUND;
77}
78
79static status_t selectEGLConfig(EGLDisplay display, EGLint format, EGLint renderableType,
80 EGLConfig* config) {
81 // select our EGLConfig. It must support EGL_RECORDABLE_ANDROID if
82 // it is to be used with WIFI displays
83 status_t err;
84 EGLint wantedAttribute;
85 EGLint wantedAttributeValue;
86
87 std::vector<EGLint> attribs;
88 if (renderableType) {
89 const ui::PixelFormat pixelFormat = static_cast<ui::PixelFormat>(format);
90 const bool is1010102 = pixelFormat == ui::PixelFormat::RGBA_1010102;
91
92 // Default to 8 bits per channel.
93 const EGLint tmpAttribs[] = {
94 EGL_RENDERABLE_TYPE,
95 renderableType,
96 EGL_RECORDABLE_ANDROID,
97 EGL_TRUE,
98 EGL_SURFACE_TYPE,
99 EGL_WINDOW_BIT | EGL_PBUFFER_BIT,
100 EGL_FRAMEBUFFER_TARGET_ANDROID,
101 EGL_TRUE,
102 EGL_RED_SIZE,
103 is1010102 ? 10 : 8,
104 EGL_GREEN_SIZE,
105 is1010102 ? 10 : 8,
106 EGL_BLUE_SIZE,
107 is1010102 ? 10 : 8,
108 EGL_ALPHA_SIZE,
109 is1010102 ? 2 : 8,
110 EGL_NONE,
111 };
112 std::copy(tmpAttribs, tmpAttribs + (sizeof(tmpAttribs) / sizeof(EGLint)),
113 std::back_inserter(attribs));
114 wantedAttribute = EGL_NONE;
115 wantedAttributeValue = EGL_NONE;
116 } else {
117 // if no renderable type specified, fallback to a simplified query
118 wantedAttribute = EGL_NATIVE_VISUAL_ID;
119 wantedAttributeValue = format;
120 }
121
122 err = selectConfigForAttribute(display, attribs.data(), wantedAttribute, wantedAttributeValue,
123 config);
124 if (err == NO_ERROR) {
125 EGLint caveat;
126 if (eglGetConfigAttrib(display, *config, EGL_CONFIG_CAVEAT, &caveat))
127 ALOGW_IF(caveat == EGL_SLOW_CONFIG, "EGL_SLOW_CONFIG selected!");
128 }
129
130 return err;
131}
132
133std::unique_ptr<SkiaGLRenderEngine> SkiaGLRenderEngine::create(
134 const RenderEngineCreationArgs& args) {
135 // initialize EGL for the default display
136 EGLDisplay display = eglGetDisplay(EGL_DEFAULT_DISPLAY);
137 if (!eglInitialize(display, nullptr, nullptr)) {
138 LOG_ALWAYS_FATAL("failed to initialize EGL");
139 }
140
141 const auto eglVersion = eglQueryStringImplementationANDROID(display, EGL_VERSION);
142 if (!eglVersion) {
143 checkGlError(__FUNCTION__, __LINE__);
144 LOG_ALWAYS_FATAL("eglQueryStringImplementationANDROID(EGL_VERSION) failed");
145 }
146
147 const auto eglExtensions = eglQueryStringImplementationANDROID(display, EGL_EXTENSIONS);
148 if (!eglExtensions) {
149 checkGlError(__FUNCTION__, __LINE__);
150 LOG_ALWAYS_FATAL("eglQueryStringImplementationANDROID(EGL_EXTENSIONS) failed");
151 }
152
153 auto& extensions = gl::GLExtensions::getInstance();
154 extensions.initWithEGLStrings(eglVersion, eglExtensions);
155
156 // The code assumes that ES2 or later is available if this extension is
157 // supported.
158 EGLConfig config = EGL_NO_CONFIG_KHR;
159 if (!extensions.hasNoConfigContext()) {
160 config = chooseEglConfig(display, args.pixelFormat, /*logConfig*/ true);
161 }
162
163 bool useContextPriority =
164 extensions.hasContextPriority() && args.contextPriority == ContextPriority::HIGH;
165 EGLContext protectedContext = EGL_NO_CONTEXT;
166 if (args.enableProtectedContext && extensions.hasProtectedContent()) {
167 protectedContext = createEglContext(display, config, nullptr, useContextPriority,
168 Protection::PROTECTED);
169 ALOGE_IF(protectedContext == EGL_NO_CONTEXT, "Can't create protected context");
170 }
171
172 EGLContext ctxt = createEglContext(display, config, protectedContext, useContextPriority,
173 Protection::UNPROTECTED);
174
175 // if can't create a GL context, we can only abort.
176 LOG_ALWAYS_FATAL_IF(ctxt == EGL_NO_CONTEXT, "EGLContext creation failed");
177
178 EGLSurface placeholder = EGL_NO_SURFACE;
179 if (!extensions.hasSurfacelessContext()) {
180 placeholder = createPlaceholderEglPbufferSurface(display, config, args.pixelFormat,
181 Protection::UNPROTECTED);
182 LOG_ALWAYS_FATAL_IF(placeholder == EGL_NO_SURFACE, "can't create placeholder pbuffer");
183 }
184 EGLBoolean success = eglMakeCurrent(display, placeholder, placeholder, ctxt);
185 LOG_ALWAYS_FATAL_IF(!success, "can't make placeholder pbuffer current");
186 extensions.initWithGLStrings(glGetString(GL_VENDOR), glGetString(GL_RENDERER),
187 glGetString(GL_VERSION), glGetString(GL_EXTENSIONS));
188
189 EGLSurface protectedPlaceholder = EGL_NO_SURFACE;
190 if (protectedContext != EGL_NO_CONTEXT && !extensions.hasSurfacelessContext()) {
191 protectedPlaceholder = createPlaceholderEglPbufferSurface(display, config, args.pixelFormat,
192 Protection::PROTECTED);
193 ALOGE_IF(protectedPlaceholder == EGL_NO_SURFACE,
194 "can't create protected placeholder pbuffer");
195 }
196
197 // initialize the renderer while GL is current
198 std::unique_ptr<SkiaGLRenderEngine> engine =
Lucas Dupinf4cb4a02020-09-22 14:19:26 -0700199 std::make_unique<SkiaGLRenderEngine>(args, display, config, ctxt, placeholder,
John Reck67b1e2b2020-08-26 13:17:24 -0700200 protectedContext, protectedPlaceholder);
201
202 ALOGI("OpenGL ES informations:");
203 ALOGI("vendor : %s", extensions.getVendor());
204 ALOGI("renderer : %s", extensions.getRenderer());
205 ALOGI("version : %s", extensions.getVersion());
206 ALOGI("extensions: %s", extensions.getExtensions());
207 ALOGI("GL_MAX_TEXTURE_SIZE = %zu", engine->getMaxTextureSize());
208 ALOGI("GL_MAX_VIEWPORT_DIMS = %zu", engine->getMaxViewportDims());
209
210 return engine;
211}
212
213EGLConfig SkiaGLRenderEngine::chooseEglConfig(EGLDisplay display, int format, bool logConfig) {
214 status_t err;
215 EGLConfig config;
216
217 // First try to get an ES3 config
218 err = selectEGLConfig(display, format, EGL_OPENGL_ES3_BIT, &config);
219 if (err != NO_ERROR) {
220 // If ES3 fails, try to get an ES2 config
221 err = selectEGLConfig(display, format, EGL_OPENGL_ES2_BIT, &config);
222 if (err != NO_ERROR) {
223 // If ES2 still doesn't work, probably because we're on the emulator.
224 // try a simplified query
225 ALOGW("no suitable EGLConfig found, trying a simpler query");
226 err = selectEGLConfig(display, format, 0, &config);
227 if (err != NO_ERROR) {
228 // this EGL is too lame for android
229 LOG_ALWAYS_FATAL("no suitable EGLConfig found, giving up");
230 }
231 }
232 }
233
234 if (logConfig) {
235 // print some debugging info
236 EGLint r, g, b, a;
237 eglGetConfigAttrib(display, config, EGL_RED_SIZE, &r);
238 eglGetConfigAttrib(display, config, EGL_GREEN_SIZE, &g);
239 eglGetConfigAttrib(display, config, EGL_BLUE_SIZE, &b);
240 eglGetConfigAttrib(display, config, EGL_ALPHA_SIZE, &a);
241 ALOGI("EGL information:");
242 ALOGI("vendor : %s", eglQueryString(display, EGL_VENDOR));
243 ALOGI("version : %s", eglQueryString(display, EGL_VERSION));
244 ALOGI("extensions: %s", eglQueryString(display, EGL_EXTENSIONS));
245 ALOGI("Client API: %s", eglQueryString(display, EGL_CLIENT_APIS) ?: "Not Supported");
246 ALOGI("EGLSurface: %d-%d-%d-%d, config=%p", r, g, b, a, config);
247 }
248
249 return config;
250}
251
Lucas Dupinf4cb4a02020-09-22 14:19:26 -0700252SkiaGLRenderEngine::SkiaGLRenderEngine(const RenderEngineCreationArgs& args, EGLDisplay display,
253 EGLConfig config, EGLContext ctxt, EGLSurface placeholder,
254 EGLContext protectedContext, EGLSurface protectedPlaceholder)
Alec Mouri081be4c2020-09-16 10:24:47 -0700255 : mEGLDisplay(display),
John Reck67b1e2b2020-08-26 13:17:24 -0700256 mEGLConfig(config),
257 mEGLContext(ctxt),
258 mPlaceholderSurface(placeholder),
259 mProtectedEGLContext(protectedContext),
260 mProtectedPlaceholderSurface(protectedPlaceholder) {
261 // Suppress unused field warnings for things we definitely will need/use
262 // These EGL fields will all be needed for toggling between protected & unprotected contexts
263 // Or we need different RE instances for that
264 (void)mEGLDisplay;
265 (void)mEGLConfig;
266 (void)mEGLContext;
267 (void)mPlaceholderSurface;
268 (void)mProtectedEGLContext;
269 (void)mProtectedPlaceholderSurface;
270
271 sk_sp<const GrGLInterface> glInterface(GrGLCreateNativeInterface());
272 LOG_ALWAYS_FATAL_IF(!glInterface.get());
273
274 GrContextOptions options;
275 options.fPreferExternalImagesOverES3 = true;
276 options.fDisableDistanceFieldPaths = true;
277 mGrContext = GrDirectContext::MakeGL(std::move(glInterface), options);
Lucas Dupinf4cb4a02020-09-22 14:19:26 -0700278
279 if (args.supportsBackgroundBlur) {
280 mBlurFilter = new BlurFilter();
281 }
John Reck67b1e2b2020-08-26 13:17:24 -0700282}
283
284base::unique_fd SkiaGLRenderEngine::flush() {
285 ATRACE_CALL();
286 if (!gl::GLExtensions::getInstance().hasNativeFenceSync()) {
287 return base::unique_fd();
288 }
289
290 EGLSyncKHR sync = eglCreateSyncKHR(mEGLDisplay, EGL_SYNC_NATIVE_FENCE_ANDROID, nullptr);
291 if (sync == EGL_NO_SYNC_KHR) {
292 ALOGW("failed to create EGL native fence sync: %#x", eglGetError());
293 return base::unique_fd();
294 }
295
296 // native fence fd will not be populated until flush() is done.
297 glFlush();
298
299 // get the fence fd
300 base::unique_fd fenceFd(eglDupNativeFenceFDANDROID(mEGLDisplay, sync));
301 eglDestroySyncKHR(mEGLDisplay, sync);
302 if (fenceFd == EGL_NO_NATIVE_FENCE_FD_ANDROID) {
303 ALOGW("failed to dup EGL native fence sync: %#x", eglGetError());
304 }
305
306 return fenceFd;
307}
308
309bool SkiaGLRenderEngine::waitFence(base::unique_fd fenceFd) {
310 if (!gl::GLExtensions::getInstance().hasNativeFenceSync() ||
311 !gl::GLExtensions::getInstance().hasWaitSync()) {
312 return false;
313 }
314
315 // release the fd and transfer the ownership to EGLSync
316 EGLint attribs[] = {EGL_SYNC_NATIVE_FENCE_FD_ANDROID, fenceFd.release(), EGL_NONE};
317 EGLSyncKHR sync = eglCreateSyncKHR(mEGLDisplay, EGL_SYNC_NATIVE_FENCE_ANDROID, attribs);
318 if (sync == EGL_NO_SYNC_KHR) {
319 ALOGE("failed to create EGL native fence sync: %#x", eglGetError());
320 return false;
321 }
322
323 // XXX: The spec draft is inconsistent as to whether this should return an
324 // EGLint or void. Ignore the return value for now, as it's not strictly
325 // needed.
326 eglWaitSyncKHR(mEGLDisplay, sync, 0);
327 EGLint error = eglGetError();
328 eglDestroySyncKHR(mEGLDisplay, sync);
329 if (error != EGL_SUCCESS) {
330 ALOGE("failed to wait for EGL native fence sync: %#x", error);
331 return false;
332 }
333
334 return true;
335}
336
337static bool hasUsage(const AHardwareBuffer_Desc& desc, uint64_t usage) {
338 return !!(desc.usage & usage);
339}
340
341void SkiaGLRenderEngine::unbindExternalTextureBuffer(uint64_t bufferId) {
342 std::lock_guard<std::mutex> lock(mRenderingMutex);
343 mImageCache.erase(bufferId);
344}
345
346status_t SkiaGLRenderEngine::drawLayers(const DisplaySettings& display,
347 const std::vector<const LayerSettings*>& layers,
348 const sp<GraphicBuffer>& buffer,
349 const bool useFramebufferCache,
350 base::unique_fd&& bufferFence, base::unique_fd* drawFence) {
351 ATRACE_NAME("SkiaGL::drawLayers");
352 std::lock_guard<std::mutex> lock(mRenderingMutex);
353 if (layers.empty()) {
354 ALOGV("Drawing empty layer stack");
355 return NO_ERROR;
356 }
357
358 if (bufferFence.get() >= 0) {
359 // Duplicate the fence for passing to waitFence.
360 base::unique_fd bufferFenceDup(dup(bufferFence.get()));
361 if (bufferFenceDup < 0 || !waitFence(std::move(bufferFenceDup))) {
362 ATRACE_NAME("Waiting before draw");
363 sync_wait(bufferFence.get(), -1);
364 }
365 }
366 if (buffer == nullptr) {
367 ALOGE("No output buffer provided. Aborting GPU composition.");
368 return BAD_VALUE;
369 }
370
371 AHardwareBuffer_Desc bufferDesc;
372 AHardwareBuffer_describe(buffer->toAHardwareBuffer(), &bufferDesc);
373
374 LOG_ALWAYS_FATAL_IF(!hasUsage(bufferDesc, AHARDWAREBUFFER_USAGE_GPU_SAMPLED_IMAGE),
375 "missing usage");
376
377 sk_sp<SkSurface> surface;
378 if (useFramebufferCache) {
379 auto iter = mSurfaceCache.find(buffer->getId());
380 if (iter != mSurfaceCache.end()) {
381 ALOGV("Cache hit!");
382 surface = iter->second;
383 }
384 }
385 if (!surface) {
386 surface = SkSurface::MakeFromAHardwareBuffer(mGrContext.get(), buffer->toAHardwareBuffer(),
387 GrSurfaceOrigin::kTopLeft_GrSurfaceOrigin,
388 SkColorSpace::MakeSRGB(), nullptr);
389 if (useFramebufferCache && surface) {
390 ALOGD("Adding to cache");
391 mSurfaceCache.insert({buffer->getId(), surface});
392 }
393 }
394 if (!surface) {
395 ALOGE("Failed to make surface");
396 return BAD_VALUE;
397 }
398 auto canvas = surface->getCanvas();
Lucas Dupinbb1a1d42020-09-18 15:17:02 -0700399 canvas->save();
John Reck67b1e2b2020-08-26 13:17:24 -0700400
Lucas Dupinbb1a1d42020-09-18 15:17:02 -0700401 // Before doing any drawing, let's make sure that we'll start at the origin of the display.
402 // Some displays don't start at 0,0 for example when we're mirroring the screen. Also, virtual
403 // displays might have different scaling when compared to the physical screen.
404 canvas->translate(display.physicalDisplay.left, display.physicalDisplay.top);
405 const auto scaleX = static_cast<SkScalar>(display.physicalDisplay.width()) /
406 static_cast<SkScalar>(display.clip.width());
407 const auto scaleY = static_cast<SkScalar>(display.physicalDisplay.height()) /
408 static_cast<SkScalar>(display.clip.height());
409 canvas->scale(scaleX, scaleY);
Lucas Dupin3f11e922020-09-22 17:31:04 -0700410 canvas->clipRect(getSkRect(display.clip));
John Reck67b1e2b2020-08-26 13:17:24 -0700411 canvas->drawColor(0, SkBlendMode::kSrc);
412 for (const auto& layer : layers) {
Lucas Dupin21f348e2020-09-16 17:31:26 -0700413 SkPaint paint;
414 const auto& bounds = layer->geometry.boundaries;
Lucas Dupin3f11e922020-09-22 17:31:04 -0700415 const auto dest = getSkRect(bounds);
Lucas Dupin21f348e2020-09-16 17:31:26 -0700416
Lucas Dupinf4cb4a02020-09-22 14:19:26 -0700417 if (layer->backgroundBlurRadius > 0) {
418 ATRACE_NAME("BackgroundBlur");
419 mBlurFilter->draw(canvas, surface, layer->backgroundBlurRadius);
420 }
421
John Reck67b1e2b2020-08-26 13:17:24 -0700422 if (layer->source.buffer.buffer) {
423 ATRACE_NAME("DrawImage");
424 const auto& item = layer->source.buffer;
425 sk_sp<SkImage> image;
426 auto iter = mImageCache.find(item.buffer->getId());
427 if (iter != mImageCache.end()) {
428 image = iter->second;
429 } else {
430 image = SkImage::MakeFromAHardwareBuffer(item.buffer->toAHardwareBuffer(),
431 item.usePremultipliedAlpha
432 ? kPremul_SkAlphaType
433 : kUnpremul_SkAlphaType);
434 mImageCache.insert({item.buffer->getId(), image});
435 }
Lucas Dupin21f348e2020-09-16 17:31:26 -0700436
437 SkMatrix matrix;
438 if (layer->geometry.roundedCornersRadius > 0) {
439 const auto roundedRect = getRoundedRect(layer);
440 matrix.setTranslate(roundedRect.getBounds().left() - dest.left(),
441 roundedRect.getBounds().top() - dest.top());
442 } else {
443 matrix.setIdentity();
444 }
445 paint.setShader(image->makeShader(matrix));
John Reck67b1e2b2020-08-26 13:17:24 -0700446 } else {
447 ATRACE_NAME("DrawColor");
John Reck67b1e2b2020-08-26 13:17:24 -0700448 const auto color = layer->source.solidColor;
449 paint.setColor(SkColor4f{.fR = color.r, .fG = color.g, .fB = color.b, layer->alpha});
450 }
Lucas Dupin21f348e2020-09-16 17:31:26 -0700451
Lucas Dupinbb1a1d42020-09-18 15:17:02 -0700452 // Layers have a local transform matrix that should be applied to them.
453 canvas->save();
454 canvas->concat(getSkM44(layer->geometry.positionTransform));
455
Lucas Dupin3f11e922020-09-22 17:31:04 -0700456 if (layer->shadow.length > 0) {
457 const auto rect = layer->geometry.roundedCornersRadius > 0
458 ? getSkRect(layer->geometry.roundedCornersCrop)
459 : dest;
460 drawShadow(canvas, rect, layer->geometry.roundedCornersRadius, layer->shadow);
461 }
462
Lucas Dupin21f348e2020-09-16 17:31:26 -0700463 if (layer->geometry.roundedCornersRadius > 0) {
464 canvas->drawRRect(getRoundedRect(layer), paint);
465 } else {
466 canvas->drawRect(dest, paint);
467 }
Lucas Dupinbb1a1d42020-09-18 15:17:02 -0700468 canvas->restore();
John Reck67b1e2b2020-08-26 13:17:24 -0700469 }
470 {
471 ATRACE_NAME("flush surface");
472 surface->flush();
473 }
Lucas Dupinbb1a1d42020-09-18 15:17:02 -0700474 canvas->restore();
John Reck67b1e2b2020-08-26 13:17:24 -0700475
476 if (drawFence != nullptr) {
477 *drawFence = flush();
478 }
479
480 // If flush failed or we don't support native fences, we need to force the
481 // gl command stream to be executed.
482 bool requireSync = drawFence == nullptr || drawFence->get() < 0;
483 if (requireSync) {
484 ATRACE_BEGIN("Submit(sync=true)");
485 } else {
486 ATRACE_BEGIN("Submit(sync=false)");
487 }
488 bool success = mGrContext->submit(requireSync);
489 ATRACE_END();
490 if (!success) {
491 ALOGE("Failed to flush RenderEngine commands");
492 // Chances are, something illegal happened (either the caller passed
493 // us bad parameters, or we messed up our shader generation).
494 return INVALID_OPERATION;
495 }
496
497 // checkErrors();
498 return NO_ERROR;
499}
500
Lucas Dupin3f11e922020-09-22 17:31:04 -0700501inline SkRect SkiaGLRenderEngine::getSkRect(const FloatRect& rect) {
502 return SkRect::MakeLTRB(rect.left, rect.top, rect.right, rect.bottom);
503}
504
505inline SkRect SkiaGLRenderEngine::getSkRect(const Rect& rect) {
506 return SkRect::MakeLTRB(rect.left, rect.top, rect.right, rect.bottom);
507}
508
Lucas Dupin21f348e2020-09-16 17:31:26 -0700509inline SkRRect SkiaGLRenderEngine::getRoundedRect(const LayerSettings* layer) {
Lucas Dupin3f11e922020-09-22 17:31:04 -0700510 const auto rect = getSkRect(layer->geometry.roundedCornersCrop);
Lucas Dupin21f348e2020-09-16 17:31:26 -0700511 const auto cornerRadius = layer->geometry.roundedCornersRadius;
512 return SkRRect::MakeRectXY(rect, cornerRadius, cornerRadius);
513}
514
Lucas Dupin3f11e922020-09-22 17:31:04 -0700515inline SkColor SkiaGLRenderEngine::getSkColor(const vec4& color) {
516 return SkColorSetARGB(color.a * 255, color.r * 255, color.g * 255, color.b * 255);
517}
518
Lucas Dupinbb1a1d42020-09-18 15:17:02 -0700519inline SkM44 SkiaGLRenderEngine::getSkM44(const mat4& matrix) {
520 return SkM44(matrix[0][0], matrix[1][0], matrix[2][0], matrix[3][0],
521 matrix[0][1], matrix[1][1], matrix[2][1], matrix[3][1],
522 matrix[0][2], matrix[1][2], matrix[2][2], matrix[3][2],
523 matrix[0][3], matrix[1][3], matrix[2][3], matrix[3][3]);
524}
525
Lucas Dupin3f11e922020-09-22 17:31:04 -0700526inline SkPoint3 SkiaGLRenderEngine::getSkPoint3(const vec3& vector) {
527 return SkPoint3::Make(vector.x, vector.y, vector.z);
528}
529
John Reck67b1e2b2020-08-26 13:17:24 -0700530size_t SkiaGLRenderEngine::getMaxTextureSize() const {
531 return mGrContext->maxTextureSize();
532}
533
534size_t SkiaGLRenderEngine::getMaxViewportDims() const {
535 return mGrContext->maxRenderTargetSize();
536}
537
Lucas Dupin3f11e922020-09-22 17:31:04 -0700538void SkiaGLRenderEngine::drawShadow(SkCanvas* canvas, const SkRect& casterRect, float cornerRadius,
539 const ShadowSettings& settings) {
540 ATRACE_CALL();
541 const float casterZ = settings.length / 2.0f;
542 const auto shadowShape = cornerRadius > 0
543 ? SkPath::RRect(SkRRect::MakeRectXY(casterRect, cornerRadius, cornerRadius))
544 : SkPath::Rect(casterRect);
545 const auto flags =
546 settings.casterIsTranslucent ? kTransparentOccluder_ShadowFlag : kNone_ShadowFlag;
547
548 SkShadowUtils::DrawShadow(canvas, shadowShape, SkPoint3::Make(0, 0, casterZ),
549 getSkPoint3(settings.lightPos), settings.lightRadius,
550 getSkColor(settings.ambientColor), getSkColor(settings.spotColor),
551 flags);
552}
553
John Reck67b1e2b2020-08-26 13:17:24 -0700554EGLContext SkiaGLRenderEngine::createEglContext(EGLDisplay display, EGLConfig config,
555 EGLContext shareContext, bool useContextPriority,
556 Protection protection) {
557 EGLint renderableType = 0;
558 if (config == EGL_NO_CONFIG_KHR) {
559 renderableType = EGL_OPENGL_ES3_BIT;
560 } else if (!eglGetConfigAttrib(display, config, EGL_RENDERABLE_TYPE, &renderableType)) {
561 LOG_ALWAYS_FATAL("can't query EGLConfig RENDERABLE_TYPE");
562 }
563 EGLint contextClientVersion = 0;
564 if (renderableType & EGL_OPENGL_ES3_BIT) {
565 contextClientVersion = 3;
566 } else if (renderableType & EGL_OPENGL_ES2_BIT) {
567 contextClientVersion = 2;
568 } else if (renderableType & EGL_OPENGL_ES_BIT) {
569 contextClientVersion = 1;
570 } else {
571 LOG_ALWAYS_FATAL("no supported EGL_RENDERABLE_TYPEs");
572 }
573
574 std::vector<EGLint> contextAttributes;
575 contextAttributes.reserve(7);
576 contextAttributes.push_back(EGL_CONTEXT_CLIENT_VERSION);
577 contextAttributes.push_back(contextClientVersion);
578 if (useContextPriority) {
579 contextAttributes.push_back(EGL_CONTEXT_PRIORITY_LEVEL_IMG);
580 contextAttributes.push_back(EGL_CONTEXT_PRIORITY_HIGH_IMG);
581 }
582 if (protection == Protection::PROTECTED) {
583 contextAttributes.push_back(EGL_PROTECTED_CONTENT_EXT);
584 contextAttributes.push_back(EGL_TRUE);
585 }
586 contextAttributes.push_back(EGL_NONE);
587
588 EGLContext context = eglCreateContext(display, config, shareContext, contextAttributes.data());
589
590 if (contextClientVersion == 3 && context == EGL_NO_CONTEXT) {
591 // eglGetConfigAttrib indicated we can create GLES 3 context, but we failed, thus
592 // EGL_NO_CONTEXT so that we can abort.
593 if (config != EGL_NO_CONFIG_KHR) {
594 return context;
595 }
596 // If |config| is EGL_NO_CONFIG_KHR, we speculatively try to create GLES 3 context, so we
597 // should try to fall back to GLES 2.
598 contextAttributes[1] = 2;
599 context = eglCreateContext(display, config, shareContext, contextAttributes.data());
600 }
601
602 return context;
603}
604
605EGLSurface SkiaGLRenderEngine::createPlaceholderEglPbufferSurface(EGLDisplay display,
606 EGLConfig config, int hwcFormat,
607 Protection protection) {
608 EGLConfig placeholderConfig = config;
609 if (placeholderConfig == EGL_NO_CONFIG_KHR) {
610 placeholderConfig = chooseEglConfig(display, hwcFormat, /*logConfig*/ true);
611 }
612 std::vector<EGLint> attributes;
613 attributes.reserve(7);
614 attributes.push_back(EGL_WIDTH);
615 attributes.push_back(1);
616 attributes.push_back(EGL_HEIGHT);
617 attributes.push_back(1);
618 if (protection == Protection::PROTECTED) {
619 attributes.push_back(EGL_PROTECTED_CONTENT_EXT);
620 attributes.push_back(EGL_TRUE);
621 }
622 attributes.push_back(EGL_NONE);
623
624 return eglCreatePbufferSurface(display, placeholderConfig, attributes.data());
625}
626
627void SkiaGLRenderEngine::cleanFramebufferCache() {
628 mSurfaceCache.clear();
629}
630
631} // namespace skia
632} // namespace renderengine
633} // namespace android