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