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