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