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