2 * Copyright (C) 2011 The Android Open Source Project
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
8 * http://www.apache.org/licenses/LICENSE-2.0
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.
16 #include "eglDisplay.h"
17 #include "HostConnection.h"
20 static const int systemEGLVersionMajor = 1;
21 static const int systemEGLVersionMinor = 4;
22 static const char systemEGLVendor[] = "Google Android emulator";
24 // list of extensions supported by this EGL implementation
25 // NOTE that each extension name should be suffixed with space
26 static const char systemStaticEGLExtensions[] =
27 "EGL_ANDROID_image_native_buffer "
30 "EGL_KHR_gl_texture_2d_image ";
32 static void *s_gles_lib = NULL;
33 static void *s_gles2_lib = NULL;
35 // The following function will be called when we (libEGL)
37 // At this point we want to unload the gles libraries we
38 // might have loaded during initialization
39 static void __attribute__ ((destructor)) do_on_unload(void)
50 eglDisplay::eglDisplay() :
54 m_hostRendererVersion(0),
56 m_numConfigAttribs(0),
57 m_attribs(DefaultKeyedVector<EGLint, EGLint>(ATTRIBUTE_NONE)),
61 m_versionString(NULL),
63 m_extensionString(NULL)
65 pthread_mutex_init(&m_lock, NULL);
68 eglDisplay::~eglDisplay()
70 pthread_mutex_destroy(&m_lock);
73 bool eglDisplay::initialize(EGLClient_eglInterface *eglIface)
75 pthread_mutex_lock(&m_lock);
79 // load GLES client API
82 m_gles_iface = loadGLESClientAPI("/system/lib64/egl/libGLESv1_CM_emulation.so",
86 m_gles_iface = loadGLESClientAPI("/system/lib/egl/libGLESv1_CM_emulation.so",
91 pthread_mutex_unlock(&m_lock);
92 ALOGE("Failed to load gles1 iface");
98 m_gles2_iface = loadGLESClientAPI("/system/lib64/egl/libGLESv2_emulation.so",
102 m_gles2_iface = loadGLESClientAPI("/system/lib/egl/libGLESv2_emulation.so",
106 // Note that if loading gles2 failed, we can still run with no
107 // GLES2 support, having GLES2 is not mandatory.
111 // establish connection with the host
113 HostConnection *hcon = HostConnection::get();
115 pthread_mutex_unlock(&m_lock);
116 ALOGE("Failed to establish connection with the host\n");
121 // get renderControl encoder instance
123 renderControl_encoder_context_t *rcEnc = hcon->rcEncoder();
125 pthread_mutex_unlock(&m_lock);
126 ALOGE("Failed to get renderControl encoder instance");
131 // Query host reneder and EGL version
133 m_hostRendererVersion = rcEnc->rcGetRendererVersion(rcEnc);
134 EGLint status = rcEnc->rcGetEGLVersion(rcEnc, &m_major, &m_minor);
135 if (status != EGL_TRUE) {
136 // host EGL initialization failed !!
137 pthread_mutex_unlock(&m_lock);
142 // Take minimum version beween what we support and what the host support
144 if (m_major > systemEGLVersionMajor) {
145 m_major = systemEGLVersionMajor;
146 m_minor = systemEGLVersionMinor;
148 else if (m_major == systemEGLVersionMajor &&
149 m_minor > systemEGLVersionMinor) {
150 m_minor = systemEGLVersionMinor;
154 // Query the host for the set of configs
156 m_numConfigs = rcEnc->rcGetNumConfigs(rcEnc, (uint32_t*)&m_numConfigAttribs);
157 if (m_numConfigs <= 0 || m_numConfigAttribs <= 0) {
158 // just sanity check - should never happen
159 pthread_mutex_unlock(&m_lock);
163 uint32_t nInts = m_numConfigAttribs * (m_numConfigs + 1);
164 EGLint tmp_buf[nInts];
165 m_configs = new EGLint[nInts-m_numConfigAttribs];
167 pthread_mutex_unlock(&m_lock);
171 //EGLint n = rcEnc->rcGetConfigs(rcEnc, nInts*sizeof(EGLint), m_configs);
172 EGLint n = rcEnc->rcGetConfigs(rcEnc, nInts*sizeof(EGLint), (GLuint*)tmp_buf);
173 if (n != m_numConfigs) {
174 pthread_mutex_unlock(&m_lock);
178 //Fill the attributes vector.
179 //The first m_numConfigAttribs values of tmp_buf are the actual attributes enums.
180 for (int i=0; i<m_numConfigAttribs; i++) {
181 m_attribs.add(tmp_buf[i], i);
184 //Copy the actual configs data to m_configs
185 memcpy(m_configs, tmp_buf + m_numConfigAttribs, m_numConfigs*m_numConfigAttribs*sizeof(EGLint));
187 m_initialized = true;
189 pthread_mutex_unlock(&m_lock);
196 void eglDisplay::processConfigs()
198 for (intptr_t i=0; i<m_numConfigs; i++) {
199 EGLConfig config = (EGLConfig)i;
200 //Setup the EGL_NATIVE_VISUAL_ID attribute
202 if (getConfigNativePixelFormat(config, &format)) {
203 setConfigAttrib(config, EGL_NATIVE_VISUAL_ID, format);
208 void eglDisplay::terminate()
210 pthread_mutex_lock(&m_lock);
212 m_initialized = false;
216 if (m_versionString) {
217 free(m_versionString);
218 m_versionString = NULL;
220 if (m_vendorString) {
221 free(m_vendorString);
222 m_vendorString = NULL;
224 if (m_extensionString) {
225 free(m_extensionString);
226 m_extensionString = NULL;
229 pthread_mutex_unlock(&m_lock);
232 EGLClient_glesInterface *eglDisplay::loadGLESClientAPI(const char *libName,
233 EGLClient_eglInterface *eglIface,
236 void *lib = dlopen(libName, RTLD_NOW);
238 ALOGE("Failed to dlopen %s", libName);
242 init_emul_gles_t init_gles_func = (init_emul_gles_t)dlsym(lib,"init_emul_gles");
243 if (!init_gles_func) {
244 ALOGE("Failed to find init_emul_gles");
250 return (*init_gles_func)(eglIface);
253 static char *queryHostEGLString(EGLint name)
255 HostConnection *hcon = HostConnection::get();
257 renderControl_encoder_context_t *rcEnc = hcon->rcEncoder();
259 int n = rcEnc->rcQueryEGLString(rcEnc, name, NULL, 0);
261 // allocate space for the string with additional
262 // space charachter to be suffixed at the end.
263 char *str = (char *)malloc(-n+2);
264 n = rcEnc->rcQueryEGLString(rcEnc, name, str, -n);
266 // add extra space at end of string which will be
267 // needed later when filtering the extension list.
280 static bool findExtInList(const char* token, int tokenlen, const char* list)
282 const char* p = list;
284 const char* q = strchr(p, ' ');
286 /* should not happen, list must be space-terminated */
289 if (tokenlen == (q - p) && !memcmp(token, p, tokenlen)) {
290 return true; /* found it */
294 return false; /* not found */
297 static char *buildExtensionString()
299 //Query host extension string
300 char *hostExt = queryHostEGLString(EGL_EXTENSIONS);
301 if (!hostExt || (hostExt[1] == '\0')) {
302 // no extensions on host - only static extension list supported
303 return strdup(systemStaticEGLExtensions);
306 int n = strlen(hostExt);
309 asprintf(&str,"%s%s", systemStaticEGLExtensions, hostExt);
310 free((char*)hostExt);
314 free((char*)hostExt);
315 return strdup(systemStaticEGLExtensions);
319 const char *eglDisplay::queryString(EGLint name)
321 if (name == EGL_CLIENT_APIS) {
324 else if (name == EGL_VERSION) {
325 pthread_mutex_lock(&m_lock);
326 if (m_versionString) {
327 pthread_mutex_unlock(&m_lock);
328 return m_versionString;
331 // build version string
332 asprintf(&m_versionString, "%d.%d", m_major, m_minor);
333 pthread_mutex_unlock(&m_lock);
335 return m_versionString;
337 else if (name == EGL_VENDOR) {
338 pthread_mutex_lock(&m_lock);
339 if (m_vendorString) {
340 pthread_mutex_unlock(&m_lock);
341 return m_vendorString;
344 // build vendor string
345 const char *hostVendor = queryHostEGLString(EGL_VENDOR);
348 asprintf(&m_vendorString, "%s Host: %s",
349 systemEGLVendor, hostVendor);
350 free((char*)hostVendor);
353 m_vendorString = (char *)systemEGLVendor;
355 pthread_mutex_unlock(&m_lock);
357 return m_vendorString;
359 else if (name == EGL_EXTENSIONS) {
360 pthread_mutex_lock(&m_lock);
361 if (m_extensionString) {
362 pthread_mutex_unlock(&m_lock);
363 return m_extensionString;
366 // build extension string
367 m_extensionString = buildExtensionString();
368 pthread_mutex_unlock(&m_lock);
370 return m_extensionString;
373 ALOGE("[%s] Unknown name %d\n", __FUNCTION__, name);
378 /* To get the value of attribute <a> of config <c> use the following formula:
379 * value = *(m_configs + (int)c*m_numConfigAttribs + a);
381 EGLBoolean eglDisplay::getAttribValue(EGLConfig config, EGLint attribIdx, EGLint * value)
383 if (attribIdx == ATTRIBUTE_NONE)
385 ALOGE("[%s] Bad attribute idx\n", __FUNCTION__);
388 *value = *(m_configs + (intptr_t)config*m_numConfigAttribs + attribIdx);
392 EGLBoolean eglDisplay::getConfigAttrib(EGLConfig config, EGLint attrib, EGLint * value)
394 //Though it seems that valueFor() is thread-safe, we don't take chanses
395 pthread_mutex_lock(&m_lock);
396 EGLBoolean ret = getAttribValue(config, m_attribs.valueFor(attrib), value);
397 pthread_mutex_unlock(&m_lock);
401 void eglDisplay::dumpConfig(EGLConfig config)
404 DBG("^^^^^^^^^^ dumpConfig %d ^^^^^^^^^^^^^^^^^^", (int)config);
405 for (int i=0; i<m_numConfigAttribs; i++) {
406 getAttribValue(config, i, &value);
407 DBG("{%d}[%d] %d\n", (int)config, i, value);
411 /* To set the value of attribute <a> of config <c> use the following formula:
412 * *(m_configs + (int)c*m_numConfigAttribs + a) = value;
414 EGLBoolean eglDisplay::setAttribValue(EGLConfig config, EGLint attribIdx, EGLint value)
416 if (attribIdx == ATTRIBUTE_NONE)
418 ALOGE("[%s] Bad attribute idx\n", __FUNCTION__);
421 *(m_configs + (intptr_t)config*m_numConfigAttribs + attribIdx) = value;
425 EGLBoolean eglDisplay::setConfigAttrib(EGLConfig config, EGLint attrib, EGLint value)
427 //Though it seems that valueFor() is thread-safe, we don't take chanses
428 pthread_mutex_lock(&m_lock);
429 EGLBoolean ret = setAttribValue(config, m_attribs.valueFor(attrib), value);
430 pthread_mutex_unlock(&m_lock);
435 EGLBoolean eglDisplay::getConfigNativePixelFormat(EGLConfig config, PixelFormat * format)
437 EGLint redSize, blueSize, greenSize, alphaSize;
439 if ( !(getAttribValue(config, m_attribs.valueFor(EGL_RED_SIZE), &redSize) &&
440 getAttribValue(config, m_attribs.valueFor(EGL_BLUE_SIZE), &blueSize) &&
441 getAttribValue(config, m_attribs.valueFor(EGL_GREEN_SIZE), &greenSize) &&
442 getAttribValue(config, m_attribs.valueFor(EGL_ALPHA_SIZE), &alphaSize)) )
444 ALOGE("Couldn't find value for one of the pixel format attributes");
448 //calculate the GL internal format
449 if ((redSize==8)&&(greenSize==8)&&(blueSize==8)&&(alphaSize==8)) *format = PIXEL_FORMAT_RGBA_8888; //XXX: BGR?
450 else if ((redSize==8)&&(greenSize==8)&&(blueSize==8)&&(alphaSize==0)) *format = PIXEL_FORMAT_RGBX_8888; //XXX or PIXEL_FORMAT_RGB_888
451 else if ((redSize==5)&&(greenSize==6)&&(blueSize==5)&&(alphaSize==0)) *format = PIXEL_FORMAT_RGB_565;
452 else if ((redSize==5)&&(greenSize==5)&&(blueSize==5)&&(alphaSize==1)) *format = PIXEL_FORMAT_RGBA_5551;
453 else if ((redSize==4)&&(greenSize==4)&&(blueSize==4)&&(alphaSize==4)) *format = PIXEL_FORMAT_RGBA_4444;
459 EGLBoolean eglDisplay::getConfigGLPixelFormat(EGLConfig config, GLenum * format)
461 EGLint redSize, blueSize, greenSize, alphaSize;
463 if ( !(getAttribValue(config, m_attribs.valueFor(EGL_RED_SIZE), &redSize) &&
464 getAttribValue(config, m_attribs.valueFor(EGL_BLUE_SIZE), &blueSize) &&
465 getAttribValue(config, m_attribs.valueFor(EGL_GREEN_SIZE), &greenSize) &&
466 getAttribValue(config, m_attribs.valueFor(EGL_ALPHA_SIZE), &alphaSize)) )
468 ALOGE("Couldn't find value for one of the pixel format attributes");
472 //calculate the GL internal format
473 if ((redSize == greenSize) && (redSize == blueSize) &&
474 ((redSize == 8) || (redSize == 16) || (redSize == 32)))
476 if (alphaSize == 0) *format = GL_RGB;
477 else *format = GL_RGBA;
479 else if ((redSize==5)&&(greenSize==6)&&(blueSize==5)&&(alphaSize==0)) *format = GL_RGB565_OES;
480 else if ((redSize==5)&&(greenSize==5)&&(blueSize==5)&&(alphaSize==1)) *format = GL_RGB5_A1_OES;
481 else if ((redSize==4)&&(greenSize==4)&&(blueSize==4)&&(alphaSize==4)) *format = GL_RGBA4_OES;
482 else return EGL_FALSE;