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