• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2 * Copyright (C) 2011 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 #include "eglDisplay.h"
17 #include "HostConnection.h"
18 #include "KeyedVectorUtils.h"
19 
20 #ifdef HOST_BUILD
21 #include "android/base/files/PathUtils.cpp"
22 #include "android/base/system/System.cpp"
23 #endif
24 
25 #include <string>
26 
27 #include <dlfcn.h>
28 
29 static const int systemEGLVersionMajor = 1;
30 static const int systemEGLVersionMinor = 4;
31 static const char systemEGLVendor[] = "Google Android emulator";
32 
33 // list of extensions supported by this EGL implementation
34 //  NOTE that each extension name should be suffixed with space
35 static const char systemStaticEGLExtensions[] =
36             "EGL_ANDROID_image_native_buffer "
37             "EGL_KHR_fence_sync "
38             "EGL_KHR_image_base "
39             "EGL_KHR_gl_texture_2d_image ";
40 
41 // extensions to add dynamically depending on host-side support
42 static const char kDynamicEGLExtNativeSync[] = "EGL_ANDROID_native_fence_sync ";
43 static const char kDynamicEGLExtWaitSync[] = "EGL_KHR_wait_sync ";
44 
45 static void *s_gles_lib = NULL;
46 static void *s_gles2_lib = NULL;
47 
48 // The following function will be called when we (libEGL)
49 // gets unloaded
50 // At this point we want to unload the gles libraries we
51 // might have loaded during initialization
do_on_unload(void)52 static void __attribute__ ((destructor)) do_on_unload(void)
53 {
54     if (s_gles_lib) {
55         dlclose(s_gles_lib);
56     }
57 
58     if (s_gles2_lib) {
59         dlclose(s_gles2_lib);
60     }
61 }
62 
eglDisplay()63 eglDisplay::eglDisplay() :
64     m_initialized(false),
65     m_major(0),
66     m_minor(0),
67     m_hostRendererVersion(0),
68     m_numConfigs(0),
69     m_numConfigAttribs(0),
70     m_attribs(),
71     m_configs(NULL),
72     m_gles_iface(NULL),
73     m_gles2_iface(NULL),
74     m_versionString(NULL),
75     m_vendorString(NULL),
76     m_extensionString(NULL)
77 {
78     pthread_mutex_init(&m_lock, NULL);
79     pthread_mutex_init(&m_ctxLock, NULL);
80     pthread_mutex_init(&m_surfaceLock, NULL);
81 }
82 
~eglDisplay()83 eglDisplay::~eglDisplay()
84 {
85     terminate();
86     pthread_mutex_destroy(&m_lock);
87     pthread_mutex_destroy(&m_ctxLock);
88     pthread_mutex_destroy(&m_surfaceLock);
89 }
90 
91 
92 
initialize(EGLClient_eglInterface * eglIface)93 bool eglDisplay::initialize(EGLClient_eglInterface *eglIface)
94 {
95     pthread_mutex_lock(&m_lock);
96     if (!m_initialized) {
97 
98         //
99         // load GLES client API
100         //
101         m_gles_iface = loadGLESClientAPI("libGLESv1_CM_emulation",
102                                          eglIface,
103                                          &s_gles_lib);
104         if (!m_gles_iface) {
105             pthread_mutex_unlock(&m_lock);
106             ALOGE("Failed to load gles1 iface");
107             return false;
108         }
109 
110 #ifdef WITH_GLES2
111         m_gles2_iface = loadGLESClientAPI("libGLESv2_emulation",
112                                           eglIface,
113                                           &s_gles2_lib);
114         // Note that if loading gles2 failed, we can still run with no
115         // GLES2 support, having GLES2 is not mandatory.
116 #endif
117 
118         //
119         // establish connection with the host
120         //
121         HostConnection *hcon = HostConnection::get();
122         if (!hcon) {
123             pthread_mutex_unlock(&m_lock);
124             ALOGE("Failed to establish connection with the host\n");
125             return false;
126         }
127         hcon->setGrallocOnly(false);
128 
129         //
130         // get renderControl encoder instance
131         //
132         renderControl_encoder_context_t *rcEnc = hcon->rcEncoder();
133         if (!rcEnc) {
134             pthread_mutex_unlock(&m_lock);
135             ALOGE("Failed to get renderControl encoder instance");
136             return false;
137         }
138 
139         //
140         // Query host reneder and EGL version
141         //
142         m_hostRendererVersion = rcEnc->rcGetRendererVersion(rcEnc);
143         EGLint status = rcEnc->rcGetEGLVersion(rcEnc, &m_major, &m_minor);
144         if (status != EGL_TRUE) {
145             // host EGL initialization failed !!
146             pthread_mutex_unlock(&m_lock);
147             return false;
148         }
149 
150         //
151         // Take minimum version beween what we support and what the host support
152         //
153         if (m_major > systemEGLVersionMajor) {
154             m_major = systemEGLVersionMajor;
155             m_minor = systemEGLVersionMinor;
156         }
157         else if (m_major == systemEGLVersionMajor &&
158                  m_minor > systemEGLVersionMinor) {
159             m_minor = systemEGLVersionMinor;
160         }
161 
162         //
163         // Query the host for the set of configs
164         //
165         m_numConfigs = rcEnc->rcGetNumConfigs(rcEnc, (uint32_t*)&m_numConfigAttribs);
166         if (m_numConfigs <= 0 || m_numConfigAttribs <= 0) {
167             // just sanity check - should never happen
168             pthread_mutex_unlock(&m_lock);
169             return false;
170         }
171 
172         uint32_t nInts = m_numConfigAttribs * (m_numConfigs + 1);
173         EGLint tmp_buf[nInts];
174         m_configs = new EGLint[nInts-m_numConfigAttribs];
175         if (!m_configs) {
176             pthread_mutex_unlock(&m_lock);
177             return false;
178         }
179 
180         EGLint n = rcEnc->rcGetConfigs(rcEnc, nInts*sizeof(EGLint), (GLuint*)tmp_buf);
181         if (n != m_numConfigs) {
182             pthread_mutex_unlock(&m_lock);
183             return false;
184         }
185 
186         // Fill the attributes vector.
187         // The first m_numConfigAttribs values of tmp_buf are the actual attributes enums.
188         for (int i=0; i<m_numConfigAttribs; i++) {
189             m_attribs[tmp_buf[i]] = i;
190         }
191 
192         memcpy(m_configs, tmp_buf + m_numConfigAttribs,
193                m_numConfigs*m_numConfigAttribs*sizeof(EGLint));
194 
195         m_initialized = true;
196     }
197     pthread_mutex_unlock(&m_lock);
198 
199     processConfigs();
200 
201     return true;
202 }
203 
processConfigs()204 void eglDisplay::processConfigs()
205 {
206     for (intptr_t i=0; i<m_numConfigs; i++) {
207         EGLConfig config = (EGLConfig)i;
208         PixelFormat format;
209         if (getConfigNativePixelFormat(config, &format)) {
210             setConfigAttrib(config, EGL_NATIVE_VISUAL_ID, format);
211         }
212     }
213 }
214 
terminate()215 void eglDisplay::terminate()
216 {
217     pthread_mutex_lock(&m_lock);
218     if (m_initialized) {
219         // Cannot use the for loop in the following code because
220         // eglDestroyContext may erase elements.
221         EGLContextSet::iterator ctxIte = m_contexts.begin();
222         while (ctxIte != m_contexts.end()) {
223             EGLContextSet::iterator ctxToDelete = ctxIte;
224             ctxIte ++;
225             eglDestroyContext(static_cast<EGLDisplay>(this), *ctxToDelete);
226         }
227         EGLSurfaceSet::iterator surfaceIte = m_surfaces.begin();
228         while (surfaceIte != m_surfaces.end()) {
229             EGLSurfaceSet::iterator surfaceToDelete = surfaceIte;
230             surfaceIte ++;
231             eglDestroySurface(static_cast<EGLDisplay>(this), *surfaceToDelete);
232         }
233         m_initialized = false;
234         delete [] m_configs;
235         m_configs = NULL;
236 
237         if (m_versionString) {
238             free(m_versionString);
239             m_versionString = NULL;
240         }
241         if (m_vendorString) {
242             free(m_vendorString);
243             m_vendorString = NULL;
244         }
245         if (m_extensionString) {
246             free(m_extensionString);
247             m_extensionString = NULL;
248         }
249     }
250     pthread_mutex_unlock(&m_lock);
251 }
252 
253 #ifdef __APPLE__
254 #define LIBSUFFIX ".dylib"
255 #else
256 #ifdef _WIN32
257 #define LIBSUFFIX ".dll"
258 #else
259 #define LIBSUFFIX ".so"
260 #endif // !_WIN32 (linux)
261 #endif // !__APPLE__
262 
263 #ifndef HOST_BUILD
264 #if PLATFORM_SDK_VERSION >= 26
265 #define PARTITION "/vendor"
266 #else
267 #define PARTITION "/system"
268 #endif // !PLATFORM_SDK_VERSION >= 26
269 #if __LP64__
270 #define LIBDIR "/lib64/egl/"
271 #else
272 #define LIBDIR "/lib/egl/"
273 #endif // !__LP64__
274 #endif // !HOST_BUILD
275 
loadGLESClientAPI(const char * basename,EGLClient_eglInterface * eglIface,void ** libHandle)276 EGLClient_glesInterface *eglDisplay::loadGLESClientAPI(const char *basename,
277                                                        EGLClient_eglInterface *eglIface,
278                                                        void **libHandle)
279 {
280 #ifdef HOST_BUILD
281     std::string baseDir =
282         android::base::System::get()->getProgramDirectory();
283     std::string path =
284         android::base::pj(
285             baseDir, "lib64", std::string(basename) + LIBSUFFIX);
286     void *lib = dlopen(path.c_str(), RTLD_NOW);
287 #else
288     std::string path(PARTITION);
289     path += LIBDIR;
290     path += basename;
291     path += LIBSUFFIX;
292     void *lib = dlopen(path.c_str(), RTLD_NOW);
293 #endif
294 
295     if (!lib) {
296         ALOGE("Failed to dlopen %s", basename);
297         return NULL;
298     }
299 
300     init_emul_gles_t init_gles_func = (init_emul_gles_t)dlsym(lib,"init_emul_gles");
301     if (!init_gles_func) {
302         ALOGE("Failed to find init_emul_gles");
303         dlclose((void*)lib);
304         return NULL;
305     }
306 
307     *libHandle = lib;
308     return (*init_gles_func)(eglIface);
309 }
310 
queryHostEGLString(EGLint name)311 static char *queryHostEGLString(EGLint name)
312 {
313     HostConnection *hcon = HostConnection::get();
314     if (hcon) {
315         renderControl_encoder_context_t *rcEnc = hcon->rcEncoder();
316         if (rcEnc) {
317             int n = rcEnc->rcQueryEGLString(rcEnc, name, NULL, 0);
318             if (n < 0) {
319                 // allocate space for the string.
320                 char *str = (char *)malloc(-n);
321                 n = rcEnc->rcQueryEGLString(rcEnc, name, str, -n);
322                 if (n > 0) {
323                     return str;
324                 }
325 
326                 free(str);
327             }
328         }
329     }
330 
331     return NULL;
332 }
333 
findExtInList(const char * token,int tokenlen,const char * list)334 static bool findExtInList(const char* token, int tokenlen, const char* list)
335 {
336     const char* p = list;
337     while (*p != '\0') {
338         const char* q = strchr(p, ' ');
339         if (q == NULL) {
340             /* should not happen, list must be space-terminated */
341             break;
342         }
343         if (tokenlen == (q - p) && !memcmp(token, p, tokenlen)) {
344             return true;  /* found it */
345         }
346         p = q+1;
347     }
348     return false;  /* not found */
349 }
350 
buildExtensionString()351 static char *buildExtensionString()
352 {
353     //Query host extension string
354     char *hostExt = queryHostEGLString(EGL_EXTENSIONS);
355     if (!hostExt || (hostExt[1] == '\0')) {
356         // no extensions on host - only static extension list supported
357         return strdup(systemStaticEGLExtensions);
358     }
359 
360     int n = strlen(hostExt);
361     if (n > 0) {
362         char *initialEGLExts;
363         char *finalEGLExts;
364 
365         HostConnection *hcon = HostConnection::get();
366         // If we got here, we must have succeeded in queryHostEGLString
367         // and we thus should have a valid connection
368         assert(hcon);
369 
370         asprintf(&initialEGLExts,"%s%s", systemStaticEGLExtensions, hostExt);
371 
372         std::string dynamicEGLExtensions;
373 
374         if (hcon->rcEncoder()->hasNativeSync() &&
375             !strstr(initialEGLExts, kDynamicEGLExtNativeSync)) {
376             dynamicEGLExtensions += kDynamicEGLExtNativeSync;
377 
378             if (hcon->rcEncoder()->hasNativeSyncV3()) {
379                 dynamicEGLExtensions += kDynamicEGLExtWaitSync;
380             }
381         }
382 
383         asprintf(&finalEGLExts, "%s%s", initialEGLExts, dynamicEGLExtensions.c_str());
384 
385         free((char*)hostExt);
386         return finalEGLExts;
387     }
388     else {
389         free((char*)hostExt);
390         return strdup(systemStaticEGLExtensions);
391     }
392 }
393 
queryString(EGLint name)394 const char *eglDisplay::queryString(EGLint name)
395 {
396     if (name == EGL_CLIENT_APIS) {
397         return "OpenGL_ES";
398     }
399     else if (name == EGL_VERSION) {
400         pthread_mutex_lock(&m_lock);
401         if (m_versionString) {
402             pthread_mutex_unlock(&m_lock);
403             return m_versionString;
404         }
405 
406         // build version string
407         asprintf(&m_versionString, "%d.%d", m_major, m_minor);
408         pthread_mutex_unlock(&m_lock);
409 
410         return m_versionString;
411     }
412     else if (name == EGL_VENDOR) {
413         pthread_mutex_lock(&m_lock);
414         if (m_vendorString) {
415             pthread_mutex_unlock(&m_lock);
416             return m_vendorString;
417         }
418 
419         // build vendor string
420         const char *hostVendor = queryHostEGLString(EGL_VENDOR);
421 
422         if (hostVendor) {
423             asprintf(&m_vendorString, "%s Host: %s",
424                                      systemEGLVendor, hostVendor);
425             free((char*)hostVendor);
426         }
427         else {
428             m_vendorString = (char *)systemEGLVendor;
429         }
430         pthread_mutex_unlock(&m_lock);
431 
432         return m_vendorString;
433     }
434     else if (name == EGL_EXTENSIONS) {
435         pthread_mutex_lock(&m_lock);
436         if (m_extensionString) {
437             pthread_mutex_unlock(&m_lock);
438             return m_extensionString;
439         }
440 
441         // build extension string
442         m_extensionString = buildExtensionString();
443         pthread_mutex_unlock(&m_lock);
444 
445         return m_extensionString;
446     }
447     else {
448         ALOGE("[%s] Unknown name %d\n", __FUNCTION__, name);
449         return NULL;
450     }
451 }
452 
453 /* To get the value of attribute <a> of config <c> use the following formula:
454  * value = *(m_configs + (int)c*m_numConfigAttribs + a);
455  */
getAttribValue(EGLConfig config,EGLint attribIdx,EGLint * value)456 EGLBoolean eglDisplay::getAttribValue(EGLConfig config, EGLint attribIdx, EGLint * value)
457 {
458     if (attribIdx == ATTRIBUTE_NONE)
459     {
460         ALOGE("[%s] Bad attribute idx\n", __FUNCTION__);
461         return EGL_FALSE;
462     }
463     *value = *(m_configs + (intptr_t)config*m_numConfigAttribs + attribIdx);
464     return EGL_TRUE;
465 }
466 
467 #define EGL_COLOR_COMPONENT_TYPE_EXT 0x3339
468 #define EGL_COLOR_COMPONENT_TYPE_FIXED_EXT 0x333A
469 
getConfigAttrib(EGLConfig config,EGLint attrib,EGLint * value)470 EGLBoolean eglDisplay::getConfigAttrib(EGLConfig config, EGLint attrib, EGLint * value)
471 {
472     if (attrib == EGL_FRAMEBUFFER_TARGET_ANDROID) {
473         *value = EGL_TRUE;
474         return EGL_TRUE;
475     }
476     if (attrib == EGL_COVERAGE_SAMPLES_NV ||
477         attrib == EGL_COVERAGE_BUFFERS_NV) {
478         *value = 0;
479         return EGL_TRUE;
480     }
481     if (attrib == EGL_DEPTH_ENCODING_NV) {
482         *value = EGL_DEPTH_ENCODING_NONE_NV;
483         return EGL_TRUE;
484     }
485     if  (attrib == EGL_COLOR_COMPONENT_TYPE_EXT) {
486         *value = EGL_COLOR_COMPONENT_TYPE_FIXED_EXT;
487         return EGL_TRUE;
488     }
489     //Though it seems that valueFor() is thread-safe, we don't take chanses
490     pthread_mutex_lock(&m_lock);
491     EGLBoolean ret =
492         getAttribValue(
493             config,
494             findObjectOrDefault(
495                 m_attribs, attrib, EGL_DONT_CARE),
496             value);
497     pthread_mutex_unlock(&m_lock);
498     return ret;
499 }
500 
dumpConfig(EGLConfig config)501 void eglDisplay::dumpConfig(EGLConfig config)
502 {
503     EGLint value = 0;
504     DBG("^^^^^^^^^^ dumpConfig %d ^^^^^^^^^^^^^^^^^^", (int)config);
505     for (int i=0; i<m_numConfigAttribs; i++) {
506         getAttribValue(config, i, &value);
507         DBG("{%d}[%d] %d\n", (int)config, i, value);
508     }
509 }
510 
511 /* To set the value of attribute <a> of config <c> use the following formula:
512  * *(m_configs + (int)c*m_numConfigAttribs + a) = value;
513  */
setAttribValue(EGLConfig config,EGLint attribIdx,EGLint value)514 EGLBoolean eglDisplay::setAttribValue(EGLConfig config, EGLint attribIdx, EGLint value)
515 {
516     if (attribIdx == ATTRIBUTE_NONE)
517     {
518         ALOGE("[%s] Bad attribute idx\n", __FUNCTION__);
519         return EGL_FALSE;
520     }
521     *(m_configs + (intptr_t)config*m_numConfigAttribs + attribIdx) = value;
522     return EGL_TRUE;
523 }
524 
setConfigAttrib(EGLConfig config,EGLint attrib,EGLint value)525 EGLBoolean eglDisplay::setConfigAttrib(EGLConfig config, EGLint attrib, EGLint value)
526 {
527     //Though it seems that valueFor() is thread-safe, we don't take chanses
528     pthread_mutex_lock(&m_lock);
529     EGLBoolean ret =
530         setAttribValue(
531             config,
532             findObjectOrDefault(
533                 m_attribs,
534                 attrib,
535                 EGL_DONT_CARE),
536             value);
537     pthread_mutex_unlock(&m_lock);
538     return ret;
539 }
540 
541 
getConfigNativePixelFormat(EGLConfig config,PixelFormat * format)542 EGLBoolean eglDisplay::getConfigNativePixelFormat(EGLConfig config, PixelFormat * format)
543 {
544     EGLint redSize, blueSize, greenSize, alphaSize;
545 
546     if (!(
547             getAttribValue(
548                 config,
549                 findObjectOrDefault(m_attribs, EGL_RED_SIZE, EGL_DONT_CARE),
550                 &redSize) &&
551             getAttribValue(
552                 config,
553                 findObjectOrDefault(m_attribs, EGL_BLUE_SIZE, EGL_DONT_CARE),
554                 &blueSize) &&
555             getAttribValue(
556                 config,
557                 findObjectOrDefault(m_attribs, EGL_GREEN_SIZE, EGL_DONT_CARE),
558                 &greenSize) &&
559             getAttribValue(
560                 config,
561                 findObjectOrDefault(m_attribs, EGL_ALPHA_SIZE, EGL_DONT_CARE),
562                 &alphaSize))) {
563         ALOGE("Couldn't find value for one of the pixel format attributes");
564         return EGL_FALSE;
565     }
566 
567     //calculate the GL internal format
568     if ((redSize==8)&&(greenSize==8)&&(blueSize==8)&&(alphaSize==8)) *format = PIXEL_FORMAT_RGBA_8888; //XXX: BGR?
569     else if ((redSize==8)&&(greenSize==8)&&(blueSize==8)&&(alphaSize==0)) *format = PIXEL_FORMAT_RGBX_8888; //XXX or PIXEL_FORMAT_RGB_888
570     else if ((redSize==5)&&(greenSize==6)&&(blueSize==5)&&(alphaSize==0)) *format = PIXEL_FORMAT_RGB_565;
571     else if ((redSize==5)&&(greenSize==5)&&(blueSize==5)&&(alphaSize==1)) *format = PIXEL_FORMAT_RGBA_5551;
572     else if ((redSize==4)&&(greenSize==4)&&(blueSize==4)&&(alphaSize==4)) *format = PIXEL_FORMAT_RGBA_4444;
573     else {
574         return EGL_FALSE;
575     }
576     return EGL_TRUE;
577 }
getConfigGLPixelFormat(EGLConfig config,GLenum * format)578 EGLBoolean eglDisplay::getConfigGLPixelFormat(EGLConfig config, GLenum * format)
579 {
580     EGLint redSize, blueSize, greenSize, alphaSize;
581 
582     if (!(
583             getAttribValue(
584                 config,
585                 findObjectOrDefault(m_attribs, EGL_RED_SIZE, EGL_DONT_CARE),
586                 &redSize) &&
587             getAttribValue(
588                 config,
589                 findObjectOrDefault(m_attribs, EGL_BLUE_SIZE, EGL_DONT_CARE),
590                 &blueSize) &&
591             getAttribValue(
592                 config,
593                 findObjectOrDefault(m_attribs, EGL_GREEN_SIZE, EGL_DONT_CARE),
594                 &greenSize) &&
595             getAttribValue(
596                 config,
597                 findObjectOrDefault(m_attribs, EGL_ALPHA_SIZE, EGL_DONT_CARE),
598                 &alphaSize))) {
599         ALOGE("Couldn't find value for one of the pixel format attributes");
600         return EGL_FALSE;
601     }
602 
603     //calculate the GL internal format
604     if ((redSize == greenSize) && (redSize == blueSize) &&
605         ((redSize == 8) || (redSize == 16) || (redSize == 32)))
606     {
607         if (alphaSize == 0) *format = GL_RGB;
608         else *format = GL_RGBA;
609     }
610     else if ((redSize==5)&&(greenSize==6)&&(blueSize==5)&&(alphaSize==0)) *format = GL_RGB565_OES;
611     else if ((redSize==5)&&(greenSize==5)&&(blueSize==5)&&(alphaSize==1)) *format = GL_RGB5_A1_OES;
612     else if ((redSize==4)&&(greenSize==4)&&(blueSize==4)&&(alphaSize==4)) *format = GL_RGBA4_OES;
613     else return EGL_FALSE;
614 
615     return EGL_TRUE;
616 }
617 
onCreateContext(EGLContext ctx)618 void eglDisplay::onCreateContext(EGLContext ctx) {
619     pthread_mutex_lock(&m_ctxLock);
620     m_contexts.insert(ctx);
621     pthread_mutex_unlock(&m_ctxLock);
622 }
623 
onCreateSurface(EGLSurface surface)624 void eglDisplay::onCreateSurface(EGLSurface surface) {
625     pthread_mutex_lock(&m_surfaceLock);
626     m_surfaces.insert(surface);
627     pthread_mutex_unlock(&m_surfaceLock);
628 }
629 
onDestroyContext(EGLContext ctx)630 void eglDisplay::onDestroyContext(EGLContext ctx) {
631     pthread_mutex_lock(&m_ctxLock);
632     m_contexts.erase(ctx);
633     pthread_mutex_unlock(&m_ctxLock);
634 }
635 
onDestroySurface(EGLSurface surface)636 void eglDisplay::onDestroySurface(EGLSurface surface) {
637     pthread_mutex_lock(&m_surfaceLock);
638     m_surfaces.erase(surface);
639     pthread_mutex_unlock(&m_surfaceLock);
640 }
641 
isContext(EGLContext ctx)642 bool eglDisplay::isContext(EGLContext ctx) {
643     pthread_mutex_lock(&m_ctxLock);
644     bool res = m_contexts.find(ctx) != m_contexts.end();
645     pthread_mutex_unlock(&m_ctxLock);
646     return res;
647 }
648 
isSurface(EGLSurface surface)649 bool eglDisplay::isSurface(EGLSurface surface) {
650     pthread_mutex_lock(&m_surfaceLock);
651     bool res = m_surfaces.find(surface) != m_surfaces.end();
652     pthread_mutex_unlock(&m_surfaceLock);
653     return res;
654 }
655