• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright 2013 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 <sched.h>
23 #include <cmath>
24 #include <fstream>
25 #include <sstream>
26 #include <unordered_set>
27 
28 #include <GLES2/gl2.h>
29 #include <GLES2/gl2ext.h>
30 #include <android-base/stringprintf.h>
31 #include <cutils/compiler.h>
32 #include <cutils/properties.h>
33 #include <gui/DebugEGLImageTracker.h>
34 #include <renderengine/Mesh.h>
35 #include <renderengine/Texture.h>
36 #include <renderengine/private/Description.h>
37 #include <sync/sync.h>
38 #include <ui/ColorSpace.h>
39 #include <ui/DebugUtils.h>
40 #include <ui/GraphicBuffer.h>
41 #include <ui/Rect.h>
42 #include <ui/Region.h>
43 #include <utils/KeyedVector.h>
44 #include <utils/Trace.h>
45 #include "GLESRenderEngine.h"
46 #include "GLExtensions.h"
47 #include "GLFramebuffer.h"
48 #include "GLImage.h"
49 #include "GLShadowVertexGenerator.h"
50 #include "Program.h"
51 #include "ProgramCache.h"
52 #include "filters/BlurFilter.h"
53 
54 extern "C" EGLAPI const char* eglQueryStringImplementationANDROID(EGLDisplay dpy, EGLint name);
55 
checkGlError(const char * op,int lineNumber)56 bool checkGlError(const char* op, int lineNumber) {
57     bool errorFound = false;
58     GLint error = glGetError();
59     while (error != GL_NO_ERROR) {
60         errorFound = true;
61         error = glGetError();
62         ALOGV("after %s() (line # %d) glError (0x%x)\n", op, lineNumber, error);
63     }
64     return errorFound;
65 }
66 
67 static constexpr bool outputDebugPPMs = false;
68 
writePPM(const char * basename,GLuint width,GLuint height)69 void writePPM(const char* basename, GLuint width, GLuint height) {
70     ALOGV("writePPM #%s: %d x %d", basename, width, height);
71 
72     std::vector<GLubyte> pixels(width * height * 4);
73     std::vector<GLubyte> outBuffer(width * height * 3);
74 
75     // TODO(courtneygo): We can now have float formats, need
76     // to remove this code or update to support.
77     // Make returned pixels fit in uint32_t, one byte per component
78     glReadPixels(0, 0, width, height, GL_RGBA, GL_UNSIGNED_BYTE, pixels.data());
79     if (checkGlError(__FUNCTION__, __LINE__)) {
80         return;
81     }
82 
83     std::string filename(basename);
84     filename.append(".ppm");
85     std::ofstream file(filename.c_str(), std::ios::binary);
86     if (!file.is_open()) {
87         ALOGE("Unable to open file: %s", filename.c_str());
88         ALOGE("You may need to do: \"adb shell setenforce 0\" to enable "
89               "surfaceflinger to write debug images");
90         return;
91     }
92 
93     file << "P6\n";
94     file << width << "\n";
95     file << height << "\n";
96     file << 255 << "\n";
97 
98     auto ptr = reinterpret_cast<char*>(pixels.data());
99     auto outPtr = reinterpret_cast<char*>(outBuffer.data());
100     for (int y = height - 1; y >= 0; y--) {
101         char* data = ptr + y * width * sizeof(uint32_t);
102 
103         for (GLuint x = 0; x < width; x++) {
104             // Only copy R, G and B components
105             outPtr[0] = data[0];
106             outPtr[1] = data[1];
107             outPtr[2] = data[2];
108             data += sizeof(uint32_t);
109             outPtr += 3;
110         }
111     }
112     file.write(reinterpret_cast<char*>(outBuffer.data()), outBuffer.size());
113 }
114 
115 namespace android {
116 namespace renderengine {
117 namespace gl {
118 
119 using base::StringAppendF;
120 using ui::Dataspace;
121 
selectConfigForAttribute(EGLDisplay dpy,EGLint const * attrs,EGLint attribute,EGLint wanted,EGLConfig * outConfig)122 static status_t selectConfigForAttribute(EGLDisplay dpy, EGLint const* attrs, EGLint attribute,
123                                          EGLint wanted, EGLConfig* outConfig) {
124     EGLint numConfigs = -1, n = 0;
125     eglGetConfigs(dpy, nullptr, 0, &numConfigs);
126     std::vector<EGLConfig> configs(numConfigs, EGL_NO_CONFIG_KHR);
127     eglChooseConfig(dpy, attrs, configs.data(), configs.size(), &n);
128     configs.resize(n);
129 
130     if (!configs.empty()) {
131         if (attribute != EGL_NONE) {
132             for (EGLConfig config : configs) {
133                 EGLint value = 0;
134                 eglGetConfigAttrib(dpy, config, attribute, &value);
135                 if (wanted == value) {
136                     *outConfig = config;
137                     return NO_ERROR;
138                 }
139             }
140         } else {
141             // just pick the first one
142             *outConfig = configs[0];
143             return NO_ERROR;
144         }
145     }
146 
147     return NAME_NOT_FOUND;
148 }
149 
selectEGLConfig(EGLDisplay display,EGLint format,EGLint renderableType,EGLConfig * config)150 static status_t selectEGLConfig(EGLDisplay display, EGLint format, EGLint renderableType,
151                                 EGLConfig* config) {
152     // select our EGLConfig. It must support EGL_RECORDABLE_ANDROID if
153     // it is to be used with WIFI displays
154     status_t err;
155     EGLint wantedAttribute;
156     EGLint wantedAttributeValue;
157 
158     std::vector<EGLint> attribs;
159     if (renderableType) {
160         const ui::PixelFormat pixelFormat = static_cast<ui::PixelFormat>(format);
161         const bool is1010102 = pixelFormat == ui::PixelFormat::RGBA_1010102;
162 
163         // Default to 8 bits per channel.
164         const EGLint tmpAttribs[] = {
165                 EGL_RENDERABLE_TYPE,
166                 renderableType,
167                 EGL_RECORDABLE_ANDROID,
168                 EGL_TRUE,
169                 EGL_SURFACE_TYPE,
170                 EGL_WINDOW_BIT | EGL_PBUFFER_BIT,
171                 EGL_FRAMEBUFFER_TARGET_ANDROID,
172                 EGL_TRUE,
173                 EGL_RED_SIZE,
174                 is1010102 ? 10 : 8,
175                 EGL_GREEN_SIZE,
176                 is1010102 ? 10 : 8,
177                 EGL_BLUE_SIZE,
178                 is1010102 ? 10 : 8,
179                 EGL_ALPHA_SIZE,
180                 is1010102 ? 2 : 8,
181                 EGL_NONE,
182         };
183         std::copy(tmpAttribs, tmpAttribs + (sizeof(tmpAttribs) / sizeof(EGLint)),
184                   std::back_inserter(attribs));
185         wantedAttribute = EGL_NONE;
186         wantedAttributeValue = EGL_NONE;
187     } else {
188         // if no renderable type specified, fallback to a simplified query
189         wantedAttribute = EGL_NATIVE_VISUAL_ID;
190         wantedAttributeValue = format;
191     }
192 
193     err = selectConfigForAttribute(display, attribs.data(), wantedAttribute, wantedAttributeValue,
194                                    config);
195     if (err == NO_ERROR) {
196         EGLint caveat;
197         if (eglGetConfigAttrib(display, *config, EGL_CONFIG_CAVEAT, &caveat))
198             ALOGW_IF(caveat == EGL_SLOW_CONFIG, "EGL_SLOW_CONFIG selected!");
199     }
200 
201     return err;
202 }
203 
create(const RenderEngineCreationArgs & args)204 std::unique_ptr<GLESRenderEngine> GLESRenderEngine::create(const RenderEngineCreationArgs& args) {
205     // initialize EGL for the default display
206     EGLDisplay display = eglGetDisplay(EGL_DEFAULT_DISPLAY);
207     if (!eglInitialize(display, nullptr, nullptr)) {
208         LOG_ALWAYS_FATAL("failed to initialize EGL");
209     }
210 
211     const auto eglVersion = eglQueryStringImplementationANDROID(display, EGL_VERSION);
212     if (!eglVersion) {
213         checkGlError(__FUNCTION__, __LINE__);
214         LOG_ALWAYS_FATAL("eglQueryStringImplementationANDROID(EGL_VERSION) failed");
215     }
216 
217     const auto eglExtensions = eglQueryStringImplementationANDROID(display, EGL_EXTENSIONS);
218     if (!eglExtensions) {
219         checkGlError(__FUNCTION__, __LINE__);
220         LOG_ALWAYS_FATAL("eglQueryStringImplementationANDROID(EGL_EXTENSIONS) failed");
221     }
222 
223     GLExtensions& extensions = GLExtensions::getInstance();
224     extensions.initWithEGLStrings(eglVersion, eglExtensions);
225 
226     // The code assumes that ES2 or later is available if this extension is
227     // supported.
228     EGLConfig config = EGL_NO_CONFIG;
229     if (!extensions.hasNoConfigContext()) {
230         config = chooseEglConfig(display, args.pixelFormat, /*logConfig*/ true);
231     }
232 
233     bool useContextPriority =
234             extensions.hasContextPriority() && args.contextPriority == ContextPriority::HIGH;
235     EGLContext protectedContext = EGL_NO_CONTEXT;
236     if (args.enableProtectedContext && extensions.hasProtectedContent()) {
237         protectedContext = createEglContext(display, config, nullptr, useContextPriority,
238                                             Protection::PROTECTED);
239         ALOGE_IF(protectedContext == EGL_NO_CONTEXT, "Can't create protected context");
240     }
241 
242     EGLContext ctxt = createEglContext(display, config, protectedContext, useContextPriority,
243                                        Protection::UNPROTECTED);
244 
245     // if can't create a GL context, we can only abort.
246     LOG_ALWAYS_FATAL_IF(ctxt == EGL_NO_CONTEXT, "EGLContext creation failed");
247 
248     EGLSurface dummy = EGL_NO_SURFACE;
249     if (!extensions.hasSurfacelessContext()) {
250         dummy = createDummyEglPbufferSurface(display, config, args.pixelFormat,
251                                              Protection::UNPROTECTED);
252         LOG_ALWAYS_FATAL_IF(dummy == EGL_NO_SURFACE, "can't create dummy pbuffer");
253     }
254     EGLBoolean success = eglMakeCurrent(display, dummy, dummy, ctxt);
255     LOG_ALWAYS_FATAL_IF(!success, "can't make dummy pbuffer current");
256     extensions.initWithGLStrings(glGetString(GL_VENDOR), glGetString(GL_RENDERER),
257                                  glGetString(GL_VERSION), glGetString(GL_EXTENSIONS));
258 
259     EGLSurface protectedDummy = EGL_NO_SURFACE;
260     if (protectedContext != EGL_NO_CONTEXT && !extensions.hasSurfacelessContext()) {
261         protectedDummy = createDummyEglPbufferSurface(display, config, args.pixelFormat,
262                                                       Protection::PROTECTED);
263         ALOGE_IF(protectedDummy == EGL_NO_SURFACE, "can't create protected dummy pbuffer");
264     }
265 
266     // now figure out what version of GL did we actually get
267     GlesVersion version = parseGlesVersion(extensions.getVersion());
268 
269     LOG_ALWAYS_FATAL_IF(args.supportsBackgroundBlur && version < GLES_VERSION_3_0,
270         "Blurs require OpenGL ES 3.0. Please unset ro.surface_flinger.supports_background_blur");
271 
272     // initialize the renderer while GL is current
273     std::unique_ptr<GLESRenderEngine> engine;
274     switch (version) {
275         case GLES_VERSION_1_0:
276         case GLES_VERSION_1_1:
277             LOG_ALWAYS_FATAL("SurfaceFlinger requires OpenGL ES 2.0 minimum to run.");
278             break;
279         case GLES_VERSION_2_0:
280         case GLES_VERSION_3_0:
281             engine = std::make_unique<GLESRenderEngine>(args, display, config, ctxt, dummy,
282                                                         protectedContext, protectedDummy);
283             break;
284     }
285 
286     ALOGI("OpenGL ES informations:");
287     ALOGI("vendor    : %s", extensions.getVendor());
288     ALOGI("renderer  : %s", extensions.getRenderer());
289     ALOGI("version   : %s", extensions.getVersion());
290     ALOGI("extensions: %s", extensions.getExtensions());
291     ALOGI("GL_MAX_TEXTURE_SIZE = %zu", engine->getMaxTextureSize());
292     ALOGI("GL_MAX_VIEWPORT_DIMS = %zu", engine->getMaxViewportDims());
293 
294     return engine;
295 }
296 
chooseEglConfig(EGLDisplay display,int format,bool logConfig)297 EGLConfig GLESRenderEngine::chooseEglConfig(EGLDisplay display, int format, bool logConfig) {
298     status_t err;
299     EGLConfig config;
300 
301     // First try to get an ES3 config
302     err = selectEGLConfig(display, format, EGL_OPENGL_ES3_BIT, &config);
303     if (err != NO_ERROR) {
304         // If ES3 fails, try to get an ES2 config
305         err = selectEGLConfig(display, format, EGL_OPENGL_ES2_BIT, &config);
306         if (err != NO_ERROR) {
307             // If ES2 still doesn't work, probably because we're on the emulator.
308             // try a simplified query
309             ALOGW("no suitable EGLConfig found, trying a simpler query");
310             err = selectEGLConfig(display, format, 0, &config);
311             if (err != NO_ERROR) {
312                 // this EGL is too lame for android
313                 LOG_ALWAYS_FATAL("no suitable EGLConfig found, giving up");
314             }
315         }
316     }
317 
318     if (logConfig) {
319         // print some debugging info
320         EGLint r, g, b, a;
321         eglGetConfigAttrib(display, config, EGL_RED_SIZE, &r);
322         eglGetConfigAttrib(display, config, EGL_GREEN_SIZE, &g);
323         eglGetConfigAttrib(display, config, EGL_BLUE_SIZE, &b);
324         eglGetConfigAttrib(display, config, EGL_ALPHA_SIZE, &a);
325         ALOGI("EGL information:");
326         ALOGI("vendor    : %s", eglQueryString(display, EGL_VENDOR));
327         ALOGI("version   : %s", eglQueryString(display, EGL_VERSION));
328         ALOGI("extensions: %s", eglQueryString(display, EGL_EXTENSIONS));
329         ALOGI("Client API: %s", eglQueryString(display, EGL_CLIENT_APIS) ?: "Not Supported");
330         ALOGI("EGLSurface: %d-%d-%d-%d, config=%p", r, g, b, a, config);
331     }
332 
333     return config;
334 }
335 
GLESRenderEngine(const RenderEngineCreationArgs & args,EGLDisplay display,EGLConfig config,EGLContext ctxt,EGLSurface dummy,EGLContext protectedContext,EGLSurface protectedDummy)336 GLESRenderEngine::GLESRenderEngine(const RenderEngineCreationArgs& args, EGLDisplay display,
337                                    EGLConfig config, EGLContext ctxt, EGLSurface dummy,
338                                    EGLContext protectedContext, EGLSurface protectedDummy)
339       : renderengine::impl::RenderEngine(args),
340         mEGLDisplay(display),
341         mEGLConfig(config),
342         mEGLContext(ctxt),
343         mDummySurface(dummy),
344         mProtectedEGLContext(protectedContext),
345         mProtectedDummySurface(protectedDummy),
346         mVpWidth(0),
347         mVpHeight(0),
348         mFramebufferImageCacheSize(args.imageCacheSize),
349         mUseColorManagement(args.useColorManagement) {
350     glGetIntegerv(GL_MAX_TEXTURE_SIZE, &mMaxTextureSize);
351     glGetIntegerv(GL_MAX_VIEWPORT_DIMS, mMaxViewportDims);
352 
353     glPixelStorei(GL_UNPACK_ALIGNMENT, 4);
354     glPixelStorei(GL_PACK_ALIGNMENT, 4);
355 
356     // Initialize protected EGL Context.
357     if (mProtectedEGLContext != EGL_NO_CONTEXT) {
358         EGLBoolean success = eglMakeCurrent(display, mProtectedDummySurface, mProtectedDummySurface,
359                                             mProtectedEGLContext);
360         ALOGE_IF(!success, "can't make protected context current");
361         glPixelStorei(GL_UNPACK_ALIGNMENT, 4);
362         glPixelStorei(GL_PACK_ALIGNMENT, 4);
363         success = eglMakeCurrent(display, mDummySurface, mDummySurface, mEGLContext);
364         LOG_ALWAYS_FATAL_IF(!success, "can't make default context current");
365     }
366 
367     // mColorBlindnessCorrection = M;
368 
369     if (mUseColorManagement) {
370         const ColorSpace srgb(ColorSpace::sRGB());
371         const ColorSpace displayP3(ColorSpace::DisplayP3());
372         const ColorSpace bt2020(ColorSpace::BT2020());
373 
374         // no chromatic adaptation needed since all color spaces use D65 for their white points.
375         mSrgbToXyz = mat4(srgb.getRGBtoXYZ());
376         mDisplayP3ToXyz = mat4(displayP3.getRGBtoXYZ());
377         mBt2020ToXyz = mat4(bt2020.getRGBtoXYZ());
378         mXyzToSrgb = mat4(srgb.getXYZtoRGB());
379         mXyzToDisplayP3 = mat4(displayP3.getXYZtoRGB());
380         mXyzToBt2020 = mat4(bt2020.getXYZtoRGB());
381 
382         // Compute sRGB to Display P3 and BT2020 transform matrix.
383         // NOTE: For now, we are limiting output wide color space support to
384         // Display-P3 and BT2020 only.
385         mSrgbToDisplayP3 = mXyzToDisplayP3 * mSrgbToXyz;
386         mSrgbToBt2020 = mXyzToBt2020 * mSrgbToXyz;
387 
388         // Compute Display P3 to sRGB and BT2020 transform matrix.
389         mDisplayP3ToSrgb = mXyzToSrgb * mDisplayP3ToXyz;
390         mDisplayP3ToBt2020 = mXyzToBt2020 * mDisplayP3ToXyz;
391 
392         // Compute BT2020 to sRGB and Display P3 transform matrix
393         mBt2020ToSrgb = mXyzToSrgb * mBt2020ToXyz;
394         mBt2020ToDisplayP3 = mXyzToDisplayP3 * mBt2020ToXyz;
395     }
396 
397     char value[PROPERTY_VALUE_MAX];
398     property_get("debug.egl.traceGpuCompletion", value, "0");
399     if (atoi(value)) {
400         mTraceGpuCompletion = true;
401         mFlushTracer = std::make_unique<FlushTracer>(this);
402     }
403 
404     if (args.supportsBackgroundBlur) {
405         mBlurFilter = new BlurFilter(*this);
406         checkErrors("BlurFilter creation");
407     }
408 
409     mImageManager = std::make_unique<ImageManager>(this);
410     mImageManager->initThread();
411     mDrawingBuffer = createFramebuffer();
412     sp<GraphicBuffer> buf =
413             new GraphicBuffer(1, 1, PIXEL_FORMAT_RGBA_8888, 1,
414                               GRALLOC_USAGE_HW_RENDER | GRALLOC_USAGE_HW_TEXTURE, "placeholder");
415 
416     const status_t err = buf->initCheck();
417     if (err != OK) {
418         ALOGE("Error allocating placeholder buffer: %d", err);
419         return;
420     }
421     mPlaceholderBuffer = buf.get();
422     EGLint attributes[] = {
423             EGL_NONE,
424     };
425     mPlaceholderImage = eglCreateImageKHR(mEGLDisplay, EGL_NO_CONTEXT, EGL_NATIVE_BUFFER_ANDROID,
426                                           mPlaceholderBuffer, attributes);
427     ALOGE_IF(mPlaceholderImage == EGL_NO_IMAGE_KHR, "Failed to create placeholder image: %#x",
428              eglGetError());
429 }
430 
~GLESRenderEngine()431 GLESRenderEngine::~GLESRenderEngine() {
432     // Destroy the image manager first.
433     mImageManager = nullptr;
434     std::lock_guard<std::mutex> lock(mRenderingMutex);
435     unbindFrameBuffer(mDrawingBuffer.get());
436     mDrawingBuffer = nullptr;
437     while (!mFramebufferImageCache.empty()) {
438         EGLImageKHR expired = mFramebufferImageCache.front().second;
439         mFramebufferImageCache.pop_front();
440         eglDestroyImageKHR(mEGLDisplay, expired);
441         DEBUG_EGL_IMAGE_TRACKER_DESTROY();
442     }
443     eglDestroyImageKHR(mEGLDisplay, mPlaceholderImage);
444     mImageCache.clear();
445     eglMakeCurrent(mEGLDisplay, EGL_NO_SURFACE, EGL_NO_SURFACE, EGL_NO_CONTEXT);
446     eglTerminate(mEGLDisplay);
447 }
448 
createFramebuffer()449 std::unique_ptr<Framebuffer> GLESRenderEngine::createFramebuffer() {
450     return std::make_unique<GLFramebuffer>(*this);
451 }
452 
createImage()453 std::unique_ptr<Image> GLESRenderEngine::createImage() {
454     return std::make_unique<GLImage>(*this);
455 }
456 
getFramebufferForDrawing()457 Framebuffer* GLESRenderEngine::getFramebufferForDrawing() {
458     return mDrawingBuffer.get();
459 }
460 
primeCache() const461 void GLESRenderEngine::primeCache() const {
462     ProgramCache::getInstance().primeCache(mInProtectedContext ? mProtectedEGLContext : mEGLContext,
463                                            mArgs.useColorManagement,
464                                            mArgs.precacheToneMapperShaderOnly);
465 }
466 
flush()467 base::unique_fd GLESRenderEngine::flush() {
468     ATRACE_CALL();
469     if (!GLExtensions::getInstance().hasNativeFenceSync()) {
470         return base::unique_fd();
471     }
472 
473     EGLSyncKHR sync = eglCreateSyncKHR(mEGLDisplay, EGL_SYNC_NATIVE_FENCE_ANDROID, nullptr);
474     if (sync == EGL_NO_SYNC_KHR) {
475         ALOGW("failed to create EGL native fence sync: %#x", eglGetError());
476         return base::unique_fd();
477     }
478 
479     // native fence fd will not be populated until flush() is done.
480     glFlush();
481 
482     // get the fence fd
483     base::unique_fd fenceFd(eglDupNativeFenceFDANDROID(mEGLDisplay, sync));
484     eglDestroySyncKHR(mEGLDisplay, sync);
485     if (fenceFd == EGL_NO_NATIVE_FENCE_FD_ANDROID) {
486         ALOGW("failed to dup EGL native fence sync: %#x", eglGetError());
487     }
488 
489     // Only trace if we have a valid fence, as current usage falls back to
490     // calling finish() if the fence fd is invalid.
491     if (CC_UNLIKELY(mTraceGpuCompletion && mFlushTracer) && fenceFd.get() >= 0) {
492         mFlushTracer->queueSync(eglCreateSyncKHR(mEGLDisplay, EGL_SYNC_FENCE_KHR, nullptr));
493     }
494 
495     return fenceFd;
496 }
497 
finish()498 bool GLESRenderEngine::finish() {
499     ATRACE_CALL();
500     if (!GLExtensions::getInstance().hasFenceSync()) {
501         ALOGW("no synchronization support");
502         return false;
503     }
504 
505     EGLSyncKHR sync = eglCreateSyncKHR(mEGLDisplay, EGL_SYNC_FENCE_KHR, nullptr);
506     if (sync == EGL_NO_SYNC_KHR) {
507         ALOGW("failed to create EGL fence sync: %#x", eglGetError());
508         return false;
509     }
510 
511     if (CC_UNLIKELY(mTraceGpuCompletion && mFlushTracer)) {
512         mFlushTracer->queueSync(eglCreateSyncKHR(mEGLDisplay, EGL_SYNC_FENCE_KHR, nullptr));
513     }
514 
515     return waitSync(sync, EGL_SYNC_FLUSH_COMMANDS_BIT_KHR);
516 }
517 
waitSync(EGLSyncKHR sync,EGLint flags)518 bool GLESRenderEngine::waitSync(EGLSyncKHR sync, EGLint flags) {
519     EGLint result = eglClientWaitSyncKHR(mEGLDisplay, sync, flags, 2000000000 /*2 sec*/);
520     EGLint error = eglGetError();
521     eglDestroySyncKHR(mEGLDisplay, sync);
522     if (result != EGL_CONDITION_SATISFIED_KHR) {
523         if (result == EGL_TIMEOUT_EXPIRED_KHR) {
524             ALOGW("fence wait timed out");
525         } else {
526             ALOGW("error waiting on EGL fence: %#x", error);
527         }
528         return false;
529     }
530 
531     return true;
532 }
533 
waitFence(base::unique_fd fenceFd)534 bool GLESRenderEngine::waitFence(base::unique_fd fenceFd) {
535     if (!GLExtensions::getInstance().hasNativeFenceSync() ||
536         !GLExtensions::getInstance().hasWaitSync()) {
537         return false;
538     }
539 
540     // release the fd and transfer the ownership to EGLSync
541     EGLint attribs[] = {EGL_SYNC_NATIVE_FENCE_FD_ANDROID, fenceFd.release(), EGL_NONE};
542     EGLSyncKHR sync = eglCreateSyncKHR(mEGLDisplay, EGL_SYNC_NATIVE_FENCE_ANDROID, attribs);
543     if (sync == EGL_NO_SYNC_KHR) {
544         ALOGE("failed to create EGL native fence sync: %#x", eglGetError());
545         return false;
546     }
547 
548     // XXX: The spec draft is inconsistent as to whether this should return an
549     // EGLint or void.  Ignore the return value for now, as it's not strictly
550     // needed.
551     eglWaitSyncKHR(mEGLDisplay, sync, 0);
552     EGLint error = eglGetError();
553     eglDestroySyncKHR(mEGLDisplay, sync);
554     if (error != EGL_SUCCESS) {
555         ALOGE("failed to wait for EGL native fence sync: %#x", error);
556         return false;
557     }
558 
559     return true;
560 }
561 
clearWithColor(float red,float green,float blue,float alpha)562 void GLESRenderEngine::clearWithColor(float red, float green, float blue, float alpha) {
563     ATRACE_CALL();
564     glDisable(GL_BLEND);
565     glClearColor(red, green, blue, alpha);
566     glClear(GL_COLOR_BUFFER_BIT);
567 }
568 
fillRegionWithColor(const Region & region,float red,float green,float blue,float alpha)569 void GLESRenderEngine::fillRegionWithColor(const Region& region, float red, float green, float blue,
570                                            float alpha) {
571     size_t c;
572     Rect const* r = region.getArray(&c);
573     Mesh mesh = Mesh::Builder()
574                         .setPrimitive(Mesh::TRIANGLES)
575                         .setVertices(c * 6 /* count */, 2 /* size */)
576                         .build();
577     Mesh::VertexArray<vec2> position(mesh.getPositionArray<vec2>());
578     for (size_t i = 0; i < c; i++, r++) {
579         position[i * 6 + 0].x = r->left;
580         position[i * 6 + 0].y = r->top;
581         position[i * 6 + 1].x = r->left;
582         position[i * 6 + 1].y = r->bottom;
583         position[i * 6 + 2].x = r->right;
584         position[i * 6 + 2].y = r->bottom;
585         position[i * 6 + 3].x = r->left;
586         position[i * 6 + 3].y = r->top;
587         position[i * 6 + 4].x = r->right;
588         position[i * 6 + 4].y = r->bottom;
589         position[i * 6 + 5].x = r->right;
590         position[i * 6 + 5].y = r->top;
591     }
592     setupFillWithColor(red, green, blue, alpha);
593     drawMesh(mesh);
594 }
595 
setScissor(const Rect & region)596 void GLESRenderEngine::setScissor(const Rect& region) {
597     glScissor(region.left, region.top, region.getWidth(), region.getHeight());
598     glEnable(GL_SCISSOR_TEST);
599 }
600 
disableScissor()601 void GLESRenderEngine::disableScissor() {
602     glDisable(GL_SCISSOR_TEST);
603 }
604 
genTextures(size_t count,uint32_t * names)605 void GLESRenderEngine::genTextures(size_t count, uint32_t* names) {
606     glGenTextures(count, names);
607 }
608 
deleteTextures(size_t count,uint32_t const * names)609 void GLESRenderEngine::deleteTextures(size_t count, uint32_t const* names) {
610     for (int i = 0; i < count; ++i) {
611         mTextureView.erase(names[i]);
612     }
613     glDeleteTextures(count, names);
614 }
615 
bindExternalTextureImage(uint32_t texName,const Image & image)616 void GLESRenderEngine::bindExternalTextureImage(uint32_t texName, const Image& image) {
617     ATRACE_CALL();
618     const GLImage& glImage = static_cast<const GLImage&>(image);
619     const GLenum target = GL_TEXTURE_EXTERNAL_OES;
620 
621     glBindTexture(target, texName);
622     if (glImage.getEGLImage() != EGL_NO_IMAGE_KHR) {
623         glEGLImageTargetTexture2DOES(target, static_cast<GLeglImageOES>(glImage.getEGLImage()));
624     }
625 }
626 
bindExternalTextureBuffer(uint32_t texName,const sp<GraphicBuffer> & buffer,const sp<Fence> & bufferFence)627 status_t GLESRenderEngine::bindExternalTextureBuffer(uint32_t texName,
628                                                      const sp<GraphicBuffer>& buffer,
629                                                      const sp<Fence>& bufferFence) {
630     if (buffer == nullptr) {
631         return BAD_VALUE;
632     }
633 
634     ATRACE_CALL();
635 
636     bool found = false;
637     {
638         std::lock_guard<std::mutex> lock(mRenderingMutex);
639         auto cachedImage = mImageCache.find(buffer->getId());
640         found = (cachedImage != mImageCache.end());
641     }
642 
643     // If we couldn't find the image in the cache at this time, then either
644     // SurfaceFlinger messed up registering the buffer ahead of time or we got
645     // backed up creating other EGLImages.
646     if (!found) {
647         status_t cacheResult = mImageManager->cache(buffer);
648         if (cacheResult != NO_ERROR) {
649             return cacheResult;
650         }
651     }
652 
653     // Whether or not we needed to cache, re-check mImageCache to make sure that
654     // there's an EGLImage. The current threading model guarantees that we don't
655     // destroy a cached image until it's really not needed anymore (i.e. this
656     // function should not be called), so the only possibility is that something
657     // terrible went wrong and we should just bind something and move on.
658     {
659         std::lock_guard<std::mutex> lock(mRenderingMutex);
660         auto cachedImage = mImageCache.find(buffer->getId());
661 
662         if (cachedImage == mImageCache.end()) {
663             // We failed creating the image if we got here, so bail out.
664             ALOGE("Failed to create an EGLImage when rendering");
665             bindExternalTextureImage(texName, *createImage());
666             return NO_INIT;
667         }
668 
669         bindExternalTextureImage(texName, *cachedImage->second);
670         mTextureView.insert_or_assign(texName, buffer->getId());
671     }
672 
673     // Wait for the new buffer to be ready.
674     if (bufferFence != nullptr && bufferFence->isValid()) {
675         if (GLExtensions::getInstance().hasWaitSync()) {
676             base::unique_fd fenceFd(bufferFence->dup());
677             if (fenceFd == -1) {
678                 ALOGE("error dup'ing fence fd: %d", errno);
679                 return -errno;
680             }
681             if (!waitFence(std::move(fenceFd))) {
682                 ALOGE("failed to wait on fence fd");
683                 return UNKNOWN_ERROR;
684             }
685         } else {
686             status_t err = bufferFence->waitForever("RenderEngine::bindExternalTextureBuffer");
687             if (err != NO_ERROR) {
688                 ALOGE("error waiting for fence: %d", err);
689                 return err;
690             }
691         }
692     }
693 
694     return NO_ERROR;
695 }
696 
cacheExternalTextureBuffer(const sp<GraphicBuffer> & buffer)697 void GLESRenderEngine::cacheExternalTextureBuffer(const sp<GraphicBuffer>& buffer) {
698     mImageManager->cacheAsync(buffer, nullptr);
699 }
700 
cacheExternalTextureBufferForTesting(const sp<GraphicBuffer> & buffer)701 std::shared_ptr<ImageManager::Barrier> GLESRenderEngine::cacheExternalTextureBufferForTesting(
702         const sp<GraphicBuffer>& buffer) {
703     auto barrier = std::make_shared<ImageManager::Barrier>();
704     mImageManager->cacheAsync(buffer, barrier);
705     return barrier;
706 }
707 
cacheExternalTextureBufferInternal(const sp<GraphicBuffer> & buffer)708 status_t GLESRenderEngine::cacheExternalTextureBufferInternal(const sp<GraphicBuffer>& buffer) {
709     if (buffer == nullptr) {
710         return BAD_VALUE;
711     }
712 
713     {
714         std::lock_guard<std::mutex> lock(mRenderingMutex);
715         if (mImageCache.count(buffer->getId()) > 0) {
716             // If there's already an image then fail fast here.
717             return NO_ERROR;
718         }
719     }
720     ATRACE_CALL();
721 
722     // Create the image without holding a lock so that we don't block anything.
723     std::unique_ptr<Image> newImage = createImage();
724 
725     bool created = newImage->setNativeWindowBuffer(buffer->getNativeBuffer(),
726                                                    buffer->getUsage() & GRALLOC_USAGE_PROTECTED);
727     if (!created) {
728         ALOGE("Failed to create image. size=%ux%u st=%u usage=%#" PRIx64 " fmt=%d",
729               buffer->getWidth(), buffer->getHeight(), buffer->getStride(), buffer->getUsage(),
730               buffer->getPixelFormat());
731         return NO_INIT;
732     }
733 
734     {
735         std::lock_guard<std::mutex> lock(mRenderingMutex);
736         if (mImageCache.count(buffer->getId()) > 0) {
737             // In theory it's possible for another thread to recache the image,
738             // so bail out if another thread won.
739             return NO_ERROR;
740         }
741         mImageCache.insert(std::make_pair(buffer->getId(), std::move(newImage)));
742     }
743 
744     return NO_ERROR;
745 }
746 
unbindExternalTextureBuffer(uint64_t bufferId)747 void GLESRenderEngine::unbindExternalTextureBuffer(uint64_t bufferId) {
748     mImageManager->releaseAsync(bufferId, nullptr);
749 }
750 
unbindExternalTextureBufferForTesting(uint64_t bufferId)751 std::shared_ptr<ImageManager::Barrier> GLESRenderEngine::unbindExternalTextureBufferForTesting(
752         uint64_t bufferId) {
753     auto barrier = std::make_shared<ImageManager::Barrier>();
754     mImageManager->releaseAsync(bufferId, barrier);
755     return barrier;
756 }
757 
unbindExternalTextureBufferInternal(uint64_t bufferId)758 void GLESRenderEngine::unbindExternalTextureBufferInternal(uint64_t bufferId) {
759     std::unique_ptr<Image> image;
760     {
761         std::lock_guard<std::mutex> lock(mRenderingMutex);
762         const auto& cachedImage = mImageCache.find(bufferId);
763 
764         if (cachedImage != mImageCache.end()) {
765             ALOGV("Destroying image for buffer: %" PRIu64, bufferId);
766             // Move the buffer out of cache first, so that we can destroy
767             // without holding the cache's lock.
768             image = std::move(cachedImage->second);
769             mImageCache.erase(bufferId);
770             return;
771         }
772     }
773     ALOGV("Failed to find image for buffer: %" PRIu64, bufferId);
774 }
775 
setupLayerCropping(const LayerSettings & layer,Mesh & mesh)776 FloatRect GLESRenderEngine::setupLayerCropping(const LayerSettings& layer, Mesh& mesh) {
777     // Translate win by the rounded corners rect coordinates, to have all values in
778     // layer coordinate space.
779     FloatRect cropWin = layer.geometry.boundaries;
780     const FloatRect& roundedCornersCrop = layer.geometry.roundedCornersCrop;
781     cropWin.left -= roundedCornersCrop.left;
782     cropWin.right -= roundedCornersCrop.left;
783     cropWin.top -= roundedCornersCrop.top;
784     cropWin.bottom -= roundedCornersCrop.top;
785     Mesh::VertexArray<vec2> cropCoords(mesh.getCropCoordArray<vec2>());
786     cropCoords[0] = vec2(cropWin.left, cropWin.top);
787     cropCoords[1] = vec2(cropWin.left, cropWin.top + cropWin.getHeight());
788     cropCoords[2] = vec2(cropWin.right, cropWin.top + cropWin.getHeight());
789     cropCoords[3] = vec2(cropWin.right, cropWin.top);
790 
791     setupCornerRadiusCropSize(roundedCornersCrop.getWidth(), roundedCornersCrop.getHeight());
792     return cropWin;
793 }
794 
handleRoundedCorners(const DisplaySettings & display,const LayerSettings & layer,const Mesh & mesh)795 void GLESRenderEngine::handleRoundedCorners(const DisplaySettings& display,
796                                             const LayerSettings& layer, const Mesh& mesh) {
797     // We separate the layer into 3 parts essentially, such that we only turn on blending for the
798     // top rectangle and the bottom rectangle, and turn off blending for the middle rectangle.
799     FloatRect bounds = layer.geometry.roundedCornersCrop;
800 
801     // Explicitly compute the transform from the clip rectangle to the physical
802     // display. Normally, this is done in glViewport but we explicitly compute
803     // it here so that we can get the scissor bounds correct.
804     const Rect& source = display.clip;
805     const Rect& destination = display.physicalDisplay;
806     // Here we compute the following transform:
807     // 1. Translate the top left corner of the source clip to (0, 0)
808     // 2. Rotate the clip rectangle about the origin in accordance with the
809     // orientation flag
810     // 3. Translate the top left corner back to the origin.
811     // 4. Scale the clip rectangle to the destination rectangle dimensions
812     // 5. Translate the top left corner to the destination rectangle's top left
813     // corner.
814     const mat4 translateSource = mat4::translate(vec4(-source.left, -source.top, 0, 1));
815     mat4 rotation;
816     int displacementX = 0;
817     int displacementY = 0;
818     float destinationWidth = static_cast<float>(destination.getWidth());
819     float destinationHeight = static_cast<float>(destination.getHeight());
820     float sourceWidth = static_cast<float>(source.getWidth());
821     float sourceHeight = static_cast<float>(source.getHeight());
822     const float rot90InRadians = 2.0f * static_cast<float>(M_PI) / 4.0f;
823     switch (display.orientation) {
824         case ui::Transform::ROT_90:
825             rotation = mat4::rotate(rot90InRadians, vec3(0, 0, 1));
826             displacementX = source.getHeight();
827             std::swap(sourceHeight, sourceWidth);
828             break;
829         case ui::Transform::ROT_180:
830             rotation = mat4::rotate(rot90InRadians * 2.0f, vec3(0, 0, 1));
831             displacementY = source.getHeight();
832             displacementX = source.getWidth();
833             break;
834         case ui::Transform::ROT_270:
835             rotation = mat4::rotate(rot90InRadians * 3.0f, vec3(0, 0, 1));
836             displacementY = source.getWidth();
837             std::swap(sourceHeight, sourceWidth);
838             break;
839         default:
840             break;
841     }
842 
843     const mat4 intermediateTranslation = mat4::translate(vec4(displacementX, displacementY, 0, 1));
844     const mat4 scale = mat4::scale(
845             vec4(destinationWidth / sourceWidth, destinationHeight / sourceHeight, 1, 1));
846     const mat4 translateDestination =
847             mat4::translate(vec4(destination.left, destination.top, 0, 1));
848     const mat4 globalTransform =
849             translateDestination * scale * intermediateTranslation * rotation * translateSource;
850 
851     const mat4 transformMatrix = globalTransform * layer.geometry.positionTransform;
852     const vec4 leftTopCoordinate(bounds.left, bounds.top, 1.0, 1.0);
853     const vec4 rightBottomCoordinate(bounds.right, bounds.bottom, 1.0, 1.0);
854     const vec4 leftTopCoordinateInBuffer = transformMatrix * leftTopCoordinate;
855     const vec4 rightBottomCoordinateInBuffer = transformMatrix * rightBottomCoordinate;
856     bounds = FloatRect(std::min(leftTopCoordinateInBuffer[0], rightBottomCoordinateInBuffer[0]),
857                        std::min(leftTopCoordinateInBuffer[1], rightBottomCoordinateInBuffer[1]),
858                        std::max(leftTopCoordinateInBuffer[0], rightBottomCoordinateInBuffer[0]),
859                        std::max(leftTopCoordinateInBuffer[1], rightBottomCoordinateInBuffer[1]));
860 
861     // Finally, we cut the layer into 3 parts, with top and bottom parts having rounded corners
862     // and the middle part without rounded corners.
863     const int32_t radius = ceil(layer.geometry.roundedCornersRadius);
864     const Rect topRect(bounds.left, bounds.top, bounds.right, bounds.top + radius);
865     setScissor(topRect);
866     drawMesh(mesh);
867     const Rect bottomRect(bounds.left, bounds.bottom - radius, bounds.right, bounds.bottom);
868     setScissor(bottomRect);
869     drawMesh(mesh);
870 
871     // The middle part of the layer can turn off blending.
872     if (topRect.bottom < bottomRect.top) {
873         const Rect middleRect(bounds.left, bounds.top + radius, bounds.right,
874                               bounds.bottom - radius);
875         setScissor(middleRect);
876         mState.cornerRadius = 0.0;
877         disableBlending();
878         drawMesh(mesh);
879     }
880     disableScissor();
881 }
882 
bindFrameBuffer(Framebuffer * framebuffer)883 status_t GLESRenderEngine::bindFrameBuffer(Framebuffer* framebuffer) {
884     ATRACE_CALL();
885     GLFramebuffer* glFramebuffer = static_cast<GLFramebuffer*>(framebuffer);
886     EGLImageKHR eglImage = glFramebuffer->getEGLImage();
887     uint32_t textureName = glFramebuffer->getTextureName();
888     uint32_t framebufferName = glFramebuffer->getFramebufferName();
889 
890     // Bind the texture and turn our EGLImage into a texture
891     glBindTexture(GL_TEXTURE_2D, textureName);
892     glEGLImageTargetTexture2DOES(GL_TEXTURE_2D, (GLeglImageOES)eglImage);
893 
894     // Bind the Framebuffer to render into
895     glBindFramebuffer(GL_FRAMEBUFFER, framebufferName);
896     glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, textureName, 0);
897 
898     uint32_t glStatus = glCheckFramebufferStatus(GL_FRAMEBUFFER);
899     ALOGE_IF(glStatus != GL_FRAMEBUFFER_COMPLETE_OES, "glCheckFramebufferStatusOES error %d",
900              glStatus);
901 
902     return glStatus == GL_FRAMEBUFFER_COMPLETE_OES ? NO_ERROR : BAD_VALUE;
903 }
904 
unbindFrameBuffer(Framebuffer *)905 void GLESRenderEngine::unbindFrameBuffer(Framebuffer* /*framebuffer*/) {
906     ATRACE_CALL();
907 
908     // back to main framebuffer
909     glBindFramebuffer(GL_FRAMEBUFFER, 0);
910 }
911 
cleanupPostRender(CleanupMode mode)912 bool GLESRenderEngine::cleanupPostRender(CleanupMode mode) {
913     ATRACE_CALL();
914 
915     if (mPriorResourcesCleaned ||
916         (mLastDrawFence != nullptr && mLastDrawFence->getStatus() != Fence::Status::Signaled)) {
917         // If we don't have a prior frame needing cleanup, then don't do anything.
918         return false;
919     }
920 
921     // This is a bit of a band-aid fix for FrameCaptureProcessor, as we should
922     // not need to keep memory around if we don't need to do so.
923     if (mode == CleanupMode::CLEAN_ALL) {
924         // TODO: SurfaceFlinger memory utilization may benefit from resetting
925         // texture bindings as well. Assess if it does and there's no performance regression
926         // when rebinding the same image data to the same texture, and if so then its mode
927         // behavior can be tweaked.
928         if (mPlaceholderImage != EGL_NO_IMAGE_KHR) {
929             for (auto [textureName, bufferId] : mTextureView) {
930                 if (bufferId && mPlaceholderImage != EGL_NO_IMAGE_KHR) {
931                     glBindTexture(GL_TEXTURE_EXTERNAL_OES, textureName);
932                     glEGLImageTargetTexture2DOES(GL_TEXTURE_EXTERNAL_OES,
933                                                  static_cast<GLeglImageOES>(mPlaceholderImage));
934                     mTextureView[textureName] = std::nullopt;
935                     checkErrors();
936                 }
937             }
938         }
939         {
940             std::lock_guard<std::mutex> lock(mRenderingMutex);
941             mImageCache.clear();
942         }
943     }
944 
945     // Bind the texture to dummy data so that backing image data can be freed.
946     GLFramebuffer* glFramebuffer = static_cast<GLFramebuffer*>(getFramebufferForDrawing());
947     glFramebuffer->allocateBuffers(1, 1, mPlaceholderDrawBuffer);
948     // Release the cached fence here, so that we don't churn reallocations when
949     // we could no-op repeated calls of this method instead.
950     mLastDrawFence = nullptr;
951     mPriorResourcesCleaned = true;
952     return true;
953 }
954 
checkErrors() const955 void GLESRenderEngine::checkErrors() const {
956     checkErrors(nullptr);
957 }
958 
checkErrors(const char * tag) const959 void GLESRenderEngine::checkErrors(const char* tag) const {
960     do {
961         // there could be more than one error flag
962         GLenum error = glGetError();
963         if (error == GL_NO_ERROR) break;
964         if (tag == nullptr) {
965             ALOGE("GL error 0x%04x", int(error));
966         } else {
967             ALOGE("GL error: %s -> 0x%04x", tag, int(error));
968         }
969     } while (true);
970 }
971 
supportsProtectedContent() const972 bool GLESRenderEngine::supportsProtectedContent() const {
973     return mProtectedEGLContext != EGL_NO_CONTEXT;
974 }
975 
useProtectedContext(bool useProtectedContext)976 bool GLESRenderEngine::useProtectedContext(bool useProtectedContext) {
977     if (useProtectedContext == mInProtectedContext) {
978         return true;
979     }
980     if (useProtectedContext && mProtectedEGLContext == EGL_NO_CONTEXT) {
981         return false;
982     }
983     const EGLSurface surface = useProtectedContext ? mProtectedDummySurface : mDummySurface;
984     const EGLContext context = useProtectedContext ? mProtectedEGLContext : mEGLContext;
985     const bool success = eglMakeCurrent(mEGLDisplay, surface, surface, context) == EGL_TRUE;
986     if (success) {
987         mInProtectedContext = useProtectedContext;
988     }
989     return success;
990 }
createFramebufferImageIfNeeded(ANativeWindowBuffer * nativeBuffer,bool isProtected,bool useFramebufferCache)991 EGLImageKHR GLESRenderEngine::createFramebufferImageIfNeeded(ANativeWindowBuffer* nativeBuffer,
992                                                              bool isProtected,
993                                                              bool useFramebufferCache) {
994     sp<GraphicBuffer> graphicBuffer = GraphicBuffer::from(nativeBuffer);
995     if (useFramebufferCache) {
996         std::lock_guard<std::mutex> lock(mFramebufferImageCacheMutex);
997         for (const auto& image : mFramebufferImageCache) {
998             if (image.first == graphicBuffer->getId()) {
999                 return image.second;
1000             }
1001         }
1002     }
1003     EGLint attributes[] = {
1004             isProtected ? EGL_PROTECTED_CONTENT_EXT : EGL_NONE,
1005             isProtected ? EGL_TRUE : EGL_NONE,
1006             EGL_NONE,
1007     };
1008     EGLImageKHR image = eglCreateImageKHR(mEGLDisplay, EGL_NO_CONTEXT, EGL_NATIVE_BUFFER_ANDROID,
1009                                           nativeBuffer, attributes);
1010     if (useFramebufferCache) {
1011         if (image != EGL_NO_IMAGE_KHR) {
1012             std::lock_guard<std::mutex> lock(mFramebufferImageCacheMutex);
1013             if (mFramebufferImageCache.size() >= mFramebufferImageCacheSize) {
1014                 EGLImageKHR expired = mFramebufferImageCache.front().second;
1015                 mFramebufferImageCache.pop_front();
1016                 eglDestroyImageKHR(mEGLDisplay, expired);
1017                 DEBUG_EGL_IMAGE_TRACKER_DESTROY();
1018             }
1019             mFramebufferImageCache.push_back({graphicBuffer->getId(), image});
1020         }
1021     }
1022 
1023     if (image != EGL_NO_IMAGE_KHR) {
1024         DEBUG_EGL_IMAGE_TRACKER_CREATE();
1025     }
1026     return image;
1027 }
1028 
drawLayers(const DisplaySettings & display,const std::vector<const LayerSettings * > & layers,ANativeWindowBuffer * const buffer,const bool useFramebufferCache,base::unique_fd && bufferFence,base::unique_fd * drawFence)1029 status_t GLESRenderEngine::drawLayers(const DisplaySettings& display,
1030                                       const std::vector<const LayerSettings*>& layers,
1031                                       ANativeWindowBuffer* const buffer,
1032                                       const bool useFramebufferCache, base::unique_fd&& bufferFence,
1033                                       base::unique_fd* drawFence) {
1034     ATRACE_CALL();
1035     if (layers.empty()) {
1036         ALOGV("Drawing empty layer stack");
1037         return NO_ERROR;
1038     }
1039 
1040     if (bufferFence.get() >= 0) {
1041         // Duplicate the fence for passing to waitFence.
1042         base::unique_fd bufferFenceDup(dup(bufferFence.get()));
1043         if (bufferFenceDup < 0 || !waitFence(std::move(bufferFenceDup))) {
1044             ATRACE_NAME("Waiting before draw");
1045             sync_wait(bufferFence.get(), -1);
1046         }
1047     }
1048 
1049     if (buffer == nullptr) {
1050         ALOGE("No output buffer provided. Aborting GPU composition.");
1051         return BAD_VALUE;
1052     }
1053 
1054     std::unique_ptr<BindNativeBufferAsFramebuffer> fbo;
1055     // Gathering layers that requested blur, we'll need them to decide when to render to an
1056     // offscreen buffer, and when to render to the native buffer.
1057     std::deque<const LayerSettings*> blurLayers;
1058     if (CC_LIKELY(mBlurFilter != nullptr)) {
1059         for (auto layer : layers) {
1060             if (layer->backgroundBlurRadius > 0) {
1061                 blurLayers.push_back(layer);
1062             }
1063         }
1064     }
1065     const auto blurLayersSize = blurLayers.size();
1066 
1067     if (blurLayersSize == 0) {
1068         fbo = std::make_unique<BindNativeBufferAsFramebuffer>(*this, buffer, useFramebufferCache);
1069         if (fbo->getStatus() != NO_ERROR) {
1070             ALOGE("Failed to bind framebuffer! Aborting GPU composition for buffer (%p).",
1071                   buffer->handle);
1072             checkErrors();
1073             return fbo->getStatus();
1074         }
1075         setViewportAndProjection(display.physicalDisplay, display.clip);
1076     } else {
1077         setViewportAndProjection(display.physicalDisplay, display.clip);
1078         auto status =
1079                 mBlurFilter->setAsDrawTarget(display, blurLayers.front()->backgroundBlurRadius);
1080         if (status != NO_ERROR) {
1081             ALOGE("Failed to prepare blur filter! Aborting GPU composition for buffer (%p).",
1082                   buffer->handle);
1083             checkErrors();
1084             return status;
1085         }
1086     }
1087 
1088     // clear the entire buffer, sometimes when we reuse buffers we'd persist
1089     // ghost images otherwise.
1090     // we also require a full transparent framebuffer for overlays. This is
1091     // probably not quite efficient on all GPUs, since we could filter out
1092     // opaque layers.
1093     clearWithColor(0.0, 0.0, 0.0, 0.0);
1094 
1095     setOutputDataSpace(display.outputDataspace);
1096     setDisplayMaxLuminance(display.maxLuminance);
1097 
1098     const mat4 projectionMatrix =
1099             ui::Transform(display.orientation).asMatrix4() * mState.projectionMatrix;
1100     if (!display.clearRegion.isEmpty()) {
1101         glDisable(GL_BLEND);
1102         fillRegionWithColor(display.clearRegion, 0.0, 0.0, 0.0, 1.0);
1103     }
1104 
1105     Mesh mesh = Mesh::Builder()
1106                         .setPrimitive(Mesh::TRIANGLE_FAN)
1107                         .setVertices(4 /* count */, 2 /* size */)
1108                         .setTexCoords(2 /* size */)
1109                         .setCropCoords(2 /* size */)
1110                         .build();
1111     for (auto const layer : layers) {
1112         if (blurLayers.size() > 0 && blurLayers.front() == layer) {
1113             blurLayers.pop_front();
1114 
1115             auto status = mBlurFilter->prepare();
1116             if (status != NO_ERROR) {
1117                 ALOGE("Failed to render blur effect! Aborting GPU composition for buffer (%p).",
1118                       buffer->handle);
1119                 checkErrors("Can't render first blur pass");
1120                 return status;
1121             }
1122 
1123             if (blurLayers.size() == 0) {
1124                 // Done blurring, time to bind the native FBO and render our blur onto it.
1125                 fbo = std::make_unique<BindNativeBufferAsFramebuffer>(*this, buffer,
1126                                                                       useFramebufferCache);
1127                 status = fbo->getStatus();
1128                 setViewportAndProjection(display.physicalDisplay, display.clip);
1129             } else {
1130                 // There's still something else to blur, so let's keep rendering to our FBO
1131                 // instead of to the display.
1132                 status = mBlurFilter->setAsDrawTarget(display,
1133                                                       blurLayers.front()->backgroundBlurRadius);
1134             }
1135             if (status != NO_ERROR) {
1136                 ALOGE("Failed to bind framebuffer! Aborting GPU composition for buffer (%p).",
1137                       buffer->handle);
1138                 checkErrors("Can't bind native framebuffer");
1139                 return status;
1140             }
1141 
1142             status = mBlurFilter->render(blurLayersSize > 1);
1143             if (status != NO_ERROR) {
1144                 ALOGE("Failed to render blur effect! Aborting GPU composition for buffer (%p).",
1145                       buffer->handle);
1146                 checkErrors("Can't render blur filter");
1147                 return status;
1148             }
1149         }
1150 
1151         mState.maxMasteringLuminance = layer->source.buffer.maxMasteringLuminance;
1152         mState.maxContentLuminance = layer->source.buffer.maxContentLuminance;
1153         mState.projectionMatrix = projectionMatrix * layer->geometry.positionTransform;
1154 
1155         const FloatRect bounds = layer->geometry.boundaries;
1156         Mesh::VertexArray<vec2> position(mesh.getPositionArray<vec2>());
1157         position[0] = vec2(bounds.left, bounds.top);
1158         position[1] = vec2(bounds.left, bounds.bottom);
1159         position[2] = vec2(bounds.right, bounds.bottom);
1160         position[3] = vec2(bounds.right, bounds.top);
1161 
1162         setupLayerCropping(*layer, mesh);
1163         setColorTransform(display.colorTransform * layer->colorTransform);
1164 
1165         bool usePremultipliedAlpha = true;
1166         bool disableTexture = true;
1167         bool isOpaque = false;
1168         if (layer->source.buffer.buffer != nullptr) {
1169             disableTexture = false;
1170             isOpaque = layer->source.buffer.isOpaque;
1171 
1172             sp<GraphicBuffer> gBuf = layer->source.buffer.buffer;
1173             bindExternalTextureBuffer(layer->source.buffer.textureName, gBuf,
1174                                       layer->source.buffer.fence);
1175 
1176             usePremultipliedAlpha = layer->source.buffer.usePremultipliedAlpha;
1177             Texture texture(Texture::TEXTURE_EXTERNAL, layer->source.buffer.textureName);
1178             mat4 texMatrix = layer->source.buffer.textureTransform;
1179 
1180             texture.setMatrix(texMatrix.asArray());
1181             texture.setFiltering(layer->source.buffer.useTextureFiltering);
1182 
1183             texture.setDimensions(gBuf->getWidth(), gBuf->getHeight());
1184             setSourceY410BT2020(layer->source.buffer.isY410BT2020);
1185 
1186             renderengine::Mesh::VertexArray<vec2> texCoords(mesh.getTexCoordArray<vec2>());
1187             texCoords[0] = vec2(0.0, 0.0);
1188             texCoords[1] = vec2(0.0, 1.0);
1189             texCoords[2] = vec2(1.0, 1.0);
1190             texCoords[3] = vec2(1.0, 0.0);
1191             setupLayerTexturing(texture);
1192         }
1193 
1194         const half3 solidColor = layer->source.solidColor;
1195         const half4 color = half4(solidColor.r, solidColor.g, solidColor.b, layer->alpha);
1196         // Buffer sources will have a black solid color ignored in the shader,
1197         // so in that scenario the solid color passed here is arbitrary.
1198         setupLayerBlending(usePremultipliedAlpha, isOpaque, disableTexture, color,
1199                            layer->geometry.roundedCornersRadius);
1200         if (layer->disableBlending) {
1201             glDisable(GL_BLEND);
1202         }
1203         setSourceDataSpace(layer->sourceDataspace);
1204 
1205         if (layer->shadow.length > 0.0f) {
1206             handleShadow(layer->geometry.boundaries, layer->geometry.roundedCornersRadius,
1207                          layer->shadow);
1208         }
1209         // We only want to do a special handling for rounded corners when having rounded corners
1210         // is the only reason it needs to turn on blending, otherwise, we handle it like the
1211         // usual way since it needs to turn on blending anyway.
1212         else if (layer->geometry.roundedCornersRadius > 0.0 && color.a >= 1.0f && isOpaque) {
1213             handleRoundedCorners(display, *layer, mesh);
1214         } else {
1215             drawMesh(mesh);
1216         }
1217 
1218         // Cleanup if there's a buffer source
1219         if (layer->source.buffer.buffer != nullptr) {
1220             disableBlending();
1221             setSourceY410BT2020(false);
1222             disableTexturing();
1223         }
1224     }
1225 
1226     if (drawFence != nullptr) {
1227         *drawFence = flush();
1228     }
1229     // If flush failed or we don't support native fences, we need to force the
1230     // gl command stream to be executed.
1231     if (drawFence == nullptr || drawFence->get() < 0) {
1232         bool success = finish();
1233         if (!success) {
1234             ALOGE("Failed to flush RenderEngine commands");
1235             checkErrors();
1236             // Chances are, something illegal happened (either the caller passed
1237             // us bad parameters, or we messed up our shader generation).
1238             return INVALID_OPERATION;
1239         }
1240         mLastDrawFence = nullptr;
1241     } else {
1242         // The caller takes ownership of drawFence, so we need to duplicate the
1243         // fd here.
1244         mLastDrawFence = new Fence(dup(drawFence->get()));
1245     }
1246     mPriorResourcesCleaned = false;
1247 
1248     checkErrors();
1249     return NO_ERROR;
1250 }
1251 
setViewportAndProjection(Rect viewport,Rect clip)1252 void GLESRenderEngine::setViewportAndProjection(Rect viewport, Rect clip) {
1253     ATRACE_CALL();
1254     mVpWidth = viewport.getWidth();
1255     mVpHeight = viewport.getHeight();
1256 
1257     // We pass the the top left corner instead of the bottom left corner,
1258     // because since we're rendering off-screen first.
1259     glViewport(viewport.left, viewport.top, mVpWidth, mVpHeight);
1260 
1261     mState.projectionMatrix = mat4::ortho(clip.left, clip.right, clip.top, clip.bottom, 0, 1);
1262 }
1263 
setupLayerBlending(bool premultipliedAlpha,bool opaque,bool disableTexture,const half4 & color,float cornerRadius)1264 void GLESRenderEngine::setupLayerBlending(bool premultipliedAlpha, bool opaque, bool disableTexture,
1265                                           const half4& color, float cornerRadius) {
1266     mState.isPremultipliedAlpha = premultipliedAlpha;
1267     mState.isOpaque = opaque;
1268     mState.color = color;
1269     mState.cornerRadius = cornerRadius;
1270 
1271     if (disableTexture) {
1272         mState.textureEnabled = false;
1273     }
1274 
1275     if (color.a < 1.0f || !opaque || cornerRadius > 0.0f) {
1276         glEnable(GL_BLEND);
1277         glBlendFunc(premultipliedAlpha ? GL_ONE : GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
1278     } else {
1279         glDisable(GL_BLEND);
1280     }
1281 }
1282 
setSourceY410BT2020(bool enable)1283 void GLESRenderEngine::setSourceY410BT2020(bool enable) {
1284     mState.isY410BT2020 = enable;
1285 }
1286 
setSourceDataSpace(Dataspace source)1287 void GLESRenderEngine::setSourceDataSpace(Dataspace source) {
1288     mDataSpace = source;
1289 }
1290 
setOutputDataSpace(Dataspace dataspace)1291 void GLESRenderEngine::setOutputDataSpace(Dataspace dataspace) {
1292     mOutputDataSpace = dataspace;
1293 }
1294 
setDisplayMaxLuminance(const float maxLuminance)1295 void GLESRenderEngine::setDisplayMaxLuminance(const float maxLuminance) {
1296     mState.displayMaxLuminance = maxLuminance;
1297 }
1298 
setupLayerTexturing(const Texture & texture)1299 void GLESRenderEngine::setupLayerTexturing(const Texture& texture) {
1300     GLuint target = texture.getTextureTarget();
1301     glBindTexture(target, texture.getTextureName());
1302     GLenum filter = GL_NEAREST;
1303     if (texture.getFiltering()) {
1304         filter = GL_LINEAR;
1305     }
1306     glTexParameteri(target, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
1307     glTexParameteri(target, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
1308     glTexParameteri(target, GL_TEXTURE_MAG_FILTER, filter);
1309     glTexParameteri(target, GL_TEXTURE_MIN_FILTER, filter);
1310 
1311     mState.texture = texture;
1312     mState.textureEnabled = true;
1313 }
1314 
setColorTransform(const mat4 & colorTransform)1315 void GLESRenderEngine::setColorTransform(const mat4& colorTransform) {
1316     mState.colorMatrix = colorTransform;
1317 }
1318 
disableTexturing()1319 void GLESRenderEngine::disableTexturing() {
1320     mState.textureEnabled = false;
1321 }
1322 
disableBlending()1323 void GLESRenderEngine::disableBlending() {
1324     glDisable(GL_BLEND);
1325 }
1326 
setupFillWithColor(float r,float g,float b,float a)1327 void GLESRenderEngine::setupFillWithColor(float r, float g, float b, float a) {
1328     mState.isPremultipliedAlpha = true;
1329     mState.isOpaque = false;
1330     mState.color = half4(r, g, b, a);
1331     mState.textureEnabled = false;
1332     glDisable(GL_BLEND);
1333 }
1334 
setupCornerRadiusCropSize(float width,float height)1335 void GLESRenderEngine::setupCornerRadiusCropSize(float width, float height) {
1336     mState.cropSize = half2(width, height);
1337 }
1338 
drawMesh(const Mesh & mesh)1339 void GLESRenderEngine::drawMesh(const Mesh& mesh) {
1340     ATRACE_CALL();
1341     if (mesh.getTexCoordsSize()) {
1342         glEnableVertexAttribArray(Program::texCoords);
1343         glVertexAttribPointer(Program::texCoords, mesh.getTexCoordsSize(), GL_FLOAT, GL_FALSE,
1344                               mesh.getByteStride(), mesh.getTexCoords());
1345     }
1346 
1347     glVertexAttribPointer(Program::position, mesh.getVertexSize(), GL_FLOAT, GL_FALSE,
1348                           mesh.getByteStride(), mesh.getPositions());
1349 
1350     if (mState.cornerRadius > 0.0f) {
1351         glEnableVertexAttribArray(Program::cropCoords);
1352         glVertexAttribPointer(Program::cropCoords, mesh.getVertexSize(), GL_FLOAT, GL_FALSE,
1353                               mesh.getByteStride(), mesh.getCropCoords());
1354     }
1355 
1356     if (mState.drawShadows) {
1357         glEnableVertexAttribArray(Program::shadowColor);
1358         glVertexAttribPointer(Program::shadowColor, mesh.getShadowColorSize(), GL_FLOAT, GL_FALSE,
1359                               mesh.getByteStride(), mesh.getShadowColor());
1360 
1361         glEnableVertexAttribArray(Program::shadowParams);
1362         glVertexAttribPointer(Program::shadowParams, mesh.getShadowParamsSize(), GL_FLOAT, GL_FALSE,
1363                               mesh.getByteStride(), mesh.getShadowParams());
1364     }
1365 
1366     Description managedState = mState;
1367     // By default, DISPLAY_P3 is the only supported wide color output. However,
1368     // when HDR content is present, hardware composer may be able to handle
1369     // BT2020 data space, in that case, the output data space is set to be
1370     // BT2020_HLG or BT2020_PQ respectively. In GPU fall back we need
1371     // to respect this and convert non-HDR content to HDR format.
1372     if (mUseColorManagement) {
1373         Dataspace inputStandard = static_cast<Dataspace>(mDataSpace & Dataspace::STANDARD_MASK);
1374         Dataspace inputTransfer = static_cast<Dataspace>(mDataSpace & Dataspace::TRANSFER_MASK);
1375         Dataspace outputStandard =
1376                 static_cast<Dataspace>(mOutputDataSpace & Dataspace::STANDARD_MASK);
1377         Dataspace outputTransfer =
1378                 static_cast<Dataspace>(mOutputDataSpace & Dataspace::TRANSFER_MASK);
1379         bool needsXYZConversion = needsXYZTransformMatrix();
1380 
1381         // NOTE: if the input standard of the input dataspace is not STANDARD_DCI_P3 or
1382         // STANDARD_BT2020, it will be  treated as STANDARD_BT709
1383         if (inputStandard != Dataspace::STANDARD_DCI_P3 &&
1384             inputStandard != Dataspace::STANDARD_BT2020) {
1385             inputStandard = Dataspace::STANDARD_BT709;
1386         }
1387 
1388         if (needsXYZConversion) {
1389             // The supported input color spaces are standard RGB, Display P3 and BT2020.
1390             switch (inputStandard) {
1391                 case Dataspace::STANDARD_DCI_P3:
1392                     managedState.inputTransformMatrix = mDisplayP3ToXyz;
1393                     break;
1394                 case Dataspace::STANDARD_BT2020:
1395                     managedState.inputTransformMatrix = mBt2020ToXyz;
1396                     break;
1397                 default:
1398                     managedState.inputTransformMatrix = mSrgbToXyz;
1399                     break;
1400             }
1401 
1402             // The supported output color spaces are BT2020, Display P3 and standard RGB.
1403             switch (outputStandard) {
1404                 case Dataspace::STANDARD_BT2020:
1405                     managedState.outputTransformMatrix = mXyzToBt2020;
1406                     break;
1407                 case Dataspace::STANDARD_DCI_P3:
1408                     managedState.outputTransformMatrix = mXyzToDisplayP3;
1409                     break;
1410                 default:
1411                     managedState.outputTransformMatrix = mXyzToSrgb;
1412                     break;
1413             }
1414         } else if (inputStandard != outputStandard) {
1415             // At this point, the input data space and output data space could be both
1416             // HDR data spaces, but they match each other, we do nothing in this case.
1417             // In addition to the case above, the input data space could be
1418             // - scRGB linear
1419             // - scRGB non-linear
1420             // - sRGB
1421             // - Display P3
1422             // - BT2020
1423             // The output data spaces could be
1424             // - sRGB
1425             // - Display P3
1426             // - BT2020
1427             switch (outputStandard) {
1428                 case Dataspace::STANDARD_BT2020:
1429                     if (inputStandard == Dataspace::STANDARD_BT709) {
1430                         managedState.outputTransformMatrix = mSrgbToBt2020;
1431                     } else if (inputStandard == Dataspace::STANDARD_DCI_P3) {
1432                         managedState.outputTransformMatrix = mDisplayP3ToBt2020;
1433                     }
1434                     break;
1435                 case Dataspace::STANDARD_DCI_P3:
1436                     if (inputStandard == Dataspace::STANDARD_BT709) {
1437                         managedState.outputTransformMatrix = mSrgbToDisplayP3;
1438                     } else if (inputStandard == Dataspace::STANDARD_BT2020) {
1439                         managedState.outputTransformMatrix = mBt2020ToDisplayP3;
1440                     }
1441                     break;
1442                 default:
1443                     if (inputStandard == Dataspace::STANDARD_DCI_P3) {
1444                         managedState.outputTransformMatrix = mDisplayP3ToSrgb;
1445                     } else if (inputStandard == Dataspace::STANDARD_BT2020) {
1446                         managedState.outputTransformMatrix = mBt2020ToSrgb;
1447                     }
1448                     break;
1449             }
1450         }
1451 
1452         // we need to convert the RGB value to linear space and convert it back when:
1453         // - there is a color matrix that is not an identity matrix, or
1454         // - there is an output transform matrix that is not an identity matrix, or
1455         // - the input transfer function doesn't match the output transfer function.
1456         if (managedState.hasColorMatrix() || managedState.hasOutputTransformMatrix() ||
1457             inputTransfer != outputTransfer) {
1458             managedState.inputTransferFunction =
1459                     Description::dataSpaceToTransferFunction(inputTransfer);
1460             managedState.outputTransferFunction =
1461                     Description::dataSpaceToTransferFunction(outputTransfer);
1462         }
1463     }
1464 
1465     ProgramCache::getInstance().useProgram(mInProtectedContext ? mProtectedEGLContext : mEGLContext,
1466                                            managedState);
1467 
1468     if (mState.drawShadows) {
1469         glDrawElements(mesh.getPrimitive(), mesh.getIndexCount(), GL_UNSIGNED_SHORT,
1470                        mesh.getIndices());
1471     } else {
1472         glDrawArrays(mesh.getPrimitive(), 0, mesh.getVertexCount());
1473     }
1474 
1475     if (mUseColorManagement && outputDebugPPMs) {
1476         static uint64_t managedColorFrameCount = 0;
1477         std::ostringstream out;
1478         out << "/data/texture_out" << managedColorFrameCount++;
1479         writePPM(out.str().c_str(), mVpWidth, mVpHeight);
1480     }
1481 
1482     if (mesh.getTexCoordsSize()) {
1483         glDisableVertexAttribArray(Program::texCoords);
1484     }
1485 
1486     if (mState.cornerRadius > 0.0f) {
1487         glDisableVertexAttribArray(Program::cropCoords);
1488     }
1489 
1490     if (mState.drawShadows) {
1491         glDisableVertexAttribArray(Program::shadowColor);
1492         glDisableVertexAttribArray(Program::shadowParams);
1493     }
1494 }
1495 
getMaxTextureSize() const1496 size_t GLESRenderEngine::getMaxTextureSize() const {
1497     return mMaxTextureSize;
1498 }
1499 
getMaxViewportDims() const1500 size_t GLESRenderEngine::getMaxViewportDims() const {
1501     return mMaxViewportDims[0] < mMaxViewportDims[1] ? mMaxViewportDims[0] : mMaxViewportDims[1];
1502 }
1503 
dump(std::string & result)1504 void GLESRenderEngine::dump(std::string& result) {
1505     const GLExtensions& extensions = GLExtensions::getInstance();
1506     ProgramCache& cache = ProgramCache::getInstance();
1507 
1508     StringAppendF(&result, "EGL implementation : %s\n", extensions.getEGLVersion());
1509     StringAppendF(&result, "%s\n", extensions.getEGLExtensions());
1510     StringAppendF(&result, "GLES: %s, %s, %s\n", extensions.getVendor(), extensions.getRenderer(),
1511                   extensions.getVersion());
1512     StringAppendF(&result, "%s\n", extensions.getExtensions());
1513     StringAppendF(&result, "RenderEngine supports protected context: %d\n",
1514                   supportsProtectedContent());
1515     StringAppendF(&result, "RenderEngine is in protected context: %d\n", mInProtectedContext);
1516     StringAppendF(&result, "RenderEngine program cache size for unprotected context: %zu\n",
1517                   cache.getSize(mEGLContext));
1518     StringAppendF(&result, "RenderEngine program cache size for protected context: %zu\n",
1519                   cache.getSize(mProtectedEGLContext));
1520     StringAppendF(&result, "RenderEngine last dataspace conversion: (%s) to (%s)\n",
1521                   dataspaceDetails(static_cast<android_dataspace>(mDataSpace)).c_str(),
1522                   dataspaceDetails(static_cast<android_dataspace>(mOutputDataSpace)).c_str());
1523     {
1524         std::lock_guard<std::mutex> lock(mRenderingMutex);
1525         StringAppendF(&result, "RenderEngine image cache size: %zu\n", mImageCache.size());
1526         StringAppendF(&result, "Dumping buffer ids...\n");
1527         for (const auto& [id, unused] : mImageCache) {
1528             StringAppendF(&result, "0x%" PRIx64 "\n", id);
1529         }
1530     }
1531     {
1532         std::lock_guard<std::mutex> lock(mFramebufferImageCacheMutex);
1533         StringAppendF(&result, "RenderEngine framebuffer image cache size: %zu\n",
1534                       mFramebufferImageCache.size());
1535         StringAppendF(&result, "Dumping buffer ids...\n");
1536         for (const auto& [id, unused] : mFramebufferImageCache) {
1537             StringAppendF(&result, "0x%" PRIx64 "\n", id);
1538         }
1539     }
1540 }
1541 
parseGlesVersion(const char * str)1542 GLESRenderEngine::GlesVersion GLESRenderEngine::parseGlesVersion(const char* str) {
1543     int major, minor;
1544     if (sscanf(str, "OpenGL ES-CM %d.%d", &major, &minor) != 2) {
1545         if (sscanf(str, "OpenGL ES %d.%d", &major, &minor) != 2) {
1546             ALOGW("Unable to parse GL_VERSION string: \"%s\"", str);
1547             return GLES_VERSION_1_0;
1548         }
1549     }
1550 
1551     if (major == 1 && minor == 0) return GLES_VERSION_1_0;
1552     if (major == 1 && minor >= 1) return GLES_VERSION_1_1;
1553     if (major == 2 && minor >= 0) return GLES_VERSION_2_0;
1554     if (major == 3 && minor >= 0) return GLES_VERSION_3_0;
1555 
1556     ALOGW("Unrecognized OpenGL ES version: %d.%d", major, minor);
1557     return GLES_VERSION_1_0;
1558 }
1559 
createEglContext(EGLDisplay display,EGLConfig config,EGLContext shareContext,bool useContextPriority,Protection protection)1560 EGLContext GLESRenderEngine::createEglContext(EGLDisplay display, EGLConfig config,
1561                                               EGLContext shareContext, bool useContextPriority,
1562                                               Protection protection) {
1563     EGLint renderableType = 0;
1564     if (config == EGL_NO_CONFIG) {
1565         renderableType = EGL_OPENGL_ES3_BIT;
1566     } else if (!eglGetConfigAttrib(display, config, EGL_RENDERABLE_TYPE, &renderableType)) {
1567         LOG_ALWAYS_FATAL("can't query EGLConfig RENDERABLE_TYPE");
1568     }
1569     EGLint contextClientVersion = 0;
1570     if (renderableType & EGL_OPENGL_ES3_BIT) {
1571         contextClientVersion = 3;
1572     } else if (renderableType & EGL_OPENGL_ES2_BIT) {
1573         contextClientVersion = 2;
1574     } else if (renderableType & EGL_OPENGL_ES_BIT) {
1575         contextClientVersion = 1;
1576     } else {
1577         LOG_ALWAYS_FATAL("no supported EGL_RENDERABLE_TYPEs");
1578     }
1579 
1580     std::vector<EGLint> contextAttributes;
1581     contextAttributes.reserve(7);
1582     contextAttributes.push_back(EGL_CONTEXT_CLIENT_VERSION);
1583     contextAttributes.push_back(contextClientVersion);
1584     if (useContextPriority) {
1585         contextAttributes.push_back(EGL_CONTEXT_PRIORITY_LEVEL_IMG);
1586         contextAttributes.push_back(EGL_CONTEXT_PRIORITY_HIGH_IMG);
1587     }
1588     if (protection == Protection::PROTECTED) {
1589         contextAttributes.push_back(EGL_PROTECTED_CONTENT_EXT);
1590         contextAttributes.push_back(EGL_TRUE);
1591     }
1592     contextAttributes.push_back(EGL_NONE);
1593 
1594     EGLContext context = eglCreateContext(display, config, shareContext, contextAttributes.data());
1595 
1596     if (contextClientVersion == 3 && context == EGL_NO_CONTEXT) {
1597         // eglGetConfigAttrib indicated we can create GLES 3 context, but we failed, thus
1598         // EGL_NO_CONTEXT so that we can abort.
1599         if (config != EGL_NO_CONFIG) {
1600             return context;
1601         }
1602         // If |config| is EGL_NO_CONFIG, we speculatively try to create GLES 3 context, so we should
1603         // try to fall back to GLES 2.
1604         contextAttributes[1] = 2;
1605         context = eglCreateContext(display, config, shareContext, contextAttributes.data());
1606     }
1607 
1608     return context;
1609 }
1610 
createDummyEglPbufferSurface(EGLDisplay display,EGLConfig config,int hwcFormat,Protection protection)1611 EGLSurface GLESRenderEngine::createDummyEglPbufferSurface(EGLDisplay display, EGLConfig config,
1612                                                           int hwcFormat, Protection protection) {
1613     EGLConfig dummyConfig = config;
1614     if (dummyConfig == EGL_NO_CONFIG) {
1615         dummyConfig = chooseEglConfig(display, hwcFormat, /*logConfig*/ true);
1616     }
1617     std::vector<EGLint> attributes;
1618     attributes.reserve(7);
1619     attributes.push_back(EGL_WIDTH);
1620     attributes.push_back(1);
1621     attributes.push_back(EGL_HEIGHT);
1622     attributes.push_back(1);
1623     if (protection == Protection::PROTECTED) {
1624         attributes.push_back(EGL_PROTECTED_CONTENT_EXT);
1625         attributes.push_back(EGL_TRUE);
1626     }
1627     attributes.push_back(EGL_NONE);
1628 
1629     return eglCreatePbufferSurface(display, dummyConfig, attributes.data());
1630 }
1631 
isHdrDataSpace(const Dataspace dataSpace) const1632 bool GLESRenderEngine::isHdrDataSpace(const Dataspace dataSpace) const {
1633     const Dataspace standard = static_cast<Dataspace>(dataSpace & Dataspace::STANDARD_MASK);
1634     const Dataspace transfer = static_cast<Dataspace>(dataSpace & Dataspace::TRANSFER_MASK);
1635     return standard == Dataspace::STANDARD_BT2020 &&
1636             (transfer == Dataspace::TRANSFER_ST2084 || transfer == Dataspace::TRANSFER_HLG);
1637 }
1638 
1639 // For convenience, we want to convert the input color space to XYZ color space first,
1640 // and then convert from XYZ color space to output color space when
1641 // - SDR and HDR contents are mixed, either SDR content will be converted to HDR or
1642 //   HDR content will be tone-mapped to SDR; Or,
1643 // - there are HDR PQ and HLG contents presented at the same time, where we want to convert
1644 //   HLG content to PQ content.
1645 // In either case above, we need to operate the Y value in XYZ color space. Thus, when either
1646 // input data space or output data space is HDR data space, and the input transfer function
1647 // doesn't match the output transfer function, we would enable an intermediate transfrom to
1648 // XYZ color space.
needsXYZTransformMatrix() const1649 bool GLESRenderEngine::needsXYZTransformMatrix() const {
1650     const bool isInputHdrDataSpace = isHdrDataSpace(mDataSpace);
1651     const bool isOutputHdrDataSpace = isHdrDataSpace(mOutputDataSpace);
1652     const Dataspace inputTransfer = static_cast<Dataspace>(mDataSpace & Dataspace::TRANSFER_MASK);
1653     const Dataspace outputTransfer =
1654             static_cast<Dataspace>(mOutputDataSpace & Dataspace::TRANSFER_MASK);
1655 
1656     return (isInputHdrDataSpace || isOutputHdrDataSpace) && inputTransfer != outputTransfer;
1657 }
1658 
isImageCachedForTesting(uint64_t bufferId)1659 bool GLESRenderEngine::isImageCachedForTesting(uint64_t bufferId) {
1660     std::lock_guard<std::mutex> lock(mRenderingMutex);
1661     const auto& cachedImage = mImageCache.find(bufferId);
1662     return cachedImage != mImageCache.end();
1663 }
1664 
isTextureNameKnownForTesting(uint32_t texName)1665 bool GLESRenderEngine::isTextureNameKnownForTesting(uint32_t texName) {
1666     const auto& entry = mTextureView.find(texName);
1667     return entry != mTextureView.end();
1668 }
1669 
getBufferIdForTextureNameForTesting(uint32_t texName)1670 std::optional<uint64_t> GLESRenderEngine::getBufferIdForTextureNameForTesting(uint32_t texName) {
1671     const auto& entry = mTextureView.find(texName);
1672     return entry != mTextureView.end() ? entry->second : std::nullopt;
1673 }
1674 
isFramebufferImageCachedForTesting(uint64_t bufferId)1675 bool GLESRenderEngine::isFramebufferImageCachedForTesting(uint64_t bufferId) {
1676     std::lock_guard<std::mutex> lock(mFramebufferImageCacheMutex);
1677     return std::any_of(mFramebufferImageCache.cbegin(), mFramebufferImageCache.cend(),
1678                        [=](std::pair<uint64_t, EGLImageKHR> image) {
1679                            return image.first == bufferId;
1680                        });
1681 }
1682 
1683 // FlushTracer implementation
FlushTracer(GLESRenderEngine * engine)1684 GLESRenderEngine::FlushTracer::FlushTracer(GLESRenderEngine* engine) : mEngine(engine) {
1685     mThread = std::thread(&GLESRenderEngine::FlushTracer::loop, this);
1686 }
1687 
~FlushTracer()1688 GLESRenderEngine::FlushTracer::~FlushTracer() {
1689     {
1690         std::lock_guard<std::mutex> lock(mMutex);
1691         mRunning = false;
1692     }
1693     mCondition.notify_all();
1694     if (mThread.joinable()) {
1695         mThread.join();
1696     }
1697 }
1698 
queueSync(EGLSyncKHR sync)1699 void GLESRenderEngine::FlushTracer::queueSync(EGLSyncKHR sync) {
1700     std::lock_guard<std::mutex> lock(mMutex);
1701     char name[64];
1702     const uint64_t frameNum = mFramesQueued++;
1703     snprintf(name, sizeof(name), "Queueing sync for frame: %lu",
1704              static_cast<unsigned long>(frameNum));
1705     ATRACE_NAME(name);
1706     mQueue.push({sync, frameNum});
1707     ATRACE_INT("GPU Frames Outstanding", mQueue.size());
1708     mCondition.notify_one();
1709 }
1710 
loop()1711 void GLESRenderEngine::FlushTracer::loop() {
1712     while (mRunning) {
1713         QueueEntry entry;
1714         {
1715             std::lock_guard<std::mutex> lock(mMutex);
1716 
1717             mCondition.wait(mMutex,
1718                             [&]() REQUIRES(mMutex) { return !mQueue.empty() || !mRunning; });
1719 
1720             if (!mRunning) {
1721                 // if mRunning is false, then FlushTracer is being destroyed, so
1722                 // bail out now.
1723                 break;
1724             }
1725             entry = mQueue.front();
1726             mQueue.pop();
1727         }
1728         {
1729             char name[64];
1730             snprintf(name, sizeof(name), "waiting for frame %lu",
1731                      static_cast<unsigned long>(entry.mFrameNum));
1732             ATRACE_NAME(name);
1733             mEngine->waitSync(entry.mSync, 0);
1734         }
1735     }
1736 }
1737 
handleShadow(const FloatRect & casterRect,float casterCornerRadius,const ShadowSettings & settings)1738 void GLESRenderEngine::handleShadow(const FloatRect& casterRect, float casterCornerRadius,
1739                                     const ShadowSettings& settings) {
1740     ATRACE_CALL();
1741     const float casterZ = settings.length / 2.0f;
1742     const GLShadowVertexGenerator shadows(casterRect, casterCornerRadius, casterZ,
1743                                           settings.casterIsTranslucent, settings.ambientColor,
1744                                           settings.spotColor, settings.lightPos,
1745                                           settings.lightRadius);
1746 
1747     // setup mesh for both shadows
1748     Mesh mesh = Mesh::Builder()
1749                         .setPrimitive(Mesh::TRIANGLES)
1750                         .setVertices(shadows.getVertexCount(), 2 /* size */)
1751                         .setShadowAttrs()
1752                         .setIndices(shadows.getIndexCount())
1753                         .build();
1754 
1755     Mesh::VertexArray<vec2> position = mesh.getPositionArray<vec2>();
1756     Mesh::VertexArray<vec4> shadowColor = mesh.getShadowColorArray<vec4>();
1757     Mesh::VertexArray<vec3> shadowParams = mesh.getShadowParamsArray<vec3>();
1758     shadows.fillVertices(position, shadowColor, shadowParams);
1759     shadows.fillIndices(mesh.getIndicesArray());
1760 
1761     mState.cornerRadius = 0.0f;
1762     mState.drawShadows = true;
1763     setupLayerTexturing(mShadowTexture.getTexture());
1764     drawMesh(mesh);
1765     mState.drawShadows = false;
1766 }
1767 
1768 } // namespace gl
1769 } // namespace renderengine
1770 } // namespace android
1771