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