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