1 /*
2  ** Copyright 2007, 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 __STDC_LIMIT_MACROS 1
18 #define ATRACE_TAG ATRACE_TAG_GRAPHICS
19 
20 #include "egl_display.h"
21 
22 #include "../egl_impl.h"
23 
24 #include <EGL/eglext_angle.h>
25 #include <private/EGL/display.h>
26 
27 #include <cutils/properties.h>
28 #include "Loader.h"
29 #include "egl_angle_platform.h"
30 #include "egl_cache.h"
31 #include "egl_object.h"
32 #include "egl_tls.h"
33 
34 #include <android/dlext.h>
35 #include <dlfcn.h>
36 #include <graphicsenv/GraphicsEnv.h>
37 
38 #include <android/hardware/configstore/1.0/ISurfaceFlingerConfigs.h>
39 #include <configstore/Utils.h>
40 
41 using namespace android::hardware::configstore;
42 using namespace android::hardware::configstore::V1_0;
43 
44 // ----------------------------------------------------------------------------
45 namespace android {
46 // ----------------------------------------------------------------------------
47 
48 static char const * const sVendorString     = "Android";
49 static char const* const sVersionString14 = "1.4 Android META-EGL";
50 static char const* const sVersionString15 = "1.5 Android META-EGL";
51 static char const * const sClientApiString  = "OpenGL_ES";
52 
53 extern char const * const gBuiltinExtensionString;
54 extern char const * const gExtensionString;
55 
56 extern void setGLHooksThreadSpecific(gl_hooks_t const *value);
57 
58 // ----------------------------------------------------------------------------
59 
findExtension(const char * exts,const char * name,size_t nameLen)60 bool findExtension(const char* exts, const char* name, size_t nameLen) {
61     if (exts) {
62         if (!nameLen) {
63             nameLen = strlen(name);
64         }
65         for (const char* match = strstr(exts, name); match; match = strstr(match + nameLen, name)) {
66             if (match[nameLen] == '\0' || match[nameLen] == ' ') {
67                 return true;
68             }
69         }
70     }
71     return false;
72 }
73 
needsAndroidPEglMitigation()74 bool needsAndroidPEglMitigation() {
75     static const int32_t vndk_version = property_get_int32("ro.vndk.version", -1);
76     return vndk_version <= 28;
77 }
78 
egl_get_init_count(EGLDisplay dpy)79 int egl_get_init_count(EGLDisplay dpy) {
80     egl_display_t* eglDisplay = egl_display_t::get(dpy);
81     return eglDisplay ? eglDisplay->getRefsCount() : 0;
82 }
83 
84 egl_display_t egl_display_t::sDisplay[NUM_DISPLAYS];
85 
egl_display_t()86 egl_display_t::egl_display_t() :
87     magic('_dpy'), finishOnSwap(false), traceGpuCompletion(false), refs(0), eglIsInitialized(false) {
88 }
89 
~egl_display_t()90 egl_display_t::~egl_display_t() {
91     magic = 0;
92     egl_cache_t::get()->terminate();
93 }
94 
get(EGLDisplay dpy)95 egl_display_t* egl_display_t::get(EGLDisplay dpy) {
96     if (uintptr_t(dpy) == 0) {
97         return nullptr;
98     }
99 
100     uintptr_t index = uintptr_t(dpy)-1U;
101     if (index >= NUM_DISPLAYS || !sDisplay[index].isValid()) {
102         return nullptr;
103     }
104     return &sDisplay[index];
105 }
106 
addObject(egl_object_t * object)107 void egl_display_t::addObject(egl_object_t* object) {
108     std::lock_guard<std::mutex> _l(lock);
109     objects.insert(object);
110 }
111 
removeObject(egl_object_t * object)112 void egl_display_t::removeObject(egl_object_t* object) {
113     std::lock_guard<std::mutex> _l(lock);
114     objects.erase(object);
115 }
116 
getObject(egl_object_t * object) const117 bool egl_display_t::getObject(egl_object_t* object) const {
118     std::lock_guard<std::mutex> _l(lock);
119     if (objects.find(object) != objects.end()) {
120         if (object->getDisplay() == this) {
121             object->incRef();
122             return true;
123         }
124     }
125     return false;
126 }
127 
getFromNativeDisplay(EGLNativeDisplayType disp,const EGLAttrib * attrib_list)128 EGLDisplay egl_display_t::getFromNativeDisplay(EGLNativeDisplayType disp,
129                                                const EGLAttrib* attrib_list) {
130     if (uintptr_t(disp) >= NUM_DISPLAYS)
131         return nullptr;
132 
133     return sDisplay[uintptr_t(disp)].getPlatformDisplay(disp, attrib_list);
134 }
135 
addAnglePlatformAttributes(egl_connection_t * const cnx,std::vector<EGLAttrib> & attrs)136 static bool addAnglePlatformAttributes(egl_connection_t* const cnx,
137                                        std::vector<EGLAttrib>& attrs) {
138     intptr_t vendorEGL = (intptr_t)cnx->vendorEGL;
139 
140     attrs.reserve(4 * 2);
141 
142     attrs.push_back(EGL_PLATFORM_ANGLE_TYPE_ANGLE);
143     attrs.push_back(cnx->angleBackend);
144 
145     switch (cnx->angleBackend) {
146         case EGL_PLATFORM_ANGLE_TYPE_VULKAN_ANGLE:
147             ALOGV("%s: Requesting Vulkan ANGLE back-end", __FUNCTION__);
148             char prop[PROPERTY_VALUE_MAX];
149             property_get("debug.angle.validation", prop, "0");
150             attrs.push_back(EGL_PLATFORM_ANGLE_DEBUG_LAYERS_ENABLED_ANGLE);
151             attrs.push_back(atoi(prop));
152             break;
153         case EGL_PLATFORM_ANGLE_TYPE_DEFAULT_ANGLE:
154             ALOGV("%s: Requesting Default ANGLE back-end", __FUNCTION__);
155             break;
156         case EGL_PLATFORM_ANGLE_TYPE_OPENGLES_ANGLE:
157             ALOGV("%s: Requesting OpenGL ES ANGLE back-end", __FUNCTION__);
158             // NOTE: This is only valid if the backend is OpenGL
159             attrs.push_back(EGL_PLATFORM_ANGLE_EGL_HANDLE_ANGLE);
160             attrs.push_back(vendorEGL);
161 
162             // Context virtualization is only available on GL back-end.
163             // Needed to support threading with GL back-end
164             attrs.push_back(EGL_PLATFORM_ANGLE_CONTEXT_VIRTUALIZATION_ANGLE);
165             attrs.push_back(EGL_FALSE);
166             break;
167         default:
168             ALOGE("%s: Requesting Unknown (%d) ANGLE back-end", __FUNCTION__, cnx->angleBackend);
169             break;
170     }
171 
172     return true;
173 }
174 
getPlatformDisplayAngle(EGLNativeDisplayType display,egl_connection_t * const cnx,const EGLAttrib * attrib_list,EGLint * error)175 static EGLDisplay getPlatformDisplayAngle(EGLNativeDisplayType display, egl_connection_t* const cnx,
176                                           const EGLAttrib* attrib_list, EGLint* error) {
177     EGLDisplay dpy = EGL_NO_DISPLAY;
178     *error = EGL_NONE;
179 
180     if (cnx->egl.eglGetPlatformDisplay) {
181         std::vector<EGLAttrib> attrs;
182         if (attrib_list) {
183             for (const EGLAttrib* attr = attrib_list; *attr != EGL_NONE; attr += 2) {
184                 attrs.push_back(attr[0]);
185                 attrs.push_back(attr[1]);
186             }
187         }
188 
189         if (!addAnglePlatformAttributes(cnx, attrs)) {
190             ALOGE("eglGetDisplay(%p) failed: Mismatch display request", display);
191             *error = EGL_BAD_PARAMETER;
192             return EGL_NO_DISPLAY;
193         }
194         attrs.push_back(EGL_NONE);
195 
196         dpy = cnx->egl.eglGetPlatformDisplay(EGL_PLATFORM_ANGLE_ANGLE,
197                                              reinterpret_cast<void*>(EGL_DEFAULT_DISPLAY),
198                                              attrs.data());
199         if (dpy == EGL_NO_DISPLAY) {
200             ALOGE("eglGetPlatformDisplay failed!");
201         } else {
202             if (!angle::initializeAnglePlatform(dpy)) {
203                 ALOGE("initializeAnglePlatform failed!");
204             }
205         }
206     } else {
207         ALOGE("eglGetDisplay(%p) failed: Unable to look up eglGetPlatformDisplay from ANGLE",
208               display);
209     }
210 
211     return dpy;
212 }
213 
getPlatformDisplay(EGLNativeDisplayType display,const EGLAttrib * attrib_list)214 EGLDisplay egl_display_t::getPlatformDisplay(EGLNativeDisplayType display,
215                                              const EGLAttrib* attrib_list) {
216     std::lock_guard<std::mutex> _l(lock);
217     ATRACE_CALL();
218 
219     // get our driver loader
220     Loader& loader(Loader::getInstance());
221 
222     egl_connection_t* const cnx = &gEGLImpl;
223     if (cnx->dso) {
224         EGLDisplay dpy = EGL_NO_DISPLAY;
225 
226         if (cnx->useAngle) {
227             EGLint error;
228             dpy = getPlatformDisplayAngle(display, cnx, attrib_list, &error);
229             if (error != EGL_NONE) {
230                 return setError(error, dpy);
231             }
232         }
233         if (dpy == EGL_NO_DISPLAY) {
234             // NOTE: eglGetPlatformDisplay with a empty attribute list
235             // behaves the same as eglGetDisplay
236             if (cnx->egl.eglGetPlatformDisplay) {
237                 dpy = cnx->egl.eglGetPlatformDisplay(EGL_PLATFORM_ANDROID_KHR, display,
238                                                      attrib_list);
239             }
240 
241             // It is possible that eglGetPlatformDisplay does not have a
242             // working implementation for Android platform; in that case,
243             // one last fallback to eglGetDisplay
244             if(dpy == EGL_NO_DISPLAY) {
245                 if (attrib_list) {
246                     ALOGW("getPlatformDisplay: unexpected attribute list, attributes ignored");
247                 }
248                 dpy = cnx->egl.eglGetDisplay(display);
249             }
250         }
251 
252         disp.dpy = dpy;
253         if (dpy == EGL_NO_DISPLAY) {
254             loader.close(cnx);
255         }
256     }
257 
258     return EGLDisplay(uintptr_t(display) + 1U);
259 }
260 
initialize(EGLint * major,EGLint * minor)261 EGLBoolean egl_display_t::initialize(EGLint *major, EGLint *minor) {
262 
263     { // scope for refLock
264         std::unique_lock<std::mutex> _l(refLock);
265         refs++;
266         if (refs > 1) {
267             // We don't know what to report until we know what the
268             // driver supports. Make sure we are initialized before
269             // returning the version info.
270             while(!eglIsInitialized) {
271                 refCond.wait(_l);
272             }
273             egl_connection_t* const cnx = &gEGLImpl;
274 
275             // TODO: If device doesn't provide 1.4 or 1.5 then we'll be
276             // changing the behavior from the past where we always advertise
277             // version 1.4. May need to check that revision is valid
278             // before using cnx->major & cnx->minor
279             if (major != nullptr) *major = cnx->major;
280             if (minor != nullptr) *minor = cnx->minor;
281             return EGL_TRUE;
282         }
283         while(eglIsInitialized) {
284             refCond.wait(_l);
285         }
286     }
287 
288     { // scope for lock
289         std::lock_guard<std::mutex> _l(lock);
290 
291         setGLHooksThreadSpecific(&gHooksNoContext);
292 
293         // initialize each EGL and
294         // build our own extension string first, based on the extension we know
295         // and the extension supported by our client implementation
296 
297         egl_connection_t* const cnx = &gEGLImpl;
298         cnx->major = -1;
299         cnx->minor = -1;
300         if (cnx->dso) {
301             EGLDisplay idpy = disp.dpy;
302             if (cnx->egl.eglInitialize(idpy, &cnx->major, &cnx->minor)) {
303                 //ALOGD("initialized dpy=%p, ver=%d.%d, cnx=%p",
304                 //        idpy, cnx->major, cnx->minor, cnx);
305 
306                 // display is now initialized
307                 disp.state = egl_display_t::INITIALIZED;
308 
309                 // get the query-strings for this display for each implementation
310                 disp.queryString.vendor = cnx->egl.eglQueryString(idpy,
311                         EGL_VENDOR);
312                 disp.queryString.version = cnx->egl.eglQueryString(idpy,
313                         EGL_VERSION);
314                 disp.queryString.extensions = cnx->egl.eglQueryString(idpy,
315                         EGL_EXTENSIONS);
316                 disp.queryString.clientApi = cnx->egl.eglQueryString(idpy,
317                         EGL_CLIENT_APIS);
318 
319             } else {
320                 ALOGW("eglInitialize(%p) failed (%s)", idpy,
321                         egl_tls_t::egl_strerror(cnx->egl.eglGetError()));
322             }
323         }
324 
325         if (cnx->minor == 5) {
326             // full list in egl_entries.in
327             if (!cnx->egl.eglCreateImage ||
328                 !cnx->egl.eglDestroyImage ||
329                 !cnx->egl.eglGetPlatformDisplay ||
330                 !cnx->egl.eglCreatePlatformWindowSurface ||
331                 !cnx->egl.eglCreatePlatformPixmapSurface ||
332                 !cnx->egl.eglCreateSync ||
333                 !cnx->egl.eglDestroySync ||
334                 !cnx->egl.eglClientWaitSync ||
335                 !cnx->egl.eglGetSyncAttrib ||
336                 !cnx->egl.eglWaitSync) {
337                 ALOGE("Driver indicates EGL 1.5 support, but does not have "
338                       "a critical API");
339                 cnx->minor = 4;
340             }
341         }
342 
343         // the query strings are per-display
344         mVendorString = sVendorString;
345         mVersionString.clear();
346         cnx->driverVersion = EGL_MAKE_VERSION(1, 4, 0);
347         mVersionString = sVersionString14;
348         if ((cnx->major == 1) && (cnx->minor == 5)) {
349             mVersionString = sVersionString15;
350             cnx->driverVersion = EGL_MAKE_VERSION(1, 5, 0);
351         }
352         if (mVersionString.empty()) {
353             ALOGW("Unexpected driver version: %d.%d, want 1.4 or 1.5", cnx->major, cnx->minor);
354             mVersionString = sVersionString14;
355         }
356         mClientApiString = sClientApiString;
357 
358         mExtensionString = gBuiltinExtensionString;
359 
360         hasColorSpaceSupport = findExtension(disp.queryString.extensions, "EGL_KHR_gl_colorspace");
361 
362         // Note: CDD requires that devices supporting wide color and/or HDR color also support
363         // the EGL_KHR_gl_colorspace extension.
364         bool wideColorBoardConfig =
365                 getBool<ISurfaceFlingerConfigs, &ISurfaceFlingerConfigs::hasWideColorDisplay>(
366                         false);
367 
368         // Add wide-color extensions if device can support wide-color
369         if (wideColorBoardConfig && hasColorSpaceSupport) {
370             mExtensionString.append(
371                     "EGL_EXT_gl_colorspace_scrgb EGL_EXT_gl_colorspace_scrgb_linear "
372                     "EGL_EXT_gl_colorspace_display_p3_linear EGL_EXT_gl_colorspace_display_p3 "
373                     "EGL_EXT_gl_colorspace_display_p3_passthrough ");
374         }
375 
376         bool hasHdrBoardConfig =
377                 getBool<ISurfaceFlingerConfigs, &ISurfaceFlingerConfigs::hasHDRDisplay>(false);
378 
379         if (hasHdrBoardConfig && hasColorSpaceSupport) {
380             // hasHDRBoardConfig indicates the system is capable of supporting HDR content.
381             // Typically that means there is an HDR capable display attached, but could be
382             // support for attaching an HDR display. In either case, advertise support for
383             // HDR color spaces.
384             mExtensionString.append(
385                     "EGL_EXT_gl_colorspace_bt2020_linear EGL_EXT_gl_colorspace_bt2020_pq ");
386         }
387 
388         char const* start = gExtensionString;
389         do {
390             // length of the extension name
391             size_t len = strcspn(start, " ");
392             if (len) {
393                 // NOTE: we could avoid the copy if we had strnstr.
394                 const std::string ext(start, len);
395                 // Mitigation for Android P vendor partitions: Adreno 530 driver shipped on
396                 // some Android P vendor partitions this extension under the draft KHR name,
397                 // but during Khronos review it was decided to demote it to EXT.
398                 if (needsAndroidPEglMitigation() && ext == "EGL_EXT_image_gl_colorspace" &&
399                     findExtension(disp.queryString.extensions, "EGL_KHR_image_gl_colorspace")) {
400                     mExtensionString.append("EGL_EXT_image_gl_colorspace ");
401                 }
402                 if (findExtension(disp.queryString.extensions, ext.c_str(), len)) {
403                     mExtensionString.append(ext + " ");
404                 }
405                 // advance to the next extension name, skipping the space.
406                 start += len;
407                 start += (*start == ' ') ? 1 : 0;
408             }
409         } while (*start != '\0');
410 
411         egl_cache_t::get()->initialize(this);
412 
413         char value[PROPERTY_VALUE_MAX];
414         property_get("debug.egl.finish", value, "0");
415         if (atoi(value)) {
416             finishOnSwap = true;
417         }
418 
419         property_get("debug.egl.traceGpuCompletion", value, "0");
420         if (atoi(value)) {
421             traceGpuCompletion = true;
422         }
423 
424         // TODO: If device doesn't provide 1.4 or 1.5 then we'll be
425         // changing the behavior from the past where we always advertise
426         // version 1.4. May need to check that revision is valid
427         // before using cnx->major & cnx->minor
428         if (major != nullptr) *major = cnx->major;
429         if (minor != nullptr) *minor = cnx->minor;
430     }
431 
432     { // scope for refLock
433         std::unique_lock<std::mutex> _l(refLock);
434         eglIsInitialized = true;
435         refCond.notify_all();
436     }
437 
438     return EGL_TRUE;
439 }
440 
terminate()441 EGLBoolean egl_display_t::terminate() {
442 
443     { // scope for refLock
444         std::unique_lock<std::mutex> _rl(refLock);
445         if (refs == 0) {
446             /*
447              * From the EGL spec (3.2):
448              * "Termination of a display that has already been terminated,
449              *  (...), is allowed, but the only effect of such a call is
450              *  to return EGL_TRUE (...)
451              */
452             return EGL_TRUE;
453         }
454 
455         // this is specific to Android, display termination is ref-counted.
456         refs--;
457         if (refs > 0) {
458             return EGL_TRUE;
459         }
460     }
461 
462     EGLBoolean res = EGL_FALSE;
463 
464     { // scope for lock
465         std::lock_guard<std::mutex> _l(lock);
466 
467         egl_connection_t* const cnx = &gEGLImpl;
468         if (cnx->dso && disp.state == egl_display_t::INITIALIZED) {
469             // If we're using ANGLE reset any custom DisplayPlatform
470             if (cnx->useAngle) {
471                 angle::resetAnglePlatform(disp.dpy);
472             }
473             if (cnx->egl.eglTerminate(disp.dpy) == EGL_FALSE) {
474                 ALOGW("eglTerminate(%p) failed (%s)", disp.dpy,
475                         egl_tls_t::egl_strerror(cnx->egl.eglGetError()));
476             }
477             // REVISIT: it's unclear what to do if eglTerminate() fails
478             disp.state = egl_display_t::TERMINATED;
479             res = EGL_TRUE;
480         }
481 
482         // Reset the extension string since it will be regenerated if we get
483         // reinitialized.
484         mExtensionString.clear();
485 
486         // Mark all objects remaining in the list as terminated, unless
487         // there are no reference to them, it which case, we're free to
488         // delete them.
489         size_t count = objects.size();
490         ALOGW_IF(count, "eglTerminate() called w/ %zu objects remaining", count);
491         for (auto o : objects) {
492             o->destroy();
493         }
494 
495         // this marks all object handles are "terminated"
496         objects.clear();
497     }
498 
499     { // scope for refLock
500         std::unique_lock<std::mutex> _rl(refLock);
501         eglIsInitialized = false;
502         refCond.notify_all();
503     }
504 
505     return res;
506 }
507 
loseCurrent(egl_context_t * cur_c)508 void egl_display_t::loseCurrent(egl_context_t * cur_c)
509 {
510     if (cur_c) {
511         egl_display_t* display = cur_c->getDisplay();
512         if (display) {
513             display->loseCurrentImpl(cur_c);
514         }
515     }
516 }
517 
loseCurrentImpl(egl_context_t * cur_c)518 void egl_display_t::loseCurrentImpl(egl_context_t * cur_c)
519 {
520     // by construction, these are either 0 or valid (possibly terminated)
521     // it should be impossible for these to be invalid
522     ContextRef _cur_c(cur_c);
523     SurfaceRef _cur_r(cur_c ? get_surface(cur_c->read) : nullptr);
524     SurfaceRef _cur_d(cur_c ? get_surface(cur_c->draw) : nullptr);
525 
526     { // scope for the lock
527         std::lock_guard<std::mutex> _l(lock);
528         cur_c->onLooseCurrent();
529 
530     }
531 
532     // This cannot be called with the lock held because it might end-up
533     // calling back into EGL (in particular when a surface is destroyed
534     // it calls ANativeWindow::disconnect
535     _cur_c.release();
536     _cur_r.release();
537     _cur_d.release();
538 }
539 
makeCurrent(egl_context_t * c,egl_context_t * cur_c,EGLSurface draw,EGLSurface read,EGLContext,EGLSurface impl_draw,EGLSurface impl_read,EGLContext impl_ctx)540 EGLBoolean egl_display_t::makeCurrent(egl_context_t* c, egl_context_t* cur_c,
541         EGLSurface draw, EGLSurface read, EGLContext /*ctx*/,
542         EGLSurface impl_draw, EGLSurface impl_read, EGLContext impl_ctx)
543 {
544     EGLBoolean result;
545 
546     // by construction, these are either 0 or valid (possibly terminated)
547     // it should be impossible for these to be invalid
548     ContextRef _cur_c(cur_c);
549     SurfaceRef _cur_r(cur_c ? get_surface(cur_c->read) : nullptr);
550     SurfaceRef _cur_d(cur_c ? get_surface(cur_c->draw) : nullptr);
551 
552     { // scope for the lock
553         std::lock_guard<std::mutex> _l(lock);
554         if (c) {
555             result = c->cnx->egl.eglMakeCurrent(
556                     disp.dpy, impl_draw, impl_read, impl_ctx);
557             if (result == EGL_TRUE) {
558                 c->onMakeCurrent(draw, read);
559             }
560         } else {
561             result = cur_c->cnx->egl.eglMakeCurrent(
562                     disp.dpy, impl_draw, impl_read, impl_ctx);
563             if (result == EGL_TRUE) {
564                 cur_c->onLooseCurrent();
565             }
566         }
567     }
568 
569     if (result == EGL_TRUE) {
570         // This cannot be called with the lock held because it might end-up
571         // calling back into EGL (in particular when a surface is destroyed
572         // it calls ANativeWindow::disconnect
573         _cur_c.release();
574         _cur_r.release();
575         _cur_d.release();
576     }
577 
578     return result;
579 }
580 
haveExtension(const char * name,size_t nameLen) const581 bool egl_display_t::haveExtension(const char* name, size_t nameLen) const {
582     if (!nameLen) {
583         nameLen = strlen(name);
584     }
585     return findExtension(mExtensionString.c_str(), name, nameLen);
586 }
587 
588 // ----------------------------------------------------------------------------
589 }; // namespace android
590 // ----------------------------------------------------------------------------
591