1 /**************************************************************************
2 *
3 * Copyright 2008 VMware, Inc.
4 * Copyright 2009-2010 Chia-I Wu <olvaffe@gmail.com>
5 * Copyright 2010-2011 LunarG, Inc.
6 * All Rights Reserved.
7 *
8 * Permission is hereby granted, free of charge, to any person obtaining a
9 * copy of this software and associated documentation files (the
10 * "Software"), to deal in the Software without restriction, including
11 * without limitation the rights to use, copy, modify, merge, publish,
12 * distribute, sub license, and/or sell copies of the Software, and to
13 * permit persons to whom the Software is furnished to do so, subject to
14 * the following conditions:
15 *
16 * The above copyright notice and this permission notice (including the
17 * next paragraph) shall be included in all copies or substantial portions
18 * of the Software.
19 *
20 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
21 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
22 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
23 * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
24 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
25 * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
26 * DEALINGS IN THE SOFTWARE.
27 *
28 **************************************************************************/
29
30
31 /**
32 * Public EGL API entrypoints
33 *
34 * Generally, we use the EGLDisplay parameter as a key to lookup the
35 * appropriate device driver handle, then jump though the driver's
36 * dispatch table to handle the function.
37 *
38 * That allows us the option of supporting multiple, simultaneous,
39 * heterogeneous hardware devices in the future.
40 *
41 * The EGLDisplay, EGLConfig, EGLContext and EGLSurface types are
42 * opaque handles. Internal objects are linked to a display to
43 * create the handles.
44 *
45 * For each public API entry point, the opaque handles are looked up
46 * before being dispatched to the drivers. When it fails to look up
47 * a handle, one of
48 *
49 * EGL_BAD_DISPLAY
50 * EGL_BAD_CONFIG
51 * EGL_BAD_CONTEXT
52 * EGL_BAD_SURFACE
53 * EGL_BAD_SCREEN_MESA
54 * EGL_BAD_MODE_MESA
55 *
56 * is generated and the driver function is not called. An
57 * uninitialized EGLDisplay has no driver associated with it. When
58 * such display is detected,
59 *
60 * EGL_NOT_INITIALIZED
61 *
62 * is generated.
63 *
64 * Some of the entry points use current display, context, or surface
65 * implicitly. For such entry points, the implicit objects are also
66 * checked before calling the driver function. Other than the
67 * errors listed above,
68 *
69 * EGL_BAD_CURRENT_SURFACE
70 *
71 * may also be generated.
72 *
73 * Notes on naming conventions:
74 *
75 * eglFooBar - public EGL function
76 * EGL_FOO_BAR - public EGL token
77 * EGLDatatype - public EGL datatype
78 *
79 * _eglFooBar - private EGL function
80 * _EGLDatatype - private EGL datatype, typedef'd struct
81 * _egl_struct - private EGL struct, non-typedef'd
82 *
83 */
84
85
86 #ifdef USE_LIBGLVND
87 #define EGLAPI
88 #undef PUBLIC
89 #define PUBLIC
90 #endif
91
92 #include <assert.h>
93 #include <stdio.h>
94 #include <stdlib.h>
95 #include <string.h>
96 #include "c99_compat.h"
97 #include "c11/threads.h"
98 #include "util/debug.h"
99 #include "util/macros.h"
100
101 #include "egldefines.h"
102 #include "eglglobals.h"
103 #include "eglcontext.h"
104 #include "egldisplay.h"
105 #include "egltypedefs.h"
106 #include "eglcurrent.h"
107 #include "egldevice.h"
108 #include "egldriver.h"
109 #include "eglsurface.h"
110 #include "eglconfig.h"
111 #include "eglimage.h"
112 #include "eglsync.h"
113 #include "egllog.h"
114
115 #include "GL/mesa_glinterop.h"
116
117 /**
118 * Macros to help return an API entrypoint.
119 *
120 * These macros will unlock the display and record the error code.
121 */
122 #define RETURN_EGL_ERROR(disp, err, ret) \
123 do { \
124 if (disp) \
125 _eglUnlockDisplay(disp); \
126 /* EGL error codes are non-zero */ \
127 if (err) \
128 _eglError(err, __func__); \
129 return ret; \
130 } while (0)
131
132 #define RETURN_EGL_SUCCESS(disp, ret) \
133 RETURN_EGL_ERROR(disp, EGL_SUCCESS, ret)
134
135 /* record EGL_SUCCESS only when ret evaluates to true */
136 #define RETURN_EGL_EVAL(disp, ret) \
137 RETURN_EGL_ERROR(disp, (ret) ? EGL_SUCCESS : 0, ret)
138
139
140 /*
141 * A bunch of macros and checks to simplify error checking.
142 */
143
144 #define _EGL_CHECK_DISPLAY(disp, ret) \
145 do { \
146 if (!_eglCheckDisplay(disp, __func__)) \
147 RETURN_EGL_ERROR(disp, 0, ret); \
148 } while (0)
149
150 #define _EGL_CHECK_OBJECT(disp, type, obj, ret) \
151 do { \
152 if (!_eglCheck ## type(disp, obj, __func__)) \
153 RETURN_EGL_ERROR(disp, 0, ret); \
154 } while (0)
155
156 #define _EGL_CHECK_SURFACE(disp, surf, ret) \
157 _EGL_CHECK_OBJECT(disp, Surface, surf, ret)
158
159 #define _EGL_CHECK_CONTEXT(disp, context, ret) \
160 _EGL_CHECK_OBJECT(disp, Context, context, ret)
161
162 #define _EGL_CHECK_CONFIG(disp, conf, ret) \
163 _EGL_CHECK_OBJECT(disp, Config, conf, ret)
164
165 #define _EGL_CHECK_SYNC(disp, s, ret) \
166 _EGL_CHECK_OBJECT(disp, Sync, s, ret)
167
168
169 extern const _EGLDriver _eglDriver;
170
171
172 struct _egl_entrypoint {
173 const char *name;
174 _EGLProc function;
175 };
176
177
178 static inline bool
_eglCheckDisplay(_EGLDisplay * disp,const char * msg)179 _eglCheckDisplay(_EGLDisplay *disp, const char *msg)
180 {
181 if (!disp) {
182 _eglError(EGL_BAD_DISPLAY, msg);
183 return false;
184 }
185 if (!disp->Initialized) {
186 _eglError(EGL_NOT_INITIALIZED, msg);
187 return false;
188 }
189 return true;
190 }
191
192
193 static inline bool
_eglCheckSurface(_EGLDisplay * disp,_EGLSurface * surf,const char * msg)194 _eglCheckSurface(_EGLDisplay *disp, _EGLSurface *surf, const char *msg)
195 {
196 if (!_eglCheckDisplay(disp, msg))
197 return false;
198 if (!surf) {
199 _eglError(EGL_BAD_SURFACE, msg);
200 return false;
201 }
202 return true;
203 }
204
205
206 static inline bool
_eglCheckContext(_EGLDisplay * disp,_EGLContext * context,const char * msg)207 _eglCheckContext(_EGLDisplay *disp, _EGLContext *context, const char *msg)
208 {
209 if (!_eglCheckDisplay(disp, msg))
210 return false;
211 if (!context) {
212 _eglError(EGL_BAD_CONTEXT, msg);
213 return false;
214 }
215 return true;
216 }
217
218
219 static inline bool
_eglCheckConfig(_EGLDisplay * disp,_EGLConfig * conf,const char * msg)220 _eglCheckConfig(_EGLDisplay *disp, _EGLConfig *conf, const char *msg)
221 {
222 if (!_eglCheckDisplay(disp, msg))
223 return false;
224 if (!conf) {
225 _eglError(EGL_BAD_CONFIG, msg);
226 return false;
227 }
228 return true;
229 }
230
231
232 static inline bool
_eglCheckSync(_EGLDisplay * disp,_EGLSync * s,const char * msg)233 _eglCheckSync(_EGLDisplay *disp, _EGLSync *s, const char *msg)
234 {
235 if (!_eglCheckDisplay(disp, msg))
236 return false;
237 if (!s) {
238 _eglError(EGL_BAD_PARAMETER, msg);
239 return false;
240 }
241 return true;
242 }
243
244
245 /**
246 * Lookup and lock a display.
247 */
248 static inline _EGLDisplay *
_eglLockDisplay(EGLDisplay dpy)249 _eglLockDisplay(EGLDisplay dpy)
250 {
251 _EGLDisplay *disp = _eglLookupDisplay(dpy);
252 if (disp)
253 mtx_lock(&disp->Mutex);
254 return disp;
255 }
256
257
258 /**
259 * Unlock a display.
260 */
261 static inline void
_eglUnlockDisplay(_EGLDisplay * disp)262 _eglUnlockDisplay(_EGLDisplay *disp)
263 {
264 mtx_unlock(&disp->Mutex);
265 }
266
267 static EGLBoolean
_eglSetFuncName(const char * funcName,_EGLDisplay * disp,EGLenum objectType,_EGLResource * object)268 _eglSetFuncName(const char *funcName, _EGLDisplay *disp, EGLenum objectType, _EGLResource *object)
269 {
270 _EGLThreadInfo *thr = _eglGetCurrentThread();
271 if (!_eglIsCurrentThreadDummy()) {
272 thr->CurrentFuncName = funcName;
273 thr->CurrentObjectLabel = NULL;
274
275 if (objectType == EGL_OBJECT_THREAD_KHR)
276 thr->CurrentObjectLabel = thr->Label;
277 else if (objectType == EGL_OBJECT_DISPLAY_KHR && disp)
278 thr->CurrentObjectLabel = disp->Label;
279 else if (object)
280 thr->CurrentObjectLabel = object->Label;
281
282 return EGL_TRUE;
283 }
284
285 _eglDebugReport(EGL_BAD_ALLOC, funcName, EGL_DEBUG_MSG_CRITICAL_KHR, NULL);
286 return EGL_FALSE;
287 }
288
289 #define _EGL_FUNC_START(disp, objectType, object, ret) \
290 do { \
291 if (!_eglSetFuncName(__func__, disp, objectType, (_EGLResource *) object)) { \
292 if (disp) \
293 _eglUnlockDisplay(disp); \
294 return ret; \
295 } \
296 } while(0)
297
298 /**
299 * Convert an attribute list from EGLint[] to EGLAttrib[].
300 *
301 * Return an EGL error code. The output parameter out_attrib_list is modified
302 * only on success.
303 */
304 static EGLint
_eglConvertIntsToAttribs(const EGLint * int_list,EGLAttrib ** out_attrib_list)305 _eglConvertIntsToAttribs(const EGLint *int_list, EGLAttrib **out_attrib_list)
306 {
307 size_t len = 0;
308 EGLAttrib *attrib_list;
309
310 if (int_list) {
311 while (int_list[2*len] != EGL_NONE)
312 ++len;
313 }
314
315 if (len == 0) {
316 *out_attrib_list = NULL;
317 return EGL_SUCCESS;
318 }
319
320 if (2*len + 1 > SIZE_MAX / sizeof(EGLAttrib))
321 return EGL_BAD_ALLOC;
322
323 attrib_list = malloc((2*len + 1) * sizeof(EGLAttrib));
324 if (!attrib_list)
325 return EGL_BAD_ALLOC;
326
327 for (size_t i = 0; i < len; ++i) {
328 attrib_list[2*i + 0] = int_list[2*i + 0];
329 attrib_list[2*i + 1] = int_list[2*i + 1];
330 }
331
332 attrib_list[2*len] = EGL_NONE;
333
334 *out_attrib_list = attrib_list;
335 return EGL_SUCCESS;
336 }
337
338
339 static EGLint *
_eglConvertAttribsToInt(const EGLAttrib * attr_list)340 _eglConvertAttribsToInt(const EGLAttrib *attr_list)
341 {
342 size_t size = _eglNumAttribs(attr_list);
343 EGLint *int_attribs = NULL;
344
345 /* Convert attributes from EGLAttrib[] to EGLint[] */
346 if (size) {
347 int_attribs = calloc(size, sizeof(int_attribs[0]));
348 if (!int_attribs)
349 return NULL;
350
351 for (size_t i = 0; i < size; i++)
352 int_attribs[i] = attr_list[i];
353 }
354 return int_attribs;
355 }
356
357
358 /**
359 * This is typically the first EGL function that an application calls.
360 * It associates a private _EGLDisplay object to the native display.
361 */
362 EGLDisplay EGLAPIENTRY
eglGetDisplay(EGLNativeDisplayType nativeDisplay)363 eglGetDisplay(EGLNativeDisplayType nativeDisplay)
364 {
365 _EGLPlatformType plat;
366 _EGLDisplay *disp;
367 void *native_display_ptr;
368
369 _EGL_FUNC_START(NULL, EGL_OBJECT_THREAD_KHR, NULL, EGL_NO_DISPLAY);
370
371 STATIC_ASSERT(sizeof(void*) == sizeof(nativeDisplay));
372 native_display_ptr = (void*) nativeDisplay;
373
374 plat = _eglGetNativePlatform(native_display_ptr);
375 disp = _eglFindDisplay(plat, native_display_ptr, NULL);
376 return _eglGetDisplayHandle(disp);
377 }
378
379 static EGLDisplay
_eglGetPlatformDisplayCommon(EGLenum platform,void * native_display,const EGLAttrib * attrib_list)380 _eglGetPlatformDisplayCommon(EGLenum platform, void *native_display,
381 const EGLAttrib *attrib_list)
382 {
383 _EGLDisplay *disp;
384
385 switch (platform) {
386 #ifdef HAVE_X11_PLATFORM
387 case EGL_PLATFORM_X11_EXT:
388 disp = _eglGetX11Display((Display*) native_display, attrib_list);
389 break;
390 #endif
391 #ifdef HAVE_DRM_PLATFORM
392 case EGL_PLATFORM_GBM_MESA:
393 disp = _eglGetGbmDisplay((struct gbm_device*) native_display,
394 attrib_list);
395 break;
396 #endif
397 #ifdef HAVE_WAYLAND_PLATFORM
398 case EGL_PLATFORM_WAYLAND_EXT:
399 disp = _eglGetWaylandDisplay((struct wl_display*) native_display,
400 attrib_list);
401 break;
402 #endif
403 case EGL_PLATFORM_SURFACELESS_MESA:
404 disp = _eglGetSurfacelessDisplay(native_display, attrib_list);
405 break;
406 #ifdef HAVE_ANDROID_PLATFORM
407 case EGL_PLATFORM_ANDROID_KHR:
408 disp = _eglGetAndroidDisplay(native_display, attrib_list);
409 break;
410 #endif
411 case EGL_PLATFORM_DEVICE_EXT:
412 disp = _eglGetDeviceDisplay(native_display, attrib_list);
413 break;
414 default:
415 RETURN_EGL_ERROR(NULL, EGL_BAD_PARAMETER, NULL);
416 }
417
418 return _eglGetDisplayHandle(disp);
419 }
420
421 static EGLDisplay EGLAPIENTRY
eglGetPlatformDisplayEXT(EGLenum platform,void * native_display,const EGLint * int_attribs)422 eglGetPlatformDisplayEXT(EGLenum platform, void *native_display,
423 const EGLint *int_attribs)
424 {
425 EGLAttrib *attrib_list;
426 EGLDisplay disp;
427
428 _EGL_FUNC_START(NULL, EGL_OBJECT_THREAD_KHR, NULL, EGL_NO_DISPLAY);
429
430 if (_eglConvertIntsToAttribs(int_attribs, &attrib_list) != EGL_SUCCESS)
431 RETURN_EGL_ERROR(NULL, EGL_BAD_ALLOC, NULL);
432
433 disp = _eglGetPlatformDisplayCommon(platform, native_display, attrib_list);
434 free(attrib_list);
435 return disp;
436 }
437
438 EGLDisplay EGLAPIENTRY
eglGetPlatformDisplay(EGLenum platform,void * native_display,const EGLAttrib * attrib_list)439 eglGetPlatformDisplay(EGLenum platform, void *native_display,
440 const EGLAttrib *attrib_list)
441 {
442 _EGL_FUNC_START(NULL, EGL_OBJECT_THREAD_KHR, NULL, EGL_NO_DISPLAY);
443 return _eglGetPlatformDisplayCommon(platform, native_display, attrib_list);
444 }
445
446 /**
447 * Copy the extension into the string and update the string pointer.
448 */
449 static EGLint
_eglAppendExtension(char ** str,const char * ext)450 _eglAppendExtension(char **str, const char *ext)
451 {
452 char *s = *str;
453 size_t len = strlen(ext);
454
455 if (s) {
456 memcpy(s, ext, len);
457 s[len++] = ' ';
458 s[len] = '\0';
459
460 *str += len;
461 }
462 else {
463 len++;
464 }
465
466 return (EGLint) len;
467 }
468
469 /**
470 * Examine the individual extension enable/disable flags and recompute
471 * the driver's Extensions string.
472 */
473 static void
_eglCreateExtensionsString(_EGLDisplay * disp)474 _eglCreateExtensionsString(_EGLDisplay *disp)
475 {
476 #define _EGL_CHECK_EXTENSION(ext) \
477 do { \
478 if (disp->Extensions.ext) { \
479 _eglAppendExtension(&exts, "EGL_" #ext); \
480 assert(exts <= disp->ExtensionsString + _EGL_MAX_EXTENSIONS_LEN); \
481 } \
482 } while (0)
483
484 char *exts = disp->ExtensionsString;
485
486 /* Please keep these sorted alphabetically. */
487 _EGL_CHECK_EXTENSION(ANDROID_blob_cache);
488 _EGL_CHECK_EXTENSION(ANDROID_framebuffer_target);
489 _EGL_CHECK_EXTENSION(ANDROID_image_native_buffer);
490 _EGL_CHECK_EXTENSION(ANDROID_native_fence_sync);
491 _EGL_CHECK_EXTENSION(ANDROID_recordable);
492
493 _EGL_CHECK_EXTENSION(CHROMIUM_sync_control);
494
495 _EGL_CHECK_EXTENSION(EXT_buffer_age);
496 _EGL_CHECK_EXTENSION(EXT_create_context_robustness);
497 _EGL_CHECK_EXTENSION(EXT_image_dma_buf_import);
498 _EGL_CHECK_EXTENSION(EXT_image_dma_buf_import_modifiers);
499 _EGL_CHECK_EXTENSION(EXT_protected_surface);
500 _EGL_CHECK_EXTENSION(EXT_surface_CTA861_3_metadata);
501 _EGL_CHECK_EXTENSION(EXT_surface_SMPTE2086_metadata);
502 _EGL_CHECK_EXTENSION(EXT_swap_buffers_with_damage);
503
504 _EGL_CHECK_EXTENSION(IMG_context_priority);
505
506 _EGL_CHECK_EXTENSION(KHR_cl_event2);
507 _EGL_CHECK_EXTENSION(KHR_config_attribs);
508 _EGL_CHECK_EXTENSION(KHR_context_flush_control);
509 _EGL_CHECK_EXTENSION(KHR_create_context);
510 _EGL_CHECK_EXTENSION(KHR_create_context_no_error);
511 _EGL_CHECK_EXTENSION(KHR_fence_sync);
512 _EGL_CHECK_EXTENSION(KHR_get_all_proc_addresses);
513 _EGL_CHECK_EXTENSION(KHR_gl_colorspace);
514 _EGL_CHECK_EXTENSION(KHR_gl_renderbuffer_image);
515 _EGL_CHECK_EXTENSION(KHR_gl_texture_2D_image);
516 _EGL_CHECK_EXTENSION(KHR_gl_texture_3D_image);
517 _EGL_CHECK_EXTENSION(KHR_gl_texture_cubemap_image);
518 if (disp->Extensions.KHR_image_base && disp->Extensions.KHR_image_pixmap)
519 disp->Extensions.KHR_image = EGL_TRUE;
520 _EGL_CHECK_EXTENSION(KHR_image);
521 _EGL_CHECK_EXTENSION(KHR_image_base);
522 _EGL_CHECK_EXTENSION(KHR_image_pixmap);
523 _EGL_CHECK_EXTENSION(KHR_mutable_render_buffer);
524 _EGL_CHECK_EXTENSION(KHR_no_config_context);
525 _EGL_CHECK_EXTENSION(KHR_partial_update);
526 _EGL_CHECK_EXTENSION(KHR_reusable_sync);
527 _EGL_CHECK_EXTENSION(KHR_surfaceless_context);
528 if (disp->Extensions.EXT_swap_buffers_with_damage)
529 _eglAppendExtension(&exts, "EGL_KHR_swap_buffers_with_damage");
530 _EGL_CHECK_EXTENSION(EXT_pixel_format_float);
531 _EGL_CHECK_EXTENSION(KHR_wait_sync);
532
533 if (disp->Extensions.KHR_no_config_context)
534 _eglAppendExtension(&exts, "EGL_MESA_configless_context");
535 _EGL_CHECK_EXTENSION(MESA_drm_image);
536 _EGL_CHECK_EXTENSION(MESA_image_dma_buf_export);
537 _EGL_CHECK_EXTENSION(MESA_query_driver);
538
539 _EGL_CHECK_EXTENSION(NOK_swap_region);
540 _EGL_CHECK_EXTENSION(NOK_texture_from_pixmap);
541
542 _EGL_CHECK_EXTENSION(NV_post_sub_buffer);
543
544 _EGL_CHECK_EXTENSION(WL_bind_wayland_display);
545 _EGL_CHECK_EXTENSION(WL_create_wayland_buffer_from_image);
546
547 #undef _EGL_CHECK_EXTENSION
548 }
549
550 static void
_eglCreateAPIsString(_EGLDisplay * disp)551 _eglCreateAPIsString(_EGLDisplay *disp)
552 {
553 #define addstr(str) \
554 { \
555 const size_t old_len = strlen(disp->ClientAPIsString); \
556 const size_t add_len = sizeof(str); \
557 const size_t max_len = sizeof(disp->ClientAPIsString) - 1; \
558 if (old_len + add_len <= max_len) \
559 strcat(disp->ClientAPIsString, str " "); \
560 else \
561 assert(!"disp->ClientAPIsString is not large enough"); \
562 }
563
564 if (disp->ClientAPIs & EGL_OPENGL_BIT)
565 addstr("OpenGL");
566
567 if (disp->ClientAPIs & EGL_OPENGL_ES_BIT ||
568 disp->ClientAPIs & EGL_OPENGL_ES2_BIT ||
569 disp->ClientAPIs & EGL_OPENGL_ES3_BIT_KHR) {
570 addstr("OpenGL_ES");
571 }
572
573 if (disp->ClientAPIs & EGL_OPENVG_BIT)
574 addstr("OpenVG");
575
576 #undef addstr
577 }
578
579 static void
_eglComputeVersion(_EGLDisplay * disp)580 _eglComputeVersion(_EGLDisplay *disp)
581 {
582 disp->Version = 14;
583
584 if (disp->Extensions.KHR_fence_sync &&
585 disp->Extensions.KHR_cl_event2 &&
586 disp->Extensions.KHR_wait_sync &&
587 disp->Extensions.KHR_image_base &&
588 disp->Extensions.KHR_gl_texture_2D_image &&
589 disp->Extensions.KHR_gl_texture_3D_image &&
590 disp->Extensions.KHR_gl_texture_cubemap_image &&
591 disp->Extensions.KHR_gl_renderbuffer_image &&
592 disp->Extensions.KHR_create_context &&
593 disp->Extensions.EXT_create_context_robustness &&
594 disp->Extensions.KHR_get_all_proc_addresses &&
595 disp->Extensions.KHR_gl_colorspace &&
596 disp->Extensions.KHR_surfaceless_context)
597 disp->Version = 15;
598
599 /* For Android P and below limit the EGL version to 1.4 */
600 #if defined(ANDROID) && ANDROID_API_LEVEL <= 28
601 disp->Version = 14;
602 #endif
603 }
604
605 /**
606 * This is typically the second EGL function that an application calls.
607 * Here we load/initialize the actual hardware driver.
608 */
609 EGLBoolean EGLAPIENTRY
eglInitialize(EGLDisplay dpy,EGLint * major,EGLint * minor)610 eglInitialize(EGLDisplay dpy, EGLint *major, EGLint *minor)
611 {
612 _EGLDisplay *disp = _eglLockDisplay(dpy);
613
614 _EGL_FUNC_START(disp, EGL_OBJECT_DISPLAY_KHR, NULL, EGL_FALSE);
615
616 if (!disp)
617 RETURN_EGL_ERROR(NULL, EGL_BAD_DISPLAY, EGL_FALSE);
618
619 if (!disp->Initialized) {
620 /* set options */
621 disp->Options.ForceSoftware =
622 env_var_as_boolean("LIBGL_ALWAYS_SOFTWARE", false);
623 if (disp->Options.ForceSoftware)
624 _eglLog(_EGL_DEBUG, "Found 'LIBGL_ALWAYS_SOFTWARE' set, will use a CPU renderer");
625
626 /**
627 * Initialize the display using the driver's function.
628 * If the initialisation fails, try again using only software rendering.
629 */
630 if (!_eglDriver.Initialize(disp)) {
631 if (disp->Options.ForceSoftware)
632 RETURN_EGL_ERROR(disp, EGL_NOT_INITIALIZED, EGL_FALSE);
633 else {
634 disp->Options.ForceSoftware = EGL_TRUE;
635 if (!_eglDriver.Initialize(disp))
636 RETURN_EGL_ERROR(disp, EGL_NOT_INITIALIZED, EGL_FALSE);
637 }
638 }
639
640 disp->Initialized = EGL_TRUE;
641 disp->Driver = &_eglDriver;
642
643 /* limit to APIs supported by core */
644 disp->ClientAPIs &= _EGL_API_ALL_BITS;
645
646 /* EGL_KHR_get_all_proc_addresses is a corner-case extension. The spec
647 * classifies it as an EGL display extension, though conceptually it's an
648 * EGL client extension.
649 *
650 * From the EGL_KHR_get_all_proc_addresses spec:
651 *
652 * The EGL implementation must expose the name
653 * EGL_KHR_client_get_all_proc_addresses if and only if it exposes
654 * EGL_KHR_get_all_proc_addresses and supports
655 * EGL_EXT_client_extensions.
656 *
657 * Mesa unconditionally exposes both client extensions mentioned above,
658 * so the spec requires that each EGLDisplay unconditionally expose
659 * EGL_KHR_get_all_proc_addresses also.
660 */
661 disp->Extensions.KHR_get_all_proc_addresses = EGL_TRUE;
662
663 /* Extensions is used to provide EGL 1.3 functionality for 1.2 aware
664 * programs. It is driver agnostic and handled in the main EGL code.
665 */
666 disp->Extensions.KHR_config_attribs = EGL_TRUE;
667
668 _eglComputeVersion(disp);
669 _eglCreateExtensionsString(disp);
670 _eglCreateAPIsString(disp);
671 snprintf(disp->VersionString, sizeof(disp->VersionString),
672 "%d.%d", disp->Version / 10, disp->Version % 10);
673 }
674
675 /* Update applications version of major and minor if not NULL */
676 if ((major != NULL) && (minor != NULL)) {
677 *major = disp->Version / 10;
678 *minor = disp->Version % 10;
679 }
680
681 RETURN_EGL_SUCCESS(disp, EGL_TRUE);
682 }
683
684
685 EGLBoolean EGLAPIENTRY
eglTerminate(EGLDisplay dpy)686 eglTerminate(EGLDisplay dpy)
687 {
688 _EGLDisplay *disp = _eglLockDisplay(dpy);
689
690 _EGL_FUNC_START(disp, EGL_OBJECT_DISPLAY_KHR, NULL, EGL_FALSE);
691
692 if (!disp)
693 RETURN_EGL_ERROR(NULL, EGL_BAD_DISPLAY, EGL_FALSE);
694
695 if (disp->Initialized) {
696 disp->Driver->Terminate(disp);
697 /* do not reset disp->Driver */
698 disp->ClientAPIsString[0] = 0;
699 disp->Initialized = EGL_FALSE;
700
701 /* Reset blob cache funcs on terminate. */
702 disp->BlobCacheSet = NULL;
703 disp->BlobCacheGet = NULL;
704 }
705
706 RETURN_EGL_SUCCESS(disp, EGL_TRUE);
707 }
708
709
710 const char * EGLAPIENTRY
eglQueryString(EGLDisplay dpy,EGLint name)711 eglQueryString(EGLDisplay dpy, EGLint name)
712 {
713 _EGLDisplay *disp;
714
715 #if !USE_LIBGLVND
716 if (dpy == EGL_NO_DISPLAY && name == EGL_EXTENSIONS) {
717 RETURN_EGL_SUCCESS(NULL, _eglGlobal.ClientExtensionString);
718 }
719 #endif
720
721 disp = _eglLockDisplay(dpy);
722 _EGL_FUNC_START(disp, EGL_OBJECT_DISPLAY_KHR, NULL, NULL);
723 _EGL_CHECK_DISPLAY(disp, NULL);
724
725 switch (name) {
726 case EGL_VENDOR:
727 RETURN_EGL_SUCCESS(disp, _EGL_VENDOR_STRING);
728 case EGL_VERSION:
729 RETURN_EGL_SUCCESS(disp, disp->VersionString);
730 case EGL_EXTENSIONS:
731 RETURN_EGL_SUCCESS(disp, disp->ExtensionsString);
732 case EGL_CLIENT_APIS:
733 RETURN_EGL_SUCCESS(disp, disp->ClientAPIsString);
734 default:
735 RETURN_EGL_ERROR(disp, EGL_BAD_PARAMETER, NULL);
736 }
737 }
738
739
740 EGLBoolean EGLAPIENTRY
eglGetConfigs(EGLDisplay dpy,EGLConfig * configs,EGLint config_size,EGLint * num_config)741 eglGetConfigs(EGLDisplay dpy, EGLConfig *configs,
742 EGLint config_size, EGLint *num_config)
743 {
744 _EGLDisplay *disp = _eglLockDisplay(dpy);
745 EGLBoolean ret;
746
747 _EGL_FUNC_START(disp, EGL_OBJECT_DISPLAY_KHR, NULL, EGL_FALSE);
748
749 _EGL_CHECK_DISPLAY(disp, EGL_FALSE);
750
751 if (!num_config)
752 RETURN_EGL_ERROR(disp, EGL_BAD_PARAMETER, EGL_FALSE);
753
754 ret = _eglGetConfigs(disp, configs, config_size, num_config);
755
756 RETURN_EGL_EVAL(disp, ret);
757 }
758
759
760 EGLBoolean EGLAPIENTRY
eglChooseConfig(EGLDisplay dpy,const EGLint * attrib_list,EGLConfig * configs,EGLint config_size,EGLint * num_config)761 eglChooseConfig(EGLDisplay dpy, const EGLint *attrib_list, EGLConfig *configs,
762 EGLint config_size, EGLint *num_config)
763 {
764 _EGLDisplay *disp = _eglLockDisplay(dpy);
765 EGLBoolean ret;
766
767 _EGL_FUNC_START(disp, EGL_OBJECT_DISPLAY_KHR, NULL, EGL_FALSE);
768
769 _EGL_CHECK_DISPLAY(disp, EGL_FALSE);
770
771 if (!num_config)
772 RETURN_EGL_ERROR(disp, EGL_BAD_PARAMETER, EGL_FALSE);
773
774 ret = _eglChooseConfig(disp, attrib_list, configs,
775 config_size, num_config);
776
777 RETURN_EGL_EVAL(disp, ret);
778 }
779
780
781 EGLBoolean EGLAPIENTRY
eglGetConfigAttrib(EGLDisplay dpy,EGLConfig config,EGLint attribute,EGLint * value)782 eglGetConfigAttrib(EGLDisplay dpy, EGLConfig config,
783 EGLint attribute, EGLint *value)
784 {
785 _EGLDisplay *disp = _eglLockDisplay(dpy);
786 _EGLConfig *conf = _eglLookupConfig(config, disp);
787 EGLBoolean ret;
788
789 _EGL_FUNC_START(disp, EGL_OBJECT_DISPLAY_KHR, NULL, EGL_FALSE);
790
791 _EGL_CHECK_CONFIG(disp, conf, EGL_FALSE);
792
793 ret = _eglGetConfigAttrib(disp, conf, attribute, value);
794
795 RETURN_EGL_EVAL(disp, ret);
796 }
797
798
799 EGLContext EGLAPIENTRY
eglCreateContext(EGLDisplay dpy,EGLConfig config,EGLContext share_list,const EGLint * attrib_list)800 eglCreateContext(EGLDisplay dpy, EGLConfig config, EGLContext share_list,
801 const EGLint *attrib_list)
802 {
803 _EGLDisplay *disp = _eglLockDisplay(dpy);
804 _EGLConfig *conf = _eglLookupConfig(config, disp);
805 _EGLContext *share = _eglLookupContext(share_list, disp);
806 _EGLContext *context;
807 EGLContext ret;
808
809 _EGL_FUNC_START(disp, EGL_OBJECT_DISPLAY_KHR, NULL, EGL_NO_CONTEXT);
810
811 _EGL_CHECK_DISPLAY(disp, EGL_NO_CONTEXT);
812
813 if (config != EGL_NO_CONFIG_KHR)
814 _EGL_CHECK_CONFIG(disp, conf, EGL_NO_CONTEXT);
815 else if (!disp->Extensions.KHR_no_config_context)
816 RETURN_EGL_ERROR(disp, EGL_BAD_CONFIG, EGL_NO_CONTEXT);
817
818 if (!share && share_list != EGL_NO_CONTEXT)
819 RETURN_EGL_ERROR(disp, EGL_BAD_CONTEXT, EGL_NO_CONTEXT);
820
821 context = disp->Driver->CreateContext(disp, conf, share, attrib_list);
822 ret = (context) ? _eglLinkContext(context) : EGL_NO_CONTEXT;
823
824 RETURN_EGL_EVAL(disp, ret);
825 }
826
827
828 EGLBoolean EGLAPIENTRY
eglDestroyContext(EGLDisplay dpy,EGLContext ctx)829 eglDestroyContext(EGLDisplay dpy, EGLContext ctx)
830 {
831 _EGLDisplay *disp = _eglLockDisplay(dpy);
832 _EGLContext *context = _eglLookupContext(ctx, disp);
833 EGLBoolean ret;
834
835 _EGL_FUNC_START(disp, EGL_OBJECT_CONTEXT_KHR, context, EGL_FALSE);
836
837 _EGL_CHECK_CONTEXT(disp, context, EGL_FALSE);
838 _eglUnlinkContext(context);
839 ret = disp->Driver->DestroyContext(disp, context);
840
841 RETURN_EGL_EVAL(disp, ret);
842 }
843
844
845 EGLBoolean EGLAPIENTRY
eglMakeCurrent(EGLDisplay dpy,EGLSurface draw,EGLSurface read,EGLContext ctx)846 eglMakeCurrent(EGLDisplay dpy, EGLSurface draw, EGLSurface read,
847 EGLContext ctx)
848 {
849 _EGLDisplay *disp = _eglLockDisplay(dpy);
850 _EGLContext *context = _eglLookupContext(ctx, disp);
851 _EGLSurface *draw_surf = _eglLookupSurface(draw, disp);
852 _EGLSurface *read_surf = _eglLookupSurface(read, disp);
853 EGLBoolean ret;
854
855 _EGL_FUNC_START(disp, EGL_OBJECT_CONTEXT_KHR, context, EGL_FALSE);
856
857 if (!disp)
858 RETURN_EGL_ERROR(disp, EGL_BAD_DISPLAY, EGL_FALSE);
859
860 /* display is allowed to be uninitialized under certain condition */
861 if (!disp->Initialized) {
862 if (draw != EGL_NO_SURFACE || read != EGL_NO_SURFACE ||
863 ctx != EGL_NO_CONTEXT)
864 RETURN_EGL_ERROR(disp, EGL_BAD_DISPLAY, EGL_FALSE);
865 }
866 if (!disp->Driver)
867 RETURN_EGL_SUCCESS(disp, EGL_TRUE);
868
869 if (!context && ctx != EGL_NO_CONTEXT)
870 RETURN_EGL_ERROR(disp, EGL_BAD_CONTEXT, EGL_FALSE);
871 if (!draw_surf || !read_surf) {
872 /* From the EGL 1.4 (20130211) spec:
873 *
874 * To release the current context without assigning a new one, set ctx
875 * to EGL_NO_CONTEXT and set draw and read to EGL_NO_SURFACE.
876 */
877 if (!disp->Extensions.KHR_surfaceless_context && ctx != EGL_NO_CONTEXT)
878 RETURN_EGL_ERROR(disp, EGL_BAD_SURFACE, EGL_FALSE);
879
880 if ((!draw_surf && draw != EGL_NO_SURFACE) ||
881 (!read_surf && read != EGL_NO_SURFACE))
882 RETURN_EGL_ERROR(disp, EGL_BAD_SURFACE, EGL_FALSE);
883 if (draw_surf || read_surf)
884 RETURN_EGL_ERROR(disp, EGL_BAD_MATCH, EGL_FALSE);
885 }
886
887 /* If a native window underlying either draw or read is no longer valid,
888 * an EGL_BAD_NATIVE_WINDOW error is generated.
889 */
890 if (draw_surf && draw_surf->Lost)
891 RETURN_EGL_ERROR(disp, EGL_BAD_NATIVE_WINDOW, EGL_FALSE);
892 if (read_surf && read_surf->Lost)
893 RETURN_EGL_ERROR(disp, EGL_BAD_NATIVE_WINDOW, EGL_FALSE);
894 /* EGL_EXT_protected_surface spec says:
895 * If EGL_PROTECTED_CONTENT_EXT attributes of read is EGL_TRUE and
896 * EGL_PROTECTED_CONTENT_EXT attributes of draw is EGL_FALSE, an
897 * EGL_BAD_ACCESS error is generated.
898 */
899 if (read_surf && read_surf->ProtectedContent &&
900 draw_surf && !draw_surf->ProtectedContent)
901 RETURN_EGL_ERROR(disp, EGL_BAD_ACCESS, EGL_FALSE);
902
903 ret = disp->Driver->MakeCurrent(disp, draw_surf, read_surf, context);
904
905 RETURN_EGL_EVAL(disp, ret);
906 }
907
908
909 EGLBoolean EGLAPIENTRY
eglQueryContext(EGLDisplay dpy,EGLContext ctx,EGLint attribute,EGLint * value)910 eglQueryContext(EGLDisplay dpy, EGLContext ctx,
911 EGLint attribute, EGLint *value)
912 {
913 _EGLDisplay *disp = _eglLockDisplay(dpy);
914 _EGLContext *context = _eglLookupContext(ctx, disp);
915 EGLBoolean ret;
916
917 _EGL_FUNC_START(disp, EGL_OBJECT_CONTEXT_KHR, context, EGL_FALSE);
918
919 _EGL_CHECK_CONTEXT(disp, context, EGL_FALSE);
920
921 ret = _eglQueryContext(context, attribute, value);
922
923 RETURN_EGL_EVAL(disp, ret);
924 }
925
926
927 /* In EGL specs 1.4 and 1.5, at the end of sections 3.5.1 and 3.5.4, it says
928 * that if native_surface was already used to create a window or pixmap, we
929 * can't create a new one. This is what this function checks for.
930 */
931 static bool
_eglNativeSurfaceAlreadyUsed(_EGLDisplay * disp,void * native_surface)932 _eglNativeSurfaceAlreadyUsed(_EGLDisplay *disp, void *native_surface)
933 {
934 _EGLResource *list;
935
936 list = disp->ResourceLists[_EGL_RESOURCE_SURFACE];
937 while (list) {
938 _EGLSurface *surf = (_EGLSurface *) list;
939
940 list = list->Next;
941
942 if (surf->Type == EGL_PBUFFER_BIT)
943 continue;
944
945 if (surf->NativeSurface == native_surface)
946 return true;
947 }
948
949 return false;
950 }
951
952
953 static EGLSurface
_eglCreateWindowSurfaceCommon(_EGLDisplay * disp,EGLConfig config,void * native_window,const EGLint * attrib_list)954 _eglCreateWindowSurfaceCommon(_EGLDisplay *disp, EGLConfig config,
955 void *native_window, const EGLint *attrib_list)
956 {
957 _EGLConfig *conf = _eglLookupConfig(config, disp);
958 _EGLSurface *surf;
959 EGLSurface ret;
960
961
962 if (native_window == NULL)
963 RETURN_EGL_ERROR(disp, EGL_BAD_NATIVE_WINDOW, EGL_NO_SURFACE);
964
965 if (disp && (disp->Platform == _EGL_PLATFORM_SURFACELESS ||
966 disp->Platform == _EGL_PLATFORM_DEVICE)) {
967 /* From the EGL_MESA_platform_surfaceless spec (v1):
968 *
969 * eglCreatePlatformWindowSurface fails when called with a <display>
970 * that belongs to the surfaceless platform. It returns
971 * EGL_NO_SURFACE and generates EGL_BAD_NATIVE_WINDOW. The
972 * justification for this unconditional failure is that the
973 * surfaceless platform has no native windows, and therefore the
974 * <native_window> parameter is always invalid.
975 *
976 * This check must occur before checking the EGLConfig, which emits
977 * EGL_BAD_CONFIG.
978 */
979 RETURN_EGL_ERROR(disp, EGL_BAD_NATIVE_WINDOW, EGL_NO_SURFACE);
980 }
981
982 _EGL_CHECK_CONFIG(disp, conf, EGL_NO_SURFACE);
983
984 if ((conf->SurfaceType & EGL_WINDOW_BIT) == 0)
985 RETURN_EGL_ERROR(disp, EGL_BAD_MATCH, EGL_NO_SURFACE);
986
987 if (_eglNativeSurfaceAlreadyUsed(disp, native_window))
988 RETURN_EGL_ERROR(disp, EGL_BAD_ALLOC, EGL_NO_SURFACE);
989
990 surf = disp->Driver->CreateWindowSurface(disp, conf, native_window, attrib_list);
991 ret = (surf) ? _eglLinkSurface(surf) : EGL_NO_SURFACE;
992
993 RETURN_EGL_EVAL(disp, ret);
994 }
995
996
997 EGLSurface EGLAPIENTRY
eglCreateWindowSurface(EGLDisplay dpy,EGLConfig config,EGLNativeWindowType window,const EGLint * attrib_list)998 eglCreateWindowSurface(EGLDisplay dpy, EGLConfig config,
999 EGLNativeWindowType window, const EGLint *attrib_list)
1000 {
1001 _EGLDisplay *disp = _eglLockDisplay(dpy);
1002
1003 _EGL_FUNC_START(disp, EGL_OBJECT_DISPLAY_KHR, NULL, EGL_NO_SURFACE);
1004 STATIC_ASSERT(sizeof(void*) == sizeof(window));
1005 return _eglCreateWindowSurfaceCommon(disp, config, (void*) window,
1006 attrib_list);
1007 }
1008
1009 static void *
_fixupNativeWindow(_EGLDisplay * disp,void * native_window)1010 _fixupNativeWindow(_EGLDisplay *disp, void *native_window)
1011 {
1012 #ifdef HAVE_X11_PLATFORM
1013 if (disp && disp->Platform == _EGL_PLATFORM_X11 && native_window != NULL) {
1014 /* The `native_window` parameter for the X11 platform differs between
1015 * eglCreateWindowSurface() and eglCreatePlatformPixmapSurfaceEXT(). In
1016 * eglCreateWindowSurface(), the type of `native_window` is an Xlib
1017 * `Window`. In eglCreatePlatformWindowSurfaceEXT(), the type is
1018 * `Window*`. Convert `Window*` to `Window` because that's what
1019 * dri2_x11_create_window_surface() expects.
1020 */
1021 return (void *)(* (Window*) native_window);
1022 }
1023 #endif
1024 return native_window;
1025 }
1026
1027 static EGLSurface EGLAPIENTRY
eglCreatePlatformWindowSurfaceEXT(EGLDisplay dpy,EGLConfig config,void * native_window,const EGLint * attrib_list)1028 eglCreatePlatformWindowSurfaceEXT(EGLDisplay dpy, EGLConfig config,
1029 void *native_window,
1030 const EGLint *attrib_list)
1031 {
1032 _EGLDisplay *disp = _eglLockDisplay(dpy);
1033
1034 native_window = _fixupNativeWindow(disp, native_window);
1035
1036 _EGL_FUNC_START(disp, EGL_OBJECT_DISPLAY_KHR, NULL, EGL_NO_SURFACE);
1037 return _eglCreateWindowSurfaceCommon(disp, config, native_window,
1038 attrib_list);
1039 }
1040
1041
1042 EGLSurface EGLAPIENTRY
eglCreatePlatformWindowSurface(EGLDisplay dpy,EGLConfig config,void * native_window,const EGLAttrib * attrib_list)1043 eglCreatePlatformWindowSurface(EGLDisplay dpy, EGLConfig config,
1044 void *native_window,
1045 const EGLAttrib *attrib_list)
1046 {
1047 _EGLDisplay *disp = _eglLockDisplay(dpy);
1048 EGLSurface surface;
1049 EGLint *int_attribs;
1050
1051 _EGL_FUNC_START(disp, EGL_OBJECT_DISPLAY_KHR, NULL, EGL_NO_SURFACE);
1052
1053 int_attribs = _eglConvertAttribsToInt(attrib_list);
1054 if (attrib_list && !int_attribs)
1055 RETURN_EGL_ERROR(disp, EGL_BAD_ALLOC, EGL_NO_SURFACE);
1056
1057 native_window = _fixupNativeWindow(disp, native_window);
1058 surface = _eglCreateWindowSurfaceCommon(disp, config, native_window,
1059 int_attribs);
1060 free(int_attribs);
1061 return surface;
1062 }
1063
1064 static void *
_fixupNativePixmap(_EGLDisplay * disp,void * native_pixmap)1065 _fixupNativePixmap(_EGLDisplay *disp, void *native_pixmap)
1066 {
1067 #ifdef HAVE_X11_PLATFORM
1068 /* The `native_pixmap` parameter for the X11 platform differs between
1069 * eglCreatePixmapSurface() and eglCreatePlatformPixmapSurfaceEXT(). In
1070 * eglCreatePixmapSurface(), the type of `native_pixmap` is an Xlib
1071 * `Pixmap`. In eglCreatePlatformPixmapSurfaceEXT(), the type is
1072 * `Pixmap*`. Convert `Pixmap*` to `Pixmap` because that's what
1073 * dri2_x11_create_pixmap_surface() expects.
1074 */
1075 if (disp && disp->Platform == _EGL_PLATFORM_X11 && native_pixmap != NULL)
1076 return (void *)(* (Pixmap*) native_pixmap);
1077 #endif
1078 return native_pixmap;
1079 }
1080
1081 static EGLSurface
_eglCreatePixmapSurfaceCommon(_EGLDisplay * disp,EGLConfig config,void * native_pixmap,const EGLint * attrib_list)1082 _eglCreatePixmapSurfaceCommon(_EGLDisplay *disp, EGLConfig config,
1083 void *native_pixmap, const EGLint *attrib_list)
1084 {
1085 _EGLConfig *conf = _eglLookupConfig(config, disp);
1086 _EGLSurface *surf;
1087 EGLSurface ret;
1088
1089 if (disp && (disp->Platform == _EGL_PLATFORM_SURFACELESS ||
1090 disp->Platform == _EGL_PLATFORM_DEVICE)) {
1091 /* From the EGL_MESA_platform_surfaceless spec (v1):
1092 *
1093 * [Like eglCreatePlatformWindowSurface,] eglCreatePlatformPixmapSurface
1094 * also fails when called with a <display> that belongs to the
1095 * surfaceless platform. It returns EGL_NO_SURFACE and generates
1096 * EGL_BAD_NATIVE_PIXMAP.
1097 *
1098 * This check must occur before checking the EGLConfig, which emits
1099 * EGL_BAD_CONFIG.
1100 */
1101 RETURN_EGL_ERROR(disp, EGL_BAD_NATIVE_PIXMAP, EGL_NO_SURFACE);
1102 }
1103
1104 _EGL_CHECK_CONFIG(disp, conf, EGL_NO_SURFACE);
1105
1106 if ((conf->SurfaceType & EGL_PIXMAP_BIT) == 0)
1107 RETURN_EGL_ERROR(disp, EGL_BAD_MATCH, EGL_NO_SURFACE);
1108
1109 if (native_pixmap == NULL)
1110 RETURN_EGL_ERROR(disp, EGL_BAD_NATIVE_PIXMAP, EGL_NO_SURFACE);
1111
1112 if (_eglNativeSurfaceAlreadyUsed(disp, native_pixmap))
1113 RETURN_EGL_ERROR(disp, EGL_BAD_ALLOC, EGL_NO_SURFACE);
1114
1115 surf = disp->Driver->CreatePixmapSurface(disp, conf, native_pixmap, attrib_list);
1116 ret = (surf) ? _eglLinkSurface(surf) : EGL_NO_SURFACE;
1117
1118 RETURN_EGL_EVAL(disp, ret);
1119 }
1120
1121
1122 EGLSurface EGLAPIENTRY
eglCreatePixmapSurface(EGLDisplay dpy,EGLConfig config,EGLNativePixmapType pixmap,const EGLint * attrib_list)1123 eglCreatePixmapSurface(EGLDisplay dpy, EGLConfig config,
1124 EGLNativePixmapType pixmap, const EGLint *attrib_list)
1125 {
1126 _EGLDisplay *disp = _eglLockDisplay(dpy);
1127
1128 _EGL_FUNC_START(disp, EGL_OBJECT_DISPLAY_KHR, NULL, EGL_NO_SURFACE);
1129 STATIC_ASSERT(sizeof(void*) == sizeof(pixmap));
1130 return _eglCreatePixmapSurfaceCommon(disp, config, (void*) pixmap,
1131 attrib_list);
1132 }
1133
1134 static EGLSurface EGLAPIENTRY
eglCreatePlatformPixmapSurfaceEXT(EGLDisplay dpy,EGLConfig config,void * native_pixmap,const EGLint * attrib_list)1135 eglCreatePlatformPixmapSurfaceEXT(EGLDisplay dpy, EGLConfig config,
1136 void *native_pixmap,
1137 const EGLint *attrib_list)
1138 {
1139 _EGLDisplay *disp = _eglLockDisplay(dpy);
1140
1141 _EGL_FUNC_START(disp, EGL_OBJECT_DISPLAY_KHR, NULL, EGL_NO_SURFACE);
1142 native_pixmap = _fixupNativePixmap(disp, native_pixmap);
1143 return _eglCreatePixmapSurfaceCommon(disp, config, native_pixmap,
1144 attrib_list);
1145 }
1146
1147
1148 EGLSurface EGLAPIENTRY
eglCreatePlatformPixmapSurface(EGLDisplay dpy,EGLConfig config,void * native_pixmap,const EGLAttrib * attrib_list)1149 eglCreatePlatformPixmapSurface(EGLDisplay dpy, EGLConfig config,
1150 void *native_pixmap,
1151 const EGLAttrib *attrib_list)
1152 {
1153 _EGLDisplay *disp = _eglLockDisplay(dpy);
1154 EGLSurface surface;
1155 EGLint *int_attribs;
1156
1157 _EGL_FUNC_START(disp, EGL_OBJECT_DISPLAY_KHR, NULL, EGL_NO_SURFACE);
1158
1159 int_attribs = _eglConvertAttribsToInt(attrib_list);
1160 if (attrib_list && !int_attribs)
1161 RETURN_EGL_ERROR(disp, EGL_BAD_ALLOC, EGL_NO_SURFACE);
1162
1163 native_pixmap = _fixupNativePixmap(disp, native_pixmap);
1164 surface = _eglCreatePixmapSurfaceCommon(disp, config, native_pixmap,
1165 int_attribs);
1166 free(int_attribs);
1167 return surface;
1168 }
1169
1170
1171 EGLSurface EGLAPIENTRY
eglCreatePbufferSurface(EGLDisplay dpy,EGLConfig config,const EGLint * attrib_list)1172 eglCreatePbufferSurface(EGLDisplay dpy, EGLConfig config,
1173 const EGLint *attrib_list)
1174 {
1175 _EGLDisplay *disp = _eglLockDisplay(dpy);
1176 _EGLConfig *conf = _eglLookupConfig(config, disp);
1177 _EGLSurface *surf;
1178 EGLSurface ret;
1179
1180 _EGL_FUNC_START(disp, EGL_OBJECT_DISPLAY_KHR, NULL, EGL_NO_SURFACE);
1181 _EGL_CHECK_CONFIG(disp, conf, EGL_NO_SURFACE);
1182
1183 if ((conf->SurfaceType & EGL_PBUFFER_BIT) == 0)
1184 RETURN_EGL_ERROR(disp, EGL_BAD_MATCH, EGL_NO_SURFACE);
1185
1186 surf = disp->Driver->CreatePbufferSurface(disp, conf, attrib_list);
1187 ret = (surf) ? _eglLinkSurface(surf) : EGL_NO_SURFACE;
1188
1189 RETURN_EGL_EVAL(disp, ret);
1190 }
1191
1192
1193 EGLBoolean EGLAPIENTRY
eglDestroySurface(EGLDisplay dpy,EGLSurface surface)1194 eglDestroySurface(EGLDisplay dpy, EGLSurface surface)
1195 {
1196 _EGLDisplay *disp = _eglLockDisplay(dpy);
1197 _EGLSurface *surf = _eglLookupSurface(surface, disp);
1198 EGLBoolean ret;
1199
1200 _EGL_FUNC_START(disp, EGL_OBJECT_SURFACE_KHR, surf, EGL_FALSE);
1201 _EGL_CHECK_SURFACE(disp, surf, EGL_FALSE);
1202 _eglUnlinkSurface(surf);
1203 ret = disp->Driver->DestroySurface(disp, surf);
1204
1205 RETURN_EGL_EVAL(disp, ret);
1206 }
1207
1208 EGLBoolean EGLAPIENTRY
eglQuerySurface(EGLDisplay dpy,EGLSurface surface,EGLint attribute,EGLint * value)1209 eglQuerySurface(EGLDisplay dpy, EGLSurface surface,
1210 EGLint attribute, EGLint *value)
1211 {
1212 _EGLDisplay *disp = _eglLockDisplay(dpy);
1213 _EGLSurface *surf = _eglLookupSurface(surface, disp);
1214 EGLBoolean ret;
1215
1216 _EGL_FUNC_START(disp, EGL_OBJECT_SURFACE_KHR, surf, EGL_FALSE);
1217 _EGL_CHECK_SURFACE(disp, surf, EGL_FALSE);
1218
1219 if (disp->Driver->QuerySurface)
1220 ret = disp->Driver->QuerySurface(disp, surf, attribute, value);
1221 else
1222 ret = _eglQuerySurface(disp, surf, attribute, value);
1223
1224 RETURN_EGL_EVAL(disp, ret);
1225 }
1226
1227 EGLBoolean EGLAPIENTRY
eglSurfaceAttrib(EGLDisplay dpy,EGLSurface surface,EGLint attribute,EGLint value)1228 eglSurfaceAttrib(EGLDisplay dpy, EGLSurface surface,
1229 EGLint attribute, EGLint value)
1230 {
1231 _EGLDisplay *disp = _eglLockDisplay(dpy);
1232 _EGLSurface *surf = _eglLookupSurface(surface, disp);
1233 EGLBoolean ret;
1234
1235 _EGL_FUNC_START(disp, EGL_OBJECT_SURFACE_KHR, surf, EGL_FALSE);
1236 _EGL_CHECK_SURFACE(disp, surf, EGL_FALSE);
1237
1238 ret = _eglSurfaceAttrib(disp, surf, attribute, value);
1239
1240 RETURN_EGL_EVAL(disp, ret);
1241 }
1242
1243
1244 EGLBoolean EGLAPIENTRY
eglBindTexImage(EGLDisplay dpy,EGLSurface surface,EGLint buffer)1245 eglBindTexImage(EGLDisplay dpy, EGLSurface surface, EGLint buffer)
1246 {
1247 _EGLDisplay *disp = _eglLockDisplay(dpy);
1248 _EGLSurface *surf = _eglLookupSurface(surface, disp);
1249 EGLBoolean ret;
1250
1251 _EGL_FUNC_START(disp, EGL_OBJECT_SURFACE_KHR, surf, EGL_FALSE);
1252 _EGL_CHECK_SURFACE(disp, surf, EGL_FALSE);
1253 ret = disp->Driver->BindTexImage(disp, surf, buffer);
1254
1255 RETURN_EGL_EVAL(disp, ret);
1256 }
1257
1258
1259 EGLBoolean EGLAPIENTRY
eglReleaseTexImage(EGLDisplay dpy,EGLSurface surface,EGLint buffer)1260 eglReleaseTexImage(EGLDisplay dpy, EGLSurface surface, EGLint buffer)
1261 {
1262 _EGLDisplay *disp = _eglLockDisplay(dpy);
1263 _EGLSurface *surf = _eglLookupSurface(surface, disp);
1264 EGLBoolean ret;
1265
1266 _EGL_FUNC_START(disp, EGL_OBJECT_SURFACE_KHR, surf, EGL_FALSE);
1267 _EGL_CHECK_SURFACE(disp, surf, EGL_FALSE);
1268 ret = disp->Driver->ReleaseTexImage(disp, surf, buffer);
1269
1270 RETURN_EGL_EVAL(disp, ret);
1271 }
1272
1273
1274 EGLBoolean EGLAPIENTRY
eglSwapInterval(EGLDisplay dpy,EGLint interval)1275 eglSwapInterval(EGLDisplay dpy, EGLint interval)
1276 {
1277 _EGLDisplay *disp = _eglLockDisplay(dpy);
1278 _EGLContext *ctx = _eglGetCurrentContext();
1279 _EGLSurface *surf = ctx ? ctx->DrawSurface : NULL;
1280 EGLBoolean ret;
1281
1282 _EGL_FUNC_START(disp, EGL_OBJECT_SURFACE_KHR, surf, EGL_FALSE);
1283 _EGL_CHECK_DISPLAY(disp, EGL_FALSE);
1284
1285 if (_eglGetContextHandle(ctx) == EGL_NO_CONTEXT ||
1286 ctx->Resource.Display != disp)
1287 RETURN_EGL_ERROR(disp, EGL_BAD_CONTEXT, EGL_FALSE);
1288
1289 if (_eglGetSurfaceHandle(surf) == EGL_NO_SURFACE)
1290 RETURN_EGL_ERROR(disp, EGL_BAD_SURFACE, EGL_FALSE);
1291
1292 if (surf->Type != EGL_WINDOW_BIT)
1293 RETURN_EGL_EVAL(disp, EGL_TRUE);
1294
1295 interval = CLAMP(interval,
1296 surf->Config->MinSwapInterval,
1297 surf->Config->MaxSwapInterval);
1298
1299 if (surf->SwapInterval != interval && disp->Driver->SwapInterval)
1300 ret = disp->Driver->SwapInterval(disp, surf, interval);
1301 else
1302 ret = EGL_TRUE;
1303
1304 if (ret)
1305 surf->SwapInterval = interval;
1306
1307 RETURN_EGL_EVAL(disp, ret);
1308 }
1309
1310
1311 EGLBoolean EGLAPIENTRY
eglSwapBuffers(EGLDisplay dpy,EGLSurface surface)1312 eglSwapBuffers(EGLDisplay dpy, EGLSurface surface)
1313 {
1314 _EGLContext *ctx = _eglGetCurrentContext();
1315 _EGLDisplay *disp = _eglLockDisplay(dpy);
1316 _EGLSurface *surf = _eglLookupSurface(surface, disp);
1317 EGLBoolean ret;
1318
1319 _EGL_FUNC_START(disp, EGL_OBJECT_SURFACE_KHR, surf, EGL_FALSE);
1320 _EGL_CHECK_SURFACE(disp, surf, EGL_FALSE);
1321
1322 /* surface must be bound to current context in EGL 1.4 */
1323 #ifndef _EGL_BUILT_IN_DRIVER_HAIKU
1324 if (_eglGetContextHandle(ctx) == EGL_NO_CONTEXT ||
1325 surf != ctx->DrawSurface)
1326 RETURN_EGL_ERROR(disp, EGL_BAD_SURFACE, EGL_FALSE);
1327 #endif
1328
1329 if (surf->Type != EGL_WINDOW_BIT)
1330 RETURN_EGL_EVAL(disp, EGL_TRUE);
1331
1332 /* From the EGL 1.5 spec:
1333 *
1334 * If eglSwapBuffers is called and the native window associated with
1335 * surface is no longer valid, an EGL_BAD_NATIVE_WINDOW error is
1336 * generated.
1337 */
1338 if (surf->Lost)
1339 RETURN_EGL_ERROR(disp, EGL_BAD_NATIVE_WINDOW, EGL_FALSE);
1340
1341 ret = disp->Driver->SwapBuffers(disp, surf);
1342
1343 /* EGL_KHR_partial_update
1344 * Frame boundary successfully reached,
1345 * reset damage region and reset BufferAgeRead
1346 */
1347 if (ret) {
1348 surf->SetDamageRegionCalled = EGL_FALSE;
1349 surf->BufferAgeRead = EGL_FALSE;
1350 }
1351
1352 RETURN_EGL_EVAL(disp, ret);
1353 }
1354
1355
1356 static EGLBoolean
_eglSwapBuffersWithDamageCommon(_EGLDisplay * disp,_EGLSurface * surf,const EGLint * rects,EGLint n_rects)1357 _eglSwapBuffersWithDamageCommon(_EGLDisplay *disp, _EGLSurface *surf,
1358 const EGLint *rects, EGLint n_rects)
1359 {
1360 _EGLContext *ctx = _eglGetCurrentContext();
1361 EGLBoolean ret;
1362
1363 _EGL_CHECK_SURFACE(disp, surf, EGL_FALSE);
1364
1365 /* surface must be bound to current context in EGL 1.4 */
1366 if (_eglGetContextHandle(ctx) == EGL_NO_CONTEXT ||
1367 surf != ctx->DrawSurface)
1368 RETURN_EGL_ERROR(disp, EGL_BAD_SURFACE, EGL_FALSE);
1369
1370 if (surf->Type != EGL_WINDOW_BIT)
1371 RETURN_EGL_EVAL(disp, EGL_TRUE);
1372
1373 if ((n_rects > 0 && rects == NULL) || n_rects < 0)
1374 RETURN_EGL_ERROR(disp, EGL_BAD_PARAMETER, EGL_FALSE);
1375
1376 ret = disp->Driver->SwapBuffersWithDamageEXT(disp, surf, rects, n_rects);
1377
1378 /* EGL_KHR_partial_update
1379 * Frame boundary successfully reached,
1380 * reset damage region and reset BufferAgeRead
1381 */
1382 if (ret) {
1383 surf->SetDamageRegionCalled = EGL_FALSE;
1384 surf->BufferAgeRead = EGL_FALSE;
1385 }
1386
1387 RETURN_EGL_EVAL(disp, ret);
1388 }
1389
1390 static EGLBoolean EGLAPIENTRY
eglSwapBuffersWithDamageEXT(EGLDisplay dpy,EGLSurface surface,const EGLint * rects,EGLint n_rects)1391 eglSwapBuffersWithDamageEXT(EGLDisplay dpy, EGLSurface surface,
1392 const EGLint *rects, EGLint n_rects)
1393 {
1394 _EGLDisplay *disp = _eglLockDisplay(dpy);
1395 _EGLSurface *surf = _eglLookupSurface(surface, disp);
1396 _EGL_FUNC_START(disp, EGL_OBJECT_SURFACE_KHR, surf, EGL_FALSE);
1397 return _eglSwapBuffersWithDamageCommon(disp, surf, rects, n_rects);
1398 }
1399
1400 static EGLBoolean EGLAPIENTRY
eglSwapBuffersWithDamageKHR(EGLDisplay dpy,EGLSurface surface,const EGLint * rects,EGLint n_rects)1401 eglSwapBuffersWithDamageKHR(EGLDisplay dpy, EGLSurface surface,
1402 const EGLint *rects, EGLint n_rects)
1403 {
1404 _EGLDisplay *disp = _eglLockDisplay(dpy);
1405 _EGLSurface *surf = _eglLookupSurface(surface, disp);
1406 _EGL_FUNC_START(disp, EGL_OBJECT_SURFACE_KHR, surf, EGL_FALSE);
1407 return _eglSwapBuffersWithDamageCommon(disp, surf, rects, n_rects);
1408 }
1409
1410 /**
1411 * Clamp the rectangles so that they lie within the surface.
1412 */
1413
1414 static void
_eglSetDamageRegionKHRClampRects(_EGLSurface * surf,EGLint * rects,EGLint n_rects)1415 _eglSetDamageRegionKHRClampRects(_EGLSurface* surf,
1416 EGLint *rects, EGLint n_rects)
1417 {
1418 EGLint i;
1419 EGLint surf_height = surf->Height;
1420 EGLint surf_width = surf->Width;
1421
1422 for (i = 0; i < (4 * n_rects); i += 4) {
1423 EGLint x1, y1, x2, y2;
1424 x1 = rects[i];
1425 y1 = rects[i + 1];
1426 x2 = rects[i + 2] + x1;
1427 y2 = rects[i + 3] + y1;
1428
1429 rects[i] = CLAMP(x1, 0, surf_width);
1430 rects[i + 1] = CLAMP(y1, 0, surf_height);
1431 rects[i + 2] = CLAMP(x2, 0, surf_width) - rects[i];
1432 rects[i + 3] = CLAMP(y2, 0, surf_height) - rects[i + 1];
1433 }
1434 }
1435
1436 static EGLBoolean EGLAPIENTRY
eglSetDamageRegionKHR(EGLDisplay dpy,EGLSurface surface,EGLint * rects,EGLint n_rects)1437 eglSetDamageRegionKHR(EGLDisplay dpy, EGLSurface surface,
1438 EGLint *rects, EGLint n_rects)
1439 {
1440 _EGLDisplay *disp = _eglLockDisplay(dpy);
1441 _EGLSurface *surf = _eglLookupSurface(surface, disp);
1442 _EGL_FUNC_START(disp, EGL_OBJECT_SURFACE_KHR, surf, EGL_FALSE);
1443 _EGLContext *ctx = _eglGetCurrentContext();
1444 EGLBoolean ret;
1445 _EGL_CHECK_SURFACE(disp, surf, EGL_FALSE);
1446
1447 if (_eglGetContextHandle(ctx) == EGL_NO_CONTEXT ||
1448 surf->Type != EGL_WINDOW_BIT ||
1449 ctx->DrawSurface != surf ||
1450 surf->SwapBehavior != EGL_BUFFER_DESTROYED)
1451 RETURN_EGL_ERROR(disp, EGL_BAD_MATCH, EGL_FALSE);
1452
1453 /* If the damage region is already set or
1454 * buffer age is not queried between
1455 * frame boundaries, throw bad access error
1456 */
1457
1458 if (surf->SetDamageRegionCalled || !surf->BufferAgeRead)
1459 RETURN_EGL_ERROR(disp, EGL_BAD_ACCESS, EGL_FALSE);
1460
1461 _eglSetDamageRegionKHRClampRects(surf, rects, n_rects);
1462 ret = disp->Driver->SetDamageRegion(disp, surf, rects, n_rects);
1463
1464 if (ret)
1465 surf->SetDamageRegionCalled = EGL_TRUE;
1466
1467 RETURN_EGL_EVAL(disp, ret);
1468 }
1469
1470 EGLBoolean EGLAPIENTRY
eglCopyBuffers(EGLDisplay dpy,EGLSurface surface,EGLNativePixmapType target)1471 eglCopyBuffers(EGLDisplay dpy, EGLSurface surface, EGLNativePixmapType target)
1472 {
1473 _EGLDisplay *disp = _eglLockDisplay(dpy);
1474 _EGLSurface *surf = _eglLookupSurface(surface, disp);
1475 EGLBoolean ret;
1476 void *native_pixmap_ptr;
1477
1478 _EGL_FUNC_START(disp, EGL_OBJECT_SURFACE_KHR, surf, EGL_FALSE);
1479 STATIC_ASSERT(sizeof(void*) == sizeof(target));
1480 native_pixmap_ptr = (void*) target;
1481
1482 _EGL_CHECK_SURFACE(disp, surf, EGL_FALSE);
1483 if (surf->ProtectedContent)
1484 RETURN_EGL_ERROR(disp, EGL_BAD_ACCESS, EGL_FALSE);
1485 ret = disp->Driver->CopyBuffers(disp, surf, native_pixmap_ptr);
1486
1487 RETURN_EGL_EVAL(disp, ret);
1488 }
1489
1490
1491 static EGLBoolean
_eglWaitClientCommon(void)1492 _eglWaitClientCommon(void)
1493 {
1494 _EGLContext *ctx = _eglGetCurrentContext();
1495 _EGLDisplay *disp;
1496 EGLBoolean ret;
1497
1498 if (!ctx)
1499 RETURN_EGL_SUCCESS(NULL, EGL_TRUE);
1500
1501 disp = ctx->Resource.Display;
1502 mtx_lock(&disp->Mutex);
1503
1504 /* let bad current context imply bad current surface */
1505 if (_eglGetContextHandle(ctx) == EGL_NO_CONTEXT ||
1506 _eglGetSurfaceHandle(ctx->DrawSurface) == EGL_NO_SURFACE)
1507 RETURN_EGL_ERROR(disp, EGL_BAD_CURRENT_SURFACE, EGL_FALSE);
1508
1509 /* a valid current context implies an initialized current display */
1510 assert(disp->Initialized);
1511 ret = disp->Driver->WaitClient(disp, ctx);
1512
1513 RETURN_EGL_EVAL(disp, ret);
1514 }
1515
1516 EGLBoolean EGLAPIENTRY
eglWaitClient(void)1517 eglWaitClient(void)
1518 {
1519 _EGL_FUNC_START(NULL, EGL_OBJECT_CONTEXT_KHR, _eglGetCurrentContext(), EGL_FALSE);
1520 return _eglWaitClientCommon();
1521 }
1522
1523 EGLBoolean EGLAPIENTRY
eglWaitGL(void)1524 eglWaitGL(void)
1525 {
1526 /* Since we only support OpenGL and GLES, eglWaitGL is equivalent to eglWaitClient. */
1527 _EGL_FUNC_START(NULL, EGL_OBJECT_CONTEXT_KHR, _eglGetCurrentContext(), EGL_FALSE);
1528 return _eglWaitClientCommon();
1529 }
1530
1531
1532 EGLBoolean EGLAPIENTRY
eglWaitNative(EGLint engine)1533 eglWaitNative(EGLint engine)
1534 {
1535 _EGLContext *ctx = _eglGetCurrentContext();
1536 _EGLDisplay *disp;
1537 EGLBoolean ret;
1538
1539 if (!ctx)
1540 RETURN_EGL_SUCCESS(NULL, EGL_TRUE);
1541
1542 _EGL_FUNC_START(NULL, EGL_OBJECT_THREAD_KHR, NULL, EGL_FALSE);
1543
1544 disp = ctx->Resource.Display;
1545 mtx_lock(&disp->Mutex);
1546
1547 /* let bad current context imply bad current surface */
1548 if (_eglGetContextHandle(ctx) == EGL_NO_CONTEXT ||
1549 _eglGetSurfaceHandle(ctx->DrawSurface) == EGL_NO_SURFACE)
1550 RETURN_EGL_ERROR(disp, EGL_BAD_CURRENT_SURFACE, EGL_FALSE);
1551
1552 /* a valid current context implies an initialized current display */
1553 assert(disp->Initialized);
1554 ret = disp->Driver->WaitNative(engine);
1555
1556 RETURN_EGL_EVAL(disp, ret);
1557 }
1558
1559
1560 EGLDisplay EGLAPIENTRY
eglGetCurrentDisplay(void)1561 eglGetCurrentDisplay(void)
1562 {
1563 _EGLContext *ctx = _eglGetCurrentContext();
1564 EGLDisplay ret;
1565
1566 ret = (ctx) ? _eglGetDisplayHandle(ctx->Resource.Display) : EGL_NO_DISPLAY;
1567
1568 RETURN_EGL_SUCCESS(NULL, ret);
1569 }
1570
1571
1572 EGLContext EGLAPIENTRY
eglGetCurrentContext(void)1573 eglGetCurrentContext(void)
1574 {
1575 _EGLContext *ctx = _eglGetCurrentContext();
1576 EGLContext ret;
1577
1578 ret = _eglGetContextHandle(ctx);
1579
1580 RETURN_EGL_SUCCESS(NULL, ret);
1581 }
1582
1583
1584 EGLSurface EGLAPIENTRY
eglGetCurrentSurface(EGLint readdraw)1585 eglGetCurrentSurface(EGLint readdraw)
1586 {
1587 _EGLContext *ctx = _eglGetCurrentContext();
1588 EGLint err = EGL_SUCCESS;
1589 _EGLSurface *surf;
1590 EGLSurface ret;
1591
1592 _EGL_FUNC_START(NULL, EGL_NONE, NULL, EGL_NO_SURFACE);
1593
1594 if (!ctx)
1595 RETURN_EGL_SUCCESS(NULL, EGL_NO_SURFACE);
1596
1597 switch (readdraw) {
1598 case EGL_DRAW:
1599 surf = ctx->DrawSurface;
1600 break;
1601 case EGL_READ:
1602 surf = ctx->ReadSurface;
1603 break;
1604 default:
1605 surf = NULL;
1606 err = EGL_BAD_PARAMETER;
1607 break;
1608 }
1609
1610 ret = _eglGetSurfaceHandle(surf);
1611
1612 RETURN_EGL_ERROR(NULL, err, ret);
1613 }
1614
1615
1616 EGLint EGLAPIENTRY
eglGetError(void)1617 eglGetError(void)
1618 {
1619 _EGLThreadInfo *t = _eglGetCurrentThread();
1620 EGLint e = t->LastError;
1621 if (!_eglIsCurrentThreadDummy())
1622 t->LastError = EGL_SUCCESS;
1623 return e;
1624 }
1625
1626
1627 /**
1628 ** EGL 1.2
1629 **/
1630
1631 /**
1632 * Specify the client API to use for subsequent calls including:
1633 * eglCreateContext()
1634 * eglGetCurrentContext()
1635 * eglGetCurrentDisplay()
1636 * eglGetCurrentSurface()
1637 * eglMakeCurrent(when the ctx parameter is EGL NO CONTEXT)
1638 * eglWaitClient()
1639 * eglWaitNative()
1640 * See section 3.7 "Rendering Context" in the EGL specification for details.
1641 */
1642 EGLBoolean EGLAPIENTRY
eglBindAPI(EGLenum api)1643 eglBindAPI(EGLenum api)
1644 {
1645 _EGLThreadInfo *t;
1646
1647 _EGL_FUNC_START(NULL, EGL_OBJECT_THREAD_KHR, NULL, EGL_FALSE);
1648
1649 t = _eglGetCurrentThread();
1650 if (_eglIsCurrentThreadDummy())
1651 RETURN_EGL_ERROR(NULL, EGL_BAD_ALLOC, EGL_FALSE);
1652
1653 if (!_eglIsApiValid(api))
1654 RETURN_EGL_ERROR(NULL, EGL_BAD_PARAMETER, EGL_FALSE);
1655
1656 t->CurrentAPI = api;
1657
1658 RETURN_EGL_SUCCESS(NULL, EGL_TRUE);
1659 }
1660
1661
1662 /**
1663 * Return the last value set with eglBindAPI().
1664 */
1665 EGLenum EGLAPIENTRY
eglQueryAPI(void)1666 eglQueryAPI(void)
1667 {
1668 _EGLThreadInfo *t = _eglGetCurrentThread();
1669 EGLenum ret;
1670
1671 /* returns one of EGL_OPENGL_API, EGL_OPENGL_ES_API or EGL_OPENVG_API */
1672 ret = t->CurrentAPI;
1673
1674 RETURN_EGL_SUCCESS(NULL, ret);
1675 }
1676
1677
1678 EGLSurface EGLAPIENTRY
eglCreatePbufferFromClientBuffer(EGLDisplay dpy,EGLenum buftype,EGLClientBuffer buffer,EGLConfig config,const EGLint * attrib_list)1679 eglCreatePbufferFromClientBuffer(EGLDisplay dpy, EGLenum buftype,
1680 EGLClientBuffer buffer, EGLConfig config,
1681 const EGLint *attrib_list)
1682 {
1683 _EGLDisplay *disp = _eglLockDisplay(dpy);
1684 _EGLConfig *conf = _eglLookupConfig(config, disp);
1685
1686 _EGL_FUNC_START(disp, EGL_OBJECT_DISPLAY_KHR, NULL, EGL_NO_SURFACE);
1687
1688 _EGL_CHECK_CONFIG(disp, conf, EGL_NO_SURFACE);
1689
1690 /* OpenVG is not supported */
1691 RETURN_EGL_ERROR(disp, EGL_BAD_ALLOC, EGL_NO_SURFACE);
1692 }
1693
1694
1695 EGLBoolean EGLAPIENTRY
eglReleaseThread(void)1696 eglReleaseThread(void)
1697 {
1698 /* unbind current contexts */
1699 if (!_eglIsCurrentThreadDummy()) {
1700 _EGLThreadInfo *t = _eglGetCurrentThread();
1701 _EGLContext *ctx = t->CurrentContext;
1702
1703 _EGL_FUNC_START(NULL, EGL_OBJECT_THREAD_KHR, NULL, EGL_FALSE);
1704
1705 if (ctx) {
1706 _EGLDisplay *disp = ctx->Resource.Display;
1707
1708 mtx_lock(&disp->Mutex);
1709 (void) disp->Driver->MakeCurrent(disp, NULL, NULL, NULL);
1710 mtx_unlock(&disp->Mutex);
1711 }
1712 }
1713
1714 _eglDestroyCurrentThread();
1715
1716 RETURN_EGL_SUCCESS(NULL, EGL_TRUE);
1717 }
1718
1719
1720 static EGLImage
_eglCreateImageCommon(_EGLDisplay * disp,EGLContext ctx,EGLenum target,EGLClientBuffer buffer,const EGLint * attr_list)1721 _eglCreateImageCommon(_EGLDisplay *disp, EGLContext ctx, EGLenum target,
1722 EGLClientBuffer buffer, const EGLint *attr_list)
1723 {
1724 _EGLContext *context = _eglLookupContext(ctx, disp);
1725 _EGLImage *img;
1726 EGLImage ret;
1727
1728 _EGL_CHECK_DISPLAY(disp, EGL_NO_IMAGE_KHR);
1729 if (!disp->Extensions.KHR_image_base)
1730 RETURN_EGL_EVAL(disp, EGL_NO_IMAGE_KHR);
1731 if (!context && ctx != EGL_NO_CONTEXT)
1732 RETURN_EGL_ERROR(disp, EGL_BAD_CONTEXT, EGL_NO_IMAGE_KHR);
1733 /* "If <target> is EGL_LINUX_DMA_BUF_EXT, <dpy> must be a valid display,
1734 * <ctx> must be EGL_NO_CONTEXT..."
1735 */
1736 if (ctx != EGL_NO_CONTEXT && target == EGL_LINUX_DMA_BUF_EXT)
1737 RETURN_EGL_ERROR(disp, EGL_BAD_PARAMETER, EGL_NO_IMAGE_KHR);
1738
1739 img = disp->Driver->CreateImageKHR(disp, context, target, buffer, attr_list);
1740 ret = (img) ? _eglLinkImage(img) : EGL_NO_IMAGE_KHR;
1741
1742 RETURN_EGL_EVAL(disp, ret);
1743 }
1744
1745 static EGLImage EGLAPIENTRY
eglCreateImageKHR(EGLDisplay dpy,EGLContext ctx,EGLenum target,EGLClientBuffer buffer,const EGLint * attr_list)1746 eglCreateImageKHR(EGLDisplay dpy, EGLContext ctx, EGLenum target,
1747 EGLClientBuffer buffer, const EGLint *attr_list)
1748 {
1749 _EGLDisplay *disp = _eglLockDisplay(dpy);
1750 _EGL_FUNC_START(disp, EGL_OBJECT_DISPLAY_KHR, NULL, EGL_NO_IMAGE_KHR);
1751 return _eglCreateImageCommon(disp, ctx, target, buffer, attr_list);
1752 }
1753
1754
1755 EGLImage EGLAPIENTRY
eglCreateImage(EGLDisplay dpy,EGLContext ctx,EGLenum target,EGLClientBuffer buffer,const EGLAttrib * attr_list)1756 eglCreateImage(EGLDisplay dpy, EGLContext ctx, EGLenum target,
1757 EGLClientBuffer buffer, const EGLAttrib *attr_list)
1758 {
1759 _EGLDisplay *disp = _eglLockDisplay(dpy);
1760 EGLImage image;
1761 EGLint *int_attribs;
1762
1763 _EGL_FUNC_START(disp, EGL_OBJECT_DISPLAY_KHR, NULL, EGL_NO_IMAGE_KHR);
1764
1765 int_attribs = _eglConvertAttribsToInt(attr_list);
1766 if (attr_list && !int_attribs)
1767 RETURN_EGL_ERROR(disp, EGL_BAD_ALLOC, EGL_NO_IMAGE);
1768
1769 image = _eglCreateImageCommon(disp, ctx, target, buffer, int_attribs);
1770 free(int_attribs);
1771 return image;
1772 }
1773
1774
1775 static EGLBoolean
_eglDestroyImageCommon(_EGLDisplay * disp,_EGLImage * img)1776 _eglDestroyImageCommon(_EGLDisplay *disp, _EGLImage *img)
1777 {
1778 EGLBoolean ret;
1779
1780 _EGL_CHECK_DISPLAY(disp, EGL_FALSE);
1781 if (!disp->Extensions.KHR_image_base)
1782 RETURN_EGL_EVAL(disp, EGL_FALSE);
1783 if (!img)
1784 RETURN_EGL_ERROR(disp, EGL_BAD_PARAMETER, EGL_FALSE);
1785
1786 _eglUnlinkImage(img);
1787 ret = disp->Driver->DestroyImageKHR(disp, img);
1788
1789 RETURN_EGL_EVAL(disp, ret);
1790 }
1791
1792 EGLBoolean EGLAPIENTRY
eglDestroyImage(EGLDisplay dpy,EGLImage image)1793 eglDestroyImage(EGLDisplay dpy, EGLImage image)
1794 {
1795 _EGLDisplay *disp = _eglLockDisplay(dpy);
1796 _EGLImage *img = _eglLookupImage(image, disp);
1797 _EGL_FUNC_START(disp, EGL_OBJECT_IMAGE_KHR, img, EGL_FALSE);
1798 return _eglDestroyImageCommon(disp, img);
1799 }
1800
1801 static EGLBoolean EGLAPIENTRY
eglDestroyImageKHR(EGLDisplay dpy,EGLImage image)1802 eglDestroyImageKHR(EGLDisplay dpy, EGLImage image)
1803 {
1804 _EGLDisplay *disp = _eglLockDisplay(dpy);
1805 _EGLImage *img = _eglLookupImage(image, disp);
1806 _EGL_FUNC_START(disp, EGL_OBJECT_IMAGE_KHR, img, EGL_FALSE);
1807 return _eglDestroyImageCommon(disp, img);
1808 }
1809
1810
1811 static EGLSync
_eglCreateSync(_EGLDisplay * disp,EGLenum type,const EGLAttrib * attrib_list,EGLBoolean orig_is_EGLAttrib,EGLenum invalid_type_error)1812 _eglCreateSync(_EGLDisplay *disp, EGLenum type, const EGLAttrib *attrib_list,
1813 EGLBoolean orig_is_EGLAttrib,
1814 EGLenum invalid_type_error)
1815 {
1816 _EGLContext *ctx = _eglGetCurrentContext();
1817 _EGLSync *sync;
1818 EGLSync ret;
1819
1820 _EGL_CHECK_DISPLAY(disp, EGL_NO_SYNC_KHR);
1821
1822 if (!disp->Extensions.KHR_cl_event2 && orig_is_EGLAttrib) {
1823 /* There exist two EGLAttrib variants of eglCreateSync*:
1824 * eglCreateSync64KHR which requires EGL_KHR_cl_event2, and eglCreateSync
1825 * which requires EGL 1.5. Here we use the presence of EGL_KHR_cl_event2
1826 * support as a proxy for EGL 1.5 support, even though that's not
1827 * entirely correct (though _eglComputeVersion does the same).
1828 *
1829 * The EGL spec provides no guidance on how to handle unsupported
1830 * functions. EGL_BAD_MATCH seems reasonable.
1831 */
1832 RETURN_EGL_ERROR(disp, EGL_BAD_MATCH, EGL_NO_SYNC_KHR);
1833 }
1834
1835 /* If type is EGL_SYNC_FENCE and no context is current for the bound API
1836 * (i.e., eglGetCurrentContext returns EGL_NO_CONTEXT ), an EGL_BAD_MATCH
1837 * error is generated.
1838 */
1839 if (!ctx &&
1840 (type == EGL_SYNC_FENCE_KHR || type == EGL_SYNC_NATIVE_FENCE_ANDROID))
1841 RETURN_EGL_ERROR(disp, EGL_BAD_MATCH, EGL_NO_SYNC_KHR);
1842
1843 /* return an error if the client API doesn't support GL_[OES|MESA]_EGL_sync. */
1844 if (ctx && (ctx->Resource.Display != disp ||
1845 (ctx->ClientAPI != EGL_OPENGL_ES_API &&
1846 ctx->ClientAPI != EGL_OPENGL_API)))
1847 RETURN_EGL_ERROR(disp, EGL_BAD_MATCH, EGL_NO_SYNC_KHR);
1848
1849 switch (type) {
1850 case EGL_SYNC_FENCE_KHR:
1851 if (!disp->Extensions.KHR_fence_sync)
1852 RETURN_EGL_ERROR(disp, invalid_type_error, EGL_NO_SYNC_KHR);
1853 break;
1854 case EGL_SYNC_REUSABLE_KHR:
1855 if (!disp->Extensions.KHR_reusable_sync)
1856 RETURN_EGL_ERROR(disp, invalid_type_error, EGL_NO_SYNC_KHR);
1857 break;
1858 case EGL_SYNC_CL_EVENT_KHR:
1859 if (!disp->Extensions.KHR_cl_event2)
1860 RETURN_EGL_ERROR(disp, invalid_type_error, EGL_NO_SYNC_KHR);
1861 break;
1862 case EGL_SYNC_NATIVE_FENCE_ANDROID:
1863 if (!disp->Extensions.ANDROID_native_fence_sync)
1864 RETURN_EGL_ERROR(disp, invalid_type_error, EGL_NO_SYNC_KHR);
1865 break;
1866 default:
1867 RETURN_EGL_ERROR(disp, invalid_type_error, EGL_NO_SYNC_KHR);
1868 }
1869
1870 sync = disp->Driver->CreateSyncKHR(disp, type, attrib_list);
1871 ret = (sync) ? _eglLinkSync(sync) : EGL_NO_SYNC_KHR;
1872
1873 RETURN_EGL_EVAL(disp, ret);
1874 }
1875
1876
1877 static EGLSync EGLAPIENTRY
eglCreateSyncKHR(EGLDisplay dpy,EGLenum type,const EGLint * int_list)1878 eglCreateSyncKHR(EGLDisplay dpy, EGLenum type, const EGLint *int_list)
1879 {
1880 _EGLDisplay *disp = _eglLockDisplay(dpy);
1881 _EGL_FUNC_START(disp, EGL_OBJECT_DISPLAY_KHR, NULL, EGL_FALSE);
1882
1883 EGLSync sync;
1884 EGLAttrib *attrib_list;
1885 EGLint err;
1886
1887 if (sizeof(int_list[0]) == sizeof(attrib_list[0])) {
1888 attrib_list = (EGLAttrib *) int_list;
1889 } else {
1890 err = _eglConvertIntsToAttribs(int_list, &attrib_list);
1891 if (err != EGL_SUCCESS)
1892 RETURN_EGL_ERROR(disp, err, EGL_NO_SYNC);
1893 }
1894
1895 sync = _eglCreateSync(disp, type, attrib_list, EGL_FALSE,
1896 EGL_BAD_ATTRIBUTE);
1897
1898 if (sizeof(int_list[0]) != sizeof(attrib_list[0]))
1899 free(attrib_list);
1900
1901 /* Don't double-unlock the display. _eglCreateSync already unlocked it. */
1902 return sync;
1903 }
1904
1905
1906 static EGLSync EGLAPIENTRY
eglCreateSync64KHR(EGLDisplay dpy,EGLenum type,const EGLAttrib * attrib_list)1907 eglCreateSync64KHR(EGLDisplay dpy, EGLenum type, const EGLAttrib *attrib_list)
1908 {
1909 _EGLDisplay *disp = _eglLockDisplay(dpy);
1910 _EGL_FUNC_START(disp, EGL_OBJECT_DISPLAY_KHR, NULL, EGL_FALSE);
1911 return _eglCreateSync(disp, type, attrib_list, EGL_TRUE,
1912 EGL_BAD_ATTRIBUTE);
1913 }
1914
1915
1916 EGLSync EGLAPIENTRY
eglCreateSync(EGLDisplay dpy,EGLenum type,const EGLAttrib * attrib_list)1917 eglCreateSync(EGLDisplay dpy, EGLenum type, const EGLAttrib *attrib_list)
1918 {
1919 _EGLDisplay *disp = _eglLockDisplay(dpy);
1920 _EGL_FUNC_START(disp, EGL_OBJECT_DISPLAY_KHR, NULL, EGL_FALSE);
1921 return _eglCreateSync(disp, type, attrib_list, EGL_TRUE,
1922 EGL_BAD_PARAMETER);
1923 }
1924
1925
1926 static EGLBoolean
_eglDestroySync(_EGLDisplay * disp,_EGLSync * s)1927 _eglDestroySync(_EGLDisplay *disp, _EGLSync *s)
1928 {
1929 EGLBoolean ret;
1930
1931 _EGL_CHECK_SYNC(disp, s, EGL_FALSE);
1932 assert(disp->Extensions.KHR_reusable_sync ||
1933 disp->Extensions.KHR_fence_sync ||
1934 disp->Extensions.ANDROID_native_fence_sync);
1935
1936 _eglUnlinkSync(s);
1937 ret = disp->Driver->DestroySyncKHR(disp, s);
1938
1939 RETURN_EGL_EVAL(disp, ret);
1940 }
1941
1942 EGLBoolean EGLAPIENTRY
eglDestroySync(EGLDisplay dpy,EGLSync sync)1943 eglDestroySync(EGLDisplay dpy, EGLSync sync)
1944 {
1945 _EGLDisplay *disp = _eglLockDisplay(dpy);
1946 _EGLSync *s = _eglLookupSync(sync, disp);
1947 _EGL_FUNC_START(disp, EGL_OBJECT_SYNC_KHR, s, EGL_FALSE);
1948 return _eglDestroySync(disp, s);
1949 }
1950
1951 static EGLBoolean EGLAPIENTRY
eglDestroySyncKHR(EGLDisplay dpy,EGLSync sync)1952 eglDestroySyncKHR(EGLDisplay dpy, EGLSync sync)
1953 {
1954 _EGLDisplay *disp = _eglLockDisplay(dpy);
1955 _EGLSync *s = _eglLookupSync(sync, disp);
1956 _EGL_FUNC_START(disp, EGL_OBJECT_SYNC_KHR, s, EGL_FALSE);
1957 return _eglDestroySync(disp, s);
1958 }
1959
1960
1961 static EGLint
_eglClientWaitSyncCommon(_EGLDisplay * disp,EGLDisplay dpy,_EGLSync * s,EGLint flags,EGLTime timeout)1962 _eglClientWaitSyncCommon(_EGLDisplay *disp, EGLDisplay dpy,
1963 _EGLSync *s, EGLint flags, EGLTime timeout)
1964 {
1965 EGLint ret;
1966
1967 _EGL_CHECK_SYNC(disp, s, EGL_FALSE);
1968 assert(disp->Extensions.KHR_reusable_sync ||
1969 disp->Extensions.KHR_fence_sync ||
1970 disp->Extensions.ANDROID_native_fence_sync);
1971
1972 if (s->SyncStatus == EGL_SIGNALED_KHR)
1973 RETURN_EGL_EVAL(disp, EGL_CONDITION_SATISFIED_KHR);
1974
1975 /* if sync type is EGL_SYNC_REUSABLE_KHR, dpy should be
1976 * unlocked here to allow other threads also to be able to
1977 * go into waiting state.
1978 */
1979
1980 if (s->Type == EGL_SYNC_REUSABLE_KHR)
1981 _eglUnlockDisplay(dpy);
1982
1983 ret = disp->Driver->ClientWaitSyncKHR(disp, s, flags, timeout);
1984
1985 /*
1986 * 'disp' is already unlocked for reusable sync type,
1987 * so passing 'NULL' to bypass unlocking display.
1988 */
1989 if (s->Type == EGL_SYNC_REUSABLE_KHR)
1990 RETURN_EGL_EVAL(NULL, ret);
1991 else
1992 RETURN_EGL_EVAL(disp, ret);
1993 }
1994
1995 EGLint EGLAPIENTRY
eglClientWaitSync(EGLDisplay dpy,EGLSync sync,EGLint flags,EGLTime timeout)1996 eglClientWaitSync(EGLDisplay dpy, EGLSync sync,
1997 EGLint flags, EGLTime timeout)
1998 {
1999 _EGLDisplay *disp = _eglLockDisplay(dpy);
2000 _EGLSync *s = _eglLookupSync(sync, disp);
2001 _EGL_FUNC_START(disp, EGL_OBJECT_SYNC_KHR, s, EGL_FALSE);
2002 return _eglClientWaitSyncCommon(disp, dpy, s, flags, timeout);
2003 }
2004
2005 static EGLint EGLAPIENTRY
eglClientWaitSyncKHR(EGLDisplay dpy,EGLSync sync,EGLint flags,EGLTime timeout)2006 eglClientWaitSyncKHR(EGLDisplay dpy, EGLSync sync,
2007 EGLint flags, EGLTime timeout)
2008 {
2009 _EGLDisplay *disp = _eglLockDisplay(dpy);
2010 _EGLSync *s = _eglLookupSync(sync, disp);
2011 _EGL_FUNC_START(disp, EGL_OBJECT_SYNC_KHR, s, EGL_FALSE);
2012 return _eglClientWaitSyncCommon(disp, dpy, s, flags, timeout);
2013 }
2014
2015
2016 static EGLint
_eglWaitSyncCommon(_EGLDisplay * disp,_EGLSync * s,EGLint flags)2017 _eglWaitSyncCommon(_EGLDisplay *disp, _EGLSync *s, EGLint flags)
2018 {
2019 _EGLContext *ctx = _eglGetCurrentContext();
2020 EGLint ret;
2021
2022 _EGL_CHECK_SYNC(disp, s, EGL_FALSE);
2023 assert(disp->Extensions.KHR_wait_sync);
2024
2025 /* return an error if the client API doesn't support GL_[OES|MESA]_EGL_sync. */
2026 if (ctx == EGL_NO_CONTEXT ||
2027 (ctx->ClientAPI != EGL_OPENGL_ES_API &&
2028 ctx->ClientAPI != EGL_OPENGL_API))
2029 RETURN_EGL_ERROR(disp, EGL_BAD_MATCH, EGL_FALSE);
2030
2031 /* the API doesn't allow any flags yet */
2032 if (flags != 0)
2033 RETURN_EGL_ERROR(disp, EGL_BAD_PARAMETER, EGL_FALSE);
2034
2035 ret = disp->Driver->WaitSyncKHR(disp, s);
2036
2037 RETURN_EGL_EVAL(disp, ret);
2038 }
2039
2040 static EGLint EGLAPIENTRY
eglWaitSyncKHR(EGLDisplay dpy,EGLSync sync,EGLint flags)2041 eglWaitSyncKHR(EGLDisplay dpy, EGLSync sync, EGLint flags)
2042 {
2043 _EGLDisplay *disp = _eglLockDisplay(dpy);
2044 _EGLSync *s = _eglLookupSync(sync, disp);
2045 _EGL_FUNC_START(disp, EGL_OBJECT_SYNC_KHR, s, EGL_FALSE);
2046 return _eglWaitSyncCommon(disp, s, flags);
2047 }
2048
2049
2050 EGLBoolean EGLAPIENTRY
eglWaitSync(EGLDisplay dpy,EGLSync sync,EGLint flags)2051 eglWaitSync(EGLDisplay dpy, EGLSync sync, EGLint flags)
2052 {
2053 /* The KHR version returns EGLint, while the core version returns
2054 * EGLBoolean. In both cases, the return values can only be EGL_FALSE and
2055 * EGL_TRUE.
2056 */
2057 _EGLDisplay *disp = _eglLockDisplay(dpy);
2058 _EGLSync *s = _eglLookupSync(sync, disp);
2059 _EGL_FUNC_START(disp, EGL_OBJECT_SYNC_KHR, s, EGL_FALSE);
2060 return _eglWaitSyncCommon(disp, s, flags);
2061 }
2062
2063
2064 static EGLBoolean EGLAPIENTRY
eglSignalSyncKHR(EGLDisplay dpy,EGLSync sync,EGLenum mode)2065 eglSignalSyncKHR(EGLDisplay dpy, EGLSync sync, EGLenum mode)
2066 {
2067 _EGLDisplay *disp = _eglLockDisplay(dpy);
2068 _EGLSync *s = _eglLookupSync(sync, disp);
2069 EGLBoolean ret;
2070
2071 _EGL_FUNC_START(disp, EGL_OBJECT_SYNC_KHR, s, EGL_FALSE);
2072
2073 _EGL_CHECK_SYNC(disp, s, EGL_FALSE);
2074 assert(disp->Extensions.KHR_reusable_sync);
2075 ret = disp->Driver->SignalSyncKHR(disp, s, mode);
2076
2077 RETURN_EGL_EVAL(disp, ret);
2078 }
2079
2080
2081 static EGLBoolean
_eglGetSyncAttribCommon(_EGLDisplay * disp,_EGLSync * s,EGLint attribute,EGLAttrib * value)2082 _eglGetSyncAttribCommon(_EGLDisplay *disp, _EGLSync *s, EGLint attribute, EGLAttrib *value)
2083 {
2084 EGLBoolean ret;
2085
2086 _EGL_CHECK_SYNC(disp, s, EGL_FALSE);
2087 assert(disp->Extensions.KHR_reusable_sync ||
2088 disp->Extensions.KHR_fence_sync ||
2089 disp->Extensions.ANDROID_native_fence_sync);
2090
2091 ret = _eglGetSyncAttrib(disp, s, attribute, value);
2092
2093 RETURN_EGL_EVAL(disp, ret);
2094 }
2095
2096 EGLBoolean EGLAPIENTRY
eglGetSyncAttrib(EGLDisplay dpy,EGLSync sync,EGLint attribute,EGLAttrib * value)2097 eglGetSyncAttrib(EGLDisplay dpy, EGLSync sync, EGLint attribute, EGLAttrib *value)
2098 {
2099 _EGLDisplay *disp = _eglLockDisplay(dpy);
2100 _EGLSync *s = _eglLookupSync(sync, disp);
2101 _EGL_FUNC_START(disp, EGL_OBJECT_SYNC_KHR, s, EGL_FALSE);
2102
2103 if (!value)
2104 RETURN_EGL_ERROR(disp, EGL_BAD_PARAMETER, EGL_FALSE);
2105
2106 return _eglGetSyncAttribCommon(disp, s, attribute, value);
2107 }
2108
2109
2110 static EGLBoolean EGLAPIENTRY
eglGetSyncAttribKHR(EGLDisplay dpy,EGLSync sync,EGLint attribute,EGLint * value)2111 eglGetSyncAttribKHR(EGLDisplay dpy, EGLSync sync, EGLint attribute, EGLint *value)
2112 {
2113 _EGLDisplay *disp = _eglLockDisplay(dpy);
2114 _EGLSync *s = _eglLookupSync(sync, disp);
2115 EGLAttrib attrib;
2116 EGLBoolean result;
2117
2118 _EGL_FUNC_START(disp, EGL_OBJECT_SYNC_KHR, s, EGL_FALSE);
2119
2120 if (!value)
2121 RETURN_EGL_ERROR(disp, EGL_BAD_PARAMETER, EGL_FALSE);
2122
2123 attrib = *value;
2124 result = _eglGetSyncAttribCommon(disp, s, attribute, &attrib);
2125
2126 /* The EGL_KHR_fence_sync spec says this about eglGetSyncAttribKHR:
2127 *
2128 * If any error occurs, <*value> is not modified.
2129 */
2130 if (result == EGL_FALSE)
2131 return result;
2132
2133 *value = attrib;
2134 return result;
2135 }
2136
2137 static EGLint EGLAPIENTRY
eglDupNativeFenceFDANDROID(EGLDisplay dpy,EGLSync sync)2138 eglDupNativeFenceFDANDROID(EGLDisplay dpy, EGLSync sync)
2139 {
2140 _EGLDisplay *disp = _eglLockDisplay(dpy);
2141 _EGLSync *s = _eglLookupSync(sync, disp);
2142 EGLBoolean ret;
2143
2144 _EGL_FUNC_START(disp, EGL_OBJECT_SYNC_KHR, s, EGL_FALSE);
2145
2146 /* the spec doesn't seem to specify what happens if the fence
2147 * type is not EGL_SYNC_NATIVE_FENCE_ANDROID, but this seems
2148 * sensible:
2149 */
2150 if (!(s && (s->Type == EGL_SYNC_NATIVE_FENCE_ANDROID)))
2151 RETURN_EGL_ERROR(disp, EGL_BAD_PARAMETER, EGL_NO_NATIVE_FENCE_FD_ANDROID);
2152
2153 _EGL_CHECK_SYNC(disp, s, EGL_NO_NATIVE_FENCE_FD_ANDROID);
2154 assert(disp->Extensions.ANDROID_native_fence_sync);
2155 ret = disp->Driver->DupNativeFenceFDANDROID(disp, s);
2156
2157 RETURN_EGL_EVAL(disp, ret);
2158 }
2159
2160 static EGLBoolean EGLAPIENTRY
eglSwapBuffersRegionNOK(EGLDisplay dpy,EGLSurface surface,EGLint numRects,const EGLint * rects)2161 eglSwapBuffersRegionNOK(EGLDisplay dpy, EGLSurface surface,
2162 EGLint numRects, const EGLint *rects)
2163 {
2164 _EGLContext *ctx = _eglGetCurrentContext();
2165 _EGLDisplay *disp = _eglLockDisplay(dpy);
2166 _EGLSurface *surf = _eglLookupSurface(surface, disp);
2167 EGLBoolean ret;
2168
2169 _EGL_FUNC_START(disp, EGL_OBJECT_SURFACE_KHR, surf, EGL_FALSE);
2170
2171 _EGL_CHECK_SURFACE(disp, surf, EGL_FALSE);
2172
2173 if (!disp->Extensions.NOK_swap_region)
2174 RETURN_EGL_EVAL(disp, EGL_FALSE);
2175
2176 /* surface must be bound to current context in EGL 1.4 */
2177 if (_eglGetContextHandle(ctx) == EGL_NO_CONTEXT ||
2178 surf != ctx->DrawSurface)
2179 RETURN_EGL_ERROR(disp, EGL_BAD_SURFACE, EGL_FALSE);
2180
2181 ret = disp->Driver->SwapBuffersRegionNOK(disp, surf, numRects, rects);
2182
2183 RETURN_EGL_EVAL(disp, ret);
2184 }
2185
2186
2187 static EGLImage EGLAPIENTRY
eglCreateDRMImageMESA(EGLDisplay dpy,const EGLint * attr_list)2188 eglCreateDRMImageMESA(EGLDisplay dpy, const EGLint *attr_list)
2189 {
2190 _EGLDisplay *disp = _eglLockDisplay(dpy);
2191 _EGLImage *img;
2192 EGLImage ret;
2193
2194 _EGL_FUNC_START(disp, EGL_OBJECT_DISPLAY_KHR, NULL, EGL_FALSE);
2195
2196 _EGL_CHECK_DISPLAY(disp, EGL_NO_IMAGE_KHR);
2197 if (!disp->Extensions.MESA_drm_image)
2198 RETURN_EGL_EVAL(disp, EGL_NO_IMAGE_KHR);
2199
2200 img = disp->Driver->CreateDRMImageMESA(disp, attr_list);
2201 ret = (img) ? _eglLinkImage(img) : EGL_NO_IMAGE_KHR;
2202
2203 RETURN_EGL_EVAL(disp, ret);
2204 }
2205
2206 static EGLBoolean EGLAPIENTRY
eglExportDRMImageMESA(EGLDisplay dpy,EGLImage image,EGLint * name,EGLint * handle,EGLint * stride)2207 eglExportDRMImageMESA(EGLDisplay dpy, EGLImage image,
2208 EGLint *name, EGLint *handle, EGLint *stride)
2209 {
2210 _EGLDisplay *disp = _eglLockDisplay(dpy);
2211 _EGLImage *img = _eglLookupImage(image, disp);
2212 EGLBoolean ret;
2213
2214 _EGL_FUNC_START(disp, EGL_OBJECT_IMAGE_KHR, img, EGL_FALSE);
2215
2216 _EGL_CHECK_DISPLAY(disp, EGL_FALSE);
2217 assert(disp->Extensions.MESA_drm_image);
2218
2219 if (!img)
2220 RETURN_EGL_ERROR(disp, EGL_BAD_PARAMETER, EGL_FALSE);
2221
2222 ret = disp->Driver->ExportDRMImageMESA(disp, img, name, handle, stride);
2223
2224 RETURN_EGL_EVAL(disp, ret);
2225 }
2226
2227
2228 struct wl_display;
2229
2230 static EGLBoolean EGLAPIENTRY
eglBindWaylandDisplayWL(EGLDisplay dpy,struct wl_display * display)2231 eglBindWaylandDisplayWL(EGLDisplay dpy, struct wl_display *display)
2232 {
2233 _EGLDisplay *disp = _eglLockDisplay(dpy);
2234 EGLBoolean ret;
2235
2236 _EGL_FUNC_START(disp, EGL_OBJECT_DISPLAY_KHR, NULL, EGL_FALSE);
2237
2238 _EGL_CHECK_DISPLAY(disp, EGL_FALSE);
2239 assert(disp->Extensions.WL_bind_wayland_display);
2240
2241 if (!display)
2242 RETURN_EGL_ERROR(disp, EGL_BAD_PARAMETER, EGL_FALSE);
2243
2244 ret = disp->Driver->BindWaylandDisplayWL(disp, display);
2245
2246 RETURN_EGL_EVAL(disp, ret);
2247 }
2248
2249 static EGLBoolean EGLAPIENTRY
eglUnbindWaylandDisplayWL(EGLDisplay dpy,struct wl_display * display)2250 eglUnbindWaylandDisplayWL(EGLDisplay dpy, struct wl_display *display)
2251 {
2252 _EGLDisplay *disp = _eglLockDisplay(dpy);
2253 EGLBoolean ret;
2254
2255 _EGL_FUNC_START(disp, EGL_OBJECT_DISPLAY_KHR, NULL, EGL_FALSE);
2256
2257 _EGL_CHECK_DISPLAY(disp, EGL_FALSE);
2258 assert(disp->Extensions.WL_bind_wayland_display);
2259
2260 if (!display)
2261 RETURN_EGL_ERROR(disp, EGL_BAD_PARAMETER, EGL_FALSE);
2262
2263 ret = disp->Driver->UnbindWaylandDisplayWL(disp, display);
2264
2265 RETURN_EGL_EVAL(disp, ret);
2266 }
2267
2268 static EGLBoolean EGLAPIENTRY
eglQueryWaylandBufferWL(EGLDisplay dpy,struct wl_resource * buffer,EGLint attribute,EGLint * value)2269 eglQueryWaylandBufferWL(EGLDisplay dpy, struct wl_resource *buffer,
2270 EGLint attribute, EGLint *value)
2271 {
2272 _EGLDisplay *disp = _eglLockDisplay(dpy);
2273 EGLBoolean ret;
2274
2275 _EGL_FUNC_START(disp, EGL_OBJECT_DISPLAY_KHR, NULL, EGL_FALSE);
2276
2277 _EGL_CHECK_DISPLAY(disp, EGL_FALSE);
2278 assert(disp->Extensions.WL_bind_wayland_display);
2279
2280 if (!buffer)
2281 RETURN_EGL_ERROR(disp, EGL_BAD_PARAMETER, EGL_FALSE);
2282
2283 ret = disp->Driver->QueryWaylandBufferWL(disp, buffer, attribute, value);
2284
2285 RETURN_EGL_EVAL(disp, ret);
2286 }
2287
2288
2289 static struct wl_buffer * EGLAPIENTRY
eglCreateWaylandBufferFromImageWL(EGLDisplay dpy,EGLImage image)2290 eglCreateWaylandBufferFromImageWL(EGLDisplay dpy, EGLImage image)
2291 {
2292 _EGLDisplay *disp = _eglLockDisplay(dpy);
2293 _EGLImage *img;
2294 struct wl_buffer *ret;
2295
2296 _EGL_FUNC_START(disp, EGL_OBJECT_DISPLAY_KHR, NULL, EGL_FALSE);
2297
2298 _EGL_CHECK_DISPLAY(disp, NULL);
2299 if (!disp->Extensions.WL_create_wayland_buffer_from_image)
2300 RETURN_EGL_EVAL(disp, NULL);
2301
2302 img = _eglLookupImage(image, disp);
2303
2304 if (!img)
2305 RETURN_EGL_ERROR(disp, EGL_BAD_PARAMETER, NULL);
2306
2307 ret = disp->Driver->CreateWaylandBufferFromImageWL(disp, img);
2308
2309 RETURN_EGL_EVAL(disp, ret);
2310 }
2311
2312 static EGLBoolean EGLAPIENTRY
eglPostSubBufferNV(EGLDisplay dpy,EGLSurface surface,EGLint x,EGLint y,EGLint width,EGLint height)2313 eglPostSubBufferNV(EGLDisplay dpy, EGLSurface surface,
2314 EGLint x, EGLint y, EGLint width, EGLint height)
2315 {
2316 _EGLDisplay *disp = _eglLockDisplay(dpy);
2317 _EGLSurface *surf = _eglLookupSurface(surface, disp);
2318 EGLBoolean ret;
2319
2320 _EGL_FUNC_START(disp, EGL_OBJECT_SURFACE_KHR, surf, EGL_FALSE);
2321
2322 _EGL_CHECK_SURFACE(disp, surf, EGL_FALSE);
2323
2324 if (!disp->Extensions.NV_post_sub_buffer)
2325 RETURN_EGL_EVAL(disp, EGL_FALSE);
2326
2327 ret = disp->Driver->PostSubBufferNV(disp, surf, x, y, width, height);
2328
2329 RETURN_EGL_EVAL(disp, ret);
2330 }
2331
2332 static EGLBoolean EGLAPIENTRY
eglGetSyncValuesCHROMIUM(EGLDisplay dpy,EGLSurface surface,EGLuint64KHR * ust,EGLuint64KHR * msc,EGLuint64KHR * sbc)2333 eglGetSyncValuesCHROMIUM(EGLDisplay dpy, EGLSurface surface,
2334 EGLuint64KHR *ust, EGLuint64KHR *msc,
2335 EGLuint64KHR *sbc)
2336 {
2337 _EGLDisplay *disp = _eglLockDisplay(dpy);
2338 _EGLSurface *surf = _eglLookupSurface(surface, disp);
2339 EGLBoolean ret;
2340
2341 _EGL_FUNC_START(disp, EGL_OBJECT_SURFACE_KHR, surf, EGL_FALSE);
2342
2343 _EGL_CHECK_SURFACE(disp, surf, EGL_FALSE);
2344 if (!disp->Extensions.CHROMIUM_sync_control)
2345 RETURN_EGL_EVAL(disp, EGL_FALSE);
2346
2347 if (!ust || !msc || !sbc)
2348 RETURN_EGL_ERROR(disp, EGL_BAD_PARAMETER, EGL_FALSE);
2349
2350 ret = disp->Driver->GetSyncValuesCHROMIUM(disp, surf, ust, msc, sbc);
2351
2352 RETURN_EGL_EVAL(disp, ret);
2353 }
2354
2355 static EGLBoolean EGLAPIENTRY
eglExportDMABUFImageQueryMESA(EGLDisplay dpy,EGLImage image,EGLint * fourcc,EGLint * nplanes,EGLuint64KHR * modifiers)2356 eglExportDMABUFImageQueryMESA(EGLDisplay dpy, EGLImage image,
2357 EGLint *fourcc, EGLint *nplanes,
2358 EGLuint64KHR *modifiers)
2359 {
2360 _EGLDisplay *disp = _eglLockDisplay(dpy);
2361 _EGLImage *img = _eglLookupImage(image, disp);
2362 EGLBoolean ret;
2363
2364 _EGL_FUNC_START(disp, EGL_OBJECT_IMAGE_KHR, img, EGL_FALSE);
2365
2366 _EGL_CHECK_DISPLAY(disp, EGL_FALSE);
2367 assert(disp->Extensions.MESA_image_dma_buf_export);
2368
2369 if (!img)
2370 RETURN_EGL_ERROR(disp, EGL_BAD_PARAMETER, EGL_FALSE);
2371
2372 ret = disp->Driver->ExportDMABUFImageQueryMESA(disp, img, fourcc, nplanes, modifiers);
2373
2374 RETURN_EGL_EVAL(disp, ret);
2375 }
2376
2377 static EGLBoolean EGLAPIENTRY
eglExportDMABUFImageMESA(EGLDisplay dpy,EGLImage image,int * fds,EGLint * strides,EGLint * offsets)2378 eglExportDMABUFImageMESA(EGLDisplay dpy, EGLImage image,
2379 int *fds, EGLint *strides, EGLint *offsets)
2380 {
2381 _EGLDisplay *disp = _eglLockDisplay(dpy);
2382 _EGLImage *img = _eglLookupImage(image, disp);
2383 EGLBoolean ret;
2384
2385 _EGL_FUNC_START(disp, EGL_OBJECT_IMAGE_KHR, img, EGL_FALSE);
2386
2387 _EGL_CHECK_DISPLAY(disp, EGL_FALSE);
2388 assert(disp->Extensions.MESA_image_dma_buf_export);
2389
2390 if (!img)
2391 RETURN_EGL_ERROR(disp, EGL_BAD_PARAMETER, EGL_FALSE);
2392
2393 ret = disp->Driver->ExportDMABUFImageMESA(disp, img, fds, strides, offsets);
2394
2395 RETURN_EGL_EVAL(disp, ret);
2396 }
2397
2398 static EGLint EGLAPIENTRY
eglLabelObjectKHR(EGLDisplay dpy,EGLenum objectType,EGLObjectKHR object,EGLLabelKHR label)2399 eglLabelObjectKHR(EGLDisplay dpy, EGLenum objectType, EGLObjectKHR object,
2400 EGLLabelKHR label)
2401 {
2402 _EGLDisplay *disp = NULL;
2403 _EGLResourceType type;
2404
2405 _EGL_FUNC_START(NULL, EGL_NONE, NULL, EGL_BAD_ALLOC);
2406
2407 if (objectType == EGL_OBJECT_THREAD_KHR) {
2408 _EGLThreadInfo *t = _eglGetCurrentThread();
2409
2410 if (!_eglIsCurrentThreadDummy()) {
2411 t->Label = label;
2412 return EGL_SUCCESS;
2413 }
2414
2415 RETURN_EGL_ERROR(NULL, EGL_BAD_ALLOC, EGL_BAD_ALLOC);
2416 }
2417
2418 disp = _eglLockDisplay(dpy);
2419 if (disp == NULL)
2420 RETURN_EGL_ERROR(disp, EGL_BAD_DISPLAY, EGL_BAD_DISPLAY);
2421
2422 if (objectType == EGL_OBJECT_DISPLAY_KHR) {
2423 if (dpy != (EGLDisplay) object)
2424 RETURN_EGL_ERROR(disp, EGL_BAD_PARAMETER, EGL_BAD_PARAMETER);
2425
2426 disp->Label = label;
2427 RETURN_EGL_EVAL(disp, EGL_SUCCESS);
2428 }
2429
2430 switch (objectType) {
2431 case EGL_OBJECT_CONTEXT_KHR:
2432 type = _EGL_RESOURCE_CONTEXT;
2433 break;
2434 case EGL_OBJECT_SURFACE_KHR:
2435 type = _EGL_RESOURCE_SURFACE;
2436 break;
2437 case EGL_OBJECT_IMAGE_KHR:
2438 type = _EGL_RESOURCE_IMAGE;
2439 break;
2440 case EGL_OBJECT_SYNC_KHR:
2441 type = _EGL_RESOURCE_SYNC;
2442 break;
2443 case EGL_OBJECT_STREAM_KHR:
2444 default:
2445 RETURN_EGL_ERROR(disp, EGL_BAD_PARAMETER, EGL_BAD_PARAMETER);
2446 }
2447
2448 if (_eglCheckResource(object, type, disp)) {
2449 _EGLResource *res = (_EGLResource *) object;
2450
2451 res->Label = label;
2452 RETURN_EGL_EVAL(disp, EGL_SUCCESS);
2453 }
2454
2455 RETURN_EGL_ERROR(disp, EGL_BAD_PARAMETER, EGL_BAD_PARAMETER);
2456 }
2457
2458 static EGLint EGLAPIENTRY
eglDebugMessageControlKHR(EGLDEBUGPROCKHR callback,const EGLAttrib * attrib_list)2459 eglDebugMessageControlKHR(EGLDEBUGPROCKHR callback,
2460 const EGLAttrib *attrib_list)
2461 {
2462 unsigned int newEnabled;
2463
2464 _EGL_FUNC_START(NULL, EGL_NONE, NULL, EGL_BAD_ALLOC);
2465
2466 mtx_lock(_eglGlobal.Mutex);
2467
2468 newEnabled = _eglGlobal.debugTypesEnabled;
2469 if (attrib_list != NULL) {
2470 int i;
2471
2472 for (i = 0; attrib_list[i] != EGL_NONE; i += 2) {
2473 switch (attrib_list[i]) {
2474 case EGL_DEBUG_MSG_CRITICAL_KHR:
2475 case EGL_DEBUG_MSG_ERROR_KHR:
2476 case EGL_DEBUG_MSG_WARN_KHR:
2477 case EGL_DEBUG_MSG_INFO_KHR:
2478 if (attrib_list[i + 1])
2479 newEnabled |= DebugBitFromType(attrib_list[i]);
2480 else
2481 newEnabled &= ~DebugBitFromType(attrib_list[i]);
2482 break;
2483 default:
2484 // On error, set the last error code, call the current
2485 // debug callback, and return the error code.
2486 mtx_unlock(_eglGlobal.Mutex);
2487 _eglReportError(EGL_BAD_ATTRIBUTE, NULL,
2488 "Invalid attribute 0x%04lx", (unsigned long) attrib_list[i]);
2489 return EGL_BAD_ATTRIBUTE;
2490 }
2491 }
2492 }
2493
2494 if (callback != NULL) {
2495 _eglGlobal.debugCallback = callback;
2496 _eglGlobal.debugTypesEnabled = newEnabled;
2497 } else {
2498 _eglGlobal.debugCallback = NULL;
2499 _eglGlobal.debugTypesEnabled = _EGL_DEBUG_BIT_CRITICAL | _EGL_DEBUG_BIT_ERROR;
2500 }
2501
2502 mtx_unlock(_eglGlobal.Mutex);
2503 return EGL_SUCCESS;
2504 }
2505
2506 static EGLBoolean EGLAPIENTRY
eglQueryDebugKHR(EGLint attribute,EGLAttrib * value)2507 eglQueryDebugKHR(EGLint attribute, EGLAttrib *value)
2508 {
2509 _EGL_FUNC_START(NULL, EGL_NONE, NULL, EGL_BAD_ALLOC);
2510
2511 mtx_lock(_eglGlobal.Mutex);
2512
2513 switch (attribute) {
2514 case EGL_DEBUG_MSG_CRITICAL_KHR:
2515 case EGL_DEBUG_MSG_ERROR_KHR:
2516 case EGL_DEBUG_MSG_WARN_KHR:
2517 case EGL_DEBUG_MSG_INFO_KHR:
2518 if (_eglGlobal.debugTypesEnabled & DebugBitFromType(attribute))
2519 *value = EGL_TRUE;
2520 else
2521 *value = EGL_FALSE;
2522 break;
2523 case EGL_DEBUG_CALLBACK_KHR:
2524 *value = (EGLAttrib) _eglGlobal.debugCallback;
2525 break;
2526 default:
2527 mtx_unlock(_eglGlobal.Mutex);
2528 _eglReportError(EGL_BAD_ATTRIBUTE, NULL,
2529 "Invalid attribute 0x%04lx", (unsigned long) attribute);
2530 return EGL_FALSE;
2531 }
2532
2533 mtx_unlock(_eglGlobal.Mutex);
2534 return EGL_TRUE;
2535 }
2536
2537 static int
_eglFunctionCompare(const void * key,const void * elem)2538 _eglFunctionCompare(const void *key, const void *elem)
2539 {
2540 const char *procname = key;
2541 const struct _egl_entrypoint *entrypoint = elem;
2542 return strcmp(procname, entrypoint->name);
2543 }
2544
2545 static EGLBoolean EGLAPIENTRY
eglQueryDmaBufFormatsEXT(EGLDisplay dpy,EGLint max_formats,EGLint * formats,EGLint * num_formats)2546 eglQueryDmaBufFormatsEXT(EGLDisplay dpy, EGLint max_formats,
2547 EGLint *formats, EGLint *num_formats)
2548 {
2549 _EGLDisplay *disp = _eglLockDisplay(dpy);
2550 EGLBoolean ret;
2551
2552 _EGL_FUNC_START(NULL, EGL_NONE, NULL, EGL_FALSE);
2553
2554 _EGL_CHECK_DISPLAY(disp, EGL_FALSE);
2555
2556 ret = disp->Driver->QueryDmaBufFormatsEXT(disp, max_formats, formats, num_formats);
2557
2558 RETURN_EGL_EVAL(disp, ret);
2559 }
2560
2561 static EGLBoolean EGLAPIENTRY
eglQueryDmaBufModifiersEXT(EGLDisplay dpy,EGLint format,EGLint max_modifiers,EGLuint64KHR * modifiers,EGLBoolean * external_only,EGLint * num_modifiers)2562 eglQueryDmaBufModifiersEXT(EGLDisplay dpy, EGLint format, EGLint max_modifiers,
2563 EGLuint64KHR *modifiers, EGLBoolean *external_only,
2564 EGLint *num_modifiers)
2565 {
2566 _EGLDisplay *disp = _eglLockDisplay(dpy);
2567 EGLBoolean ret;
2568
2569 _EGL_FUNC_START(NULL, EGL_NONE, NULL, EGL_FALSE);
2570
2571 _EGL_CHECK_DISPLAY(disp, EGL_FALSE);
2572
2573 ret = disp->Driver->QueryDmaBufModifiersEXT(disp, format, max_modifiers, modifiers,
2574 external_only, num_modifiers);
2575
2576 RETURN_EGL_EVAL(disp, ret);
2577 }
2578
2579 static void EGLAPIENTRY
eglSetBlobCacheFuncsANDROID(EGLDisplay * dpy,EGLSetBlobFuncANDROID set,EGLGetBlobFuncANDROID get)2580 eglSetBlobCacheFuncsANDROID(EGLDisplay *dpy, EGLSetBlobFuncANDROID set,
2581 EGLGetBlobFuncANDROID get)
2582 {
2583 /* This function does not return anything so we cannot
2584 * utilize the helper macros _EGL_FUNC_START or _EGL_CHECK_DISPLAY.
2585 */
2586 _EGLDisplay *disp = _eglLockDisplay(dpy);
2587 if (!_eglSetFuncName(__func__, disp, EGL_OBJECT_DISPLAY_KHR, NULL)) {
2588 if (disp)
2589 _eglUnlockDisplay(disp);
2590 return;
2591 }
2592
2593 if (!_eglCheckDisplay(disp, __func__)) {
2594 if (disp)
2595 _eglUnlockDisplay(disp);
2596 return;
2597 }
2598
2599 if (!set || !get) {
2600 _eglError(EGL_BAD_PARAMETER,
2601 "eglSetBlobCacheFuncsANDROID: NULL handler given");
2602 _eglUnlockDisplay(disp);
2603 return;
2604 }
2605
2606 if (disp->BlobCacheSet) {
2607 _eglError(EGL_BAD_PARAMETER,
2608 "eglSetBlobCacheFuncsANDROID: functions already set");
2609 _eglUnlockDisplay(disp);
2610 return;
2611 }
2612
2613 disp->BlobCacheSet = set;
2614 disp->BlobCacheGet = get;
2615
2616 disp->Driver->SetBlobCacheFuncsANDROID(disp, set, get);
2617
2618 _eglUnlockDisplay(disp);
2619 }
2620
2621 static EGLBoolean EGLAPIENTRY
eglQueryDeviceAttribEXT(EGLDeviceEXT device,EGLint attribute,EGLAttrib * value)2622 eglQueryDeviceAttribEXT(EGLDeviceEXT device,
2623 EGLint attribute,
2624 EGLAttrib *value)
2625 {
2626 _EGLDevice *dev = _eglLookupDevice(device);
2627 EGLBoolean ret;
2628
2629 _EGL_FUNC_START(NULL, EGL_NONE, NULL, EGL_FALSE);
2630 if (!dev)
2631 RETURN_EGL_ERROR(NULL, EGL_BAD_DEVICE_EXT, EGL_FALSE);
2632
2633 ret = _eglQueryDeviceAttribEXT(dev, attribute, value);
2634 RETURN_EGL_EVAL(NULL, ret);
2635 }
2636
2637 static const char * EGLAPIENTRY
eglQueryDeviceStringEXT(EGLDeviceEXT device,EGLint name)2638 eglQueryDeviceStringEXT(EGLDeviceEXT device,
2639 EGLint name)
2640 {
2641 _EGLDevice *dev = _eglLookupDevice(device);
2642
2643 _EGL_FUNC_START(NULL, EGL_NONE, NULL, NULL);
2644 if (!dev)
2645 RETURN_EGL_ERROR(NULL, EGL_BAD_DEVICE_EXT, NULL);
2646
2647 RETURN_EGL_EVAL(NULL, _eglQueryDeviceStringEXT(dev, name));
2648 }
2649
2650 static EGLBoolean EGLAPIENTRY
eglQueryDevicesEXT(EGLint max_devices,EGLDeviceEXT * devices,EGLint * num_devices)2651 eglQueryDevicesEXT(EGLint max_devices,
2652 EGLDeviceEXT *devices,
2653 EGLint *num_devices)
2654 {
2655 EGLBoolean ret;
2656
2657 _EGL_FUNC_START(NULL, EGL_NONE, NULL, EGL_FALSE);
2658 ret = _eglQueryDevicesEXT(max_devices, (_EGLDevice **) devices,
2659 num_devices);
2660 RETURN_EGL_EVAL(NULL, ret);
2661 }
2662
2663 static EGLBoolean EGLAPIENTRY
eglQueryDisplayAttribEXT(EGLDisplay dpy,EGLint attribute,EGLAttrib * value)2664 eglQueryDisplayAttribEXT(EGLDisplay dpy,
2665 EGLint attribute,
2666 EGLAttrib *value)
2667 {
2668 _EGLDisplay *disp = _eglLockDisplay(dpy);
2669
2670 _EGL_FUNC_START(NULL, EGL_NONE, NULL, EGL_FALSE);
2671 _EGL_CHECK_DISPLAY(disp, EGL_FALSE);
2672
2673 switch (attribute) {
2674 case EGL_DEVICE_EXT:
2675 *value = (EGLAttrib) disp->Device;
2676 break;
2677 default:
2678 RETURN_EGL_ERROR(disp, EGL_BAD_ATTRIBUTE, EGL_FALSE);
2679 }
2680 RETURN_EGL_SUCCESS(disp, EGL_TRUE);
2681 }
2682
2683 static char * EGLAPIENTRY
eglGetDisplayDriverConfig(EGLDisplay dpy)2684 eglGetDisplayDriverConfig(EGLDisplay dpy)
2685 {
2686 _EGLDisplay *disp = _eglLockDisplay(dpy);
2687 char *ret;
2688
2689 _EGL_FUNC_START(disp, EGL_NONE, NULL, NULL);
2690 _EGL_CHECK_DISPLAY(disp, NULL);
2691
2692 assert(disp->Extensions.MESA_query_driver);
2693
2694 ret = disp->Driver->QueryDriverConfig(disp);
2695 RETURN_EGL_EVAL(disp, ret);
2696 }
2697
2698 static const char * EGLAPIENTRY
eglGetDisplayDriverName(EGLDisplay dpy)2699 eglGetDisplayDriverName(EGLDisplay dpy)
2700 {
2701 _EGLDisplay *disp = _eglLockDisplay(dpy);
2702 const char *ret;
2703
2704 _EGL_FUNC_START(disp, EGL_NONE, NULL, NULL);
2705 _EGL_CHECK_DISPLAY(disp, NULL);
2706
2707 assert(disp->Extensions.MESA_query_driver);
2708
2709 ret = disp->Driver->QueryDriverName(disp);
2710 RETURN_EGL_EVAL(disp, ret);
2711 }
2712
2713 __eglMustCastToProperFunctionPointerType EGLAPIENTRY
eglGetProcAddress(const char * procname)2714 eglGetProcAddress(const char *procname)
2715 {
2716 static const struct _egl_entrypoint egl_functions[] = {
2717 #define EGL_ENTRYPOINT(f) { .name = #f, .function = (_EGLProc) f },
2718 #include "eglentrypoint.h"
2719 #undef EGL_ENTRYPOINT
2720 };
2721 _EGLProc ret = NULL;
2722
2723 if (!procname)
2724 RETURN_EGL_SUCCESS(NULL, NULL);
2725
2726 _EGL_FUNC_START(NULL, EGL_NONE, NULL, NULL);
2727
2728 if (strncmp(procname, "egl", 3) == 0) {
2729 const struct _egl_entrypoint *entrypoint =
2730 bsearch(procname,
2731 egl_functions, ARRAY_SIZE(egl_functions),
2732 sizeof(egl_functions[0]),
2733 _eglFunctionCompare);
2734 if (entrypoint)
2735 ret = entrypoint->function;
2736 }
2737
2738 if (!ret && _eglDriver.GetProcAddress)
2739 ret = _eglDriver.GetProcAddress(procname);
2740
2741 RETURN_EGL_SUCCESS(NULL, ret);
2742 }
2743
2744 static int
_eglLockDisplayInterop(EGLDisplay dpy,EGLContext context,_EGLDisplay ** disp,_EGLContext ** ctx)2745 _eglLockDisplayInterop(EGLDisplay dpy, EGLContext context,
2746 _EGLDisplay **disp, _EGLContext **ctx)
2747 {
2748
2749 *disp = _eglLockDisplay(dpy);
2750 if (!*disp || !(*disp)->Initialized || !(*disp)->Driver) {
2751 if (*disp)
2752 _eglUnlockDisplay(*disp);
2753 return MESA_GLINTEROP_INVALID_DISPLAY;
2754 }
2755
2756 *ctx = _eglLookupContext(context, *disp);
2757 if (!*ctx ||
2758 ((*ctx)->ClientAPI != EGL_OPENGL_API &&
2759 (*ctx)->ClientAPI != EGL_OPENGL_ES_API)) {
2760 _eglUnlockDisplay(*disp);
2761 return MESA_GLINTEROP_INVALID_CONTEXT;
2762 }
2763
2764 return MESA_GLINTEROP_SUCCESS;
2765 }
2766
2767 PUBLIC int
MesaGLInteropEGLQueryDeviceInfo(EGLDisplay dpy,EGLContext context,struct mesa_glinterop_device_info * out)2768 MesaGLInteropEGLQueryDeviceInfo(EGLDisplay dpy, EGLContext context,
2769 struct mesa_glinterop_device_info *out)
2770 {
2771 _EGLDisplay *disp;
2772 _EGLContext *ctx;
2773 int ret;
2774
2775 ret = _eglLockDisplayInterop(dpy, context, &disp, &ctx);
2776 if (ret != MESA_GLINTEROP_SUCCESS)
2777 return ret;
2778
2779 if (disp->Driver->GLInteropQueryDeviceInfo)
2780 ret = disp->Driver->GLInteropQueryDeviceInfo(disp, ctx, out);
2781 else
2782 ret = MESA_GLINTEROP_UNSUPPORTED;
2783
2784 _eglUnlockDisplay(disp);
2785 return ret;
2786 }
2787
2788 PUBLIC int
MesaGLInteropEGLExportObject(EGLDisplay dpy,EGLContext context,struct mesa_glinterop_export_in * in,struct mesa_glinterop_export_out * out)2789 MesaGLInteropEGLExportObject(EGLDisplay dpy, EGLContext context,
2790 struct mesa_glinterop_export_in *in,
2791 struct mesa_glinterop_export_out *out)
2792 {
2793 _EGLDisplay *disp;
2794 _EGLContext *ctx;
2795 int ret;
2796
2797 ret = _eglLockDisplayInterop(dpy, context, &disp, &ctx);
2798 if (ret != MESA_GLINTEROP_SUCCESS)
2799 return ret;
2800
2801 if (disp->Driver->GLInteropExportObject)
2802 ret = disp->Driver->GLInteropExportObject(disp, ctx, in, out);
2803 else
2804 ret = MESA_GLINTEROP_UNSUPPORTED;
2805
2806 _eglUnlockDisplay(disp);
2807 return ret;
2808 }
2809