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