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