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