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