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