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