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