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