• 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 #include <dlfcn.h>
27 #include <GLES3/gl31.h>
28 
29 #include <system/graphics.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         m_gles2_iface = loadGLESClientAPI("libGLESv2_emulation",
115                                           eglIface,
116                                           &s_gles2_lib);
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 
175         m_configs = new EGLint[nInts-m_numConfigAttribs];
176 
177         if (!m_configs) {
178             pthread_mutex_unlock(&m_lock);
179             return false;
180         }
181 
182         EGLint n = rcEnc->rcGetConfigs(rcEnc, nInts*sizeof(EGLint), (GLuint*)tmp_buf);
183         if (n != m_numConfigs) {
184             pthread_mutex_unlock(&m_lock);
185             return false;
186         }
187 
188         // Fill the attributes vector.
189         // The first m_numConfigAttribs values of tmp_buf are the actual attributes enums.
190         for (int i=0; i<m_numConfigAttribs; i++) {
191             m_attribs[tmp_buf[i]] = i;
192         }
193 
194         memcpy(m_configs, tmp_buf + m_numConfigAttribs,
195                m_numConfigs*m_numConfigAttribs*sizeof(EGLint));
196 
197         m_initialized = true;
198     }
199     pthread_mutex_unlock(&m_lock);
200 
201     processConfigs();
202 
203     return true;
204 }
205 
processConfigs()206 void eglDisplay::processConfigs()
207 {
208     for (intptr_t i=0; i<m_numConfigs; i++) {
209         EGLConfig config = getConfigAtIndex(i);
210         uint32_t format;
211         if (getConfigNativePixelFormat(config, &format)) {
212             setConfigAttrib(config, EGL_NATIVE_VISUAL_ID, format);
213         }
214     }
215 }
216 
terminate()217 void eglDisplay::terminate()
218 {
219     pthread_mutex_lock(&m_lock);
220     if (m_initialized) {
221         // Cannot use the for loop in the following code because
222         // eglDestroyContext may erase elements.
223         EGLContextSet::iterator ctxIte = m_contexts.begin();
224         while (ctxIte != m_contexts.end()) {
225             EGLContextSet::iterator ctxToDelete = ctxIte;
226             ctxIte ++;
227             eglDestroyContext(static_cast<EGLDisplay>(this), *ctxToDelete);
228         }
229         EGLSurfaceSet::iterator surfaceIte = m_surfaces.begin();
230         while (surfaceIte != m_surfaces.end()) {
231             EGLSurfaceSet::iterator surfaceToDelete = surfaceIte;
232             surfaceIte ++;
233             eglDestroySurface(static_cast<EGLDisplay>(this), *surfaceToDelete);
234         }
235         m_initialized = false;
236         delete [] m_configs;
237         m_configs = NULL;
238 
239         if (m_versionString) {
240             free(m_versionString);
241             m_versionString = NULL;
242         }
243         if (m_vendorString) {
244             free(m_vendorString);
245             m_vendorString = NULL;
246         }
247         if (m_extensionString) {
248             free(m_extensionString);
249             m_extensionString = NULL;
250         }
251     }
252     pthread_mutex_unlock(&m_lock);
253 }
254 
255 #ifdef __APPLE__
256 #define LIBSUFFIX ".dylib"
257 #else
258 #ifdef _WIN32
259 #define LIBSUFFIX ".dll"
260 #else
261 #define LIBSUFFIX ".so"
262 #endif // !_WIN32 (linux)
263 #endif // !__APPLE__
264 
265 #ifndef HOST_BUILD
266 #if PLATFORM_SDK_VERSION >= 26
267 #define PARTITION "/vendor"
268 #else
269 #define PARTITION "/system"
270 #endif // !PLATFORM_SDK_VERSION >= 26
271 #if __LP64__
272 #define LIBDIR "/lib64/egl/"
273 #else
274 #define LIBDIR "/lib/egl/"
275 #endif // !__LP64__
276 #endif // !HOST_BUILD
277 
loadGLESClientAPI(const char * basename,EGLClient_eglInterface * eglIface,void ** libHandle)278 EGLClient_glesInterface *eglDisplay::loadGLESClientAPI(const char *basename,
279                                                        EGLClient_eglInterface *eglIface,
280                                                        void **libHandle)
281 {
282 #ifdef HOST_BUILD
283     std::string baseDir =
284         android::base::System::get()->getProgramDirectory();
285     std::string path =
286         android::base::pj(
287             baseDir, "lib64", std::string(basename) + LIBSUFFIX);
288     void *lib = dlopen(path.c_str(), RTLD_NOW);
289 #else
290     std::string path(PARTITION);
291     path += LIBDIR;
292     path += basename;
293     path += LIBSUFFIX;
294     void *lib = dlopen(path.c_str(), RTLD_NOW);
295 #endif
296 
297     if (!lib) {
298         ALOGE("Failed to dlopen %s", basename);
299         return NULL;
300     }
301 
302     init_emul_gles_t init_gles_func = (init_emul_gles_t)dlsym(lib,"init_emul_gles");
303     if (!init_gles_func) {
304         ALOGE("Failed to find init_emul_gles");
305         dlclose((void*)lib);
306         return NULL;
307     }
308 
309     *libHandle = lib;
310     return (*init_gles_func)(eglIface);
311 }
312 
queryHostEGLString(EGLint name)313 static char *queryHostEGLString(EGLint name)
314 {
315     HostConnection *hcon = HostConnection::get();
316     if (hcon) {
317         renderControl_encoder_context_t *rcEnc = hcon->rcEncoder();
318         if (rcEnc) {
319             int n = rcEnc->rcQueryEGLString(rcEnc, name, NULL, 0);
320             if (n < 0) {
321                 // allocate space for the string.
322                 char *str = (char *)malloc(-n);
323                 n = rcEnc->rcQueryEGLString(rcEnc, name, str, -n);
324                 if (n > 0) {
325                     return str;
326                 }
327 
328                 free(str);
329             }
330         }
331     }
332 
333     return NULL;
334 }
335 
buildExtensionString()336 static char *buildExtensionString()
337 {
338     //Query host extension string
339     char *hostExt = queryHostEGLString(EGL_EXTENSIONS);
340     if (!hostExt || (hostExt[1] == '\0')) {
341         // no extensions on host - only static extension list supported
342         return strdup(systemStaticEGLExtensions);
343     }
344 
345     int n = strlen(hostExt);
346     if (n > 0) {
347         char *initialEGLExts;
348         char *finalEGLExts;
349 
350         HostConnection *hcon = HostConnection::get();
351         // If we got here, we must have succeeded in queryHostEGLString
352         // and we thus should have a valid connection
353         assert(hcon);
354 
355         asprintf(&initialEGLExts,"%s%s", systemStaticEGLExtensions, hostExt);
356 
357         std::string dynamicEGLExtensions;
358 
359         if ((hcon->rcEncoder()->hasVirtioGpuNativeSync() || hcon->rcEncoder()->hasNativeSync()) &&
360             !strstr(initialEGLExts, kDynamicEGLExtNativeSync)) {
361             dynamicEGLExtensions += kDynamicEGLExtNativeSync;
362 
363             if (hcon->rcEncoder()->hasVirtioGpuNativeSync() || hcon->rcEncoder()->hasNativeSyncV3()) {
364                 dynamicEGLExtensions += kDynamicEGLExtWaitSync;
365             }
366         }
367 
368         asprintf(&finalEGLExts, "%s%s", initialEGLExts, dynamicEGLExtensions.c_str());
369 
370         free((char*)hostExt);
371         return finalEGLExts;
372     }
373     else {
374         free((char*)hostExt);
375         return strdup(systemStaticEGLExtensions);
376     }
377 }
378 
queryString(EGLint name)379 const char *eglDisplay::queryString(EGLint name)
380 {
381     if (name == EGL_CLIENT_APIS) {
382         return "OpenGL_ES";
383     }
384     else if (name == EGL_VERSION) {
385         pthread_mutex_lock(&m_lock);
386         if (m_versionString) {
387             pthread_mutex_unlock(&m_lock);
388             return m_versionString;
389         }
390 
391         // build version string
392         asprintf(&m_versionString, "%d.%d", m_major, m_minor);
393         pthread_mutex_unlock(&m_lock);
394 
395         return m_versionString;
396     }
397     else if (name == EGL_VENDOR) {
398         pthread_mutex_lock(&m_lock);
399         if (m_vendorString) {
400             pthread_mutex_unlock(&m_lock);
401             return m_vendorString;
402         }
403 
404         // build vendor string
405         const char *hostVendor = queryHostEGLString(EGL_VENDOR);
406 
407         if (hostVendor) {
408             asprintf(&m_vendorString, "%s Host: %s",
409                                      systemEGLVendor, hostVendor);
410             free((char*)hostVendor);
411         }
412         else {
413             m_vendorString = (char *)systemEGLVendor;
414         }
415         pthread_mutex_unlock(&m_lock);
416 
417         return m_vendorString;
418     }
419     else if (name == EGL_EXTENSIONS) {
420         pthread_mutex_lock(&m_lock);
421         if (m_extensionString) {
422             pthread_mutex_unlock(&m_lock);
423             return m_extensionString;
424         }
425 
426         // build extension string
427         m_extensionString = buildExtensionString();
428         pthread_mutex_unlock(&m_lock);
429 
430         return m_extensionString;
431     }
432     else {
433         ALOGE("[%s] Unknown name %d\n", __FUNCTION__, name);
434         return NULL;
435     }
436 }
437 
438 /* To get the value of attribute <a> of config <c> use the following formula:
439  * value = *(m_configs + (int)c*m_numConfigAttribs + a);
440  */
getAttribValue(EGLConfig config,EGLint attribIdx,EGLint * value)441 EGLBoolean eglDisplay::getAttribValue(EGLConfig config, EGLint attribIdx, EGLint * value)
442 {
443     if (attribIdx == ATTRIBUTE_NONE)
444     {
445         ALOGE("[%s] Bad attribute idx\n", __FUNCTION__);
446         return EGL_FALSE;
447     }
448     *value = *(m_configs + (intptr_t)(getIndexOfConfig(config))*m_numConfigAttribs + attribIdx);
449     return EGL_TRUE;
450 }
451 
452 #define EGL_COLOR_COMPONENT_TYPE_EXT 0x3339
453 #define EGL_COLOR_COMPONENT_TYPE_FIXED_EXT 0x333A
454 
getConfigAtIndex(uint32_t index) const455 EGLConfig eglDisplay::getConfigAtIndex(uint32_t index) const {
456     uintptr_t asPtr = (uintptr_t)index;
457     return (EGLConfig)(asPtr + 1);
458 }
459 
getIndexOfConfig(EGLConfig config) const460 uint32_t eglDisplay::getIndexOfConfig(EGLConfig config) const {
461     uintptr_t asInteger = (uintptr_t)config;
462     return (uint32_t)(asInteger - 1);
463 }
464 
isValidConfig(EGLConfig cfg) const465 bool eglDisplay::isValidConfig(EGLConfig cfg) const {
466     uint32_t index = getIndexOfConfig(cfg);
467     intptr_t asInt = (intptr_t)index;
468     return !(asInt < 0 || asInt > m_numConfigs);
469 }
470 
getConfigAttrib(EGLConfig config,EGLint attrib,EGLint * value)471 EGLBoolean eglDisplay::getConfigAttrib(EGLConfig config, EGLint attrib, EGLint * value)
472 {
473     if (attrib == EGL_FRAMEBUFFER_TARGET_ANDROID) {
474         *value = EGL_TRUE;
475         return EGL_TRUE;
476     }
477     if (attrib == EGL_COVERAGE_SAMPLES_NV ||
478         attrib == EGL_COVERAGE_BUFFERS_NV) {
479         *value = 0;
480         return EGL_TRUE;
481     }
482     if (attrib == EGL_DEPTH_ENCODING_NV) {
483         *value = EGL_DEPTH_ENCODING_NONE_NV;
484         return EGL_TRUE;
485     }
486     if  (attrib == EGL_COLOR_COMPONENT_TYPE_EXT) {
487         *value = EGL_COLOR_COMPONENT_TYPE_FIXED_EXT;
488         return EGL_TRUE;
489     }
490     //Though it seems that valueFor() is thread-safe, we don't take chanses
491     pthread_mutex_lock(&m_lock);
492     EGLBoolean ret =
493         getAttribValue(
494             config,
495             findObjectOrDefault(
496                 m_attribs, attrib, EGL_DONT_CARE),
497             value);
498     pthread_mutex_unlock(&m_lock);
499     return ret;
500 }
501 
dumpConfig(EGLConfig config)502 void eglDisplay::dumpConfig(EGLConfig config)
503 {
504     EGLint value = 0;
505     DBG("^^^^^^^^^^ dumpConfig %p ^^^^^^^^^^^^^^^^^^", config);
506     for (int i=0; i<m_numConfigAttribs; i++) {
507         getAttribValue(config, i, &value);
508         DBG("Config %p: {%u}[%d] %d\n", config, getIndexOfConfig(config), i, value);
509     }
510 }
511 
512 /* To set the value of attribute <a> of config <c> use the following formula:
513  * *(m_configs + (int)c*m_numConfigAttribs + a) = value;
514  */
setAttribValue(EGLConfig config,EGLint attribIdx,EGLint value)515 EGLBoolean eglDisplay::setAttribValue(EGLConfig config, EGLint attribIdx, EGLint value)
516 {
517     if (attribIdx == ATTRIBUTE_NONE)
518     {
519         ALOGE("[%s] Bad attribute idx\n", __FUNCTION__);
520         return EGL_FALSE;
521     }
522     *(m_configs + (intptr_t)(getIndexOfConfig(config))*m_numConfigAttribs + attribIdx) = value;
523     return EGL_TRUE;
524 }
525 
setConfigAttrib(EGLConfig config,EGLint attrib,EGLint value)526 EGLBoolean eglDisplay::setConfigAttrib(EGLConfig config, EGLint attrib, EGLint value)
527 {
528     //Though it seems that valueFor() is thread-safe, we don't take chanses
529     pthread_mutex_lock(&m_lock);
530     EGLBoolean ret =
531         setAttribValue(
532             config,
533             findObjectOrDefault(
534                 m_attribs,
535                 attrib,
536                 EGL_DONT_CARE),
537             value);
538     pthread_mutex_unlock(&m_lock);
539     return ret;
540 }
541 
542 
getConfigNativePixelFormat(EGLConfig config,uint32_t * format)543 EGLBoolean eglDisplay::getConfigNativePixelFormat(EGLConfig config, uint32_t * format)
544 {
545     EGLint redSize, blueSize, greenSize, alphaSize;
546 
547     if (!(
548             getAttribValue(
549                 config,
550                 findObjectOrDefault(m_attribs, EGL_RED_SIZE, EGL_DONT_CARE),
551                 &redSize) &&
552             getAttribValue(
553                 config,
554                 findObjectOrDefault(m_attribs, EGL_BLUE_SIZE, EGL_DONT_CARE),
555                 &blueSize) &&
556             getAttribValue(
557                 config,
558                 findObjectOrDefault(m_attribs, EGL_GREEN_SIZE, EGL_DONT_CARE),
559                 &greenSize) &&
560             getAttribValue(
561                 config,
562                 findObjectOrDefault(m_attribs, EGL_ALPHA_SIZE, EGL_DONT_CARE),
563                 &alphaSize))) {
564         ALOGE("Couldn't find value for one of the pixel format attributes");
565         return EGL_FALSE;
566     }
567 
568     //calculate the GL internal format
569     if ((redSize==8)&&(greenSize==8)&&(blueSize==8)&&(alphaSize==8)) *format = HAL_PIXEL_FORMAT_RGBA_8888; //XXX: BGR?
570     else if ((redSize==8)&&(greenSize==8)&&(blueSize==8)&&(alphaSize==0)) *format = HAL_PIXEL_FORMAT_RGBX_8888; //XXX or HAL_PIXEL_FORMAT_RGB_888
571     else if ((redSize==5)&&(greenSize==6)&&(blueSize==5)&&(alphaSize==0)) *format = HAL_PIXEL_FORMAT_RGB_565;
572     else {
573         return EGL_FALSE;
574     }
575     return EGL_TRUE;
576 }
getConfigGLPixelFormat(EGLConfig config,GLenum * format)577 EGLBoolean eglDisplay::getConfigGLPixelFormat(EGLConfig config, GLenum * format)
578 {
579     EGLint redSize, blueSize, greenSize, alphaSize;
580 
581     if (!(
582             getAttribValue(
583                 config,
584                 findObjectOrDefault(m_attribs, EGL_RED_SIZE, EGL_DONT_CARE),
585                 &redSize) &&
586             getAttribValue(
587                 config,
588                 findObjectOrDefault(m_attribs, EGL_BLUE_SIZE, EGL_DONT_CARE),
589                 &blueSize) &&
590             getAttribValue(
591                 config,
592                 findObjectOrDefault(m_attribs, EGL_GREEN_SIZE, EGL_DONT_CARE),
593                 &greenSize) &&
594             getAttribValue(
595                 config,
596                 findObjectOrDefault(m_attribs, EGL_ALPHA_SIZE, EGL_DONT_CARE),
597                 &alphaSize))) {
598         ALOGE("Couldn't find value for one of the pixel format attributes");
599         return EGL_FALSE;
600     }
601 
602     //calculate the GL internal format
603     if ((redSize == greenSize) && (redSize == blueSize) &&
604         ((redSize == 8) || (redSize == 16) || (redSize == 32)))
605     {
606         if (alphaSize == 0) *format = GL_RGB;
607         else *format = GL_RGBA;
608     }
609     else if ((redSize==5)&&(greenSize==6)&&(blueSize==5)&&(alphaSize==0)) *format = GL_RGB565_OES;
610     else if ((redSize==5)&&(greenSize==5)&&(blueSize==5)&&(alphaSize==1)) *format = GL_RGB5_A1_OES;
611     else if ((redSize==4)&&(greenSize==4)&&(blueSize==4)&&(alphaSize==4)) *format = GL_RGBA4_OES;
612     else return EGL_FALSE;
613 
614     return EGL_TRUE;
615 }
616 
onCreateContext(EGLContext ctx)617 void eglDisplay::onCreateContext(EGLContext ctx) {
618     pthread_mutex_lock(&m_ctxLock);
619     m_contexts.insert(ctx);
620     pthread_mutex_unlock(&m_ctxLock);
621 }
622 
onCreateSurface(EGLSurface surface)623 void eglDisplay::onCreateSurface(EGLSurface surface) {
624     pthread_mutex_lock(&m_surfaceLock);
625     m_surfaces.insert(surface);
626     pthread_mutex_unlock(&m_surfaceLock);
627 }
628 
onDestroyContext(EGLContext ctx)629 void eglDisplay::onDestroyContext(EGLContext ctx) {
630     pthread_mutex_lock(&m_ctxLock);
631     m_contexts.erase(ctx);
632     pthread_mutex_unlock(&m_ctxLock);
633 }
634 
onDestroySurface(EGLSurface surface)635 void eglDisplay::onDestroySurface(EGLSurface surface) {
636     pthread_mutex_lock(&m_surfaceLock);
637     m_surfaces.erase(surface);
638     pthread_mutex_unlock(&m_surfaceLock);
639 }
640 
isContext(EGLContext ctx)641 bool eglDisplay::isContext(EGLContext ctx) {
642     pthread_mutex_lock(&m_ctxLock);
643     bool res = m_contexts.find(ctx) != m_contexts.end();
644     pthread_mutex_unlock(&m_ctxLock);
645     return res;
646 }
647 
isSurface(EGLSurface surface)648 bool eglDisplay::isSurface(EGLSurface surface) {
649     pthread_mutex_lock(&m_surfaceLock);
650     bool res = m_surfaces.find(surface) != m_surfaces.end();
651     pthread_mutex_unlock(&m_surfaceLock);
652     return res;
653 }
654 
getHostDriverCaps(int majorVersion,int minorVersion)655 HostDriverCaps eglDisplay::getHostDriverCaps(int majorVersion, int minorVersion) {
656     pthread_mutex_lock(&m_lock);
657     if (majorVersion <= m_hostDriverCaps_knownMajorVersion &&
658         minorVersion <= m_hostDriverCaps_knownMinorVersion) {
659         pthread_mutex_unlock(&m_lock);
660         return m_hostDriverCaps;
661     }
662 
663     memset(&m_hostDriverCaps, 0x0, sizeof(m_hostDriverCaps));
664 
665     m_hostDriverCaps.max_color_attachments = 8;
666 
667     // Can we query gles2?
668     if (majorVersion >= 1) {
669         m_gles2_iface->getIntegerv(GL_MAX_VERTEX_ATTRIBS, &m_hostDriverCaps.max_vertex_attribs);
670         m_gles2_iface->getIntegerv(GL_MAX_COMBINED_TEXTURE_IMAGE_UNITS, &m_hostDriverCaps.max_combined_texture_image_units);
671 
672         m_gles2_iface->getIntegerv(GL_MAX_TEXTURE_SIZE, &m_hostDriverCaps.max_texture_size);
673         m_gles2_iface->getIntegerv(GL_MAX_CUBE_MAP_TEXTURE_SIZE, &m_hostDriverCaps.max_texture_size_cube_map);
674         m_gles2_iface->getIntegerv(GL_MAX_RENDERBUFFER_SIZE, &m_hostDriverCaps.max_renderbuffer_size);
675         m_hostDriverCaps_knownMajorVersion = 2;
676     }
677 
678     // Can we query gles3.0?
679     if (majorVersion >= 3) {
680         m_gles2_iface->getIntegerv(GL_MAX_COLOR_ATTACHMENTS, &m_hostDriverCaps.max_color_attachments);
681         m_gles2_iface->getIntegerv(GL_MAX_DRAW_BUFFERS, &m_hostDriverCaps.max_draw_buffers);
682         m_gles2_iface->getIntegerv(GL_UNIFORM_BUFFER_OFFSET_ALIGNMENT, &m_hostDriverCaps.ubo_offset_alignment);
683         m_gles2_iface->getIntegerv(GL_MAX_UNIFORM_BUFFER_BINDINGS, &m_hostDriverCaps.max_uniform_buffer_bindings);
684         m_gles2_iface->getIntegerv(GL_MAX_TRANSFORM_FEEDBACK_SEPARATE_ATTRIBS, &m_hostDriverCaps.max_transform_feedback_separate_attribs);
685         m_gles2_iface->getIntegerv(GL_MAX_3D_TEXTURE_SIZE, &m_hostDriverCaps.max_texture_size_3d);
686         m_gles2_iface->getIntegerv(GL_MAX_ARRAY_TEXTURE_LAYERS, &m_hostDriverCaps.max_array_texture_layers);
687 
688         m_hostDriverCaps_knownMajorVersion = 3;
689 
690         // Can we query gles3.1?
691         if (minorVersion >= 1) {
692             m_gles2_iface->getIntegerv(GL_MAX_ATOMIC_COUNTER_BUFFER_BINDINGS, &m_hostDriverCaps.max_atomic_counter_buffer_bindings);
693             m_gles2_iface->getIntegerv(GL_MAX_SHADER_STORAGE_BUFFER_BINDINGS, &m_hostDriverCaps.max_shader_storage_buffer_bindings);
694             m_gles2_iface->getIntegerv(GL_MAX_VERTEX_ATTRIB_BINDINGS, &m_hostDriverCaps.max_vertex_attrib_bindings);
695             m_gles2_iface->getIntegerv(GL_MAX_VERTEX_ATTRIB_STRIDE, &m_hostDriverCaps.max_vertex_attrib_stride);
696             m_gles2_iface->getIntegerv(GL_SHADER_STORAGE_BUFFER_OFFSET_ALIGNMENT, &m_hostDriverCaps.ssbo_offset_alignment);
697             m_hostDriverCaps_knownMinorVersion = 1;
698         }
699     }
700 
701     pthread_mutex_unlock(&m_lock);
702 
703     return m_hostDriverCaps;
704 }
705 
706