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