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