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 _EGL_CHECK_EXTENSION(MESA_query_driver);
532
533 _EGL_CHECK_EXTENSION(NOK_swap_region);
534 _EGL_CHECK_EXTENSION(NOK_texture_from_pixmap);
535
536 _EGL_CHECK_EXTENSION(NV_post_sub_buffer);
537
538 _EGL_CHECK_EXTENSION(WL_bind_wayland_display);
539 _EGL_CHECK_EXTENSION(WL_create_wayland_buffer_from_image);
540
541 #undef _EGL_CHECK_EXTENSION
542 }
543
544 static void
545 _eglCreateAPIsString(_EGLDisplay *dpy)
546 {
547 #define addstr(str) \
548 { \
549 const size_t old_len = strlen(dpy->ClientAPIsString); \
550 const size_t add_len = sizeof(str); \
551 const size_t max_len = sizeof(dpy->ClientAPIsString) - 1; \
552 if (old_len + add_len <= max_len) \
553 strcat(dpy->ClientAPIsString, str " "); \
554 else \
555 assert(!"dpy->ClientAPIsString is not large enough"); \
556 }
557
558 if (dpy->ClientAPIs & EGL_OPENGL_BIT)
559 addstr("OpenGL");
560
561 if (dpy->ClientAPIs & EGL_OPENGL_ES_BIT ||
562 dpy->ClientAPIs & EGL_OPENGL_ES2_BIT ||
563 dpy->ClientAPIs & EGL_OPENGL_ES3_BIT_KHR) {
564 addstr("OpenGL_ES");
565 }
566
567 if (dpy->ClientAPIs & EGL_OPENVG_BIT)
568 addstr("OpenVG");
569
570 #undef addstr
571 }
572
573 static void
574 _eglComputeVersion(_EGLDisplay *disp)
575 {
576 disp->Version = 14;
577
578 if (disp->Extensions.KHR_fence_sync &&
579 disp->Extensions.KHR_cl_event2 &&
580 disp->Extensions.KHR_wait_sync &&
581 disp->Extensions.KHR_image_base &&
582 disp->Extensions.KHR_gl_texture_2D_image &&
583 disp->Extensions.KHR_gl_texture_3D_image &&
584 disp->Extensions.KHR_gl_texture_cubemap_image &&
585 disp->Extensions.KHR_gl_renderbuffer_image &&
586 disp->Extensions.KHR_create_context &&
587 disp->Extensions.EXT_create_context_robustness &&
588 disp->Extensions.KHR_get_all_proc_addresses &&
589 disp->Extensions.KHR_gl_colorspace &&
590 disp->Extensions.KHR_surfaceless_context)
591 disp->Version = 15;
592 }
593
594 /**
595 * This is typically the second EGL function that an application calls.
596 * Here we load/initialize the actual hardware driver.
597 */
598 EGLBoolean EGLAPIENTRY
599 eglInitialize(EGLDisplay dpy, EGLint *major, EGLint *minor)
600 {
601 _EGLDisplay *disp = _eglLockDisplay(dpy);
602
603 _EGL_FUNC_START(disp, EGL_OBJECT_DISPLAY_KHR, NULL, EGL_FALSE);
604
605 if (!disp)
606 RETURN_EGL_ERROR(NULL, EGL_BAD_DISPLAY, EGL_FALSE);
607
608 if (!disp->Initialized) {
609 if (!_eglMatchDriver(disp))
610 RETURN_EGL_ERROR(disp, EGL_NOT_INITIALIZED, EGL_FALSE);
611
612 /* limit to APIs supported by core */
613 disp->ClientAPIs &= _EGL_API_ALL_BITS;
614
615 /* EGL_KHR_get_all_proc_addresses is a corner-case extension. The spec
616 * classifies it as an EGL display extension, though conceptually it's an
617 * EGL client extension.
618 *
619 * From the EGL_KHR_get_all_proc_addresses spec:
620 *
621 * The EGL implementation must expose the name
622 * EGL_KHR_client_get_all_proc_addresses if and only if it exposes
623 * EGL_KHR_get_all_proc_addresses and supports
624 * EGL_EXT_client_extensions.
625 *
626 * Mesa unconditionally exposes both client extensions mentioned above,
627 * so the spec requires that each EGLDisplay unconditionally expose
628 * EGL_KHR_get_all_proc_addresses also.
629 */
630 disp->Extensions.KHR_get_all_proc_addresses = EGL_TRUE;
631
632 /* Extensions is used to provide EGL 1.3 functionality for 1.2 aware
633 * programs. It is driver agnostic and handled in the main EGL code.
634 */
635 disp->Extensions.KHR_config_attribs = EGL_TRUE;
636
637 _eglComputeVersion(disp);
638 _eglCreateExtensionsString(disp);
639 _eglCreateAPIsString(disp);
640 snprintf(disp->VersionString, sizeof(disp->VersionString),
641 "%d.%d", disp->Version / 10, disp->Version % 10);
642 }
643
644 /* Update applications version of major and minor if not NULL */
645 if ((major != NULL) && (minor != NULL)) {
646 *major = disp->Version / 10;
647 *minor = disp->Version % 10;
648 }
649
650 RETURN_EGL_SUCCESS(disp, EGL_TRUE);
651 }
652
653
654 EGLBoolean EGLAPIENTRY
655 eglTerminate(EGLDisplay dpy)
656 {
657 _EGLDisplay *disp = _eglLockDisplay(dpy);
658
659 _EGL_FUNC_START(disp, EGL_OBJECT_DISPLAY_KHR, NULL, EGL_FALSE);
660
661 if (!disp)
662 RETURN_EGL_ERROR(NULL, EGL_BAD_DISPLAY, EGL_FALSE);
663
664 if (disp->Initialized) {
665 _EGLDriver *drv = disp->Driver;
666
667 drv->API.Terminate(drv, disp);
668 /* do not reset disp->Driver */
669 disp->ClientAPIsString[0] = 0;
670 disp->Initialized = EGL_FALSE;
671 }
672
673 RETURN_EGL_SUCCESS(disp, EGL_TRUE);
674 }
675
676
677 const char * EGLAPIENTRY
678 eglQueryString(EGLDisplay dpy, EGLint name)
679 {
680 _EGLDisplay *disp;
681 _EGLDriver *drv;
682
683 if (dpy == EGL_NO_DISPLAY && name == EGL_EXTENSIONS) {
684 const char *ret = _eglGetClientExtensionString();
685 if (ret != NULL)
686 RETURN_EGL_SUCCESS(NULL, ret);
687 else
688 RETURN_EGL_ERROR(NULL, EGL_BAD_ALLOC, NULL);
689 }
690
691 disp = _eglLockDisplay(dpy);
692 _EGL_FUNC_START(disp, EGL_OBJECT_DISPLAY_KHR, NULL, NULL);
693 _EGL_CHECK_DISPLAY(disp, NULL, drv);
694
695 switch (name) {
696 case EGL_VENDOR:
697 RETURN_EGL_SUCCESS(disp, _EGL_VENDOR_STRING);
698 case EGL_VERSION:
699 RETURN_EGL_SUCCESS(disp, disp->VersionString);
700 case EGL_EXTENSIONS:
701 RETURN_EGL_SUCCESS(disp, disp->ExtensionsString);
702 case EGL_CLIENT_APIS:
703 RETURN_EGL_SUCCESS(disp, disp->ClientAPIsString);
704 default:
705 RETURN_EGL_ERROR(disp, EGL_BAD_PARAMETER, NULL);
706 }
707 }
708
709
710 EGLBoolean EGLAPIENTRY
711 eglGetConfigs(EGLDisplay dpy, EGLConfig *configs,
712 EGLint config_size, EGLint *num_config)
713 {
714 _EGLDisplay *disp = _eglLockDisplay(dpy);
715 _EGLDriver *drv;
716 EGLBoolean ret;
717
718 _EGL_FUNC_START(disp, EGL_OBJECT_DISPLAY_KHR, NULL, EGL_FALSE);
719
720 _EGL_CHECK_DISPLAY(disp, EGL_FALSE, drv);
721 ret = drv->API.GetConfigs(drv, disp, configs, config_size, num_config);
722
723 RETURN_EGL_EVAL(disp, ret);
724 }
725
726
727 EGLBoolean EGLAPIENTRY
728 eglChooseConfig(EGLDisplay dpy, const EGLint *attrib_list, EGLConfig *configs,
729 EGLint config_size, EGLint *num_config)
730 {
731 _EGLDisplay *disp = _eglLockDisplay(dpy);
732 _EGLDriver *drv;
733 EGLBoolean ret;
734
735 _EGL_FUNC_START(disp, EGL_OBJECT_DISPLAY_KHR, NULL, EGL_FALSE);
736
737 _EGL_CHECK_DISPLAY(disp, EGL_FALSE, drv);
738 ret = drv->API.ChooseConfig(drv, disp, attrib_list, configs,
739 config_size, num_config);
740
741 RETURN_EGL_EVAL(disp, ret);
742 }
743
744
745 EGLBoolean EGLAPIENTRY
746 eglGetConfigAttrib(EGLDisplay dpy, EGLConfig config,
747 EGLint attribute, EGLint *value)
748 {
749 _EGLDisplay *disp = _eglLockDisplay(dpy);
750 _EGLConfig *conf = _eglLookupConfig(config, disp);
751 _EGLDriver *drv;
752 EGLBoolean ret;
753
754 _EGL_FUNC_START(disp, EGL_OBJECT_DISPLAY_KHR, NULL, EGL_FALSE);
755
756 _EGL_CHECK_CONFIG(disp, conf, EGL_FALSE, drv);
757 ret = drv->API.GetConfigAttrib(drv, disp, conf, attribute, value);
758
759 RETURN_EGL_EVAL(disp, ret);
760 }
761
762
763 EGLContext EGLAPIENTRY
764 eglCreateContext(EGLDisplay dpy, EGLConfig config, EGLContext share_list,
765 const EGLint *attrib_list)
766 {
767 _EGLDisplay *disp = _eglLockDisplay(dpy);
768 _EGLConfig *conf = _eglLookupConfig(config, disp);
769 _EGLContext *share = _eglLookupContext(share_list, disp);
770 _EGLDriver *drv;
771 _EGLContext *context;
772 EGLContext ret;
773
774 _EGL_FUNC_START(disp, EGL_OBJECT_DISPLAY_KHR, NULL, EGL_NO_CONTEXT);
775
776 _EGL_CHECK_DISPLAY(disp, EGL_NO_CONTEXT, drv);
777
778 if (config != EGL_NO_CONFIG_KHR)
779 _EGL_CHECK_CONFIG(disp, conf, EGL_NO_CONTEXT, drv);
780 else if (!disp->Extensions.KHR_no_config_context)
781 RETURN_EGL_ERROR(disp, EGL_BAD_CONFIG, EGL_NO_CONTEXT);
782
783 if (!share && share_list != EGL_NO_CONTEXT)
784 RETURN_EGL_ERROR(disp, EGL_BAD_CONTEXT, EGL_NO_CONTEXT);
785
786 context = drv->API.CreateContext(drv, disp, conf, share, attrib_list);
787 ret = (context) ? _eglLinkContext(context) : EGL_NO_CONTEXT;
788
789 RETURN_EGL_EVAL(disp, ret);
790 }
791
792
793 EGLBoolean EGLAPIENTRY
794 eglDestroyContext(EGLDisplay dpy, EGLContext ctx)
795 {
796 _EGLDisplay *disp = _eglLockDisplay(dpy);
797 _EGLContext *context = _eglLookupContext(ctx, disp);
798 _EGLDriver *drv;
799 EGLBoolean ret;
800
801 _EGL_FUNC_START(disp, EGL_OBJECT_CONTEXT_KHR, context, EGL_FALSE);
802
803 _EGL_CHECK_CONTEXT(disp, context, EGL_FALSE, drv);
804 _eglUnlinkContext(context);
805 ret = drv->API.DestroyContext(drv, disp, context);
806
807 RETURN_EGL_EVAL(disp, ret);
808 }
809
810
811 EGLBoolean EGLAPIENTRY
812 eglMakeCurrent(EGLDisplay dpy, EGLSurface draw, EGLSurface read,
813 EGLContext ctx)
814 {
815 _EGLDisplay *disp = _eglLockDisplay(dpy);
816 _EGLContext *context = _eglLookupContext(ctx, disp);
817 _EGLSurface *draw_surf = _eglLookupSurface(draw, disp);
818 _EGLSurface *read_surf = _eglLookupSurface(read, disp);
819 _EGLDriver *drv;
820 EGLBoolean ret;
821
822 _EGL_FUNC_START(disp, EGL_OBJECT_CONTEXT_KHR, context, EGL_FALSE);
823
824 if (!disp)
825 RETURN_EGL_ERROR(disp, EGL_BAD_DISPLAY, EGL_FALSE);
826 drv = disp->Driver;
827
828 /* display is allowed to be uninitialized under certain condition */
829 if (!disp->Initialized) {
830 if (draw != EGL_NO_SURFACE || read != EGL_NO_SURFACE ||
831 ctx != EGL_NO_CONTEXT)
832 RETURN_EGL_ERROR(disp, EGL_BAD_DISPLAY, EGL_FALSE);
833 }
834 if (!drv)
835 RETURN_EGL_SUCCESS(disp, EGL_TRUE);
836
837 if (!context && ctx != EGL_NO_CONTEXT)
838 RETURN_EGL_ERROR(disp, EGL_BAD_CONTEXT, EGL_FALSE);
839 if (!draw_surf || !read_surf) {
840 /* From the EGL 1.4 (20130211) spec:
841 *
842 * To release the current context without assigning a new one, set ctx
843 * to EGL_NO_CONTEXT and set draw and read to EGL_NO_SURFACE.
844 */
845 if (!disp->Extensions.KHR_surfaceless_context && ctx != EGL_NO_CONTEXT)
846 RETURN_EGL_ERROR(disp, EGL_BAD_SURFACE, EGL_FALSE);
847
848 if ((!draw_surf && draw != EGL_NO_SURFACE) ||
849 (!read_surf && read != EGL_NO_SURFACE))
850 RETURN_EGL_ERROR(disp, EGL_BAD_SURFACE, EGL_FALSE);
851 if (draw_surf || read_surf)
852 RETURN_EGL_ERROR(disp, EGL_BAD_MATCH, EGL_FALSE);
853 }
854
855 /* If a native window underlying either draw or read is no longer valid,
856 * an EGL_BAD_NATIVE_WINDOW error is generated.
857 */
858 if (draw_surf && draw_surf->Lost)
859 RETURN_EGL_ERROR(disp, EGL_BAD_NATIVE_WINDOW, EGL_FALSE);
860 if (read_surf && read_surf->Lost)
861 RETURN_EGL_ERROR(disp, EGL_BAD_NATIVE_WINDOW, EGL_FALSE);
862
863 ret = drv->API.MakeCurrent(drv, disp, draw_surf, read_surf, context);
864
865 RETURN_EGL_EVAL(disp, ret);
866 }
867
868
869 EGLBoolean EGLAPIENTRY
870 eglQueryContext(EGLDisplay dpy, EGLContext ctx,
871 EGLint attribute, EGLint *value)
872 {
873 _EGLDisplay *disp = _eglLockDisplay(dpy);
874 _EGLContext *context = _eglLookupContext(ctx, disp);
875 _EGLDriver *drv;
876 EGLBoolean ret;
877
878 _EGL_FUNC_START(disp, EGL_OBJECT_CONTEXT_KHR, context, EGL_FALSE);
879
880 _EGL_CHECK_CONTEXT(disp, context, EGL_FALSE, drv);
881 ret = drv->API.QueryContext(drv, disp, context, attribute, value);
882
883 RETURN_EGL_EVAL(disp, ret);
884 }
885
886
887 static EGLSurface
888 _eglCreateWindowSurfaceCommon(_EGLDisplay *disp, EGLConfig config,
889 void *native_window, const EGLint *attrib_list)
890 {
891 _EGLConfig *conf = _eglLookupConfig(config, disp);
892 _EGLDriver *drv;
893 _EGLSurface *surf;
894 EGLSurface ret;
895
896
897 if (native_window == NULL)
898 RETURN_EGL_ERROR(disp, EGL_BAD_NATIVE_WINDOW, EGL_NO_SURFACE);
899
900 #ifdef HAVE_SURFACELESS_PLATFORM
901 if (disp && disp->Platform == _EGL_PLATFORM_SURFACELESS) {
902 /* From the EGL_MESA_platform_surfaceless spec (v1):
903 *
904 * eglCreatePlatformWindowSurface fails when called with a <display>
905 * that belongs to the surfaceless platform. It returns
906 * EGL_NO_SURFACE and generates EGL_BAD_NATIVE_WINDOW. The
907 * justification for this unconditional failure is that the
908 * surfaceless platform has no native windows, and therefore the
909 * <native_window> parameter is always invalid.
910 *
911 * This check must occur before checking the EGLConfig, which emits
912 * EGL_BAD_CONFIG.
913 */
914 RETURN_EGL_ERROR(disp, EGL_BAD_NATIVE_WINDOW, EGL_NO_SURFACE);
915 }
916 #endif
917
918 _EGL_CHECK_CONFIG(disp, conf, EGL_NO_SURFACE, drv);
919
920 if ((conf->SurfaceType & EGL_WINDOW_BIT) == 0)
921 RETURN_EGL_ERROR(disp, EGL_BAD_MATCH, EGL_NO_SURFACE);
922
923 surf = drv->API.CreateWindowSurface(drv, disp, conf, native_window,
924 attrib_list);
925 ret = (surf) ? _eglLinkSurface(surf) : EGL_NO_SURFACE;
926
927 RETURN_EGL_EVAL(disp, ret);
928 }
929
930
931 EGLSurface EGLAPIENTRY
932 eglCreateWindowSurface(EGLDisplay dpy, EGLConfig config,
933 EGLNativeWindowType window, const EGLint *attrib_list)
934 {
935 _EGLDisplay *disp = _eglLockDisplay(dpy);
936
937 _EGL_FUNC_START(disp, EGL_OBJECT_DISPLAY_KHR, NULL, EGL_NO_SURFACE);
938 STATIC_ASSERT(sizeof(void*) == sizeof(window));
939 return _eglCreateWindowSurfaceCommon(disp, config, (void*) window,
940 attrib_list);
941 }
942
943 static void *
944 _fixupNativeWindow(_EGLDisplay *disp, void *native_window)
945 {
946 #ifdef HAVE_X11_PLATFORM
947 if (disp && disp->Platform == _EGL_PLATFORM_X11 && native_window != NULL) {
948 /* The `native_window` parameter for the X11 platform differs between
949 * eglCreateWindowSurface() and eglCreatePlatformPixmapSurfaceEXT(). In
950 * eglCreateWindowSurface(), the type of `native_window` is an Xlib
951 * `Window`. In eglCreatePlatformWindowSurfaceEXT(), the type is
952 * `Window*`. Convert `Window*` to `Window` because that's what
953 * dri2_x11_create_window_surface() expects.
954 */
955 return (void *)(* (Window*) native_window);
956 }
957 #endif
958 return native_window;
959 }
960
961 static EGLSurface EGLAPIENTRY
962 eglCreatePlatformWindowSurfaceEXT(EGLDisplay dpy, EGLConfig config,
963 void *native_window,
964 const EGLint *attrib_list)
965 {
966 _EGLDisplay *disp = _eglLockDisplay(dpy);
967
968 native_window = _fixupNativeWindow(disp, native_window);
969
970 _EGL_FUNC_START(disp, EGL_OBJECT_DISPLAY_KHR, NULL, EGL_NO_SURFACE);
971 return _eglCreateWindowSurfaceCommon(disp, config, native_window,
972 attrib_list);
973 }
974
975
976 EGLSurface EGLAPIENTRY
977 eglCreatePlatformWindowSurface(EGLDisplay dpy, EGLConfig config,
978 void *native_window,
979 const EGLAttrib *attrib_list)
980 {
981 _EGLDisplay *disp = _eglLockDisplay(dpy);
982 EGLSurface surface;
983 EGLint *int_attribs;
984
985 _EGL_FUNC_START(disp, EGL_OBJECT_DISPLAY_KHR, NULL, EGL_NO_SURFACE);
986
987 int_attribs = _eglConvertAttribsToInt(attrib_list);
988 if (attrib_list && !int_attribs)
989 RETURN_EGL_ERROR(disp, EGL_BAD_ALLOC, EGL_NO_SURFACE);
990
991 native_window = _fixupNativeWindow(disp, native_window);
992 surface = _eglCreateWindowSurfaceCommon(disp, config, native_window,
993 int_attribs);
994 free(int_attribs);
995 return surface;
996 }
997
998 static void *
999 _fixupNativePixmap(_EGLDisplay *disp, void *native_pixmap)
1000 {
1001 #ifdef HAVE_X11_PLATFORM
1002 /* The `native_pixmap` parameter for the X11 platform differs between
1003 * eglCreatePixmapSurface() and eglCreatePlatformPixmapSurfaceEXT(). In
1004 * eglCreatePixmapSurface(), the type of `native_pixmap` is an Xlib
1005 * `Pixmap`. In eglCreatePlatformPixmapSurfaceEXT(), the type is
1006 * `Pixmap*`. Convert `Pixmap*` to `Pixmap` because that's what
1007 * dri2_x11_create_pixmap_surface() expects.
1008 */
1009 if (disp && disp->Platform == _EGL_PLATFORM_X11 && native_pixmap != NULL)
1010 return (void *)(* (Pixmap*) native_pixmap);
1011 #endif
1012 return native_pixmap;
1013 }
1014
1015 static EGLSurface
1016 _eglCreatePixmapSurfaceCommon(_EGLDisplay *disp, EGLConfig config,
1017 void *native_pixmap, const EGLint *attrib_list)
1018 {
1019 _EGLConfig *conf = _eglLookupConfig(config, disp);
1020 _EGLDriver *drv;
1021 _EGLSurface *surf;
1022 EGLSurface ret;
1023
1024 #if HAVE_SURFACELESS_PLATFORM
1025 if (disp && disp->Platform == _EGL_PLATFORM_SURFACELESS) {
1026 /* From the EGL_MESA_platform_surfaceless spec (v1):
1027 *
1028 * [Like eglCreatePlatformWindowSurface,] eglCreatePlatformPixmapSurface
1029 * also fails when called with a <display> that belongs to the
1030 * surfaceless platform. It returns EGL_NO_SURFACE and generates
1031 * EGL_BAD_NATIVE_PIXMAP.
1032 *
1033 * This check must occur before checking the EGLConfig, which emits
1034 * EGL_BAD_CONFIG.
1035 */
1036 RETURN_EGL_ERROR(disp, EGL_BAD_NATIVE_PIXMAP, EGL_NO_SURFACE);
1037 }
1038 #endif
1039
1040 _EGL_CHECK_CONFIG(disp, conf, EGL_NO_SURFACE, drv);
1041
1042 if ((conf->SurfaceType & EGL_PIXMAP_BIT) == 0)
1043 RETURN_EGL_ERROR(disp, EGL_BAD_MATCH, EGL_NO_SURFACE);
1044
1045 if (native_pixmap == NULL)
1046 RETURN_EGL_ERROR(disp, EGL_BAD_NATIVE_PIXMAP, EGL_NO_SURFACE);
1047
1048 surf = drv->API.CreatePixmapSurface(drv, disp, conf, native_pixmap,
1049 attrib_list);
1050 ret = (surf) ? _eglLinkSurface(surf) : EGL_NO_SURFACE;
1051
1052 RETURN_EGL_EVAL(disp, ret);
1053 }
1054
1055
1056 EGLSurface EGLAPIENTRY
1057 eglCreatePixmapSurface(EGLDisplay dpy, EGLConfig config,
1058 EGLNativePixmapType pixmap, const EGLint *attrib_list)
1059 {
1060 _EGLDisplay *disp = _eglLockDisplay(dpy);
1061
1062 _EGL_FUNC_START(disp, EGL_OBJECT_DISPLAY_KHR, NULL, EGL_NO_SURFACE);
1063 STATIC_ASSERT(sizeof(void*) == sizeof(pixmap));
1064 return _eglCreatePixmapSurfaceCommon(disp, config, (void*) pixmap,
1065 attrib_list);
1066 }
1067
1068 static EGLSurface EGLAPIENTRY
1069 eglCreatePlatformPixmapSurfaceEXT(EGLDisplay dpy, EGLConfig config,
1070 void *native_pixmap,
1071 const EGLint *attrib_list)
1072 {
1073 _EGLDisplay *disp = _eglLockDisplay(dpy);
1074
1075 _EGL_FUNC_START(disp, EGL_OBJECT_DISPLAY_KHR, NULL, EGL_NO_SURFACE);
1076 native_pixmap = _fixupNativePixmap(disp, native_pixmap);
1077 return _eglCreatePixmapSurfaceCommon(disp, config, native_pixmap,
1078 attrib_list);
1079 }
1080
1081
1082 EGLSurface EGLAPIENTRY
1083 eglCreatePlatformPixmapSurface(EGLDisplay dpy, EGLConfig config,
1084 void *native_pixmap,
1085 const EGLAttrib *attrib_list)
1086 {
1087 _EGLDisplay *disp = _eglLockDisplay(dpy);
1088 EGLSurface surface;
1089 EGLint *int_attribs;
1090
1091 _EGL_FUNC_START(disp, EGL_OBJECT_DISPLAY_KHR, NULL, EGL_NO_SURFACE);
1092
1093 int_attribs = _eglConvertAttribsToInt(attrib_list);
1094 if (attrib_list && !int_attribs)
1095 RETURN_EGL_ERROR(disp, EGL_BAD_ALLOC, EGL_NO_SURFACE);
1096
1097 native_pixmap = _fixupNativePixmap(disp, native_pixmap);
1098 surface = _eglCreatePixmapSurfaceCommon(disp, config, native_pixmap,
1099 int_attribs);
1100 free(int_attribs);
1101 return surface;
1102 }
1103
1104
1105 EGLSurface EGLAPIENTRY
1106 eglCreatePbufferSurface(EGLDisplay dpy, EGLConfig config,
1107 const EGLint *attrib_list)
1108 {
1109 _EGLDisplay *disp = _eglLockDisplay(dpy);
1110 _EGLConfig *conf = _eglLookupConfig(config, disp);
1111 _EGLDriver *drv;
1112 _EGLSurface *surf;
1113 EGLSurface ret;
1114
1115 _EGL_FUNC_START(disp, EGL_OBJECT_DISPLAY_KHR, NULL, EGL_NO_SURFACE);
1116 _EGL_CHECK_CONFIG(disp, conf, EGL_NO_SURFACE, drv);
1117
1118 if ((conf->SurfaceType & EGL_PBUFFER_BIT) == 0)
1119 RETURN_EGL_ERROR(disp, EGL_BAD_MATCH, EGL_NO_SURFACE);
1120
1121 surf = drv->API.CreatePbufferSurface(drv, disp, conf, attrib_list);
1122 ret = (surf) ? _eglLinkSurface(surf) : EGL_NO_SURFACE;
1123
1124 RETURN_EGL_EVAL(disp, ret);
1125 }
1126
1127
1128 EGLBoolean EGLAPIENTRY
1129 eglDestroySurface(EGLDisplay dpy, EGLSurface surface)
1130 {
1131 _EGLDisplay *disp = _eglLockDisplay(dpy);
1132 _EGLSurface *surf = _eglLookupSurface(surface, disp);
1133 _EGLDriver *drv;
1134 EGLBoolean ret;
1135
1136 _EGL_FUNC_START(disp, EGL_OBJECT_SURFACE_KHR, surf, EGL_FALSE);
1137 _EGL_CHECK_SURFACE(disp, surf, EGL_FALSE, drv);
1138 _eglUnlinkSurface(surf);
1139 ret = drv->API.DestroySurface(drv, disp, surf);
1140
1141 RETURN_EGL_EVAL(disp, ret);
1142 }
1143
1144 EGLBoolean EGLAPIENTRY
1145 eglQuerySurface(EGLDisplay dpy, EGLSurface surface,
1146 EGLint attribute, EGLint *value)
1147 {
1148 _EGLDisplay *disp = _eglLockDisplay(dpy);
1149 _EGLSurface *surf = _eglLookupSurface(surface, disp);
1150 _EGLDriver *drv;
1151 EGLBoolean ret;
1152
1153 _EGL_FUNC_START(disp, EGL_OBJECT_SURFACE_KHR, surf, EGL_FALSE);
1154 _EGL_CHECK_SURFACE(disp, surf, EGL_FALSE, drv);
1155 ret = drv->API.QuerySurface(drv, disp, surf, attribute, value);
1156
1157 RETURN_EGL_EVAL(disp, ret);
1158 }
1159
1160 EGLBoolean EGLAPIENTRY
1161 eglSurfaceAttrib(EGLDisplay dpy, EGLSurface surface,
1162 EGLint attribute, EGLint value)
1163 {
1164 _EGLDisplay *disp = _eglLockDisplay(dpy);
1165 _EGLSurface *surf = _eglLookupSurface(surface, disp);
1166 _EGLDriver *drv;
1167 EGLBoolean ret;
1168
1169 _EGL_FUNC_START(disp, EGL_OBJECT_SURFACE_KHR, surf, EGL_FALSE);
1170 _EGL_CHECK_SURFACE(disp, surf, EGL_FALSE, drv);
1171 ret = drv->API.SurfaceAttrib(drv, disp, surf, attribute, value);
1172
1173 RETURN_EGL_EVAL(disp, ret);
1174 }
1175
1176
1177 EGLBoolean EGLAPIENTRY
1178 eglBindTexImage(EGLDisplay dpy, EGLSurface surface, EGLint buffer)
1179 {
1180 _EGLDisplay *disp = _eglLockDisplay(dpy);
1181 _EGLSurface *surf = _eglLookupSurface(surface, disp);
1182 _EGLDriver *drv;
1183 EGLBoolean ret;
1184
1185 _EGL_FUNC_START(disp, EGL_OBJECT_SURFACE_KHR, surf, EGL_FALSE);
1186 _EGL_CHECK_SURFACE(disp, surf, EGL_FALSE, drv);
1187 ret = drv->API.BindTexImage(drv, disp, surf, buffer);
1188
1189 RETURN_EGL_EVAL(disp, ret);
1190 }
1191
1192
1193 EGLBoolean EGLAPIENTRY
1194 eglReleaseTexImage(EGLDisplay dpy, EGLSurface surface, EGLint buffer)
1195 {
1196 _EGLDisplay *disp = _eglLockDisplay(dpy);
1197 _EGLSurface *surf = _eglLookupSurface(surface, disp);
1198 _EGLDriver *drv;
1199 EGLBoolean ret;
1200
1201 _EGL_FUNC_START(disp, EGL_OBJECT_SURFACE_KHR, surf, EGL_FALSE);
1202 _EGL_CHECK_SURFACE(disp, surf, EGL_FALSE, drv);
1203 ret = drv->API.ReleaseTexImage(drv, disp, surf, buffer);
1204
1205 RETURN_EGL_EVAL(disp, ret);
1206 }
1207
1208
1209 EGLBoolean EGLAPIENTRY
1210 eglSwapInterval(EGLDisplay dpy, EGLint interval)
1211 {
1212 _EGLDisplay *disp = _eglLockDisplay(dpy);
1213 _EGLContext *ctx = _eglGetCurrentContext();
1214 _EGLSurface *surf = ctx ? ctx->DrawSurface : NULL;
1215 _EGLDriver *drv;
1216 EGLBoolean ret;
1217
1218 _EGL_FUNC_START(disp, EGL_OBJECT_SURFACE_KHR, surf, EGL_FALSE);
1219 _EGL_CHECK_DISPLAY(disp, EGL_FALSE, drv);
1220
1221 if (_eglGetContextHandle(ctx) == EGL_NO_CONTEXT ||
1222 ctx->Resource.Display != disp)
1223 RETURN_EGL_ERROR(disp, EGL_BAD_CONTEXT, EGL_FALSE);
1224
1225 if (_eglGetSurfaceHandle(surf) == EGL_NO_SURFACE)
1226 RETURN_EGL_ERROR(disp, EGL_BAD_SURFACE, EGL_FALSE);
1227
1228 if (surf->Type != EGL_WINDOW_BIT)
1229 RETURN_EGL_EVAL(disp, EGL_TRUE);
1230
1231 interval = CLAMP(interval,
1232 surf->Config->MinSwapInterval,
1233 surf->Config->MaxSwapInterval);
1234
1235 if (surf->SwapInterval != interval)
1236 ret = drv->API.SwapInterval(drv, disp, surf, interval);
1237 else
1238 ret = EGL_TRUE;
1239
1240 if (ret)
1241 surf->SwapInterval = interval;
1242
1243 RETURN_EGL_EVAL(disp, ret);
1244 }
1245
1246
1247 EGLBoolean EGLAPIENTRY
1248 eglSwapBuffers(EGLDisplay dpy, EGLSurface surface)
1249 {
1250 _EGLContext *ctx = _eglGetCurrentContext();
1251 _EGLDisplay *disp = _eglLockDisplay(dpy);
1252 _EGLSurface *surf = _eglLookupSurface(surface, disp);
1253 _EGLDriver *drv;
1254 EGLBoolean ret;
1255
1256 _EGL_FUNC_START(disp, EGL_OBJECT_SURFACE_KHR, surf, EGL_FALSE);
1257 _EGL_CHECK_SURFACE(disp, surf, EGL_FALSE, drv);
1258
1259 /* surface must be bound to current context in EGL 1.4 */
1260 #ifndef _EGL_BUILT_IN_DRIVER_HAIKU
1261 if (_eglGetContextHandle(ctx) == EGL_NO_CONTEXT ||
1262 surf != ctx->DrawSurface)
1263 RETURN_EGL_ERROR(disp, EGL_BAD_SURFACE, EGL_FALSE);
1264 #endif
1265
1266 if (surf->Type != EGL_WINDOW_BIT)
1267 RETURN_EGL_EVAL(disp, EGL_TRUE);
1268
1269 /* From the EGL 1.5 spec:
1270 *
1271 * If eglSwapBuffers is called and the native window associated with
1272 * surface is no longer valid, an EGL_BAD_NATIVE_WINDOW error is
1273 * generated.
1274 */
1275 if (surf->Lost)
1276 RETURN_EGL_ERROR(disp, EGL_BAD_NATIVE_WINDOW, EGL_FALSE);
1277
1278 ret = drv->API.SwapBuffers(drv, disp, surf);
1279
1280 /* EGL_KHR_partial_update
1281 * Frame boundary successfully reached,
1282 * reset damage region and reset BufferAgeRead
1283 */
1284 if (ret) {
1285 surf->SetDamageRegionCalled = EGL_FALSE;
1286 surf->BufferAgeRead = EGL_FALSE;
1287 }
1288
1289 RETURN_EGL_EVAL(disp, ret);
1290 }
1291
1292
1293 static EGLBoolean
1294 _eglSwapBuffersWithDamageCommon(_EGLDisplay *disp, _EGLSurface *surf,
1295 EGLint *rects, EGLint n_rects)
1296 {
1297 _EGLContext *ctx = _eglGetCurrentContext();
1298 _EGLDriver *drv;
1299 EGLBoolean ret;
1300
1301 _EGL_CHECK_SURFACE(disp, surf, EGL_FALSE, drv);
1302
1303 /* surface must be bound to current context in EGL 1.4 */
1304 if (_eglGetContextHandle(ctx) == EGL_NO_CONTEXT ||
1305 surf != ctx->DrawSurface)
1306 RETURN_EGL_ERROR(disp, EGL_BAD_SURFACE, EGL_FALSE);
1307
1308 if (surf->Type != EGL_WINDOW_BIT)
1309 RETURN_EGL_EVAL(disp, EGL_TRUE);
1310
1311 if ((n_rects > 0 && rects == NULL) || n_rects < 0)
1312 RETURN_EGL_ERROR(disp, EGL_BAD_PARAMETER, EGL_FALSE);
1313
1314 ret = drv->API.SwapBuffersWithDamageEXT(drv, disp, surf, rects, n_rects);
1315
1316 /* EGL_KHR_partial_update
1317 * Frame boundary successfully reached,
1318 * reset damage region and reset BufferAgeRead
1319 */
1320 if (ret) {
1321 surf->SetDamageRegionCalled = EGL_FALSE;
1322 surf->BufferAgeRead = EGL_FALSE;
1323 }
1324
1325 RETURN_EGL_EVAL(disp, ret);
1326 }
1327
1328 static EGLBoolean EGLAPIENTRY
1329 eglSwapBuffersWithDamageEXT(EGLDisplay dpy, EGLSurface surface,
1330 EGLint *rects, EGLint n_rects)
1331 {
1332 _EGLDisplay *disp = _eglLockDisplay(dpy);
1333 _EGLSurface *surf = _eglLookupSurface(surface, disp);
1334 _EGL_FUNC_START(disp, EGL_OBJECT_SURFACE_KHR, surf, EGL_FALSE);
1335 return _eglSwapBuffersWithDamageCommon(disp, surf, rects, n_rects);
1336 }
1337
1338 static EGLBoolean EGLAPIENTRY
1339 eglSwapBuffersWithDamageKHR(EGLDisplay dpy, EGLSurface surface,
1340 EGLint *rects, EGLint n_rects)
1341 {
1342 _EGLDisplay *disp = _eglLockDisplay(dpy);
1343 _EGLSurface *surf = _eglLookupSurface(surface, disp);
1344 _EGL_FUNC_START(disp, EGL_OBJECT_SURFACE_KHR, surf, EGL_FALSE);
1345 return _eglSwapBuffersWithDamageCommon(disp, surf, rects, n_rects);
1346 }
1347
1348 /**
1349 * Clamp the rectangles so that they lie within the surface.
1350 */
1351
1352 static void
1353 _eglSetDamageRegionKHRClampRects(_EGLDisplay* disp, _EGLSurface* surf,
1354 EGLint *rects, EGLint n_rects)
1355 {
1356 EGLint i;
1357 EGLint surf_height = surf->Height;
1358 EGLint surf_width = surf->Width;
1359
1360 for (i = 0; i < (4 * n_rects); i += 4) {
1361 EGLint x1, y1, x2, y2;
1362 x1 = rects[i];
1363 y1 = rects[i + 1];
1364 x2 = rects[i + 2] + x1;
1365 y2 = rects[i + 3] + y1;
1366
1367 rects[i] = CLAMP(x1, 0, surf_width);
1368 rects[i + 1] = CLAMP(y1, 0, surf_height);
1369 rects[i + 2] = CLAMP(x2, 0, surf_width) - rects[i];
1370 rects[i + 3] = CLAMP(y2, 0, surf_height) - rects[i + 1];
1371 }
1372 }
1373
1374 static EGLBoolean EGLAPIENTRY
1375 eglSetDamageRegionKHR(EGLDisplay dpy, EGLSurface surface,
1376 EGLint *rects, EGLint n_rects)
1377 {
1378 _EGLDisplay *disp = _eglLockDisplay(dpy);
1379 _EGLSurface *surf = _eglLookupSurface(surface, disp);
1380 _EGL_FUNC_START(disp, EGL_OBJECT_SURFACE_KHR, surf, EGL_FALSE);
1381 _EGLContext *ctx = _eglGetCurrentContext();
1382 _EGLDriver *drv;
1383 EGLBoolean ret;
1384 _EGL_CHECK_SURFACE(disp, surf, EGL_FALSE, drv);
1385
1386 if (_eglGetContextHandle(ctx) == EGL_NO_CONTEXT ||
1387 surf->Type != EGL_WINDOW_BIT ||
1388 ctx->DrawSurface != surf ||
1389 surf->SwapBehavior != EGL_BUFFER_DESTROYED)
1390 RETURN_EGL_ERROR(disp, EGL_BAD_MATCH, EGL_FALSE);
1391
1392 /* If the damage region is already set or
1393 * buffer age is not queried between
1394 * frame boundaries, throw bad access error
1395 */
1396
1397 if (surf->SetDamageRegionCalled || !surf->BufferAgeRead)
1398 RETURN_EGL_ERROR(disp, EGL_BAD_ACCESS, EGL_FALSE);
1399
1400 _eglSetDamageRegionKHRClampRects(disp, surf, rects, n_rects);
1401 ret = drv->API.SetDamageRegion(drv, disp, surf, rects, n_rects);
1402
1403 if (ret)
1404 surf->SetDamageRegionCalled = EGL_TRUE;
1405
1406 RETURN_EGL_EVAL(disp, ret);
1407 }
1408
1409 EGLBoolean EGLAPIENTRY
1410 eglCopyBuffers(EGLDisplay dpy, EGLSurface surface, EGLNativePixmapType target)
1411 {
1412 _EGLDisplay *disp = _eglLockDisplay(dpy);
1413 _EGLSurface *surf = _eglLookupSurface(surface, disp);
1414 _EGLDriver *drv;
1415 EGLBoolean ret;
1416 void *native_pixmap_ptr;
1417
1418 _EGL_FUNC_START(disp, EGL_OBJECT_SURFACE_KHR, surf, EGL_FALSE);
1419 STATIC_ASSERT(sizeof(void*) == sizeof(target));
1420 native_pixmap_ptr = (void*) target;
1421
1422 _EGL_CHECK_SURFACE(disp, surf, EGL_FALSE, drv);
1423 ret = drv->API.CopyBuffers(drv, disp, surf, native_pixmap_ptr);
1424
1425 RETURN_EGL_EVAL(disp, ret);
1426 }
1427
1428
1429 static EGLBoolean
1430 _eglWaitClientCommon(void)
1431 {
1432 _EGLContext *ctx = _eglGetCurrentContext();
1433 _EGLDisplay *disp;
1434 _EGLDriver *drv;
1435 EGLBoolean ret;
1436
1437 if (!ctx)
1438 RETURN_EGL_SUCCESS(NULL, EGL_TRUE);
1439
1440 disp = ctx->Resource.Display;
1441 mtx_lock(&disp->Mutex);
1442
1443 /* let bad current context imply bad current surface */
1444 if (_eglGetContextHandle(ctx) == EGL_NO_CONTEXT ||
1445 _eglGetSurfaceHandle(ctx->DrawSurface) == EGL_NO_SURFACE)
1446 RETURN_EGL_ERROR(disp, EGL_BAD_CURRENT_SURFACE, EGL_FALSE);
1447
1448 /* a valid current context implies an initialized current display */
1449 assert(disp->Initialized);
1450 drv = disp->Driver;
1451 ret = drv->API.WaitClient(drv, disp, ctx);
1452
1453 RETURN_EGL_EVAL(disp, ret);
1454 }
1455
1456 EGLBoolean EGLAPIENTRY
1457 eglWaitClient(void)
1458 {
1459 _EGL_FUNC_START(NULL, EGL_OBJECT_CONTEXT_KHR, _eglGetCurrentContext(), EGL_FALSE);
1460 return _eglWaitClientCommon();
1461 }
1462
1463 EGLBoolean EGLAPIENTRY
1464 eglWaitGL(void)
1465 {
1466 /* Since we only support OpenGL and GLES, eglWaitGL is equivalent to eglWaitClient. */
1467 _EGL_FUNC_START(NULL, EGL_OBJECT_CONTEXT_KHR, _eglGetCurrentContext(), EGL_FALSE);
1468 return _eglWaitClientCommon();
1469 }
1470
1471
1472 EGLBoolean EGLAPIENTRY
1473 eglWaitNative(EGLint engine)
1474 {
1475 _EGLContext *ctx = _eglGetCurrentContext();
1476 _EGLDisplay *disp;
1477 _EGLDriver *drv;
1478 EGLBoolean ret;
1479
1480 if (!ctx)
1481 RETURN_EGL_SUCCESS(NULL, EGL_TRUE);
1482
1483 _EGL_FUNC_START(NULL, EGL_OBJECT_THREAD_KHR, NULL, EGL_FALSE);
1484
1485 disp = ctx->Resource.Display;
1486 mtx_lock(&disp->Mutex);
1487
1488 /* let bad current context imply bad current surface */
1489 if (_eglGetContextHandle(ctx) == EGL_NO_CONTEXT ||
1490 _eglGetSurfaceHandle(ctx->DrawSurface) == EGL_NO_SURFACE)
1491 RETURN_EGL_ERROR(disp, EGL_BAD_CURRENT_SURFACE, EGL_FALSE);
1492
1493 /* a valid current context implies an initialized current display */
1494 assert(disp->Initialized);
1495 drv = disp->Driver;
1496 ret = drv->API.WaitNative(drv, disp, engine);
1497
1498 RETURN_EGL_EVAL(disp, ret);
1499 }
1500
1501
1502 EGLDisplay EGLAPIENTRY
1503 eglGetCurrentDisplay(void)
1504 {
1505 _EGLContext *ctx = _eglGetCurrentContext();
1506 EGLDisplay ret;
1507
1508 ret = (ctx) ? _eglGetDisplayHandle(ctx->Resource.Display) : EGL_NO_DISPLAY;
1509
1510 RETURN_EGL_SUCCESS(NULL, ret);
1511 }
1512
1513
1514 EGLContext EGLAPIENTRY
1515 eglGetCurrentContext(void)
1516 {
1517 _EGLContext *ctx = _eglGetCurrentContext();
1518 EGLContext ret;
1519
1520 ret = _eglGetContextHandle(ctx);
1521
1522 RETURN_EGL_SUCCESS(NULL, ret);
1523 }
1524
1525
1526 EGLSurface EGLAPIENTRY
1527 eglGetCurrentSurface(EGLint readdraw)
1528 {
1529 _EGLContext *ctx = _eglGetCurrentContext();
1530 EGLint err = EGL_SUCCESS;
1531 _EGLSurface *surf;
1532 EGLSurface ret;
1533
1534 _EGL_FUNC_START(NULL, EGL_NONE, NULL, EGL_NO_SURFACE);
1535
1536 if (!ctx)
1537 RETURN_EGL_SUCCESS(NULL, EGL_NO_SURFACE);
1538
1539 switch (readdraw) {
1540 case EGL_DRAW:
1541 surf = ctx->DrawSurface;
1542 break;
1543 case EGL_READ:
1544 surf = ctx->ReadSurface;
1545 break;
1546 default:
1547 surf = NULL;
1548 err = EGL_BAD_PARAMETER;
1549 break;
1550 }
1551
1552 ret = _eglGetSurfaceHandle(surf);
1553
1554 RETURN_EGL_ERROR(NULL, err, ret);
1555 }
1556
1557
1558 EGLint EGLAPIENTRY
1559 eglGetError(void)
1560 {
1561 _EGLThreadInfo *t = _eglGetCurrentThread();
1562 EGLint e = t->LastError;
1563 if (!_eglIsCurrentThreadDummy())
1564 t->LastError = EGL_SUCCESS;
1565 return e;
1566 }
1567
1568
1569 /**
1570 ** EGL 1.2
1571 **/
1572
1573 /**
1574 * Specify the client API to use for subsequent calls including:
1575 * eglCreateContext()
1576 * eglGetCurrentContext()
1577 * eglGetCurrentDisplay()
1578 * eglGetCurrentSurface()
1579 * eglMakeCurrent(when the ctx parameter is EGL NO CONTEXT)
1580 * eglWaitClient()
1581 * eglWaitNative()
1582 * See section 3.7 "Rendering Context" in the EGL specification for details.
1583 */
1584 EGLBoolean EGLAPIENTRY
1585 eglBindAPI(EGLenum api)
1586 {
1587 _EGLThreadInfo *t;
1588
1589 _EGL_FUNC_START(NULL, EGL_OBJECT_THREAD_KHR, NULL, EGL_FALSE);
1590
1591 t = _eglGetCurrentThread();
1592 if (_eglIsCurrentThreadDummy())
1593 RETURN_EGL_ERROR(NULL, EGL_BAD_ALLOC, EGL_FALSE);
1594
1595 if (!_eglIsApiValid(api))
1596 RETURN_EGL_ERROR(NULL, EGL_BAD_PARAMETER, EGL_FALSE);
1597
1598 t->CurrentAPI = api;
1599
1600 RETURN_EGL_SUCCESS(NULL, EGL_TRUE);
1601 }
1602
1603
1604 /**
1605 * Return the last value set with eglBindAPI().
1606 */
1607 EGLenum EGLAPIENTRY
1608 eglQueryAPI(void)
1609 {
1610 _EGLThreadInfo *t = _eglGetCurrentThread();
1611 EGLenum ret;
1612
1613 /* returns one of EGL_OPENGL_API, EGL_OPENGL_ES_API or EGL_OPENVG_API */
1614 ret = t->CurrentAPI;
1615
1616 RETURN_EGL_SUCCESS(NULL, ret);
1617 }
1618
1619
1620 EGLSurface EGLAPIENTRY
1621 eglCreatePbufferFromClientBuffer(EGLDisplay dpy, EGLenum buftype,
1622 EGLClientBuffer buffer, EGLConfig config,
1623 const EGLint *attrib_list)
1624 {
1625 _EGLDisplay *disp = _eglLockDisplay(dpy);
1626 _EGLConfig *conf = _eglLookupConfig(config, disp);
1627 _EGLDriver *drv;
1628 _EGLSurface *surf;
1629 EGLSurface ret;
1630
1631 _EGL_FUNC_START(disp, EGL_OBJECT_DISPLAY_KHR, NULL, EGL_NO_SURFACE);
1632
1633 _EGL_CHECK_CONFIG(disp, conf, EGL_NO_SURFACE, drv);
1634
1635 surf = drv->API.CreatePbufferFromClientBuffer(drv, disp, buftype, buffer,
1636 conf, attrib_list);
1637 ret = (surf) ? _eglLinkSurface(surf) : EGL_NO_SURFACE;
1638
1639 RETURN_EGL_EVAL(disp, ret);
1640 }
1641
1642
1643 EGLBoolean EGLAPIENTRY
1644 eglReleaseThread(void)
1645 {
1646 /* unbind current contexts */
1647 if (!_eglIsCurrentThreadDummy()) {
1648 _EGLThreadInfo *t = _eglGetCurrentThread();
1649 _EGLContext *ctx = t->CurrentContext;
1650
1651 _EGL_FUNC_START(NULL, EGL_OBJECT_THREAD_KHR, NULL, EGL_FALSE);
1652
1653 if (ctx) {
1654 _EGLDisplay *disp = ctx->Resource.Display;
1655 _EGLDriver *drv;
1656
1657 mtx_lock(&disp->Mutex);
1658 drv = disp->Driver;
1659 (void) drv->API.MakeCurrent(drv, disp, NULL, NULL, NULL);
1660 mtx_unlock(&disp->Mutex);
1661 }
1662 }
1663
1664 _eglDestroyCurrentThread();
1665
1666 RETURN_EGL_SUCCESS(NULL, EGL_TRUE);
1667 }
1668
1669
1670 static EGLImage
1671 _eglCreateImageCommon(_EGLDisplay *disp, EGLContext ctx, EGLenum target,
1672 EGLClientBuffer buffer, const EGLint *attr_list)
1673 {
1674 _EGLContext *context = _eglLookupContext(ctx, disp);
1675 _EGLDriver *drv;
1676 _EGLImage *img;
1677 EGLImage ret;
1678
1679 _EGL_CHECK_DISPLAY(disp, EGL_NO_IMAGE_KHR, drv);
1680 if (!disp->Extensions.KHR_image_base)
1681 RETURN_EGL_EVAL(disp, EGL_NO_IMAGE_KHR);
1682 if (!context && ctx != EGL_NO_CONTEXT)
1683 RETURN_EGL_ERROR(disp, EGL_BAD_CONTEXT, EGL_NO_IMAGE_KHR);
1684 /* "If <target> is EGL_LINUX_DMA_BUF_EXT, <dpy> must be a valid display,
1685 * <ctx> must be EGL_NO_CONTEXT..."
1686 */
1687 if (ctx != EGL_NO_CONTEXT && target == EGL_LINUX_DMA_BUF_EXT)
1688 RETURN_EGL_ERROR(disp, EGL_BAD_PARAMETER, EGL_NO_IMAGE_KHR);
1689
1690 img = drv->API.CreateImageKHR(drv, disp, context, target,
1691 buffer, attr_list);
1692 ret = (img) ? _eglLinkImage(img) : EGL_NO_IMAGE_KHR;
1693
1694 RETURN_EGL_EVAL(disp, ret);
1695 }
1696
1697 static EGLImage EGLAPIENTRY
1698 eglCreateImageKHR(EGLDisplay dpy, EGLContext ctx, EGLenum target,
1699 EGLClientBuffer buffer, const EGLint *attr_list)
1700 {
1701 _EGLDisplay *disp = _eglLockDisplay(dpy);
1702 _EGL_FUNC_START(disp, EGL_OBJECT_DISPLAY_KHR, NULL, EGL_NO_IMAGE_KHR);
1703 return _eglCreateImageCommon(disp, ctx, target, buffer, attr_list);
1704 }
1705
1706
1707 EGLImage EGLAPIENTRY
1708 eglCreateImage(EGLDisplay dpy, EGLContext ctx, EGLenum target,
1709 EGLClientBuffer buffer, const EGLAttrib *attr_list)
1710 {
1711 _EGLDisplay *disp = _eglLockDisplay(dpy);
1712 EGLImage image;
1713 EGLint *int_attribs;
1714
1715 _EGL_FUNC_START(disp, EGL_OBJECT_DISPLAY_KHR, NULL, EGL_NO_IMAGE_KHR);
1716
1717 int_attribs = _eglConvertAttribsToInt(attr_list);
1718 if (attr_list && !int_attribs)
1719 RETURN_EGL_ERROR(disp, EGL_BAD_ALLOC, EGL_NO_IMAGE);
1720
1721 image = _eglCreateImageCommon(disp, ctx, target, buffer, int_attribs);
1722 free(int_attribs);
1723 return image;
1724 }
1725
1726
1727 static EGLBoolean
1728 _eglDestroyImageCommon(_EGLDisplay *disp, _EGLImage *img)
1729 {
1730 _EGLDriver *drv;
1731 EGLBoolean ret;
1732
1733 _EGL_CHECK_DISPLAY(disp, EGL_FALSE, drv);
1734 if (!disp->Extensions.KHR_image_base)
1735 RETURN_EGL_EVAL(disp, EGL_FALSE);
1736 if (!img)
1737 RETURN_EGL_ERROR(disp, EGL_BAD_PARAMETER, EGL_FALSE);
1738
1739 _eglUnlinkImage(img);
1740 ret = drv->API.DestroyImageKHR(drv, disp, img);
1741
1742 RETURN_EGL_EVAL(disp, ret);
1743 }
1744
1745 EGLBoolean EGLAPIENTRY
1746 eglDestroyImage(EGLDisplay dpy, EGLImage image)
1747 {
1748 _EGLDisplay *disp = _eglLockDisplay(dpy);
1749 _EGLImage *img = _eglLookupImage(image, disp);
1750 _EGL_FUNC_START(disp, EGL_OBJECT_IMAGE_KHR, img, EGL_FALSE);
1751 return _eglDestroyImageCommon(disp, img);
1752 }
1753
1754 static EGLBoolean EGLAPIENTRY
1755 eglDestroyImageKHR(EGLDisplay dpy, EGLImage image)
1756 {
1757 _EGLDisplay *disp = _eglLockDisplay(dpy);
1758 _EGLImage *img = _eglLookupImage(image, disp);
1759 _EGL_FUNC_START(disp, EGL_OBJECT_IMAGE_KHR, img, EGL_FALSE);
1760 return _eglDestroyImageCommon(disp, img);
1761 }
1762
1763
1764 static EGLSync
1765 _eglCreateSync(_EGLDisplay *disp, EGLenum type, const EGLAttrib *attrib_list,
1766 EGLBoolean orig_is_EGLAttrib,
1767 EGLenum invalid_type_error)
1768 {
1769 _EGLContext *ctx = _eglGetCurrentContext();
1770 _EGLDriver *drv;
1771 _EGLSync *sync;
1772 EGLSync ret;
1773
1774 _EGL_CHECK_DISPLAY(disp, EGL_NO_SYNC_KHR, drv);
1775
1776 if (!disp->Extensions.KHR_cl_event2 && orig_is_EGLAttrib) {
1777 /* There exist two EGLAttrib variants of eglCreateSync*:
1778 * eglCreateSync64KHR which requires EGL_KHR_cl_event2, and eglCreateSync
1779 * which requires EGL 1.5. Here we use the presence of EGL_KHR_cl_event2
1780 * support as a proxy for EGL 1.5 support, even though that's not
1781 * entirely correct (though _eglComputeVersion does the same).
1782 *
1783 * The EGL spec provides no guidance on how to handle unsupported
1784 * functions. EGL_BAD_MATCH seems reasonable.
1785 */
1786 RETURN_EGL_ERROR(disp, EGL_BAD_MATCH, EGL_NO_SYNC_KHR);
1787 }
1788
1789 /* If type is EGL_SYNC_FENCE and no context is current for the bound API
1790 * (i.e., eglGetCurrentContext returns EGL_NO_CONTEXT ), an EGL_BAD_MATCH
1791 * error is generated.
1792 */
1793 if (!ctx &&
1794 (type == EGL_SYNC_FENCE_KHR || type == EGL_SYNC_NATIVE_FENCE_ANDROID))
1795 RETURN_EGL_ERROR(disp, EGL_BAD_MATCH, EGL_NO_SYNC_KHR);
1796
1797 /* return an error if the client API doesn't support GL_OES_EGL_sync */
1798 if (ctx && (ctx->Resource.Display != disp ||
1799 ctx->ClientAPI != EGL_OPENGL_ES_API))
1800 RETURN_EGL_ERROR(disp, EGL_BAD_MATCH, EGL_NO_SYNC_KHR);
1801
1802 switch (type) {
1803 case EGL_SYNC_FENCE_KHR:
1804 if (!disp->Extensions.KHR_fence_sync)
1805 RETURN_EGL_ERROR(disp, invalid_type_error, EGL_NO_SYNC_KHR);
1806 break;
1807 case EGL_SYNC_REUSABLE_KHR:
1808 if (!disp->Extensions.KHR_reusable_sync)
1809 RETURN_EGL_ERROR(disp, invalid_type_error, EGL_NO_SYNC_KHR);
1810 break;
1811 case EGL_SYNC_CL_EVENT_KHR:
1812 if (!disp->Extensions.KHR_cl_event2)
1813 RETURN_EGL_ERROR(disp, invalid_type_error, EGL_NO_SYNC_KHR);
1814 break;
1815 case EGL_SYNC_NATIVE_FENCE_ANDROID:
1816 if (!disp->Extensions.ANDROID_native_fence_sync)
1817 RETURN_EGL_ERROR(disp, invalid_type_error, EGL_NO_SYNC_KHR);
1818 break;
1819 default:
1820 RETURN_EGL_ERROR(disp, invalid_type_error, EGL_NO_SYNC_KHR);
1821 }
1822
1823 sync = drv->API.CreateSyncKHR(drv, disp, type, attrib_list);
1824 ret = (sync) ? _eglLinkSync(sync) : EGL_NO_SYNC_KHR;
1825
1826 RETURN_EGL_EVAL(disp, ret);
1827 }
1828
1829
1830 static EGLSync EGLAPIENTRY
1831 eglCreateSyncKHR(EGLDisplay dpy, EGLenum type, const EGLint *int_list)
1832 {
1833 _EGLDisplay *disp = _eglLockDisplay(dpy);
1834 _EGL_FUNC_START(disp, EGL_OBJECT_DISPLAY_KHR, NULL, EGL_FALSE);
1835
1836 EGLSync sync;
1837 EGLAttrib *attrib_list;
1838 EGLint err;
1839
1840 if (sizeof(int_list[0]) == sizeof(attrib_list[0])) {
1841 attrib_list = (EGLAttrib *) int_list;
1842 } else {
1843 err = _eglConvertIntsToAttribs(int_list, &attrib_list);
1844 if (err != EGL_SUCCESS)
1845 RETURN_EGL_ERROR(disp, err, EGL_NO_SYNC);
1846 }
1847
1848 sync = _eglCreateSync(disp, type, attrib_list, EGL_FALSE,
1849 EGL_BAD_ATTRIBUTE);
1850
1851 if (sizeof(int_list[0]) != sizeof(attrib_list[0]))
1852 free(attrib_list);
1853
1854 /* Don't double-unlock the display. _eglCreateSync already unlocked it. */
1855 return sync;
1856 }
1857
1858
1859 static EGLSync EGLAPIENTRY
1860 eglCreateSync64KHR(EGLDisplay dpy, EGLenum type, const EGLAttrib *attrib_list)
1861 {
1862 _EGLDisplay *disp = _eglLockDisplay(dpy);
1863 _EGL_FUNC_START(disp, EGL_OBJECT_DISPLAY_KHR, NULL, EGL_FALSE);
1864 return _eglCreateSync(disp, type, attrib_list, EGL_TRUE,
1865 EGL_BAD_ATTRIBUTE);
1866 }
1867
1868
1869 EGLSync EGLAPIENTRY
1870 eglCreateSync(EGLDisplay dpy, EGLenum type, const EGLAttrib *attrib_list)
1871 {
1872 _EGLDisplay *disp = _eglLockDisplay(dpy);
1873 _EGL_FUNC_START(disp, EGL_OBJECT_DISPLAY_KHR, NULL, EGL_FALSE);
1874 return _eglCreateSync(disp, type, attrib_list, EGL_TRUE,
1875 EGL_BAD_PARAMETER);
1876 }
1877
1878
1879 static EGLBoolean
1880 _eglDestroySync(_EGLDisplay *disp, _EGLSync *s)
1881 {
1882 _EGLDriver *drv;
1883 EGLBoolean ret;
1884
1885 _EGL_CHECK_SYNC(disp, s, EGL_FALSE, drv);
1886 assert(disp->Extensions.KHR_reusable_sync ||
1887 disp->Extensions.KHR_fence_sync ||
1888 disp->Extensions.ANDROID_native_fence_sync);
1889
1890 _eglUnlinkSync(s);
1891 ret = drv->API.DestroySyncKHR(drv, disp, s);
1892
1893 RETURN_EGL_EVAL(disp, ret);
1894 }
1895
1896 EGLBoolean EGLAPIENTRY
1897 eglDestroySync(EGLDisplay dpy, EGLSync sync)
1898 {
1899 _EGLDisplay *disp = _eglLockDisplay(dpy);
1900 _EGLSync *s = _eglLookupSync(sync, disp);
1901 _EGL_FUNC_START(disp, EGL_OBJECT_SYNC_KHR, s, EGL_FALSE);
1902 return _eglDestroySync(disp, s);
1903 }
1904
1905 static EGLBoolean EGLAPIENTRY
1906 eglDestroySyncKHR(EGLDisplay dpy, EGLSync sync)
1907 {
1908 _EGLDisplay *disp = _eglLockDisplay(dpy);
1909 _EGLSync *s = _eglLookupSync(sync, disp);
1910 _EGL_FUNC_START(disp, EGL_OBJECT_SYNC_KHR, s, EGL_FALSE);
1911 return _eglDestroySync(disp, s);
1912 }
1913
1914
1915 static EGLint
1916 _eglClientWaitSyncCommon(_EGLDisplay *disp, EGLDisplay dpy,
1917 _EGLSync *s, EGLint flags, EGLTime timeout)
1918 {
1919 _EGLDriver *drv;
1920 EGLint ret;
1921
1922 _EGL_CHECK_SYNC(disp, s, EGL_FALSE, drv);
1923 assert(disp->Extensions.KHR_reusable_sync ||
1924 disp->Extensions.KHR_fence_sync ||
1925 disp->Extensions.ANDROID_native_fence_sync);
1926
1927 if (s->SyncStatus == EGL_SIGNALED_KHR)
1928 RETURN_EGL_EVAL(disp, EGL_CONDITION_SATISFIED_KHR);
1929
1930 /* if sync type is EGL_SYNC_REUSABLE_KHR, dpy should be
1931 * unlocked here to allow other threads also to be able to
1932 * go into waiting state.
1933 */
1934
1935 if (s->Type == EGL_SYNC_REUSABLE_KHR)
1936 _eglUnlockDisplay(dpy);
1937
1938 ret = drv->API.ClientWaitSyncKHR(drv, disp, s, flags, timeout);
1939
1940 /*
1941 * 'disp' is already unlocked for reusable sync type,
1942 * so passing 'NULL' to bypass unlocking display.
1943 */
1944 if (s->Type == EGL_SYNC_REUSABLE_KHR)
1945 RETURN_EGL_EVAL(NULL, ret);
1946 else
1947 RETURN_EGL_EVAL(disp, ret);
1948 }
1949
1950 EGLint EGLAPIENTRY
1951 eglClientWaitSync(EGLDisplay dpy, EGLSync sync,
1952 EGLint flags, EGLTime timeout)
1953 {
1954 _EGLDisplay *disp = _eglLockDisplay(dpy);
1955 _EGLSync *s = _eglLookupSync(sync, disp);
1956 _EGL_FUNC_START(disp, EGL_OBJECT_SYNC_KHR, s, EGL_FALSE);
1957 return _eglClientWaitSyncCommon(disp, dpy, s, flags, timeout);
1958 }
1959
1960 static EGLint EGLAPIENTRY
1961 eglClientWaitSyncKHR(EGLDisplay dpy, EGLSync sync,
1962 EGLint flags, EGLTime timeout)
1963 {
1964 _EGLDisplay *disp = _eglLockDisplay(dpy);
1965 _EGLSync *s = _eglLookupSync(sync, disp);
1966 _EGL_FUNC_START(disp, EGL_OBJECT_SYNC_KHR, s, EGL_FALSE);
1967 return _eglClientWaitSyncCommon(disp, dpy, s, flags, timeout);
1968 }
1969
1970
1971 static EGLint
1972 _eglWaitSyncCommon(_EGLDisplay *disp, _EGLSync *s, EGLint flags)
1973 {
1974 _EGLContext *ctx = _eglGetCurrentContext();
1975 _EGLDriver *drv;
1976 EGLint ret;
1977
1978 _EGL_CHECK_SYNC(disp, s, EGL_FALSE, drv);
1979 assert(disp->Extensions.KHR_wait_sync);
1980
1981 /* return an error if the client API doesn't support GL_OES_EGL_sync */
1982 if (ctx == EGL_NO_CONTEXT || ctx->ClientAPI != EGL_OPENGL_ES_API)
1983 RETURN_EGL_ERROR(disp, EGL_BAD_MATCH, EGL_FALSE);
1984
1985 /* the API doesn't allow any flags yet */
1986 if (flags != 0)
1987 RETURN_EGL_ERROR(disp, EGL_BAD_PARAMETER, EGL_FALSE);
1988
1989 ret = drv->API.WaitSyncKHR(drv, disp, s);
1990
1991 RETURN_EGL_EVAL(disp, ret);
1992 }
1993
1994 static EGLint EGLAPIENTRY
1995 eglWaitSyncKHR(EGLDisplay dpy, EGLSync sync, EGLint flags)
1996 {
1997 _EGLDisplay *disp = _eglLockDisplay(dpy);
1998 _EGLSync *s = _eglLookupSync(sync, disp);
1999 _EGL_FUNC_START(disp, EGL_OBJECT_SYNC_KHR, s, EGL_FALSE);
2000 return _eglWaitSyncCommon(disp, s, flags);
2001 }
2002
2003
2004 EGLBoolean EGLAPIENTRY
2005 eglWaitSync(EGLDisplay dpy, EGLSync sync, EGLint flags)
2006 {
2007 /* The KHR version returns EGLint, while the core version returns
2008 * EGLBoolean. In both cases, the return values can only be EGL_FALSE and
2009 * EGL_TRUE.
2010 */
2011 _EGLDisplay *disp = _eglLockDisplay(dpy);
2012 _EGLSync *s = _eglLookupSync(sync, disp);
2013 _EGL_FUNC_START(disp, EGL_OBJECT_SYNC_KHR, s, EGL_FALSE);
2014 return _eglWaitSyncCommon(disp, s, flags);
2015 }
2016
2017
2018 static EGLBoolean EGLAPIENTRY
2019 eglSignalSyncKHR(EGLDisplay dpy, EGLSync sync, EGLenum mode)
2020 {
2021 _EGLDisplay *disp = _eglLockDisplay(dpy);
2022 _EGLSync *s = _eglLookupSync(sync, disp);
2023 _EGLDriver *drv;
2024 EGLBoolean ret;
2025
2026 _EGL_FUNC_START(disp, EGL_OBJECT_SYNC_KHR, s, EGL_FALSE);
2027
2028 _EGL_CHECK_SYNC(disp, s, EGL_FALSE, drv);
2029 assert(disp->Extensions.KHR_reusable_sync);
2030 ret = drv->API.SignalSyncKHR(drv, disp, s, mode);
2031
2032 RETURN_EGL_EVAL(disp, ret);
2033 }
2034
2035
2036 static EGLBoolean
2037 _eglGetSyncAttribCommon(_EGLDisplay *disp, _EGLSync *s, EGLint attribute, EGLAttrib *value)
2038 {
2039 _EGLDriver *drv;
2040 EGLBoolean ret;
2041
2042 _EGL_CHECK_SYNC(disp, s, EGL_FALSE, drv);
2043 assert(disp->Extensions.KHR_reusable_sync ||
2044 disp->Extensions.KHR_fence_sync ||
2045 disp->Extensions.ANDROID_native_fence_sync);
2046 ret = drv->API.GetSyncAttrib(drv, disp, s, attribute, value);
2047
2048 RETURN_EGL_EVAL(disp, ret);
2049 }
2050
2051 EGLBoolean EGLAPIENTRY
2052 eglGetSyncAttrib(EGLDisplay dpy, EGLSync sync, EGLint attribute, EGLAttrib *value)
2053 {
2054 _EGLDisplay *disp = _eglLockDisplay(dpy);
2055 _EGLSync *s = _eglLookupSync(sync, disp);
2056 _EGL_FUNC_START(disp, EGL_OBJECT_SYNC_KHR, s, EGL_FALSE);
2057 return _eglGetSyncAttribCommon(disp, s, attribute, value);
2058 }
2059
2060
2061 static EGLBoolean EGLAPIENTRY
2062 eglGetSyncAttribKHR(EGLDisplay dpy, EGLSync sync, EGLint attribute, EGLint *value)
2063 {
2064 _EGLDisplay *disp = _eglLockDisplay(dpy);
2065 _EGLSync *s = _eglLookupSync(sync, disp);
2066 EGLAttrib attrib;
2067 EGLBoolean result;
2068
2069 _EGL_FUNC_START(disp, EGL_OBJECT_SYNC_KHR, s, EGL_FALSE);
2070
2071 if (!value)
2072 RETURN_EGL_ERROR(disp, EGL_BAD_PARAMETER, EGL_FALSE);
2073
2074 attrib = *value;
2075 result = _eglGetSyncAttribCommon(disp, s, attribute, &attrib);
2076
2077 /* The EGL_KHR_fence_sync spec says this about eglGetSyncAttribKHR:
2078 *
2079 * If any error occurs, <*value> is not modified.
2080 */
2081 if (result == EGL_FALSE)
2082 return result;
2083
2084 *value = attrib;
2085 return result;
2086 }
2087
2088 static EGLint EGLAPIENTRY
2089 eglDupNativeFenceFDANDROID(EGLDisplay dpy, EGLSync sync)
2090 {
2091 _EGLDisplay *disp = _eglLockDisplay(dpy);
2092 _EGLSync *s = _eglLookupSync(sync, disp);
2093 _EGLDriver *drv;
2094 EGLBoolean ret;
2095
2096 _EGL_FUNC_START(disp, EGL_OBJECT_SYNC_KHR, s, EGL_FALSE);
2097
2098 /* the spec doesn't seem to specify what happens if the fence
2099 * type is not EGL_SYNC_NATIVE_FENCE_ANDROID, but this seems
2100 * sensible:
2101 */
2102 if (!(s && (s->Type == EGL_SYNC_NATIVE_FENCE_ANDROID)))
2103 RETURN_EGL_ERROR(disp, EGL_BAD_PARAMETER, EGL_NO_NATIVE_FENCE_FD_ANDROID);
2104
2105 _EGL_CHECK_SYNC(disp, s, EGL_NO_NATIVE_FENCE_FD_ANDROID, drv);
2106 assert(disp->Extensions.ANDROID_native_fence_sync);
2107 ret = drv->API.DupNativeFenceFDANDROID(drv, disp, s);
2108
2109 RETURN_EGL_EVAL(disp, ret);
2110 }
2111
2112 static EGLBoolean EGLAPIENTRY
2113 eglSwapBuffersRegionNOK(EGLDisplay dpy, EGLSurface surface,
2114 EGLint numRects, const EGLint *rects)
2115 {
2116 _EGLContext *ctx = _eglGetCurrentContext();
2117 _EGLDisplay *disp = _eglLockDisplay(dpy);
2118 _EGLSurface *surf = _eglLookupSurface(surface, disp);
2119 _EGLDriver *drv;
2120 EGLBoolean ret;
2121
2122 _EGL_FUNC_START(disp, EGL_OBJECT_SURFACE_KHR, surf, EGL_FALSE);
2123
2124 _EGL_CHECK_SURFACE(disp, surf, EGL_FALSE, drv);
2125
2126 if (!disp->Extensions.NOK_swap_region)
2127 RETURN_EGL_EVAL(disp, EGL_FALSE);
2128
2129 /* surface must be bound to current context in EGL 1.4 */
2130 if (_eglGetContextHandle(ctx) == EGL_NO_CONTEXT ||
2131 surf != ctx->DrawSurface)
2132 RETURN_EGL_ERROR(disp, EGL_BAD_SURFACE, EGL_FALSE);
2133
2134 ret = drv->API.SwapBuffersRegionNOK(drv, disp, surf, numRects, rects);
2135
2136 RETURN_EGL_EVAL(disp, ret);
2137 }
2138
2139
2140 static EGLImage EGLAPIENTRY
2141 eglCreateDRMImageMESA(EGLDisplay dpy, const EGLint *attr_list)
2142 {
2143 _EGLDisplay *disp = _eglLockDisplay(dpy);
2144 _EGLDriver *drv;
2145 _EGLImage *img;
2146 EGLImage ret;
2147
2148 _EGL_FUNC_START(disp, EGL_OBJECT_DISPLAY_KHR, NULL, EGL_FALSE);
2149
2150 _EGL_CHECK_DISPLAY(disp, EGL_NO_IMAGE_KHR, drv);
2151 if (!disp->Extensions.MESA_drm_image)
2152 RETURN_EGL_EVAL(disp, EGL_NO_IMAGE_KHR);
2153
2154 img = drv->API.CreateDRMImageMESA(drv, disp, attr_list);
2155 ret = (img) ? _eglLinkImage(img) : EGL_NO_IMAGE_KHR;
2156
2157 RETURN_EGL_EVAL(disp, ret);
2158 }
2159
2160 static EGLBoolean EGLAPIENTRY
2161 eglExportDRMImageMESA(EGLDisplay dpy, EGLImage image,
2162 EGLint *name, EGLint *handle, EGLint *stride)
2163 {
2164 _EGLDisplay *disp = _eglLockDisplay(dpy);
2165 _EGLImage *img = _eglLookupImage(image, disp);
2166 _EGLDriver *drv;
2167 EGLBoolean ret;
2168
2169 _EGL_FUNC_START(disp, EGL_OBJECT_IMAGE_KHR, img, EGL_FALSE);
2170
2171 _EGL_CHECK_DISPLAY(disp, EGL_FALSE, drv);
2172 assert(disp->Extensions.MESA_drm_image);
2173
2174 if (!img)
2175 RETURN_EGL_ERROR(disp, EGL_BAD_PARAMETER, EGL_FALSE);
2176
2177 ret = drv->API.ExportDRMImageMESA(drv, disp, img, name, handle, stride);
2178
2179 RETURN_EGL_EVAL(disp, ret);
2180 }
2181
2182
2183 struct wl_display;
2184
2185 static EGLBoolean EGLAPIENTRY
2186 eglBindWaylandDisplayWL(EGLDisplay dpy, struct wl_display *display)
2187 {
2188 _EGLDisplay *disp = _eglLockDisplay(dpy);
2189 _EGLDriver *drv;
2190 EGLBoolean ret;
2191
2192 _EGL_FUNC_START(disp, EGL_OBJECT_DISPLAY_KHR, NULL, EGL_FALSE);
2193
2194 _EGL_CHECK_DISPLAY(disp, EGL_FALSE, drv);
2195 assert(disp->Extensions.WL_bind_wayland_display);
2196
2197 if (!display)
2198 RETURN_EGL_ERROR(disp, EGL_BAD_PARAMETER, EGL_FALSE);
2199
2200 ret = drv->API.BindWaylandDisplayWL(drv, disp, display);
2201
2202 RETURN_EGL_EVAL(disp, ret);
2203 }
2204
2205 static EGLBoolean EGLAPIENTRY
2206 eglUnbindWaylandDisplayWL(EGLDisplay dpy, struct wl_display *display)
2207 {
2208 _EGLDisplay *disp = _eglLockDisplay(dpy);
2209 _EGLDriver *drv;
2210 EGLBoolean ret;
2211
2212 _EGL_FUNC_START(disp, EGL_OBJECT_DISPLAY_KHR, NULL, EGL_FALSE);
2213
2214 _EGL_CHECK_DISPLAY(disp, EGL_FALSE, drv);
2215 assert(disp->Extensions.WL_bind_wayland_display);
2216
2217 if (!display)
2218 RETURN_EGL_ERROR(disp, EGL_BAD_PARAMETER, EGL_FALSE);
2219
2220 ret = drv->API.UnbindWaylandDisplayWL(drv, disp, display);
2221
2222 RETURN_EGL_EVAL(disp, ret);
2223 }
2224
2225 static EGLBoolean EGLAPIENTRY
2226 eglQueryWaylandBufferWL(EGLDisplay dpy, struct wl_resource *buffer,
2227 EGLint attribute, EGLint *value)
2228 {
2229 _EGLDisplay *disp = _eglLockDisplay(dpy);
2230 _EGLDriver *drv;
2231 EGLBoolean ret;
2232
2233 _EGL_FUNC_START(disp, EGL_OBJECT_DISPLAY_KHR, NULL, EGL_FALSE);
2234
2235 _EGL_CHECK_DISPLAY(disp, EGL_FALSE, drv);
2236 assert(disp->Extensions.WL_bind_wayland_display);
2237
2238 if (!buffer)
2239 RETURN_EGL_ERROR(disp, EGL_BAD_PARAMETER, EGL_FALSE);
2240
2241 ret = drv->API.QueryWaylandBufferWL(drv, disp, buffer, attribute, value);
2242
2243 RETURN_EGL_EVAL(disp, ret);
2244 }
2245
2246
2247 static struct wl_buffer * EGLAPIENTRY
2248 eglCreateWaylandBufferFromImageWL(EGLDisplay dpy, EGLImage image)
2249 {
2250 _EGLDisplay *disp = _eglLockDisplay(dpy);
2251 _EGLImage *img;
2252 _EGLDriver *drv;
2253 struct wl_buffer *ret;
2254
2255 _EGL_FUNC_START(disp, EGL_OBJECT_DISPLAY_KHR, NULL, EGL_FALSE);
2256
2257 _EGL_CHECK_DISPLAY(disp, NULL, drv);
2258 if (!disp->Extensions.WL_create_wayland_buffer_from_image)
2259 RETURN_EGL_EVAL(disp, NULL);
2260
2261 img = _eglLookupImage(image, disp);
2262
2263 if (!img)
2264 RETURN_EGL_ERROR(disp, EGL_BAD_PARAMETER, NULL);
2265
2266 ret = drv->API.CreateWaylandBufferFromImageWL(drv, disp, img);
2267
2268 RETURN_EGL_EVAL(disp, ret);
2269 }
2270
2271 static EGLBoolean EGLAPIENTRY
2272 eglPostSubBufferNV(EGLDisplay dpy, EGLSurface surface,
2273 EGLint x, EGLint y, EGLint width, EGLint height)
2274 {
2275 _EGLDisplay *disp = _eglLockDisplay(dpy);
2276 _EGLSurface *surf = _eglLookupSurface(surface, disp);
2277 _EGLDriver *drv;
2278 EGLBoolean ret;
2279
2280 _EGL_FUNC_START(disp, EGL_OBJECT_SURFACE_KHR, surf, EGL_FALSE);
2281
2282 _EGL_CHECK_SURFACE(disp, surf, EGL_FALSE, drv);
2283
2284 if (!disp->Extensions.NV_post_sub_buffer)
2285 RETURN_EGL_EVAL(disp, EGL_FALSE);
2286
2287 ret = drv->API.PostSubBufferNV(drv, disp, surf, x, y, width, height);
2288
2289 RETURN_EGL_EVAL(disp, ret);
2290 }
2291
2292 static EGLBoolean EGLAPIENTRY
2293 eglGetSyncValuesCHROMIUM(EGLDisplay display, EGLSurface surface,
2294 EGLuint64KHR *ust, EGLuint64KHR *msc,
2295 EGLuint64KHR *sbc)
2296 {
2297 _EGLDisplay *disp = _eglLockDisplay(display);
2298 _EGLSurface *surf = _eglLookupSurface(surface, disp);
2299 _EGLDriver *drv;
2300 EGLBoolean ret;
2301
2302 _EGL_FUNC_START(disp, EGL_OBJECT_SURFACE_KHR, surf, EGL_FALSE);
2303
2304 _EGL_CHECK_SURFACE(disp, surf, EGL_FALSE, drv);
2305 if (!disp->Extensions.CHROMIUM_sync_control)
2306 RETURN_EGL_EVAL(disp, EGL_FALSE);
2307
2308 if (!ust || !msc || !sbc)
2309 RETURN_EGL_ERROR(disp, EGL_BAD_PARAMETER, EGL_FALSE);
2310
2311 ret = drv->API.GetSyncValuesCHROMIUM(disp, surf, ust, msc, sbc);
2312
2313 RETURN_EGL_EVAL(disp, ret);
2314 }
2315
2316 static EGLBoolean EGLAPIENTRY
2317 eglExportDMABUFImageQueryMESA(EGLDisplay dpy, EGLImage image,
2318 EGLint *fourcc, EGLint *nplanes,
2319 EGLuint64KHR *modifiers)
2320 {
2321 _EGLDisplay *disp = _eglLockDisplay(dpy);
2322 _EGLImage *img = _eglLookupImage(image, disp);
2323 _EGLDriver *drv;
2324 EGLBoolean ret;
2325
2326 _EGL_FUNC_START(disp, EGL_OBJECT_IMAGE_KHR, img, EGL_FALSE);
2327
2328 _EGL_CHECK_DISPLAY(disp, EGL_FALSE, drv);
2329 assert(disp->Extensions.MESA_image_dma_buf_export);
2330
2331 if (!img)
2332 RETURN_EGL_ERROR(disp, EGL_BAD_PARAMETER, EGL_FALSE);
2333
2334 ret = drv->API.ExportDMABUFImageQueryMESA(drv, disp, img, fourcc, nplanes,
2335 modifiers);
2336
2337 RETURN_EGL_EVAL(disp, ret);
2338 }
2339
2340 static EGLBoolean EGLAPIENTRY
2341 eglExportDMABUFImageMESA(EGLDisplay dpy, EGLImage image,
2342 int *fds, EGLint *strides, EGLint *offsets)
2343 {
2344 _EGLDisplay *disp = _eglLockDisplay(dpy);
2345 _EGLImage *img = _eglLookupImage(image, disp);
2346 _EGLDriver *drv;
2347 EGLBoolean ret;
2348
2349 _EGL_FUNC_START(disp, EGL_OBJECT_IMAGE_KHR, img, EGL_FALSE);
2350
2351 _EGL_CHECK_DISPLAY(disp, EGL_FALSE, drv);
2352 assert(disp->Extensions.MESA_image_dma_buf_export);
2353
2354 if (!img)
2355 RETURN_EGL_ERROR(disp, EGL_BAD_PARAMETER, EGL_FALSE);
2356
2357 ret = drv->API.ExportDMABUFImageMESA(drv, disp, img, fds, strides, offsets);
2358
2359 RETURN_EGL_EVAL(disp, ret);
2360 }
2361
2362 static EGLint EGLAPIENTRY
2363 eglLabelObjectKHR(EGLDisplay dpy, EGLenum objectType, EGLObjectKHR object,
2364 EGLLabelKHR label)
2365 {
2366 _EGLDisplay *disp = NULL;
2367 _EGLResourceType type;
2368
2369 _EGL_FUNC_START(NULL, EGL_NONE, NULL, EGL_BAD_ALLOC);
2370
2371 if (objectType == EGL_OBJECT_THREAD_KHR) {
2372 _EGLThreadInfo *t = _eglGetCurrentThread();
2373
2374 if (!_eglIsCurrentThreadDummy()) {
2375 t->Label = label;
2376 return EGL_SUCCESS;
2377 }
2378
2379 RETURN_EGL_ERROR(NULL, EGL_BAD_ALLOC, EGL_BAD_ALLOC);
2380 }
2381
2382 disp = _eglLockDisplay(dpy);
2383 if (disp == NULL)
2384 RETURN_EGL_ERROR(disp, EGL_BAD_DISPLAY, EGL_BAD_DISPLAY);
2385
2386 if (objectType == EGL_OBJECT_DISPLAY_KHR) {
2387 if (dpy != (EGLDisplay) object)
2388 RETURN_EGL_ERROR(disp, EGL_BAD_PARAMETER, EGL_BAD_PARAMETER);
2389
2390 disp->Label = label;
2391 RETURN_EGL_EVAL(disp, EGL_SUCCESS);
2392 }
2393
2394 switch (objectType) {
2395 case EGL_OBJECT_CONTEXT_KHR:
2396 type = _EGL_RESOURCE_CONTEXT;
2397 break;
2398 case EGL_OBJECT_SURFACE_KHR:
2399 type = _EGL_RESOURCE_SURFACE;
2400 break;
2401 case EGL_OBJECT_IMAGE_KHR:
2402 type = _EGL_RESOURCE_IMAGE;
2403 break;
2404 case EGL_OBJECT_SYNC_KHR:
2405 type = _EGL_RESOURCE_SYNC;
2406 break;
2407 case EGL_OBJECT_STREAM_KHR:
2408 default:
2409 RETURN_EGL_ERROR(disp, EGL_BAD_PARAMETER, EGL_BAD_PARAMETER);
2410 }
2411
2412 if (_eglCheckResource(object, type, disp)) {
2413 _EGLResource *res = (_EGLResource *) object;
2414
2415 res->Label = label;
2416 RETURN_EGL_EVAL(disp, EGL_SUCCESS);
2417 }
2418
2419 RETURN_EGL_ERROR(disp, EGL_BAD_PARAMETER, EGL_BAD_PARAMETER);
2420 }
2421
2422 static EGLint EGLAPIENTRY
2423 eglDebugMessageControlKHR(EGLDEBUGPROCKHR callback,
2424 const EGLAttrib *attrib_list)
2425 {
2426 unsigned int newEnabled;
2427
2428 _EGL_FUNC_START(NULL, EGL_NONE, NULL, EGL_BAD_ALLOC);
2429
2430 mtx_lock(_eglGlobal.Mutex);
2431
2432 newEnabled = _eglGlobal.debugTypesEnabled;
2433 if (attrib_list != NULL) {
2434 int i;
2435
2436 for (i = 0; attrib_list[i] != EGL_NONE; i += 2) {
2437 switch (attrib_list[i]) {
2438 case EGL_DEBUG_MSG_CRITICAL_KHR:
2439 case EGL_DEBUG_MSG_ERROR_KHR:
2440 case EGL_DEBUG_MSG_WARN_KHR:
2441 case EGL_DEBUG_MSG_INFO_KHR:
2442 if (attrib_list[i + 1])
2443 newEnabled |= DebugBitFromType(attrib_list[i]);
2444 else
2445 newEnabled &= ~DebugBitFromType(attrib_list[i]);
2446 break;
2447 default:
2448 // On error, set the last error code, call the current
2449 // debug callback, and return the error code.
2450 mtx_unlock(_eglGlobal.Mutex);
2451 _eglReportError(EGL_BAD_ATTRIBUTE, NULL,
2452 "Invalid attribute 0x%04lx", (unsigned long) attrib_list[i]);
2453 return EGL_BAD_ATTRIBUTE;
2454 }
2455 }
2456 }
2457
2458 if (callback != NULL) {
2459 _eglGlobal.debugCallback = callback;
2460 _eglGlobal.debugTypesEnabled = newEnabled;
2461 } else {
2462 _eglGlobal.debugCallback = NULL;
2463 _eglGlobal.debugTypesEnabled = _EGL_DEBUG_BIT_CRITICAL | _EGL_DEBUG_BIT_ERROR;
2464 }
2465
2466 mtx_unlock(_eglGlobal.Mutex);
2467 return EGL_SUCCESS;
2468 }
2469
2470 static EGLBoolean EGLAPIENTRY
2471 eglQueryDebugKHR(EGLint attribute, EGLAttrib *value)
2472 {
2473 _EGL_FUNC_START(NULL, EGL_NONE, NULL, EGL_BAD_ALLOC);
2474
2475 mtx_lock(_eglGlobal.Mutex);
2476
2477 switch (attribute) {
2478 case EGL_DEBUG_MSG_CRITICAL_KHR:
2479 case EGL_DEBUG_MSG_ERROR_KHR:
2480 case EGL_DEBUG_MSG_WARN_KHR:
2481 case EGL_DEBUG_MSG_INFO_KHR:
2482 if (_eglGlobal.debugTypesEnabled & DebugBitFromType(attribute))
2483 *value = EGL_TRUE;
2484 else
2485 *value = EGL_FALSE;
2486 break;
2487 case EGL_DEBUG_CALLBACK_KHR:
2488 *value = (EGLAttrib) _eglGlobal.debugCallback;
2489 break;
2490 default:
2491 mtx_unlock(_eglGlobal.Mutex);
2492 _eglReportError(EGL_BAD_ATTRIBUTE, NULL,
2493 "Invalid attribute 0x%04lx", (unsigned long) attribute);
2494 return EGL_FALSE;
2495 }
2496
2497 mtx_unlock(_eglGlobal.Mutex);
2498 return EGL_TRUE;
2499 }
2500
2501 static int
2502 _eglFunctionCompare(const void *key, const void *elem)
2503 {
2504 const char *procname = key;
2505 const struct _egl_entrypoint *entrypoint = elem;
2506 return strcmp(procname, entrypoint->name);
2507 }
2508
2509 static EGLBoolean EGLAPIENTRY
2510 eglQueryDmaBufFormatsEXT(EGLDisplay dpy, EGLint max_formats,
2511 EGLint *formats, EGLint *num_formats)
2512 {
2513 _EGLDisplay *disp = _eglLockDisplay(dpy);
2514 _EGLDriver *drv;
2515 EGLBoolean ret;
2516
2517 _EGL_FUNC_START(NULL, EGL_NONE, NULL, EGL_FALSE);
2518
2519 _EGL_CHECK_DISPLAY(disp, EGL_FALSE, drv);
2520
2521 ret = drv->API.QueryDmaBufFormatsEXT(drv, disp, max_formats, formats,
2522 num_formats);
2523
2524 RETURN_EGL_EVAL(disp, ret);
2525 }
2526
2527 static EGLBoolean EGLAPIENTRY
2528 eglQueryDmaBufModifiersEXT(EGLDisplay dpy, EGLint format, EGLint max_modifiers,
2529 EGLuint64KHR *modifiers, EGLBoolean *external_only,
2530 EGLint *num_modifiers)
2531 {
2532 _EGLDisplay *disp = _eglLockDisplay(dpy);
2533 _EGLDriver *drv;
2534 EGLBoolean ret;
2535
2536 _EGL_FUNC_START(NULL, EGL_NONE, NULL, EGL_FALSE);
2537
2538 _EGL_CHECK_DISPLAY(disp, EGL_FALSE, drv);
2539
2540 ret = drv->API.QueryDmaBufModifiersEXT(drv, disp, format, max_modifiers,
2541 modifiers, external_only,
2542 num_modifiers);
2543
2544 RETURN_EGL_EVAL(disp, ret);
2545 }
2546
2547 static void EGLAPIENTRY
2548 eglSetBlobCacheFuncsANDROID(EGLDisplay *dpy, EGLSetBlobFuncANDROID set,
2549 EGLGetBlobFuncANDROID get)
2550 {
2551 /* This function does not return anything so we cannot
2552 * utilize the helper macros _EGL_FUNC_START or _EGL_CHECK_DISPLAY.
2553 */
2554 _EGLDisplay *disp = _eglLockDisplay(dpy);
2555 if (!_eglSetFuncName(__func__, disp, EGL_OBJECT_DISPLAY_KHR, NULL)) {
2556 if (disp)
2557 _eglUnlockDisplay(disp);
2558 return;
2559 }
2560
2561 _EGLDriver *drv = _eglCheckDisplay(disp, __func__);
2562 if (!drv) {
2563 if (disp)
2564 _eglUnlockDisplay(disp);
2565 return;
2566 }
2567
2568 if (!set || !get) {
2569 _eglError(EGL_BAD_PARAMETER,
2570 "eglSetBlobCacheFuncsANDROID: NULL handler given");
2571 _eglUnlockDisplay(disp);
2572 return;
2573 }
2574
2575 if (disp->BlobCacheSet) {
2576 _eglError(EGL_BAD_PARAMETER,
2577 "eglSetBlobCacheFuncsANDROID: functions already set");
2578 _eglUnlockDisplay(disp);
2579 return;
2580 }
2581
2582 disp->BlobCacheSet = set;
2583 disp->BlobCacheGet = get;
2584
2585 drv->API.SetBlobCacheFuncsANDROID(drv, disp, set, get);
2586
2587 _eglUnlockDisplay(disp);
2588 }
2589
2590 static EGLBoolean EGLAPIENTRY
2591 eglQueryDeviceAttribEXT(EGLDeviceEXT device,
2592 EGLint attribute,
2593 EGLAttrib *value)
2594 {
2595 _EGLDevice *dev = _eglLookupDevice(device);
2596 EGLBoolean ret;
2597
2598 _EGL_FUNC_START(NULL, EGL_NONE, NULL, EGL_FALSE);
2599 if (!dev)
2600 RETURN_EGL_ERROR(NULL, EGL_BAD_DEVICE_EXT, EGL_FALSE);
2601
2602 ret = _eglQueryDeviceAttribEXT(dev, attribute, value);
2603 RETURN_EGL_EVAL(NULL, ret);
2604 }
2605
2606 static const char * EGLAPIENTRY
2607 eglQueryDeviceStringEXT(EGLDeviceEXT device,
2608 EGLint name)
2609 {
2610 _EGLDevice *dev = _eglLookupDevice(device);
2611
2612 _EGL_FUNC_START(NULL, EGL_NONE, NULL, NULL);
2613 if (!dev)
2614 RETURN_EGL_ERROR(NULL, EGL_BAD_DEVICE_EXT, NULL);
2615
2616 RETURN_EGL_EVAL(NULL, _eglQueryDeviceStringEXT(dev, name));
2617 }
2618
2619 static EGLBoolean EGLAPIENTRY
2620 eglQueryDevicesEXT(EGLint max_devices,
2621 EGLDeviceEXT *devices,
2622 EGLint *num_devices)
2623 {
2624 EGLBoolean ret;
2625
2626 _EGL_FUNC_START(NULL, EGL_NONE, NULL, EGL_FALSE);
2627 ret = _eglQueryDevicesEXT(max_devices, (_EGLDevice **) devices,
2628 num_devices);
2629 RETURN_EGL_EVAL(NULL, ret);
2630 }
2631
2632 static EGLBoolean EGLAPIENTRY
2633 eglQueryDisplayAttribEXT(EGLDisplay dpy,
2634 EGLint attribute,
2635 EGLAttrib *value)
2636 {
2637 _EGLDisplay *disp = _eglLockDisplay(dpy);
2638 _EGLDriver *drv;
2639
2640 _EGL_FUNC_START(NULL, EGL_NONE, NULL, EGL_FALSE);
2641 _EGL_CHECK_DISPLAY(disp, EGL_FALSE, drv);
2642
2643 switch (attribute) {
2644 case EGL_DEVICE_EXT:
2645 *value = (EGLAttrib) disp->Device;
2646 break;
2647 default:
2648 RETURN_EGL_ERROR(disp, EGL_BAD_ATTRIBUTE, EGL_FALSE);
2649 }
2650 RETURN_EGL_SUCCESS(disp, EGL_TRUE);
2651 }
2652
2653 char * EGLAPIENTRY
2654 eglGetDisplayDriverConfig(EGLDisplay dpy)
2655 {
2656 _EGLDisplay *disp = _eglLockDisplay(dpy);
2657 _EGLDriver *drv;
2658 char *ret;
2659
2660 _EGL_FUNC_START(disp, EGL_NONE, NULL, NULL);
2661 _EGL_CHECK_DISPLAY(disp, NULL, drv);
2662
2663 assert(disp->Extensions.MESA_query_driver);
2664
2665 ret = drv->API.QueryDriverConfig(disp);
2666 RETURN_EGL_EVAL(disp, ret);
2667 }
2668
2669 const char * EGLAPIENTRY
2670 eglGetDisplayDriverName(EGLDisplay dpy)
2671 {
2672 _EGLDisplay *disp = _eglLockDisplay(dpy);
2673 _EGLDriver *drv;
2674 const char *ret;
2675
2676 _EGL_FUNC_START(disp, EGL_NONE, NULL, NULL);
2677 _EGL_CHECK_DISPLAY(disp, NULL, drv);
2678
2679 assert(disp->Extensions.MESA_query_driver);
2680
2681 ret = drv->API.QueryDriverName(disp);
2682 RETURN_EGL_EVAL(disp, ret);
2683 }
2684
2685 __eglMustCastToProperFunctionPointerType EGLAPIENTRY
2686 eglGetProcAddress(const char *procname)
2687 {
2688 static const struct _egl_entrypoint egl_functions[] = {
2689 #define EGL_ENTRYPOINT(f) { .name = #f, .function = (_EGLProc) f },
2690 #include "eglentrypoint.h"
2691 #undef EGL_ENTRYPOINT
2692 };
2693 _EGLProc ret = NULL;
2694
2695 if (!procname)
2696 RETURN_EGL_SUCCESS(NULL, NULL);
2697
2698 _EGL_FUNC_START(NULL, EGL_NONE, NULL, NULL);
2699
2700 if (strncmp(procname, "egl", 3) == 0) {
2701 const struct _egl_entrypoint *entrypoint =
2702 bsearch(procname,
2703 egl_functions, ARRAY_SIZE(egl_functions),
2704 sizeof(egl_functions[0]),
2705 _eglFunctionCompare);
2706 if (entrypoint)
2707 ret = entrypoint->function;
2708 }
2709
2710 if (!ret)
2711 ret = _eglGetDriverProc(procname);
2712
2713 RETURN_EGL_SUCCESS(NULL, ret);
2714 }
2715
2716 static int
2717 _eglLockDisplayInterop(EGLDisplay dpy, EGLContext context,
2718 _EGLDisplay **disp, _EGLDriver **drv,
2719 _EGLContext **ctx)
2720 {
2721
2722 *disp = _eglLockDisplay(dpy);
2723 if (!*disp || !(*disp)->Initialized || !(*disp)->Driver) {
2724 if (*disp)
2725 _eglUnlockDisplay(*disp);
2726 return MESA_GLINTEROP_INVALID_DISPLAY;
2727 }
2728
2729 *drv = (*disp)->Driver;
2730
2731 *ctx = _eglLookupContext(context, *disp);
2732 if (!*ctx ||
2733 ((*ctx)->ClientAPI != EGL_OPENGL_API &&
2734 (*ctx)->ClientAPI != EGL_OPENGL_ES_API)) {
2735 _eglUnlockDisplay(*disp);
2736 return MESA_GLINTEROP_INVALID_CONTEXT;
2737 }
2738
2739 return MESA_GLINTEROP_SUCCESS;
2740 }
2741
2742 PUBLIC int
2743 MesaGLInteropEGLQueryDeviceInfo(EGLDisplay dpy, EGLContext context,
2744 struct mesa_glinterop_device_info *out)
2745 {
2746 _EGLDisplay *disp;
2747 _EGLDriver *drv;
2748 _EGLContext *ctx;
2749 int ret;
2750
2751 ret = _eglLockDisplayInterop(dpy, context, &disp, &drv, &ctx);
2752 if (ret != MESA_GLINTEROP_SUCCESS)
2753 return ret;
2754
2755 if (drv->API.GLInteropQueryDeviceInfo)
2756 ret = drv->API.GLInteropQueryDeviceInfo(disp, ctx, out);
2757 else
2758 ret = MESA_GLINTEROP_UNSUPPORTED;
2759
2760 _eglUnlockDisplay(disp);
2761 return ret;
2762 }
2763
2764 PUBLIC int
2765 MesaGLInteropEGLExportObject(EGLDisplay dpy, EGLContext context,
2766 struct mesa_glinterop_export_in *in,
2767 struct mesa_glinterop_export_out *out)
2768 {
2769 _EGLDisplay *disp;
2770 _EGLDriver *drv;
2771 _EGLContext *ctx;
2772 int ret;
2773
2774 ret = _eglLockDisplayInterop(dpy, context, &disp, &drv, &ctx);
2775 if (ret != MESA_GLINTEROP_SUCCESS)
2776 return ret;
2777
2778 if (drv->API.GLInteropExportObject)
2779 ret = drv->API.GLInteropExportObject(disp, ctx, in, out);
2780 else
2781 ret = MESA_GLINTEROP_UNSUPPORTED;
2782
2783 _eglUnlockDisplay(disp);
2784 return ret;
2785 }