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