• 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 #ifdef _WIN32
17 #undef EGLAPI
18 #define EGLAPI
19 #define EGLAPIENTRY
20 #endif
21 
22 #include <GLcommon/GLESmacros.h>
23 #include "GLcommon/GLEScontext.h"
24 #include "GLcommon/GLutils.h"
25 #include "GLcommon/TextureData.h"
26 #include "GLcommon/TextureUtils.h"
27 #include "GLcommon/TranslatorIfaces.h"
28 #include "ThreadInfo.h"
29 #include "aemu/base/synchronization/Lock.h"
30 #include "aemu/base/files/Stream.h"
31 #include "aemu/base/system/System.h"
32 #include "aemu/base/SharedLibrary.h"
33 #include "host-common/GfxstreamFatalError.h"
34 #include "host-common/emugl_vm_operations.h"
35 #include "host-common/logging.h"
36 
37 #include "EglWindowSurface.h"
38 #include "EglPbufferSurface.h"
39 #include "EglGlobalInfo.h"
40 #include "EglThreadInfo.h"
41 #include "EglValidate.h"
42 #include "EglDisplay.h"
43 #include "EglContext.h"
44 #include "EglConfig.h"
45 #include "EglOsApi.h"
46 #include "GraphicsDriverLock.h"
47 #include "ClientAPIExts.h"
48 
49 #include <EGL/egl.h>
50 #include <EGL/eglext.h>
51 
52 #include <stdio.h>
53 #include <sys/types.h>
54 #include <sys/stat.h>
55 
56 #define MAJOR          1
57 #define MINOR          4
58 
59 using emugl::ABORT_REASON_OTHER;
60 using emugl::FatalError;
61 using gfxstream::graphicsDriverLock;
62 
63 //declarations
64 
65 namespace translator {
66 namespace egl {
67 
68 ImagePtr getEGLImage(unsigned int imageId);
69 GLEScontext* getGLESContext();
70 GlLibrary* getGlLibrary();
71 void* getProcAddressFromEGL(const char*);
72 static bool createAndBindAuxiliaryContext(
73     EGLContext* context_out, EGLSurface* surface_out);
74 static bool unbindAndDestroyAuxiliaryContext(
75     EGLContext context, EGLSurface surface);
76 static bool bindAuxiliaryContext(
77     EGLContext context, EGLSurface surface);
78 static bool unbindAuxiliaryContext();
79 
80 } // namespace translator
81 } // namespace egl
82 
83 #define tls_thread  EglThreadInfo::get()
84 
85 EglGlobalInfo* g_eglInfo = NULL;
86 android::base::Lock  s_surfaceDestroyLock;
87 
initGlobalInfo()88 void initGlobalInfo()
89 {
90     android::base::AutoLock mutex(*graphicsDriverLock());
91     if (!g_eglInfo) {
92         g_eglInfo = EglGlobalInfo::getInstance();
93     }
94 }
95 
96 static const EGLiface s_eglIface = {
97     .getGLESContext = translator::egl::getGLESContext,
98     .getEGLImage = translator::egl::getEGLImage,
99     .eglGetGlLibrary = translator::egl::getGlLibrary,
100     .createAndBindAuxiliaryContext = translator::egl::createAndBindAuxiliaryContext,
101     .unbindAndDestroyAuxiliaryContext = translator::egl::unbindAndDestroyAuxiliaryContext,
102     .bindAuxiliaryContext = translator::egl::bindAuxiliaryContext,
103     .unbindAuxiliaryContext = translator::egl::unbindAuxiliaryContext,
104     .getProcAddress = translator::egl::getProcAddressFromEGL,
105 };
106 
initGLESx(GLESVersion version)107 static void initGLESx(GLESVersion version) {
108     const GLESiface* iface = g_eglInfo->getIface(version);
109     if (!iface) {
110         ERR("EGL failed to initialize GLESv%d; incompatible interface", version);
111         return;
112     }
113     iface->initGLESx(EglGlobalInfo::isEgl2Egl());
114 }
115 
116 /*****************************************  supported extensions  ***********************************************************************/
117 
118 namespace translator {
119 namespace egl {
120 
121 EGLAPI EGLImageKHR EGLAPIENTRY eglCreateImageKHR(EGLDisplay display, EGLContext context, EGLenum target, EGLClientBuffer buffer, const EGLint *attrib_list);
122 EGLAPI EGLBoolean EGLAPIENTRY eglDestroyImageKHR(EGLDisplay display, EGLImageKHR image);
123 EGLAPI EGLSyncKHR EGLAPIENTRY eglCreateSyncKHR(EGLDisplay display, EGLenum type, const EGLint* attribs);
124 EGLAPI EGLint EGLAPIENTRY eglClientWaitSyncKHR(EGLDisplay display, EGLSyncKHR sync, EGLint flags, EGLTimeKHR timeout);
125 EGLAPI EGLBoolean EGLAPIENTRY eglDestroySyncKHR(EGLDisplay display, EGLSyncKHR sync);
126 EGLAPI EGLint EGLAPIENTRY eglGetMaxGLESVersion(EGLDisplay display);
127 EGLAPI EGLint EGLAPIENTRY eglWaitSyncKHR(EGLDisplay display, EGLSyncKHR sync, EGLint flags);
128 EGLAPI void EGLAPIENTRY eglBlitFromCurrentReadBufferANDROID(EGLDisplay display, EGLImageKHR image);
129 EGLAPI void* EGLAPIENTRY eglSetImageFenceANDROID(EGLDisplay display, EGLImageKHR image);
130 EGLAPI void EGLAPIENTRY eglWaitImageFenceANDROID(EGLDisplay display, void* fence);
131 EGLAPI void EGLAPIENTRY eglAddLibrarySearchPathANDROID(const char* path);
132 EGLAPI EGLBoolean EGLAPIENTRY eglQueryVulkanInteropSupportANDROID(void);
133 EGLAPI EGLBoolean EGLAPIENTRY eglGetSyncAttribKHR(EGLDisplay display, EGLSyncKHR sync, EGLint attribute, EGLint *value);
134 EGLAPI EGLBoolean EGLAPIENTRY eglSetNativeTextureDecompressionEnabledANDROID(EGLDisplay display, EGLBoolean enabled);
135 EGLAPI EGLBoolean EGLAPIENTRY eglSetProgramBinaryLinkStatusEnabledANDROID(EGLDisplay display, EGLBoolean enabled);
136 
137 EGLAPI EGLBoolean EGLAPIENTRY eglSaveConfig(EGLDisplay display, EGLConfig config, EGLStreamKHR stream);
138 EGLAPI EGLConfig EGLAPIENTRY eglLoadConfig(EGLDisplay display, EGLStreamKHR stream);
139 
140 EGLAPI EGLBoolean EGLAPIENTRY eglPreSaveContext(EGLDisplay display, EGLContext contex, EGLStreamKHR stream);
141 EGLAPI EGLBoolean EGLAPIENTRY eglSaveContext(EGLDisplay display, EGLContext contex, EGLStreamKHR stream);
142 EGLAPI EGLBoolean EGLAPIENTRY eglPostSaveContext(EGLDisplay display, EGLContext context, EGLStreamKHR stream);
143 EGLAPI EGLContext EGLAPIENTRY eglLoadContext(EGLDisplay display, const EGLint *attrib_list, EGLStreamKHR stream);
144 
145 EGLAPI EGLBoolean EGLAPIENTRY eglSaveAllImages(EGLDisplay display,
146                                                EGLStreamKHR stream,
147                                                const void* textureSaver);
148 EGLAPI EGLBoolean EGLAPIENTRY eglLoadAllImages(EGLDisplay display,
149                                                EGLStreamKHR stream,
150                                                const void* textureLoader);
151 EGLAPI EGLBoolean EGLAPIENTRY eglPostLoadAllImages(EGLDisplay display, EGLStreamKHR stream);
152 EGLAPI void EGLAPIENTRY eglUseOsEglApi(EGLBoolean enable, EGLBoolean nullEgl);
153 EGLAPI void EGLAPIENTRY eglSetMaxGLESVersion(EGLint version);
154 EGLAPI void EGLAPIENTRY eglFillUsages(void* usages);
155 
156 EGLAPI EGLDisplay EGLAPIENTRY eglGetNativeDisplayANDROID(EGLDisplay);
157 EGLAPI EGLContext EGLAPIENTRY eglGetNativeContextANDROID(EGLDisplay, EGLContext);
158 EGLAPI EGLImage EGLAPIENTRY eglGetNativeImageANDROID(EGLDisplay, EGLImage);
159 EGLAPI EGLBoolean EGLAPIENTRY eglSetImageInfoANDROID(EGLDisplay, EGLImage, EGLint, EGLint, EGLint);
160 EGLAPI EGLImage EGLAPIENTRY eglImportImageANDROID(EGLDisplay, EGLImage);
161 
162 EGLint eglDebugMessageControlKHR(EGLDEBUGPROCKHR callback, const EGLAttrib * attrib_list);
163 
164 } // namespace translator
165 } // namespace egl
166 
167 namespace translator {
168 namespace egl {
169 
170 static const ExtensionDescriptor s_eglExtensions[] = {
171         {"eglCreateImageKHR" ,
172                 (__eglMustCastToProperFunctionPointerType)eglCreateImageKHR },
173         {"eglDestroyImageKHR",
174                 (__eglMustCastToProperFunctionPointerType)eglDestroyImageKHR },
175         {"eglCreateSyncKHR" ,
176                 (__eglMustCastToProperFunctionPointerType)eglCreateSyncKHR },
177         {"eglClientWaitSyncKHR",
178                 (__eglMustCastToProperFunctionPointerType)eglClientWaitSyncKHR },
179         {"eglDestroySyncKHR",
180                 (__eglMustCastToProperFunctionPointerType)eglDestroySyncKHR },
181         {"eglGetMaxGLESVersion",
182                 (__eglMustCastToProperFunctionPointerType)eglGetMaxGLESVersion },
183         {"eglWaitSyncKHR",
184                 (__eglMustCastToProperFunctionPointerType)eglWaitSyncKHR },
185         {"eglBlitFromCurrentReadBufferANDROID",
186                 (__eglMustCastToProperFunctionPointerType)eglBlitFromCurrentReadBufferANDROID },
187         {"eglSetImageFenceANDROID",
188                 (__eglMustCastToProperFunctionPointerType)eglSetImageFenceANDROID },
189         {"eglWaitImageFenceANDROID",
190                 (__eglMustCastToProperFunctionPointerType)eglWaitImageFenceANDROID },
191         {"eglAddLibrarySearchPathANDROID",
192                 (__eglMustCastToProperFunctionPointerType)eglAddLibrarySearchPathANDROID },
193         {"eglQueryVulkanInteropSupportANDROID",
194                 (__eglMustCastToProperFunctionPointerType)eglQueryVulkanInteropSupportANDROID },
195         {"eglGetSyncAttribKHR",
196                 (__eglMustCastToProperFunctionPointerType)eglGetSyncAttribKHR },
197         {"eglSetNativeTextureDecompressionEnabledANDROID",
198                 (__eglMustCastToProperFunctionPointerType)eglSetNativeTextureDecompressionEnabledANDROID },
199         {"eglSetProgramBinaryLinkStatusEnabledANDROID",
200                 (__eglMustCastToProperFunctionPointerType)eglSetProgramBinaryLinkStatusEnabledANDROID },
201 };
202 
203 static const int s_eglExtensionsSize =
204         sizeof(s_eglExtensions) / sizeof(ExtensionDescriptor);
205 
206 } // namespace translator
207 } // namespace egl
208 
209 /****************************************************************************************************************************************/
210 //macros for accessing global egl info & tls objects
211 
212 extern "C" {
213 }
214 
215 namespace translator {
216 namespace egl {
217 
218 #define CURRENT_THREAD() do {} while (0);
219 
220 #define RETURN_ERROR(ret,err)                                \
221         CURRENT_THREAD()                                     \
222         if(tls_thread->getError() == EGL_SUCCESS) {          \
223           tls_thread->setError(err);                         \
224         }                                                    \
225         return ret;
226 
227 #define VALIDATE_DISPLAY_RETURN(EGLDisplay, ret)                \
228     MEM_TRACE_IF(strncmp(__FUNCTION__, "egl", 3) == 0, "EMUGL") \
229     EglDisplay* dpy = g_eglInfo->getDisplay(EGLDisplay);        \
230     if (!dpy) {                                                 \
231         RETURN_ERROR(ret, EGL_BAD_DISPLAY);                     \
232     }                                                           \
233     if (!dpy->isInitialize()) {                                 \
234         RETURN_ERROR(ret, EGL_NOT_INITIALIZED);                 \
235     }
236 
237 #define VALIDATE_CONFIG_RETURN(EGLConfig,ret)                \
238         EglConfig* cfg = dpy->getConfig(EGLConfig);          \
239         if(!cfg) {                                           \
240             RETURN_ERROR(ret,EGL_BAD_CONFIG);                \
241         }
242 
243 #define VALIDATE_SURFACE_RETURN(EGLSurface,ret,varName)      \
244         SurfacePtr varName = dpy->getSurface(EGLSurface);    \
245         if(!varName.get()) {                                 \
246             RETURN_ERROR(ret,EGL_BAD_SURFACE);               \
247         }
248 
249 #define VALIDATE_CONTEXT_RETURN(EGLContext,ret)              \
250         ContextPtr ctx = dpy->getContext(EGLContext);        \
251         if(!ctx.get()) {                                     \
252             RETURN_ERROR(ret,EGL_BAD_CONTEXT);               \
253         }
254 
255 
256 #define VALIDATE_DISPLAY(EGLDisplay) \
257         VALIDATE_DISPLAY_RETURN(EGLDisplay,EGL_FALSE)
258 
259 #define VALIDATE_CONFIG(EGLConfig)   \
260         VALIDATE_CONFIG_RETURN(EGLConfig,EGL_FALSE)
261 
262 #define VALIDATE_SURFACE(EGLSurface,varName) \
263         VALIDATE_SURFACE_RETURN(EGLSurface,EGL_FALSE,varName)
264 
265 #define VALIDATE_CONTEXT(EGLContext) \
266         VALIDATE_CONTEXT_RETURN(EGLContext,EGL_FALSE)
267 
268 
getGLESContext()269 GLEScontext* getGLESContext()
270 {
271     ThreadInfo* thread  = getThreadInfo();
272     return thread->glesContext;
273 }
274 
getGlLibrary()275 GlLibrary* getGlLibrary() {
276     return EglGlobalInfo::getInstance()->getOsEngine()->getGlLibrary();
277 }
278 
getProcAddressFromEGL(const char * func)279 void* getProcAddressFromEGL(const char* func) {
280     return EglGlobalInfo::getInstance()->getOsEngine()->eglGetProcAddress(func);
281 }
282 
eglGetDisplay(EGLNativeDisplayType display_id)283 EGLAPI EGLDisplay EGLAPIENTRY eglGetDisplay(EGLNativeDisplayType display_id) {
284     MEM_TRACE("EMUGL");
285     EglDisplay* dpy = NULL;
286     EglOS::Display* internalDisplay = NULL;
287 
288     initGlobalInfo();
289 
290     if ((dpy = g_eglInfo->getDisplayFromDisplayType(display_id))) {
291         return dpy;
292     }
293     if (display_id != EGL_DEFAULT_DISPLAY) {
294         return EGL_NO_DISPLAY;
295     }
296     internalDisplay = g_eglInfo->getDefaultNativeDisplay();
297     dpy = g_eglInfo->addDisplay(display_id,internalDisplay);
298     if(!dpy) {
299         return EGL_NO_DISPLAY;
300     }
301     return dpy;
302 }
303 
304 } // namespace translator
305 } // namespace egl
306 
307 #define TRANSLATOR_GETIFACE_NAME "__translator_getIfaces"
308 
309 extern "C" {
310 GLESiface* static_translator_glescm_getIfaces(const EGLiface*);
311 GLESiface* static_translator_glesv2_getIfaces(const EGLiface*);
312 }; // extern "C"
313 
314 #define STATIC_TRANSLATOR_GETIFACE_NAME_GLES_CM static_translator_glescm_getIfaces
315 #define STATIC_TRANSLATOR_GETIFACE_NAME_GLES_V2 static_translator_glesv2_getIfaces
316 
317 #define LIB_GLES_CM_NAME EMUGL_LIBNAME("GLES_CM_translator")
318 #define LIB_GLES_V2_NAME EMUGL_LIBNAME("GLES_V2_translator")
319 
loadIfaces(const char * libName,char * error,size_t errorSize)320 static __translator_getGLESIfaceFunc loadIfaces(const char* libName,
321                                                 char* error,
322                                                 size_t errorSize) {
323 
324     if (!strcmp(libName, LIB_GLES_CM_NAME)) {
325         return STATIC_TRANSLATOR_GETIFACE_NAME_GLES_CM;
326     }
327 
328     if (!strcmp(libName, LIB_GLES_V2_NAME)) {
329         return STATIC_TRANSLATOR_GETIFACE_NAME_GLES_V2;
330     }
331 
332     return 0;
333 }
334 
335 namespace translator {
336 namespace egl {
337 
eglInitialize(EGLDisplay display,EGLint * major,EGLint * minor)338 EGLAPI EGLBoolean EGLAPIENTRY eglInitialize(EGLDisplay display, EGLint *major, EGLint *minor) {
339     MEM_TRACE("EMUGL");
340 
341     initGlobalInfo();
342 
343     EglDisplay* dpy = g_eglInfo->getDisplay(display);
344     if(!dpy) {
345          RETURN_ERROR(EGL_FALSE,EGL_BAD_DISPLAY);
346     }
347 
348     if(major) *major = MAJOR;
349     if(minor) *minor = MINOR;
350 
351     __translator_getGLESIfaceFunc func  = NULL;
352     int renderableType = EGL_OPENGL_ES_BIT;
353 
354     g_eglInfo->setEglIface(&s_eglIface);
355 
356     char error[256];
357     // When running on top of another GLES library, our GLES1
358     // translator uses the GLES library's underlying GLES3.
359     if(!g_eglInfo->getIface(GLES_1_1)) {
360         func  = loadIfaces(LIB_GLES_CM_NAME, error, sizeof(error));
361         if (func) {
362             g_eglInfo->setIface(func(&s_eglIface),GLES_1_1);
363         } else {
364            fprintf(stderr, "%s: Could not find ifaces for GLES CM 1.1 [%s]\n",
365                    __FUNCTION__, error);
366            return EGL_FALSE;
367         }
368         initGLESx(GLES_1_1);
369     }
370     if(!g_eglInfo->getIface(GLES_2_0)) {
371         func  = loadIfaces(LIB_GLES_V2_NAME, error, sizeof(error));
372         if (func) {
373             renderableType |= EGL_OPENGL_ES2_BIT;
374             g_eglInfo->setIface(func(&s_eglIface),GLES_2_0);
375         } else {
376            fprintf(stderr, "%s: Could not find ifaces for GLES 2.0 [%s]\n",
377                    __FUNCTION__, error);
378         }
379         initGLESx(GLES_2_0);
380     }
381     if(!g_eglInfo->getIface(GLES_3_0)) {
382         func  = loadIfaces(LIB_GLES_V2_NAME, error, sizeof(error));
383         if (func) {
384             renderableType |= EGL_OPENGL_ES2_BIT | EGL_OPENGL_ES3_BIT;
385             g_eglInfo->setIface(func(&s_eglIface),GLES_3_0);
386         } else {
387            fprintf(stderr, "%s: Could not find ifaces for GLES 3.x [%s]\n",
388                    __FUNCTION__, error);
389         }
390         initGLESx(GLES_3_0);
391     }
392     if(!g_eglInfo->getIface(GLES_3_1)) {
393         func  = loadIfaces(LIB_GLES_V2_NAME, error, sizeof(error));
394         if (func) {
395             renderableType |= EGL_OPENGL_ES2_BIT | EGL_OPENGL_ES3_BIT;
396             g_eglInfo->setIface(func(&s_eglIface),GLES_3_1);
397         } else {
398            fprintf(stderr, "%s: Could not find ifaces for GLES 3.x [%s]\n",
399                    __FUNCTION__, error);
400         }
401         initGLESx(GLES_3_1);
402     }
403     dpy->initialize(renderableType);
404     return EGL_TRUE;
405 }
406 
eglTerminate(EGLDisplay display)407 EGLAPI EGLBoolean EGLAPIENTRY eglTerminate(EGLDisplay display) {
408     VALIDATE_DISPLAY(display);
409     dpy->terminate();
410     return EGL_TRUE;
411 }
412 
eglQueryString(EGLDisplay display,EGLint name)413 EGLAPI const char * EGLAPIENTRY eglQueryString(EGLDisplay display, EGLint name) {
414     VALIDATE_DISPLAY(display);
415     static const char* version    = "1.4";
416     static const char* extensions = "EGL_KHR_image EGL_KHR_image_base "
417                                     "EGL_KHR_gl_texture_2D_image "
418                                     "EGL_ANDROID_recordable ";
419     if(!EglValidate::stringName(name)) {
420         RETURN_ERROR(NULL,EGL_BAD_PARAMETER);
421     }
422     switch(name) {
423     case EGL_VENDOR:
424         return dpy->getVendorString();
425     case EGL_VERSION:
426         return version;
427     case EGL_EXTENSIONS:
428         return extensions;
429     }
430     return NULL;
431 }
432 
eglGetConfigs(EGLDisplay display,EGLConfig * configs,EGLint config_size,EGLint * num_config)433 EGLAPI EGLBoolean EGLAPIENTRY eglGetConfigs(EGLDisplay display, EGLConfig *configs,
434              EGLint config_size, EGLint *num_config) {
435     VALIDATE_DISPLAY(display);
436     if(!num_config) {
437         RETURN_ERROR(EGL_FALSE,EGL_BAD_PARAMETER);
438     }
439 
440     if(configs == NULL) {
441         *num_config = dpy->nConfigs();
442     } else {
443         *num_config = dpy->getConfigs(configs,config_size);
444     }
445 
446     return EGL_TRUE;
447 }
448 
eglChooseConfig(EGLDisplay display,const EGLint * attrib_list,EGLConfig * configs,EGLint config_size,EGLint * num_config)449 EGLAPI EGLBoolean EGLAPIENTRY eglChooseConfig(EGLDisplay display, const EGLint *attrib_list,
450                EGLConfig *configs, EGLint config_size,
451                EGLint *num_config) {
452     CHOOSE_CONFIG_DLOG("eglChooseConfig: begin. validating arguments...");
453 
454     VALIDATE_DISPLAY(display);
455     if(!num_config) {
456          CHOOSE_CONFIG_DLOG("num_config is NULL. issue EGL_BAD_PARAMETER");
457          RETURN_ERROR(EGL_FALSE,EGL_BAD_PARAMETER);
458     }
459 
460         //selection defaults
461         // NOTE: Some variables below are commented out to reduce compiler warnings.
462         // TODO(digit): Look if these variables are really needed or not, and if so
463         // fix the code to do it properly.
464         EGLint      surface_type       = EGL_WINDOW_BIT;
465         EGLint      renderable_type    = EGL_OPENGL_ES_BIT;
466         //EGLBoolean  bind_to_tex_rgb    = EGL_DONT_CARE;
467         //EGLBoolean  bind_to_tex_rgba   = EGL_DONT_CARE;
468         EGLenum     caveat             = EGL_DONT_CARE;
469         EGLint      config_id          = EGL_DONT_CARE;
470         EGLBoolean  native_renderable  = EGL_DONT_CARE;
471         EGLint      native_visual_type = EGL_DONT_CARE;
472         //EGLint      max_swap_interval  = EGL_DONT_CARE;
473         //EGLint      min_swap_interval  = EGL_DONT_CARE;
474         EGLint      trans_red_val      = EGL_DONT_CARE;
475         EGLint      trans_green_val    = EGL_DONT_CARE;
476         EGLint      trans_blue_val     = EGL_DONT_CARE;
477         EGLenum     transparent_type   = EGL_NONE;
478         // EGLint      buffer_size        = 0;
479         EGLint      red_size           = 0;
480         EGLint      green_size         = 0;
481         EGLint      blue_size          = 0;
482         EGLint      alpha_size         = 0;
483         EGLint      alpha_mask_size    = 0;
484         EGLint      depth_size         = 0;
485         EGLint      frame_buffer_level = 0;
486         EGLint      sample_buffers_num = 0;
487         EGLint      samples_per_pixel  = 0;
488         EGLint      stencil_size       = 0;
489         EGLint      conformant         = 0;
490 
491         EGLBoolean  recordable_android = EGL_FALSE;
492         EGLBoolean  framebuffer_target_android = EGL_DONT_CARE;
493 
494         EGLint luminance_size = 0;
495         EGLint wanted_buffer_size = EGL_DONT_CARE;
496 
497         std::vector<EGLint> wanted_attribs;
498 
499     if(!EglValidate::noAttribs(attrib_list)) { //there are attribs
500         int i = 0 ;
501         bool hasConfigId = false;
502         while(attrib_list[i] != EGL_NONE && !hasConfigId) {
503 #define CHOOSE_CONFIG_DLOG_BAD_ATTRIBUTE(attrname) \
504             CHOOSE_CONFIG_DLOG("EGL_BAD_ATTRIBUTE: " #attrname "defined as 0x%x", attrib_list[i+1]);
505 
506             if (attrib_list[i] != EGL_LEVEL &&
507                 attrib_list[i] != EGL_MATCH_NATIVE_PIXMAP &&
508                 attrib_list[i + 1] == EGL_DONT_CARE) {
509                 i+=2;
510                 continue;
511             }
512 
513             switch(attrib_list[i]) {
514             case EGL_MAX_PBUFFER_WIDTH:
515             case EGL_MAX_PBUFFER_HEIGHT:
516             case EGL_MAX_PBUFFER_PIXELS:
517             case EGL_NATIVE_VISUAL_ID:
518                 break; //we dont care from those selection crateria
519             case EGL_LEVEL:
520                 if(attrib_list[i+1] == EGL_DONT_CARE) {
521                     CHOOSE_CONFIG_DLOG_BAD_ATTRIBUTE(EGL_LEVEL);
522                     RETURN_ERROR(EGL_FALSE,EGL_BAD_ATTRIBUTE);
523                 }
524                 frame_buffer_level = attrib_list[i+1];
525                 wanted_attribs.push_back(EGL_LEVEL);
526                 break;
527             case EGL_BUFFER_SIZE:
528                 if(attrib_list[i+1] < 0) {
529                     CHOOSE_CONFIG_DLOG_BAD_ATTRIBUTE(EGL_BUFFER_SIZE);
530                     RETURN_ERROR(EGL_FALSE,EGL_BAD_ATTRIBUTE);
531                 }
532                 wanted_attribs.push_back(EGL_BUFFER_SIZE);
533                 wanted_buffer_size = attrib_list[i + 1];
534                 break;
535             case EGL_RED_SIZE:
536                 if(attrib_list[i+1] < 0) {
537                     CHOOSE_CONFIG_DLOG_BAD_ATTRIBUTE(EGL_RED_SIZE);
538                      RETURN_ERROR(EGL_FALSE,EGL_BAD_ATTRIBUTE);
539                 }
540                 red_size = attrib_list[i+1];
541                 wanted_attribs.push_back(EGL_RED_SIZE);
542                 break;
543             case EGL_GREEN_SIZE:
544                 if(attrib_list[i+1] < 0) {
545                     CHOOSE_CONFIG_DLOG_BAD_ATTRIBUTE(EGL_GREEN_SIZE);
546                     RETURN_ERROR(EGL_FALSE,EGL_BAD_ATTRIBUTE);
547                 }
548                 green_size = attrib_list[i+1];
549                 wanted_attribs.push_back(EGL_GREEN_SIZE);
550                 break;
551             case EGL_BLUE_SIZE:
552                 if(attrib_list[i+1] < 0) {
553                     CHOOSE_CONFIG_DLOG_BAD_ATTRIBUTE(EGL_BLUE_SIZE);
554                     RETURN_ERROR(EGL_FALSE,EGL_BAD_ATTRIBUTE);
555                 }
556                 blue_size = attrib_list[i+1];
557                 wanted_attribs.push_back(EGL_BLUE_SIZE);
558                 break;
559             case EGL_LUMINANCE_SIZE:
560                 if(attrib_list[i+1] < 0) {
561                     CHOOSE_CONFIG_DLOG_BAD_ATTRIBUTE(EGL_LUMINANCE_SIZE);
562                     RETURN_ERROR(EGL_FALSE,EGL_BAD_ATTRIBUTE);
563                 }
564                 wanted_attribs.push_back(EGL_LUMINANCE_SIZE);
565                 luminance_size = attrib_list[i + 1];
566                 break;
567             case EGL_ALPHA_SIZE:
568                 if(attrib_list[i+1] < 0) {
569                     CHOOSE_CONFIG_DLOG_BAD_ATTRIBUTE(EGL_ALPHA_SIZE);
570                     RETURN_ERROR(EGL_FALSE,EGL_BAD_ATTRIBUTE);
571                 }
572                 alpha_size = attrib_list[i+1];
573                 wanted_attribs.push_back(EGL_ALPHA_SIZE);
574                 break;
575             case EGL_ALPHA_MASK_SIZE:
576                 if(attrib_list[i+1] < 0) {
577                     CHOOSE_CONFIG_DLOG_BAD_ATTRIBUTE(EGL_ALPHA_MASK_SIZE);
578                     RETURN_ERROR(EGL_FALSE,EGL_BAD_ATTRIBUTE);
579                 }
580                 alpha_mask_size = attrib_list[i+1];
581                 wanted_attribs.push_back(EGL_ALPHA_MASK_SIZE);
582                 break;
583             case EGL_BIND_TO_TEXTURE_RGB:
584                 if (attrib_list[i+1] != EGL_TRUE &&
585                     attrib_list[i+1] != EGL_FALSE) {
586                     CHOOSE_CONFIG_DLOG_BAD_ATTRIBUTE(EGL_BIND_TO_TEXTURE_RGB);
587                     RETURN_ERROR(EGL_FALSE,EGL_BAD_ATTRIBUTE);
588                 }
589                 wanted_attribs.push_back(EGL_BIND_TO_TEXTURE_RGB);
590                 //bind_to_tex_rgb = attrib_list[i+1];
591                 break;
592             case EGL_BIND_TO_TEXTURE_RGBA:
593                 if (attrib_list[i+1] != EGL_TRUE &&
594                     attrib_list[i+1] != EGL_FALSE) {
595                     CHOOSE_CONFIG_DLOG_BAD_ATTRIBUTE(EGL_BIND_TO_TEXTURE_RGBA);
596                     RETURN_ERROR(EGL_FALSE,EGL_BAD_ATTRIBUTE);
597                 }
598                 wanted_attribs.push_back(EGL_BIND_TO_TEXTURE_RGBA);
599                 //bind_to_tex_rgba = attrib_list[i+1];
600                 break;
601             case EGL_CONFIG_CAVEAT:
602                 if(attrib_list[i+1] != EGL_NONE &&
603                    attrib_list[i+1] != EGL_SLOW_CONFIG &&
604                    attrib_list[i+1] != EGL_NON_CONFORMANT_CONFIG) {
605                     CHOOSE_CONFIG_DLOG_BAD_ATTRIBUTE(EGL_CONFIG_CAVEAT);
606                     RETURN_ERROR(EGL_FALSE,EGL_BAD_ATTRIBUTE);
607                 }
608                 caveat = attrib_list[i+1];
609                 wanted_attribs.push_back(EGL_CONFIG_CAVEAT);
610                 break;
611             case EGL_CONFORMANT:
612                 conformant = attrib_list[i+1];
613                 wanted_attribs.push_back(EGL_CONFORMANT);
614                 break;
615             case EGL_CONFIG_ID:
616                 if(attrib_list[i+1] < 0) {
617                     CHOOSE_CONFIG_DLOG_BAD_ATTRIBUTE(EGL_CONFIG_ID);
618                     RETURN_ERROR(EGL_FALSE,EGL_BAD_ATTRIBUTE);
619                 }
620                 config_id = attrib_list[i+1];
621                 hasConfigId = true;
622                 wanted_attribs.push_back(EGL_CONFIG_ID);
623                 break;
624             case EGL_DEPTH_SIZE:
625                 if(attrib_list[i+1] < 0) {
626                     CHOOSE_CONFIG_DLOG_BAD_ATTRIBUTE(EGL_DEPTH_SIZE);
627                     RETURN_ERROR(EGL_FALSE,EGL_BAD_ATTRIBUTE);
628                 }
629                 depth_size = attrib_list[i+1];
630                 wanted_attribs.push_back(EGL_DEPTH_SIZE);
631                 break;
632             case EGL_MAX_SWAP_INTERVAL:
633                 if(attrib_list[i+1] < 0) {
634                     CHOOSE_CONFIG_DLOG_BAD_ATTRIBUTE(EGL_MAX_SWAP_INTERVAL);
635                     RETURN_ERROR(EGL_FALSE,EGL_BAD_ATTRIBUTE);
636                 }
637                 //max_swap_interval = attrib_list[i+1];
638                 wanted_attribs.push_back(EGL_MAX_SWAP_INTERVAL);
639                 break;
640             case EGL_MIN_SWAP_INTERVAL:
641                 if(attrib_list[i+1] < 0) {
642                     CHOOSE_CONFIG_DLOG_BAD_ATTRIBUTE(EGL_MIN_SWAP_INTERVAL);
643                     RETURN_ERROR(EGL_FALSE,EGL_BAD_ATTRIBUTE);
644                 }
645                 //min_swap_interval = attrib_list[i+1];
646                 wanted_attribs.push_back(EGL_MIN_SWAP_INTERVAL);
647                 break;
648             case EGL_NATIVE_RENDERABLE:
649                 if (attrib_list[i+1] != EGL_TRUE &&
650                     attrib_list[i+1] != EGL_FALSE) {
651                     CHOOSE_CONFIG_DLOG_BAD_ATTRIBUTE(EGL_NATIVE_RENDERABLE);
652                     RETURN_ERROR(EGL_FALSE,EGL_BAD_ATTRIBUTE);
653                 }
654                 native_renderable = attrib_list[i+1];
655                 wanted_attribs.push_back(EGL_NATIVE_RENDERABLE);
656                 break;
657             case EGL_RENDERABLE_TYPE:
658                 renderable_type = attrib_list[i+1];
659                 wanted_attribs.push_back(EGL_RENDERABLE_TYPE);
660                 break;
661             case EGL_NATIVE_VISUAL_TYPE:
662                 native_visual_type = attrib_list[i+1];
663                 break;
664                 if(attrib_list[i+1] < 0 || attrib_list[i+1] > 1 ) {
665                     CHOOSE_CONFIG_DLOG_BAD_ATTRIBUTE(EGL_NATIVE_VISUAL_TYPE);
666                     RETURN_ERROR(EGL_FALSE,EGL_BAD_ATTRIBUTE);
667                 }
668                 wanted_attribs.push_back(EGL_NATIVE_VISUAL_TYPE);
669             case EGL_SAMPLE_BUFFERS:
670                 if(attrib_list[i+1] < 0) {
671                     CHOOSE_CONFIG_DLOG_BAD_ATTRIBUTE(EGL_SAMPLE_BUFFERS);
672                     RETURN_ERROR(EGL_FALSE,EGL_BAD_ATTRIBUTE);
673                 }
674                 sample_buffers_num = attrib_list[i+1];
675                 wanted_attribs.push_back(EGL_SAMPLE_BUFFERS);
676                 break;
677             case EGL_SAMPLES:
678                 if(attrib_list[i+1] < 0) {
679                     CHOOSE_CONFIG_DLOG_BAD_ATTRIBUTE(EGL_SAMPLES);
680                     RETURN_ERROR(EGL_FALSE,EGL_BAD_ATTRIBUTE);
681                 }
682                 samples_per_pixel = attrib_list[i+1];
683                 wanted_attribs.push_back(EGL_SAMPLES);
684                 break;
685             case EGL_STENCIL_SIZE:
686                 if(attrib_list[i+1] < 0) {
687                     CHOOSE_CONFIG_DLOG_BAD_ATTRIBUTE(EGL_STENCIL_SIZE);
688                     RETURN_ERROR(EGL_FALSE,EGL_BAD_ATTRIBUTE);
689                 }
690                 stencil_size = attrib_list[i+1];
691                 wanted_attribs.push_back(EGL_STENCIL_SIZE);
692                 break;
693             case EGL_SURFACE_TYPE:
694                 surface_type = attrib_list[i+1];
695                 wanted_attribs.push_back(EGL_SURFACE_TYPE);
696                 break;
697             case EGL_TRANSPARENT_TYPE:
698                 if(attrib_list[i+1] != EGL_NONE &&
699                    attrib_list[i+1] != EGL_TRANSPARENT_RGB ) {
700                     CHOOSE_CONFIG_DLOG_BAD_ATTRIBUTE(EGL_TRANSPARENT_TYPE);
701                     RETURN_ERROR(EGL_FALSE,EGL_BAD_ATTRIBUTE);
702                 }
703                 transparent_type = attrib_list[i+1];
704                 wanted_attribs.push_back(EGL_TRANSPARENT_TYPE);
705                 break;
706             case EGL_TRANSPARENT_RED_VALUE:
707                 trans_red_val = attrib_list[i+1];
708                 wanted_attribs.push_back(EGL_TRANSPARENT_RED_VALUE);
709                 break;
710             case EGL_TRANSPARENT_GREEN_VALUE:
711                 trans_green_val = attrib_list[i+1];
712                 wanted_attribs.push_back(EGL_TRANSPARENT_GREEN_VALUE);
713                 break;
714             case EGL_TRANSPARENT_BLUE_VALUE:
715                 trans_blue_val = attrib_list[i+1];
716                 wanted_attribs.push_back(EGL_TRANSPARENT_BLUE_VALUE);
717                 break;
718             case EGL_COLOR_BUFFER_TYPE:
719                 if(attrib_list[i+1] != EGL_RGB_BUFFER &&
720                    attrib_list[i+1] != EGL_LUMINANCE_BUFFER) {
721                     CHOOSE_CONFIG_DLOG_BAD_ATTRIBUTE(EGL_COLOR_BUFFER_TYPE);
722                     RETURN_ERROR(EGL_FALSE,EGL_BAD_ATTRIBUTE);
723                 }
724                 wanted_attribs.push_back(EGL_COLOR_BUFFER_TYPE);
725                 break;
726             case EGL_RECORDABLE_ANDROID:
727                 recordable_android = attrib_list[i+1];
728                 wanted_attribs.push_back(EGL_RECORDABLE_ANDROID);
729                 break;
730             case EGL_FRAMEBUFFER_TARGET_ANDROID:
731                 framebuffer_target_android = attrib_list[i+1];
732                 wanted_attribs.push_back(EGL_FRAMEBUFFER_TARGET_ANDROID);
733                 break;
734             default:
735                 CHOOSE_CONFIG_DLOG("EGL_BAD_ATTRIBUTE: Unknown attribute key 0x%x", attrib_list[i]);
736                 RETURN_ERROR(EGL_FALSE,EGL_BAD_ATTRIBUTE);
737             }
738             i+=2;
739         }
740         if(hasConfigId) {
741             EglConfig* pConfig = dpy->getConfig(config_id);
742             if(pConfig) {
743                 if(configs) {
744                     configs[0]  = static_cast<EGLConfig>(pConfig);
745                 }
746                 *num_config = 1;
747                 CHOOSE_CONFIG_DLOG("Using config id 0x%x. Return EGL_TRUE", config_id);
748                 return EGL_TRUE;
749             } else {
750                 CHOOSE_CONFIG_DLOG("EGL_BAD_ATTRIBUTE: Using missing config id 0x%x", config_id);
751                 RETURN_ERROR(EGL_FALSE,EGL_BAD_ATTRIBUTE);
752             }
753         }
754     }
755     EglConfig dummy(red_size,green_size,blue_size,alpha_size,alpha_mask_size,caveat,conformant,depth_size,
756                     frame_buffer_level,0,0,0,native_renderable,renderable_type,0,native_visual_type,
757                     sample_buffers_num, samples_per_pixel,stencil_size,luminance_size,wanted_buffer_size,
758                     surface_type,transparent_type,trans_red_val,trans_green_val,trans_blue_val,recordable_android, framebuffer_target_android,
759                     NULL);
760     for (size_t i = 0; i < wanted_attribs.size(); i++) {
761         dummy.addWantedAttrib(wanted_attribs[i]);
762     }
763     *num_config = dpy->chooseConfigs(dummy,configs,config_size);
764     CHOOSE_CONFIG_DLOG("eglChooseConfig: Success(EGL_TRUE). Num configs returned:%d", *num_config);
765 
766     return EGL_TRUE;
767 }
768 
eglGetConfigAttrib(EGLDisplay display,EGLConfig config,EGLint attribute,EGLint * value)769 EGLAPI EGLBoolean EGLAPIENTRY eglGetConfigAttrib(EGLDisplay display, EGLConfig config,
770                   EGLint attribute, EGLint *value) {
771     VALIDATE_DISPLAY(display);
772     VALIDATE_CONFIG(config);
773     if(!EglValidate::confAttrib(attribute)){
774         RETURN_ERROR(EGL_FALSE, EGL_BAD_ATTRIBUTE);
775     }
776     return cfg->getConfAttrib(attribute,value)? EGL_TRUE:EGL_FALSE;
777 }
778 
eglCreateWindowSurface(EGLDisplay display,EGLConfig config,EGLNativeWindowType win,const EGLint * attrib_list)779 EGLAPI EGLSurface EGLAPIENTRY eglCreateWindowSurface(EGLDisplay display, EGLConfig config,
780                   EGLNativeWindowType win,
781                   const EGLint *attrib_list) {
782     VALIDATE_DISPLAY_RETURN(display,EGL_NO_SURFACE);
783     VALIDATE_CONFIG_RETURN(config,EGL_NO_SURFACE);
784 
785     if(!(cfg->surfaceType() & EGL_WINDOW_BIT)) {
786         RETURN_ERROR(EGL_NO_SURFACE,EGL_BAD_MATCH);
787     }
788     if(!dpy->nativeType()->isValidNativeWin(win)) {
789         RETURN_ERROR(EGL_NO_SURFACE,EGL_BAD_NATIVE_WINDOW);
790     }
791     if(!EglValidate::noAttribs(attrib_list)) {
792         RETURN_ERROR(EGL_NO_SURFACE,EGL_BAD_ATTRIBUTE);
793     }
794     if(EglWindowSurface::alreadyAssociatedWithConfig(win)) {
795         RETURN_ERROR(EGL_NO_SURFACE,EGL_BAD_ALLOC);
796     }
797 
798     android::base::AutoLock mutex(*graphicsDriverLock());
799     unsigned int width,height;
800     if(!dpy->nativeType()->checkWindowPixelFormatMatch(
801             win, cfg->nativeFormat(), &width, &height)) {
802         RETURN_ERROR(EGL_NO_SURFACE,EGL_BAD_ALLOC);
803     }
804     SurfacePtr wSurface(new EglWindowSurface(dpy, win,cfg,width,height));
805     if(!wSurface.get()) {
806         RETURN_ERROR(EGL_NO_SURFACE,EGL_BAD_ALLOC);
807     }
808     return dpy->addSurface(wSurface);
809 }
810 
eglCreatePbufferSurface(EGLDisplay display,EGLConfig config,const EGLint * attrib_list)811 EGLAPI EGLSurface EGLAPIENTRY eglCreatePbufferSurface(
812         EGLDisplay display,
813         EGLConfig config,
814         const EGLint *attrib_list) {
815     VALIDATE_DISPLAY_RETURN(display,EGL_NO_SURFACE);
816     VALIDATE_CONFIG_RETURN(config,EGL_NO_SURFACE);
817     if(!(cfg->surfaceType() & EGL_PBUFFER_BIT)) {
818         RETURN_ERROR(EGL_NO_SURFACE,EGL_BAD_MATCH);
819     }
820 
821     SurfacePtr pbSurface(new EglPbufferSurface(dpy,cfg));
822     if(!pbSurface.get()) {
823         RETURN_ERROR(EGL_NO_SURFACE,EGL_BAD_ALLOC);
824     }
825 
826     if(!EglValidate::noAttribs(attrib_list)) { // There are attribs.
827         int i = 0 ;
828         while(attrib_list[i] != EGL_NONE) {
829             if(!pbSurface->setAttrib(attrib_list[i],attrib_list[i+1])) {
830                 RETURN_ERROR(EGL_NO_SURFACE,EGL_BAD_ATTRIBUTE);
831             }
832             i+=2;
833         }
834     }
835 
836     EGLint width, height, largest, texTarget, texFormat;
837     EglPbufferSurface* tmpPbSurfacePtr =
838             static_cast<EglPbufferSurface*>(pbSurface.get());
839 
840     tmpPbSurfacePtr->getDim(&width, &height, &largest);
841     tmpPbSurfacePtr->getTexInfo(&texTarget, &texFormat);
842 
843     if(!EglValidate::pbufferAttribs(width,
844                                     height,
845                                     texFormat == EGL_NO_TEXTURE,
846                                     texTarget == EGL_NO_TEXTURE)) {
847         //TODO: RETURN_ERROR(EGL_NO_SURFACE,EGL_BAD_VALUE); dont have bad_value
848         RETURN_ERROR(EGL_NO_SURFACE,EGL_BAD_ATTRIBUTE);
849     }
850 
851     EglOS::PbufferInfo pbinfo;
852 
853     pbinfo.width = width;
854     pbinfo.height = height;
855     pbinfo.largest = largest;
856     pbinfo.target = texTarget;
857     pbinfo.format = texFormat;
858 
859     tmpPbSurfacePtr->getAttrib(EGL_MIPMAP_TEXTURE, &pbinfo.hasMipmap);
860 
861     android::base::AutoLock mutex(*graphicsDriverLock());
862     EglOS::Surface* pb = dpy->nativeType()->createPbufferSurface(
863             cfg->nativeFormat(), &pbinfo);
864     if(!pb) {
865         //TODO: RETURN_ERROR(EGL_NO_SURFACE,EGL_BAD_VALUE); dont have bad value
866         RETURN_ERROR(EGL_NO_SURFACE,EGL_BAD_ATTRIBUTE);
867     }
868 
869     tmpPbSurfacePtr->setNativePbuffer(pb);
870     return dpy->addSurface(pbSurface);
871 }
872 
eglDestroySurface(EGLDisplay display,EGLSurface surface)873 EGLAPI EGLBoolean EGLAPIENTRY eglDestroySurface(EGLDisplay display, EGLSurface surface) {
874     VALIDATE_DISPLAY(display);
875     android::base::AutoLock mutex(*graphicsDriverLock());
876     SurfacePtr srfc = dpy->getSurface(surface);
877     if(!srfc.get()) {
878         RETURN_ERROR(EGL_FALSE,EGL_BAD_SURFACE);
879     }
880     g_eglInfo->markSurfaceForDestroy(dpy, surface);
881     return EGL_TRUE;
882 }
883 
eglQuerySurface(EGLDisplay display,EGLSurface surface,EGLint attribute,EGLint * value)884 EGLAPI EGLBoolean EGLAPIENTRY eglQuerySurface(EGLDisplay display, EGLSurface surface,
885                EGLint attribute, EGLint *value) {
886    VALIDATE_DISPLAY(display);
887    VALIDATE_SURFACE(surface,srfc);
888 
889    if(!srfc->getAttrib(attribute,value)) {
890        RETURN_ERROR(EGL_FALSE,EGL_BAD_ATTRIBUTE);
891    }
892    return EGL_TRUE;
893 }
894 
eglSurfaceAttrib(EGLDisplay display,EGLSurface surface,EGLint attribute,EGLint value)895 EGLAPI EGLBoolean EGLAPIENTRY eglSurfaceAttrib(EGLDisplay display, EGLSurface surface,
896                 EGLint attribute, EGLint value) {
897    VALIDATE_DISPLAY(display);
898    VALIDATE_SURFACE(surface,srfc);
899    if(!srfc->setAttrib(attribute,value)) {
900        RETURN_ERROR(EGL_FALSE,EGL_BAD_ATTRIBUTE);
901    }
902    return EGL_TRUE;
903 }
904 
905 // eglCreateOrLoadContext is the implementation of eglCreateContext and
906 // eglLoadContext.
907 // |stream| is the snapshot file to load from when calling from eglLoadContext
908 // when |stream| is available, config and share group ID will be loaded from stream
909 
eglCreateOrLoadContext(EGLDisplay display,EGLConfig config,EGLContext share_context,const EGLint * attrib_list,android::base::Stream * stream)910 static EGLContext eglCreateOrLoadContext(EGLDisplay display, EGLConfig config,
911                 EGLContext share_context,
912                 const EGLint *attrib_list,
913                 android::base::Stream *stream) {
914     assert(share_context == EGL_NO_CONTEXT || stream == nullptr);
915     VALIDATE_DISPLAY_RETURN(display,EGL_NO_CONTEXT);
916 
917     uint64_t shareGroupId = 0;
918     EglConfig* cfg = nullptr;
919     if (!stream) {
920         cfg = dpy->getConfig(config);
921         if (!cfg) return EGL_NO_CONTEXT;
922     }
923 
924     EGLint major_version = 0;
925     EGLint minor_version = 0;
926     EGLint context_flags = 0;
927     EGLint profile_mask = 0;
928     EGLint reset_notification_strategy = 0;
929     if(!EglValidate::noAttribs(attrib_list)) {
930         int i = 0;
931         while(attrib_list[i] != EGL_NONE) {
932             EGLint attrib_val = attrib_list[i + 1];
933             switch(attrib_list[i]) {
934             case EGL_CONTEXT_MAJOR_VERSION_KHR:
935                 major_version = attrib_val;
936                 break;
937             case EGL_CONTEXT_MINOR_VERSION_KHR:
938                 minor_version = attrib_val;
939                 break;
940             case EGL_CONTEXT_FLAGS_KHR:
941                 if ((attrib_val | EGL_CONTEXT_OPENGL_DEBUG_BIT_KHR) ||
942                     (attrib_val | EGL_CONTEXT_OPENGL_FORWARD_COMPATIBLE_BIT_KHR)  ||
943                     (attrib_val | EGL_CONTEXT_OPENGL_ROBUST_ACCESS_BIT_KHR)) {
944                     context_flags = attrib_val;
945                 } else {
946                     fprintf(stderr, "%s: wrong context flags, return\n", __func__);
947                     RETURN_ERROR(EGL_NO_CONTEXT,EGL_BAD_ATTRIBUTE);
948                 }
949                 break;
950             case EGL_CONTEXT_OPENGL_PROFILE_MASK_KHR:
951                 if ((attrib_val | EGL_CONTEXT_OPENGL_CORE_PROFILE_BIT_KHR) ||
952                     (attrib_val | EGL_CONTEXT_OPENGL_COMPATIBILITY_PROFILE_BIT_KHR)) {
953                     profile_mask = attrib_val;
954                 } else {
955                     fprintf(stderr, "%s: wrong profile mask, return\n", __func__);
956                     RETURN_ERROR(EGL_NO_CONTEXT,EGL_BAD_ATTRIBUTE);
957                 }
958                 break;
959             case EGL_CONTEXT_OPENGL_RESET_NOTIFICATION_STRATEGY_KHR:
960                 switch (attrib_val) {
961                 case EGL_NO_RESET_NOTIFICATION_KHR:
962                 case EGL_LOSE_CONTEXT_ON_RESET_KHR:
963                     break;
964                 default:
965                     fprintf(stderr, "%s: wrong reset notif strat, return\n", __func__);
966                     RETURN_ERROR(EGL_NO_CONTEXT,EGL_BAD_ATTRIBUTE);
967                 }
968                 reset_notification_strategy = attrib_val;
969                 break;
970             default:
971                 fprintf(stderr, "%s: unknown attrib 0x%x\n", __func__, attrib_list[i]);
972                 RETURN_ERROR(EGL_NO_CONTEXT,EGL_BAD_ATTRIBUTE);
973             }
974             i+=2;
975         }
976     }
977 
978     // TODO: Investigate these ignored flags and see which are needed
979     (void)context_flags;
980     (void)reset_notification_strategy;
981 
982     GLESVersion glesVersion;
983     switch (major_version) {
984      case 1:
985          glesVersion = GLES_1_1;
986          break;
987      case 2:
988          glesVersion = GLES_2_0;
989          break;
990      case 3:
991          switch (minor_version) {
992          case 0:
993              glesVersion = GLES_3_0;
994              break;
995          case 1:
996              glesVersion = GLES_3_1;
997              break;
998          default:
999              RETURN_ERROR(EGL_NO_CONTEXT, EGL_BAD_ATTRIBUTE);
1000              break;
1001          }
1002          break;
1003      default:
1004          RETURN_ERROR(EGL_NO_CONTEXT, EGL_BAD_ATTRIBUTE);
1005          break;
1006     }
1007 
1008     const GLESiface* iface = g_eglInfo->getIface(glesVersion);
1009     GLEScontext* glesCtx = NULL;
1010     if(iface) {
1011         glesCtx = iface->createGLESContext(major_version, minor_version,
1012                 dpy->getGlobalNameSpace(), stream);
1013     } else { // there is no interface for this gles version
1014                 RETURN_ERROR(EGL_NO_CONTEXT,EGL_BAD_ATTRIBUTE);
1015     }
1016 
1017     if(share_context != EGL_NO_CONTEXT) {
1018         ContextPtr sharedCtxPtr = dpy->getContext(share_context);
1019         if(!sharedCtxPtr.get()) {
1020             RETURN_ERROR(EGL_NO_CONTEXT,EGL_BAD_CONTEXT);
1021         }
1022         shareGroupId = sharedCtxPtr->getShareGroup()->getId();
1023         assert(shareGroupId);
1024     }
1025 
1026     android::base::AutoLock mutex(*graphicsDriverLock());
1027 
1028     ContextPtr ctx(new EglContext(dpy, shareGroupId, cfg,
1029                                   glesCtx, glesVersion,
1030                                   profile_mask,
1031                                   dpy->getManager(glesVersion),
1032                                   stream));
1033     if(ctx->nativeType()) {
1034         return dpy->addContext(ctx);
1035     } else {
1036         iface->deleteGLESContext(glesCtx);
1037     }
1038 
1039     return EGL_NO_CONTEXT;
1040 }
1041 
eglCreateContext(EGLDisplay display,EGLConfig config,EGLContext share_context,const EGLint * attrib_list)1042 EGLAPI EGLContext EGLAPIENTRY eglCreateContext(EGLDisplay display, EGLConfig config,
1043                 EGLContext share_context,
1044                 const EGLint *attrib_list) {
1045     return eglCreateOrLoadContext(display, config, share_context, attrib_list, nullptr);
1046 }
1047 
eglLoadContext(EGLDisplay display,const EGLint * attrib_list,android::base::Stream * stream)1048 EGLAPI EGLContext EGLAPIENTRY eglLoadContext(EGLDisplay display, const EGLint *attrib_list,
1049                                              android::base::Stream *stream) {
1050     return eglCreateOrLoadContext(display, (EGLConfig)0, (EGLContext)0, attrib_list, stream);
1051 }
1052 
eglDestroyContext(EGLDisplay display,EGLContext context)1053 EGLAPI EGLBoolean EGLAPIENTRY eglDestroyContext(EGLDisplay display, EGLContext context) {
1054     VALIDATE_DISPLAY(display);
1055     VALIDATE_CONTEXT(context);
1056 
1057     android::base::AutoLock mutex(*graphicsDriverLock());
1058     dpy->removeContext(context);
1059     return EGL_TRUE;
1060 }
1061 
sGetPbufferSurfaceGLProperties(EglPbufferSurface * surface,EGLint * width,EGLint * height,GLint * multisamples,GLint * colorFormat,GLint * depthStencilFormat)1062 static void sGetPbufferSurfaceGLProperties(
1063         EglPbufferSurface* surface,
1064         EGLint* width, EGLint* height, GLint* multisamples,
1065         GLint* colorFormat, GLint* depthStencilFormat) {
1066 
1067     assert(width);
1068     assert(height);
1069     assert(multisamples);
1070     assert(colorFormat);
1071     assert(depthStencilFormat);
1072 
1073     EGLint r, g, b, a, d, s;
1074     surface->getAttrib(EGL_WIDTH, width);
1075     surface->getAttrib(EGL_HEIGHT, height);
1076     surface->getAttrib(EGL_RED_SIZE, &r);
1077     surface->getAttrib(EGL_GREEN_SIZE, &g);
1078     surface->getAttrib(EGL_BLUE_SIZE, &b);
1079     surface->getAttrib(EGL_ALPHA_SIZE, &a);
1080     surface->getAttrib(EGL_DEPTH_SIZE, &d);
1081     surface->getAttrib(EGL_STENCIL_SIZE, &s);
1082     surface->getAttrib(EGL_SAMPLES, multisamples);
1083 
1084     // Currently supported: RGBA8888/RGB888/RGB565/RGBA4/RGB5A1
1085     if (r == 8 && g == 8 && b == 8 && a == 8) {
1086         *colorFormat = GL_RGBA8;
1087     } else if (r == 8 && g == 8 && b == 8 && a == 0) {
1088         *colorFormat = GL_RGB8;
1089     } else if (r == 5 && g == 6 && b == 5 && a == 0) {
1090         *colorFormat = GL_RGB565;
1091     } else if (r == 4 && g == 4 && b == 4 && a == 4) {
1092         *colorFormat = GL_RGBA4;
1093     } else if (r == 5 && g == 5 && b == 5 && a == 1) {
1094         *colorFormat = GL_RGB5_A1;
1095     } else {
1096         GFXSTREAM_ABORT(FatalError(ABORT_REASON_OTHER))
1097             << "invalid color format R" << r << "G" << g << "B" << b << "A" << a;
1098     }
1099 
1100     // Blanket provide 24/8 depth/stencil format for now.
1101     *depthStencilFormat = GL_DEPTH24_STENCIL8;
1102 
1103     // TODO: Support more if necessary, or even restrict
1104     // EGL configs from host display to only these ones.
1105 }
1106 
eglMakeCurrent(EGLDisplay display,EGLSurface draw,EGLSurface read,EGLContext context)1107 EGLAPI EGLBoolean EGLAPIENTRY eglMakeCurrent(EGLDisplay display,
1108                                              EGLSurface draw,
1109                                              EGLSurface read,
1110                                              EGLContext context) {
1111     VALIDATE_DISPLAY(display);
1112 
1113     bool releaseContext = EglValidate::releaseContext(context, read, draw);
1114     if(!releaseContext && EglValidate::badContextMatch(context, read, draw)) {
1115         RETURN_ERROR(EGL_FALSE, EGL_BAD_MATCH);
1116     }
1117 
1118     ThreadInfo* thread = getThreadInfo();
1119     ContextPtr prevCtx = thread->eglContext;
1120 
1121     if(releaseContext) { //releasing current context
1122        if(prevCtx.get()) {
1123            g_eglInfo->getIface(prevCtx->version())->flush();
1124            android::base::AutoLock mutex(*graphicsDriverLock());
1125            if(!dpy->nativeType()->makeCurrent(NULL,NULL,NULL)) {
1126                RETURN_ERROR(EGL_FALSE,EGL_BAD_ACCESS);
1127            }
1128            thread->updateInfo(ContextPtr(),dpy,NULL,ShareGroupPtr(),dpy->getManager(prevCtx->version()));
1129        }
1130     } else { //assining new context
1131         VALIDATE_CONTEXT(context);
1132         VALIDATE_SURFACE(draw,newDrawSrfc);
1133         VALIDATE_SURFACE(read,newReadSrfc);
1134 
1135         EglSurface* newDrawPtr = newDrawSrfc.get();
1136         EglSurface* newReadPtr = newReadSrfc.get();
1137         ContextPtr  newCtx     = ctx;
1138 
1139         if (newCtx.get() && prevCtx.get()) {
1140             if (newCtx.get() == prevCtx.get()) {
1141                 if (newDrawPtr == prevCtx->draw().get() &&
1142                     newReadPtr == prevCtx->read().get()) {
1143                     // nothing to do
1144                     return EGL_TRUE;
1145                 }
1146             }
1147             else {
1148                 // Make sure previous context is detached from surfaces
1149                 releaseContext = true;
1150             }
1151         }
1152 
1153         //surfaces compatibility check
1154         if(!((*ctx->getConfig()).compatibleWith((*newDrawPtr->getConfig()))) ||
1155            !((*ctx->getConfig()).compatibleWith((*newReadPtr->getConfig())))) {
1156             RETURN_ERROR(EGL_FALSE,EGL_BAD_MATCH);
1157         }
1158 
1159          EglOS::Display* nativeDisplay = dpy->nativeType();
1160          EglOS::Surface* nativeRead = newReadPtr->native();
1161          EglOS::Surface* nativeDraw = newDrawPtr->native();
1162         //checking native window validity
1163         if(newReadPtr->type() == EglSurface::WINDOW &&
1164                 !nativeDisplay->isValidNativeWin(nativeRead)) {
1165             RETURN_ERROR(EGL_FALSE,EGL_BAD_NATIVE_WINDOW);
1166         }
1167         if(newDrawPtr->type() == EglSurface::WINDOW &&
1168                 !nativeDisplay->isValidNativeWin(nativeDraw)) {
1169             RETURN_ERROR(EGL_FALSE,EGL_BAD_NATIVE_WINDOW);
1170         }
1171 
1172         if(prevCtx.get()) {
1173             g_eglInfo->getIface(prevCtx->version())->flush();
1174         }
1175 
1176         {
1177             android::base::AutoLock mutex(*graphicsDriverLock());
1178             if (!dpy->nativeType()->makeCurrent(
1179                         newReadPtr->native(),
1180                         newDrawPtr->native(),
1181                         newCtx->nativeType())) {
1182                 RETURN_ERROR(EGL_FALSE,EGL_BAD_ACCESS);
1183             }
1184             //TODO: handle the following errors
1185             // EGL_BAD_CURRENT_SURFACE , EGL_CONTEXT_LOST  , EGL_BAD_ACCESS
1186 
1187             thread->updateInfo(newCtx,dpy,newCtx->getGlesContext(),newCtx->getShareGroup(),dpy->getManager(newCtx->version()));
1188             newCtx->setSurfaces(newReadSrfc,newDrawSrfc);
1189             g_eglInfo->getIface(newCtx->version())->initContext(newCtx->getGlesContext(), newCtx->getShareGroup(),
1190                                                                 dpy->nativeTextureDecompressionEnabled(),
1191                                                                 dpy->programBinaryLinkStatusEnabled());
1192             g_eglInfo->sweepDestroySurfaces();
1193         }
1194 
1195         if (newDrawPtr->type() == EglSurface::PBUFFER &&
1196             newReadPtr->type() == EglSurface::PBUFFER) {
1197 
1198             EglPbufferSurface* tmpPbSurfacePtr =
1199                 static_cast<EglPbufferSurface*>(newDrawPtr);
1200             EglPbufferSurface* tmpReadPbSurfacePtr =
1201                 static_cast<EglPbufferSurface*>(newReadPtr);
1202 
1203             EGLint width, height, readWidth, readHeight;
1204             GLint colorFormat, depthStencilFormat, multisamples;
1205             GLint readColorFormat, readDepthStencilFormat, readMultisamples;
1206 
1207             sGetPbufferSurfaceGLProperties(
1208                     tmpPbSurfacePtr,
1209                     &width, &height,
1210                     &multisamples,
1211                     &colorFormat, &depthStencilFormat);
1212 
1213             sGetPbufferSurfaceGLProperties(
1214                     tmpReadPbSurfacePtr,
1215                     &readWidth, &readHeight,
1216                     &readMultisamples,
1217                     &readColorFormat, &readDepthStencilFormat);
1218 
1219             newCtx->getGlesContext()->initDefaultFBO(
1220                     width, height,
1221                     colorFormat, depthStencilFormat, multisamples,
1222                     &tmpPbSurfacePtr->glRboColor,
1223                     &tmpPbSurfacePtr->glRboDepth,
1224                     readWidth, readHeight,
1225                     readColorFormat, readDepthStencilFormat, readMultisamples,
1226                     &tmpReadPbSurfacePtr->glRboColor,
1227                     &tmpReadPbSurfacePtr->glRboDepth);
1228         }
1229 
1230         // Initialize the GLES extension function table used in
1231         // eglGetProcAddress for the context's GLES version if not
1232         // yet initialized. We initialize it here to make sure we call the
1233         // GLES getProcAddress after when a context is bound.
1234         g_eglInfo->initClientExtFuncTable(newCtx->version());
1235     }
1236 
1237     // release previous context surface binding
1238     if(prevCtx.get() && releaseContext) {
1239         prevCtx->setSurfaces(SurfacePtr(),SurfacePtr());
1240     }
1241 
1242     return EGL_TRUE;
1243 }
1244 
eglQueryContext(EGLDisplay display,EGLContext context,EGLint attribute,EGLint * value)1245 EGLAPI EGLBoolean EGLAPIENTRY eglQueryContext(EGLDisplay display, EGLContext context,
1246                EGLint attribute, EGLint *value) {
1247     VALIDATE_DISPLAY(display);
1248     VALIDATE_CONTEXT(context);
1249 
1250     if(!ctx->getAttrib(attribute,value)){
1251         RETURN_ERROR(EGL_FALSE,EGL_BAD_ATTRIBUTE);
1252     }
1253     return EGL_TRUE;
1254 }
1255 
eglSwapBuffers(EGLDisplay display,EGLSurface surface)1256 EGLAPI EGLBoolean EGLAPIENTRY eglSwapBuffers(EGLDisplay display, EGLSurface surface) {
1257     VALIDATE_DISPLAY(display);
1258     VALIDATE_SURFACE(surface,Srfc);
1259     ThreadInfo* thread        = getThreadInfo();
1260     ContextPtr currentCtx    = thread->eglContext;
1261 
1262 
1263     //if surface not window return
1264     if(Srfc->type() != EglSurface::WINDOW){
1265         RETURN_ERROR(EGL_TRUE,EGL_SUCCESS);
1266     }
1267 
1268     if(!currentCtx.get() || !currentCtx->usingSurface(Srfc) ||
1269             !dpy->nativeType()->isValidNativeWin(Srfc.get()->native())) {
1270         RETURN_ERROR(EGL_FALSE,EGL_BAD_SURFACE);
1271     }
1272 
1273     {
1274         android::base::AutoLock mutex(*graphicsDriverLock());
1275         dpy->nativeType()->swapBuffers(Srfc->native());
1276     }
1277     return EGL_TRUE;
1278 }
1279 
eglGetCurrentContext(void)1280 EGLAPI EGLContext EGLAPIENTRY eglGetCurrentContext(void) {
1281     MEM_TRACE("EMUGL");
1282     android::base::AutoLock mutex(*graphicsDriverLock());
1283     ThreadInfo* thread = getThreadInfo();
1284     EglDisplay* dpy    = static_cast<EglDisplay*>(thread->eglDisplay);
1285     ContextPtr  ctx    = thread->eglContext;
1286     if(dpy && ctx.get()){
1287         // This double check is required because a context might still be current after it is destroyed - in which case
1288         // its handle should be invalid, that is EGL_NO_CONTEXT should be returned even though the context is current
1289         EGLContext c = (EGLContext)SafePointerFromUInt(ctx->getHndl());
1290         if(dpy->getContext(c).get())
1291         {
1292             return c;
1293         }
1294     }
1295     return EGL_NO_CONTEXT;
1296 }
1297 
eglGetCurrentSurface(EGLint readdraw)1298 EGLAPI EGLSurface EGLAPIENTRY eglGetCurrentSurface(EGLint readdraw) {
1299     MEM_TRACE("EMUGL");
1300     android::base::AutoLock mutex(*graphicsDriverLock());
1301     if (!EglValidate::surfaceTarget(readdraw)) {
1302         return EGL_NO_SURFACE;
1303     }
1304 
1305     ThreadInfo* thread = getThreadInfo();
1306     EglDisplay* dpy    = static_cast<EglDisplay*>(thread->eglDisplay);
1307     ContextPtr  ctx    = thread->eglContext;
1308 
1309     if(dpy && ctx.get()) {
1310         SurfacePtr surface = readdraw == EGL_READ ? ctx->read() : ctx->draw();
1311         if(surface.get())
1312         {
1313             // This double check is required because a surface might still be
1314             // current after it is destroyed - in which case its handle should
1315             // be invalid, that is EGL_NO_SURFACE should be returned even
1316             // though the surface is current.
1317             EGLSurface s = (EGLSurface)SafePointerFromUInt(surface->getHndl());
1318             surface = dpy->getSurface(s);
1319             if(surface.get())
1320             {
1321                 return s;
1322             }
1323         }
1324     }
1325     return EGL_NO_SURFACE;
1326 }
1327 
eglGetCurrentDisplay(void)1328 EGLAPI EGLDisplay EGLAPIENTRY eglGetCurrentDisplay(void) {
1329     MEM_TRACE("EMUGL");
1330     ThreadInfo* thread = getThreadInfo();
1331     return (thread->eglContext.get()) ? thread->eglDisplay : EGL_NO_DISPLAY;
1332 }
1333 
eglBindAPI(EGLenum api)1334 EGLAPI EGLBoolean EGLAPIENTRY eglBindAPI(EGLenum api) {
1335     MEM_TRACE("EMUGL");
1336     if(!EglValidate::supportedApi(api)) {
1337         RETURN_ERROR(EGL_FALSE,EGL_BAD_PARAMETER);
1338     }
1339     CURRENT_THREAD();
1340     tls_thread->setApi(api);
1341     return EGL_TRUE;
1342 }
1343 
eglQueryAPI(void)1344 EGLAPI EGLenum EGLAPIENTRY eglQueryAPI(void) {
1345     MEM_TRACE("EMUGL");
1346     CURRENT_THREAD();
1347     return tls_thread->getApi();
1348 }
1349 
eglReleaseThread(void)1350 EGLAPI EGLBoolean EGLAPIENTRY eglReleaseThread(void) {
1351     MEM_TRACE("EMUGL");
1352     ThreadInfo* thread  = getThreadInfo();
1353     EglDisplay* dpy     = static_cast<EglDisplay*>(thread->eglDisplay);
1354     if (!dpy) {
1355         return EGL_TRUE;
1356     }
1357     if (!translator::egl::eglMakeCurrent(dpy,EGL_NO_SURFACE,EGL_NO_SURFACE,EGL_NO_CONTEXT)) {
1358         return EGL_FALSE;
1359     }
1360     return dpy->releaseThread();
1361 }
1362 
1363 EGLAPI void* EGLAPIENTRY
eglGetProcAddress(const char * procname)1364 eglGetProcAddress(const char *procname){
1365     __eglMustCastToProperFunctionPointerType retVal = NULL;
1366 
1367     if(!strncmp(procname,"egl",3)) { //EGL proc
1368         for(int i=0;i < s_eglExtensionsSize;i++){
1369             if(strcmp(procname,s_eglExtensions[i].name) == 0){
1370                 retVal = s_eglExtensions[i].address;
1371                 break;
1372             }
1373         }
1374     }
1375     else {
1376         // Look at the clientAPI (GLES) supported extension
1377         // function table.
1378         retVal = ClientAPIExts::getProcAddress(procname);
1379     }
1380     return (void*)retVal;
1381 }
1382 
1383 /************************** KHR IMAGE *************************************************************/
getEGLImage(unsigned int imageId)1384 ImagePtr getEGLImage(unsigned int imageId)
1385 {
1386     ThreadInfo* thread  = getThreadInfo();
1387     EglDisplay* dpy     = static_cast<EglDisplay*>(thread->eglDisplay);
1388     ContextPtr  ctx     = thread->eglContext;
1389     if (ctx.get()) {
1390         const GLESiface* iface = g_eglInfo->getIface(GLES_2_0);
1391         return dpy->getImage(reinterpret_cast<EGLImageKHR>(imageId),
1392                 iface->restoreTexture);
1393     } else {
1394         // Maybe this is a native image, so we don't need a current gl context.
1395         const GLESiface* iface = g_eglInfo->getIface(GLES_2_0);
1396         return dpy->getImage(reinterpret_cast<EGLImageKHR>(imageId),
1397                 iface->restoreTexture);
1398     }
1399     return nullptr;
1400 }
1401 
eglCreateImageKHR(EGLDisplay display,EGLContext context,EGLenum target,EGLClientBuffer buffer,const EGLint * attrib_list)1402 EGLAPI EGLImageKHR EGLAPIENTRY eglCreateImageKHR(EGLDisplay display, EGLContext context, EGLenum target, EGLClientBuffer buffer, const EGLint *attrib_list)
1403 {
1404     VALIDATE_DISPLAY(display);
1405 
1406     if (target != EGL_GL_TEXTURE_2D_KHR) {
1407         // Create image from underlying and add to registry
1408         EGLImage image = dpy->createNativeImage(dpy->getHostDriverDisplay(), 0, target, buffer, attrib_list);
1409 
1410         if (image == EGL_NO_IMAGE_KHR) {
1411             return EGL_NO_IMAGE_KHR;
1412         }
1413 
1414         ImagePtr img( new EglImage() );
1415         img->isNative = true;
1416         img->nativeImage = image;
1417         img->width = 0;
1418         img->height = 0;
1419         if (attrib_list) {
1420             const EGLint* current = attrib_list;
1421             while (EGL_NONE != *current) {
1422                 switch (*current) {
1423                     case EGL_WIDTH:
1424                         img->width = current[1];
1425                         break;
1426                     case EGL_HEIGHT:
1427                         img->height = current[1];
1428                         break;
1429                     case EGL_LINUX_DRM_FOURCC_EXT:
1430                         // TODO: Translate drm fourcc to internal format
1431                         // img->fourcc = current[1];
1432                         break;
1433                 }
1434                 current += 2;
1435             }
1436         }
1437         get_emugl_vm_operations().setSkipSnapshotSave(true);
1438         return dpy->addImageKHR(img);
1439     }
1440 
1441     ThreadInfo* thread  = getThreadInfo();
1442     ShareGroupPtr sg = thread->shareGroup;
1443     if (sg.get() != NULL) {
1444         NamedObjectPtr globalTexObject = sg->getNamedObject(NamedObjectType::TEXTURE,
1445                                                             SafeUIntFromPointer(buffer));
1446         if (!globalTexObject) return EGL_NO_IMAGE_KHR;
1447 
1448         ImagePtr img( new EglImage() );
1449         if (img.get() != NULL) {
1450             auto objData = sg->getObjectData(
1451                     NamedObjectType::TEXTURE, SafeUIntFromPointer(buffer));
1452             if (!objData) return EGL_NO_IMAGE_KHR;
1453 
1454             TextureData *texData = (TextureData *)objData;
1455             if(!texData->width || !texData->height) return EGL_NO_IMAGE_KHR;
1456             img->width = texData->width;
1457             img->height = texData->height;
1458             img->border = texData->border;
1459             img->internalFormat = texData->internalFormat;
1460             img->globalTexObj = globalTexObject;
1461             img->format = texData->format;
1462             img->type = texData->type;
1463             img->texStorageLevels = texData->texStorageLevels;
1464             img->saveableTexture = texData->getSaveableTexture();
1465             img->needRestore = false;
1466             img->sync = nullptr;
1467             return dpy->addImageKHR(img);
1468         }
1469     }
1470 
1471     return EGL_NO_IMAGE_KHR;
1472 }
1473 
1474 
eglDestroyImageKHR(EGLDisplay display,EGLImageKHR image)1475 EGLAPI EGLBoolean EGLAPIENTRY eglDestroyImageKHR(EGLDisplay display, EGLImageKHR image)
1476 {
1477     VALIDATE_DISPLAY(display);
1478     unsigned int imagehndl = SafeUIntFromPointer(image);
1479     ImagePtr img = getEGLImage(imagehndl);
1480 
1481     if (!img) return EGL_FALSE;
1482 
1483     const GLESiface* iface = g_eglInfo->getIface(GLES_2_0);
1484 
1485     if (img->sync) {
1486         iface->deleteSync((GLsync)img->sync);
1487         img->sync = nullptr;
1488     }
1489 
1490     if (img->isNative && !img->isImported) {
1491         dpy->destroyNativeImage(dpy->getHostDriverDisplay(), img->nativeImage);
1492     }
1493 
1494     return dpy->destroyImageKHR(image) ? EGL_TRUE:EGL_FALSE;
1495 }
1496 
1497 
eglCreateSyncKHR(EGLDisplay dpy,EGLenum type,const EGLint * attrib_list)1498 EGLAPI EGLSyncKHR EGLAPIENTRY eglCreateSyncKHR(EGLDisplay dpy, EGLenum type, const EGLint* attrib_list) {
1499     MEM_TRACE("EMUGL");
1500     // swiftshader_indirect used to have a bug with eglCreateSyncKHR
1501     // but it seems to have been fixed now.
1502     // BUG: 65587659
1503     // BUG: 246740239
1504     if (!g_eglInfo->isEgl2EglSyncSafeToUse()) {
1505         return (EGLSyncKHR)0x42;
1506     }
1507 
1508     const GLESiface* iface = g_eglInfo->getIface(GLES_2_0);
1509     GLsync res = iface->fenceSync(GL_SYNC_GPU_COMMANDS_COMPLETE, 0);
1510     return (EGLSyncKHR)res;
1511 }
1512 
eglClientWaitSyncKHR(EGLDisplay dpy,EGLSyncKHR sync,EGLint flags,EGLTimeKHR timeout)1513 EGLAPI EGLint EGLAPIENTRY eglClientWaitSyncKHR(EGLDisplay dpy, EGLSyncKHR sync, EGLint flags, EGLTimeKHR timeout) {
1514     MEM_TRACE("EMUGL");
1515     android::base::AutoLock mutex(*graphicsDriverLock());
1516     if (!g_eglInfo->isEgl2EglSyncSafeToUse()) {
1517         return EGL_CONDITION_SATISFIED_KHR;
1518     }
1519     const GLESiface* iface = g_eglInfo->getIface(GLES_2_0);
1520     GLenum gl_wait_result =
1521         iface->clientWaitSync((GLsync)sync, GL_SYNC_FLUSH_COMMANDS_BIT, timeout);
1522     EGLint egl_wait_result;
1523 
1524     switch (gl_wait_result) {
1525     case GL_ALREADY_SIGNALED:
1526     case GL_CONDITION_SATISFIED:
1527         egl_wait_result = EGL_CONDITION_SATISFIED_KHR;
1528         break;
1529     case GL_TIMEOUT_EXPIRED:
1530         egl_wait_result = EGL_TIMEOUT_EXPIRED_KHR;
1531         break;
1532     case GL_WAIT_FAILED:
1533         egl_wait_result = EGL_FALSE;
1534         break;
1535     default:
1536         egl_wait_result = EGL_CONDITION_SATISFIED_KHR;
1537     }
1538     return egl_wait_result;
1539 }
1540 
eglDestroySyncKHR(EGLDisplay dpy,EGLSyncKHR sync)1541 EGLAPI EGLBoolean EGLAPIENTRY eglDestroySyncKHR(EGLDisplay dpy, EGLSyncKHR sync) {
1542     MEM_TRACE("EMUGL");
1543     if (!g_eglInfo->isEgl2EglSyncSafeToUse()) {
1544         return EGL_TRUE;
1545     }
1546     const GLESiface* iface = g_eglInfo->getIface(GLES_2_0);
1547     iface->deleteSync((GLsync)sync);
1548     return EGL_TRUE;
1549 }
1550 
eglGetSyncAttribKHR(EGLDisplay dpy,EGLSyncKHR sync,EGLint attribute,EGLint * value)1551 EGLAPI EGLBoolean EGLAPIENTRY eglGetSyncAttribKHR(
1552     EGLDisplay dpy, EGLSyncKHR sync,
1553     EGLint attribute, EGLint *value) {
1554     MEM_TRACE("EMUGL");
1555 
1556     if (!g_eglInfo->isEgl2EglSyncSafeToUse()) {
1557         switch (attribute) {
1558             case EGL_SYNC_TYPE_KHR:
1559                 *value = EGL_SYNC_FENCE_KHR;
1560                 break;
1561             case EGL_SYNC_CONDITION_KHR:
1562                 *value = EGL_SYNC_PRIOR_COMMANDS_COMPLETE_KHR;
1563                 break;
1564             case EGL_SYNC_STATUS_KHR: {
1565                 *value = EGL_SIGNALED_KHR;
1566                 break;
1567             default:
1568                 return EGL_FALSE;
1569             }
1570         }
1571         return EGL_TRUE;
1572     }
1573 
1574     switch (attribute) {
1575         // Guest doesn't care about sync type (handled in guest),
1576         // but host side might care
1577         case EGL_SYNC_TYPE_KHR:
1578             *value = EGL_SYNC_FENCE_KHR;
1579             break;
1580         case EGL_SYNC_CONDITION_KHR:
1581             *value = EGL_SYNC_PRIOR_COMMANDS_COMPLETE_KHR;
1582             break;
1583         case EGL_SYNC_STATUS_KHR: {
1584             const GLESiface* iface = g_eglInfo->getIface(GLES_2_0);
1585             GLint status = -1;
1586             iface->getSynciv((GLsync)sync, GL_SYNC_STATUS, sizeof(GLint), nullptr, &status);
1587             switch (status) {
1588                 case GL_UNSIGNALED:
1589                     *value = EGL_UNSIGNALED_KHR;
1590                     break;
1591                 case GL_SIGNALED:
1592                     *value = EGL_SIGNALED_KHR;
1593                     break;
1594                 default:
1595                     // error, return EGL_FALSE
1596                     return EGL_FALSE;
1597             }
1598             break;
1599         }
1600         default:
1601             return EGL_FALSE;
1602     }
1603 
1604     return EGL_TRUE;
1605 }
1606 
eglGetMaxGLESVersion(EGLDisplay display)1607 EGLAPI EGLint EGLAPIENTRY eglGetMaxGLESVersion(EGLDisplay display) {
1608     // 0: es2 1: es3.0 2: es3.1 3: es3.2
1609     VALIDATE_DISPLAY_RETURN(display, 0 /* gles2 */);
1610     return (EGLint)dpy->getMaxGlesVersion();
1611 }
1612 
eglWaitSyncKHR(EGLDisplay dpy,EGLSyncKHR sync,EGLint flags)1613 EGLAPI EGLint EGLAPIENTRY eglWaitSyncKHR(EGLDisplay dpy, EGLSyncKHR sync, EGLint flags) {
1614     MEM_TRACE("EMUGL");
1615     if (!g_eglInfo->isEgl2EglSyncSafeToUse()) {
1616         return EGL_TRUE;
1617     }
1618     const GLESiface* iface = g_eglInfo->getIface(GLES_2_0);
1619     iface->waitSync((GLsync)sync, 0, -1);
1620     return EGL_TRUE;
1621 }
1622 
eglBlitFromCurrentReadBufferANDROID(EGLDisplay dpy,EGLImageKHR image)1623 EGLAPI void EGLAPIENTRY eglBlitFromCurrentReadBufferANDROID(EGLDisplay dpy, EGLImageKHR image) {
1624     MEM_TRACE("EMUGL");
1625     const GLESiface* iface = g_eglInfo->getIface(GLES_2_0);
1626     iface->blitFromCurrentReadBufferANDROID((GLeglImageOES)image);
1627 }
1628 
1629 // Creates a fence checkpoint for operations that have happened to |image|.
1630 // Other users of |image| can choose to wait on the resulting return fence so
1631 // that operations on |image| occur in the correct order on the GPU.  For
1632 // example, we might render some objects or upload image data to |image| in
1633 // Thread A, and then in Thread B, read the results. It is not guaranteed that
1634 // the write operations on |image| have finished on the GPU when we start
1635 // reading, so we call eglSetImageFenceANDROID at the end of writing operations
1636 // in Thread A, and then wait on the fence in Thread B.
eglSetImageFenceANDROID(EGLDisplay dpy,EGLImageKHR image)1637 EGLAPI void* EGLAPIENTRY eglSetImageFenceANDROID(EGLDisplay dpy, EGLImageKHR image) {
1638     MEM_TRACE("EMUGL");
1639     unsigned int imagehndl = SafeUIntFromPointer(image);
1640     ImagePtr img = getEGLImage(imagehndl);
1641     const GLESiface* iface = g_eglInfo->getIface(GLES_2_0);
1642     if (!img) return iface->fenceSync(GL_SYNC_GPU_COMMANDS_COMPLETE, 0);
1643 
1644     if (img->sync) {
1645         iface->deleteSync((GLsync)img->sync);
1646         img->sync = nullptr;
1647     }
1648 
1649     GLsync res = iface->fenceSync(GL_SYNC_GPU_COMMANDS_COMPLETE, 0);
1650     iface->flush();
1651     img->sync = res;
1652     return (void*)res;
1653 }
1654 
eglWaitImageFenceANDROID(EGLDisplay dpy,void * fence)1655 EGLAPI void EGLAPIENTRY eglWaitImageFenceANDROID(EGLDisplay dpy, void* fence) {
1656     MEM_TRACE("EMUGL");
1657     const GLESiface* iface = g_eglInfo->getIface(GLES_2_0);
1658     iface->waitSync((GLsync)fence, 0, -1);
1659 }
1660 
eglAddLibrarySearchPathANDROID(const char * path)1661 EGLAPI void EGLAPIENTRY eglAddLibrarySearchPathANDROID(const char* path) {
1662     MEM_TRACE("EMUGL");
1663     android::base::SharedLibrary::addLibrarySearchPath(path);
1664 }
1665 
eglQueryVulkanInteropSupportANDROID(void)1666 EGLAPI EGLBoolean EGLAPIENTRY eglQueryVulkanInteropSupportANDROID(void) {
1667     MEM_TRACE("EMUGL");
1668     const GLESiface* iface = g_eglInfo->getIface(GLES_2_0);
1669     return iface->vulkanInteropSupported() ? EGL_TRUE : EGL_FALSE;
1670 }
1671 
eglSetNativeTextureDecompressionEnabledANDROID(EGLDisplay display,EGLBoolean enabled)1672 EGLAPI EGLBoolean EGLAPIENTRY eglSetNativeTextureDecompressionEnabledANDROID(EGLDisplay display, EGLBoolean enabled) {
1673     MEM_TRACE("EMUGL");
1674     VALIDATE_DISPLAY_RETURN(display, EGL_FALSE);
1675     dpy->setNativeTextureDecompressionEnabled(enabled == EGL_TRUE);
1676     return EGL_TRUE;
1677 }
1678 
eglSetProgramBinaryLinkStatusEnabledANDROID(EGLDisplay display,EGLBoolean enabled)1679 EGLAPI EGLBoolean EGLAPIENTRY eglSetProgramBinaryLinkStatusEnabledANDROID(EGLDisplay display, EGLBoolean enabled) {
1680     MEM_TRACE("EMUGL");
1681     VALIDATE_DISPLAY_RETURN(display, EGL_FALSE);
1682     dpy->setProgramBinaryLinkStatusEnabled(enabled == EGL_TRUE);
1683     return EGL_TRUE;
1684 }
1685 
1686 /*********************************************************************************/
1687 
eglPreSaveContext(EGLDisplay display,EGLContext contex,EGLStreamKHR stream)1688 EGLAPI EGLBoolean EGLAPIENTRY eglPreSaveContext(EGLDisplay display, EGLContext contex, EGLStreamKHR stream) {
1689     const GLESiface* iface = g_eglInfo->getIface(GLES_2_0);
1690     assert(iface->saveTexture);
1691     if (!iface || !iface->saveTexture) return EGL_TRUE;
1692     VALIDATE_DISPLAY(display);
1693     VALIDATE_CONTEXT(contex);
1694     ctx->getShareGroup()->preSave(dpy->getGlobalNameSpace());
1695     return EGL_TRUE;
1696 }
1697 
eglSaveContext(EGLDisplay display,EGLContext contex,EGLStreamKHR stream)1698 EGLAPI EGLBoolean EGLAPIENTRY eglSaveContext(EGLDisplay display, EGLContext contex, EGLStreamKHR stream) {
1699     VALIDATE_DISPLAY(display);
1700     VALIDATE_CONTEXT(contex);
1701     ctx->onSave((android::base::Stream*)stream);
1702     return EGL_TRUE;
1703 }
1704 
eglLoadContext(EGLDisplay display,const EGLint * attrib_list,EGLStreamKHR stream)1705 EGLAPI EGLContext EGLAPIENTRY eglLoadContext(EGLDisplay display, const EGLint *attrib_list, EGLStreamKHR stream) {
1706     return eglCreateOrLoadContext(display, (EGLConfig)0, EGL_NO_CONTEXT, attrib_list, (android::base::Stream*)stream);
1707 }
1708 
eglPostSaveContext(EGLDisplay display,EGLContext context,EGLStreamKHR stream)1709 EGLAPI EGLBoolean EGLAPIENTRY eglPostSaveContext(EGLDisplay display, EGLContext context, EGLStreamKHR stream) {
1710     VALIDATE_DISPLAY(display);
1711     VALIDATE_CONTEXT(context);
1712     ctx->postSave((android::base::Stream*)stream);
1713     return EGL_TRUE;
1714 }
1715 
eglSaveConfig(EGLDisplay display,EGLConfig config,EGLStreamKHR stream)1716 EGLAPI EGLBoolean EGLAPIENTRY eglSaveConfig(EGLDisplay display,
1717         EGLConfig config, EGLStreamKHR stream) {
1718     VALIDATE_DISPLAY(display);
1719     VALIDATE_CONFIG(config);
1720     android::base::Stream* stm = static_cast<android::base::Stream*>(stream);
1721     stm->putBe32(cfg->id());
1722     return EGL_TRUE;
1723 }
1724 
eglLoadConfig(EGLDisplay display,EGLStreamKHR stream)1725 EGLAPI EGLConfig EGLAPIENTRY eglLoadConfig(EGLDisplay display, EGLStreamKHR stream) {
1726     VALIDATE_DISPLAY(display);
1727     android::base::Stream* stm = static_cast<android::base::Stream*>(stream);
1728     EGLint cfgId = stm->getBe32();
1729     EglConfig* cfg = dpy->getConfig(cfgId);
1730     if (!cfg) {
1731         fprintf(stderr,
1732                 "WARNING: EGL config mismatch, fallback to default configs\n");
1733         cfg = dpy->getDefaultConfig();
1734     }
1735     return static_cast<EGLConfig>(cfg);
1736 }
1737 
eglSaveAllImages(EGLDisplay display,EGLStreamKHR stream,const void * textureSaver)1738 EGLAPI EGLBoolean EGLAPIENTRY eglSaveAllImages(EGLDisplay display,
1739                                                EGLStreamKHR stream,
1740                                                const void* textureSaver) {
1741     const GLESiface* iface = g_eglInfo->getIface(GLES_2_0);
1742     assert(iface->saveTexture);
1743     if (!iface || !iface->saveTexture)
1744         return true;
1745     VALIDATE_DISPLAY(display);
1746     android::base::Stream* stm = static_cast<android::base::Stream*>(stream);
1747     iface->preSaveTexture();
1748     dpy->onSaveAllImages(
1749             stm,
1750             *static_cast<const android::snapshot::ITextureSaverPtr*>(textureSaver),
1751             iface->saveTexture,
1752             iface->restoreTexture);
1753     iface->postSaveTexture();
1754     return EGL_TRUE;
1755 }
1756 
eglLoadAllImages(EGLDisplay display,EGLStreamKHR stream,const void * textureLoader)1757 EGLAPI EGLBoolean EGLAPIENTRY eglLoadAllImages(EGLDisplay display,
1758                                                EGLStreamKHR stream,
1759                                                const void* textureLoader) {
1760     const GLESiface* iface = g_eglInfo->getIface(GLES_2_0);
1761     assert(iface->createTexture);
1762     if (!iface || !iface->createTexture)
1763         return true;
1764     VALIDATE_DISPLAY(display);
1765     android::base::Stream* stm = static_cast<android::base::Stream*>(stream);
1766     dpy->onLoadAllImages(
1767             stm,
1768             *static_cast<const android::snapshot::ITextureLoaderPtr*>(textureLoader),
1769             iface->createTexture);
1770     return EGL_TRUE;
1771 }
1772 
eglPostLoadAllImages(EGLDisplay display,EGLStreamKHR stream)1773 EGLAPI EGLBoolean EGLAPIENTRY eglPostLoadAllImages(EGLDisplay display, EGLStreamKHR stream) {
1774     VALIDATE_DISPLAY(display);
1775     android::base::Stream* stm = static_cast<android::base::Stream*>(stream);
1776     dpy->postLoadAllImages(stm);
1777     return true;
1778 }
1779 
eglUseOsEglApi(EGLBoolean enable,EGLBoolean nullEgl)1780 EGLAPI void EGLAPIENTRY eglUseOsEglApi(EGLBoolean enable, EGLBoolean nullEgl) {
1781     MEM_TRACE("EMUGL");
1782     EglGlobalInfo::setEgl2Egl(enable, nullEgl == EGL_TRUE);
1783     EglGlobalInfo::setEgl2EglSyncSafeToUse(EGL_TRUE);
1784 }
1785 
eglSetMaxGLESVersion(EGLint version)1786 EGLAPI void EGLAPIENTRY eglSetMaxGLESVersion(EGLint version) {
1787     MEM_TRACE("EMUGL");
1788     // The "version" here follows the convention of eglGetMaxGLESVesion
1789     // 0: es2 1: es3.0 2: es3.1 3: es3.2
1790     GLESVersion glesVersion = GLES_2_0;
1791     switch (version) {
1792     case 0:
1793         glesVersion = GLES_2_0;
1794         break;
1795     case 1:
1796         glesVersion = GLES_3_0;
1797         break;
1798     case 2:
1799     case 3: // TODO: GLES 3.2 support?
1800         glesVersion = GLES_3_1;
1801         break;
1802     }
1803 
1804     if (g_eglInfo->getIface(GLES_1_1)) {
1805         g_eglInfo->getIface(GLES_1_1)->setMaxGlesVersion(glesVersion);
1806     }
1807     g_eglInfo->getIface(GLES_2_0)->setMaxGlesVersion(glesVersion);
1808 }
1809 
eglFillUsages(void * usages)1810 EGLAPI void EGLAPIENTRY eglFillUsages(void* usages) {
1811     MEM_TRACE("EMUGL");
1812     // TODO: Figure out better usage metrics interface
1813     // that doesn't require linking protobuf into Translator
1814     // if (g_eglInfo->getIface(GLES_1_1) &&
1815     //         g_eglInfo->getIface(GLES_1_1)->fillGLESUsages) {
1816     //     g_eglInfo->getIface(GLES_1_1)->fillGLESUsages(
1817     //         (android_studio::EmulatorGLESUsages*)usages);
1818     // }
1819     // if (g_eglInfo->getIface(GLES_2_0) &&
1820     //         g_eglInfo->getIface(GLES_2_0)->fillGLESUsages) {
1821     //     g_eglInfo->getIface(GLES_2_0)->fillGLESUsages(
1822     //         (android_studio::EmulatorGLESUsages*)usages);
1823     // }
1824 }
1825 
eglGetNativeDisplayANDROID(EGLDisplay display)1826 EGLAPI EGLDisplay EGLAPIENTRY eglGetNativeDisplayANDROID(EGLDisplay display) {
1827     VALIDATE_DISPLAY_RETURN(display, (EGLDisplay)0);
1828     return dpy->getHostDriverDisplay();
1829 }
1830 
eglGetNativeContextANDROID(EGLDisplay display,EGLContext context)1831 EGLAPI EGLContext EGLAPIENTRY eglGetNativeContextANDROID(EGLDisplay display, EGLContext context) {
1832     VALIDATE_DISPLAY_RETURN(display, (EGLContext)0);
1833     VALIDATE_CONTEXT_RETURN(context, (EGLContext)0);
1834     return dpy->getNativeContext(context);
1835 }
1836 
eglGetNativeImageANDROID(EGLDisplay display,EGLImage image)1837 EGLAPI EGLImage EGLAPIENTRY eglGetNativeImageANDROID(EGLDisplay display, EGLImage image) {
1838     VALIDATE_DISPLAY_RETURN(display, (EGLImage)0);
1839     unsigned int imagehndl = SafeUIntFromPointer(image);
1840     ImagePtr img = getEGLImage(imagehndl);
1841     if (!img || !img->isNative) return (EGLImage)0;
1842     return img->nativeImage;
1843 }
1844 
eglSetImageInfoANDROID(EGLDisplay display,EGLImage image,EGLint width,EGLint height,EGLint internalFormat)1845 EGLAPI EGLBoolean EGLAPIENTRY eglSetImageInfoANDROID(EGLDisplay display, EGLImage image, EGLint width, EGLint height, EGLint internalFormat) {
1846     VALIDATE_DISPLAY_RETURN(display, EGL_FALSE);
1847     unsigned int imagehndl = SafeUIntFromPointer(image);
1848     ImagePtr img = getEGLImage(imagehndl);
1849     if (!img) {
1850         fprintf(stderr, "%s: error: Could not find image %p\n", __func__, image);
1851         return EGL_FALSE;
1852     }
1853 
1854     img->width = width;
1855     img->height = height;
1856     img->internalFormat = internalFormat;
1857     img->format = getFormatFromInternalFormat(internalFormat);
1858     img->type = getTypeFromInternalFormat(internalFormat);
1859 
1860     return EGL_TRUE;
1861 }
1862 
eglImportImageANDROID(EGLDisplay display,EGLImage nativeImage)1863 EGLImage eglImportImageANDROID(EGLDisplay display, EGLImage nativeImage) {
1864     VALIDATE_DISPLAY_RETURN(display, (EGLImage)0);
1865 	ImagePtr img( new EglImage() );
1866 	img->isNative = true;
1867 	img->isImported = true;
1868 	img->nativeImage = nativeImage;
1869     return dpy->addImageKHR(img);
1870 }
1871 
eglDebugMessageControlKHR(EGLDEBUGPROCKHR callback,const EGLAttrib * attribs)1872 EGLint eglDebugMessageControlKHR(EGLDEBUGPROCKHR callback, const EGLAttrib* attribs) {
1873     return EglGlobalInfo::getInstance()->getOsEngine()->eglDebugMessageControlKHR(callback, attribs);
1874 }
1875 
1876 static const GLint kAuxiliaryContextAttribsCompat[] = {
1877     EGL_CONTEXT_CLIENT_VERSION, 2, EGL_NONE
1878 };
1879 
1880 static const GLint kAuxiliaryContextAttribsCore[] = {
1881     EGL_CONTEXT_CLIENT_VERSION, 2,
1882     EGL_CONTEXT_OPENGL_PROFILE_MASK_KHR,
1883     EGL_CONTEXT_OPENGL_CORE_PROFILE_BIT_KHR,
1884     EGL_NONE
1885 };
1886 
1887 #define NAMESPACED_EGL(f) translator::egl::f
1888 
createAndBindAuxiliaryContext(EGLContext * context_out,EGLSurface * surface_out)1889 static bool createAndBindAuxiliaryContext(EGLContext* context_out, EGLSurface* surface_out) {
1890     // create the context
1891     EGLDisplay dpy = NAMESPACED_EGL(eglGetDisplay)(EGL_DEFAULT_DISPLAY);
1892 
1893     NAMESPACED_EGL(eglBindAPI)(EGL_OPENGL_ES_API);
1894 
1895     static const GLint configAttribs[] = {
1896         EGL_SURFACE_TYPE, EGL_PBUFFER_BIT,
1897         EGL_RENDERABLE_TYPE,
1898         EGL_OPENGL_ES2_BIT, EGL_NONE };
1899 
1900     EGLConfig config;
1901     int numConfigs;
1902     if (!NAMESPACED_EGL(eglChooseConfig)(dpy, configAttribs, &config, 1, &numConfigs) ||
1903         numConfigs == 0) {
1904         fprintf(stderr, "%s: could not find gles 2 config!\n", __func__);
1905         return false;
1906     }
1907 
1908     static const EGLint pbufAttribs[] =
1909         { EGL_WIDTH, 1, EGL_HEIGHT, 1, EGL_NONE };
1910     EGLSurface surface = eglCreatePbufferSurface(dpy, config, pbufAttribs);
1911     if (!surface) {
1912         fprintf(stderr, "%s: could not create surface\n", __func__);
1913         return false;
1914     }
1915 
1916     EGLContext context =
1917         NAMESPACED_EGL(eglCreateContext)(dpy, config, EGL_NO_CONTEXT,
1918             isCoreProfile() ? kAuxiliaryContextAttribsCore :
1919                               kAuxiliaryContextAttribsCompat);
1920 
1921     if (!NAMESPACED_EGL(eglMakeCurrent)(dpy, surface, surface, context)) {
1922         fprintf(stderr, "%s: eglMakeCurrent failed\n", __func__);
1923         return false;
1924     }
1925 
1926     if (context_out) *context_out = context;
1927     if (surface_out) *surface_out = surface;
1928 
1929     return true;
1930 }
1931 
unbindAndDestroyAuxiliaryContext(EGLContext context,EGLSurface surface)1932 static bool unbindAndDestroyAuxiliaryContext(EGLContext context, EGLSurface surface) {
1933 
1934     // create the context
1935     EGLDisplay dpy = NAMESPACED_EGL(eglGetDisplay)(EGL_DEFAULT_DISPLAY);
1936 
1937     if (!NAMESPACED_EGL(eglMakeCurrent)(
1938             dpy, EGL_NO_SURFACE, EGL_NO_SURFACE,
1939             EGL_NO_CONTEXT)) {
1940         fprintf(stderr, "%s: failure to unbind current context!\n",
1941                 __func__);
1942         return false;
1943     }
1944 
1945 
1946     if (!eglDestroySurface(dpy, surface)) {
1947         fprintf(stderr, "%s: failure to destroy surface!\n",
1948                 __func__);
1949         return false;
1950     }
1951 
1952     if (!eglDestroyContext(dpy, context)) {
1953         fprintf(stderr, "%s: failure to destroy context!\n",
1954                 __func__);
1955         return false;
1956     }
1957 
1958     return true;
1959 }
1960 
bindAuxiliaryContext(EGLContext context,EGLSurface surface)1961 static bool bindAuxiliaryContext(EGLContext context, EGLSurface surface) {
1962     // create the context
1963     EGLDisplay dpy = NAMESPACED_EGL(eglGetDisplay)(EGL_DEFAULT_DISPLAY);
1964 
1965     if (!eglMakeCurrent(dpy, surface, surface, context)) {
1966         fprintf(stderr, "%s: eglMakeCurrent failed\n", __func__);
1967         return false;
1968     }
1969 
1970     return true;
1971 }
1972 
unbindAuxiliaryContext()1973 static bool unbindAuxiliaryContext() {
1974 
1975     // create the context
1976     EGLDisplay dpy = NAMESPACED_EGL(eglGetDisplay)(EGL_DEFAULT_DISPLAY);
1977 
1978     if (!eglMakeCurrent(
1979             dpy, EGL_NO_SURFACE, EGL_NO_SURFACE,
1980             EGL_NO_CONTEXT)) {
1981         fprintf(stderr, "%s: failure to unbind current context!\n",
1982                 __func__);
1983         return false;
1984     }
1985 
1986     return true;
1987 }
1988 
eglGetError(void)1989 EGLAPI EGLint EGLAPIENTRY eglGetError(void) {
1990     MEM_TRACE("EMUGL");
1991     CURRENT_THREAD();
1992     EGLint err = tls_thread->getError();
1993     tls_thread->setError(EGL_SUCCESS);
1994     return err;
1995 }
1996 
1997 
1998 } // namespace translator
1999 } // namespace egl
2000