vk/vulkan.h: Switch BindObjectMemory to a device function and remove the index
[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 "eglcompiler.h"
92
93 #include "eglglobals.h"
94 #include "eglcontext.h"
95 #include "egldisplay.h"
96 #include "egltypedefs.h"
97 #include "eglcurrent.h"
98 #include "egldriver.h"
99 #include "eglsurface.h"
100 #include "eglconfig.h"
101 #include "eglimage.h"
102 #include "eglsync.h"
103 #include "eglstring.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 static inline _EGLDriver *
161 _eglCheckDisplay(_EGLDisplay *disp, const char *msg)
162 {
163 if (!disp) {
164 _eglError(EGL_BAD_DISPLAY, msg);
165 return NULL;
166 }
167 if (!disp->Initialized) {
168 _eglError(EGL_NOT_INITIALIZED, msg);
169 return NULL;
170 }
171 return disp->Driver;
172 }
173
174
175 static inline _EGLDriver *
176 _eglCheckSurface(_EGLDisplay *disp, _EGLSurface *surf, const char *msg)
177 {
178 _EGLDriver *drv = _eglCheckDisplay(disp, msg);
179 if (!drv)
180 return NULL;
181 if (!surf) {
182 _eglError(EGL_BAD_SURFACE, msg);
183 return NULL;
184 }
185 return drv;
186 }
187
188
189 static inline _EGLDriver *
190 _eglCheckContext(_EGLDisplay *disp, _EGLContext *context, const char *msg)
191 {
192 _EGLDriver *drv = _eglCheckDisplay(disp, msg);
193 if (!drv)
194 return NULL;
195 if (!context) {
196 _eglError(EGL_BAD_CONTEXT, msg);
197 return NULL;
198 }
199 return drv;
200 }
201
202
203 static inline _EGLDriver *
204 _eglCheckConfig(_EGLDisplay *disp, _EGLConfig *conf, const char *msg)
205 {
206 _EGLDriver *drv = _eglCheckDisplay(disp, msg);
207 if (!drv)
208 return NULL;
209 if (!conf) {
210 _eglError(EGL_BAD_CONFIG, msg);
211 return NULL;
212 }
213 return drv;
214 }
215
216
217 static inline _EGLDriver *
218 _eglCheckSync(_EGLDisplay *disp, _EGLSync *s, const char *msg)
219 {
220 _EGLDriver *drv = _eglCheckDisplay(disp, msg);
221 if (!drv)
222 return NULL;
223 if (!s) {
224 _eglError(EGL_BAD_PARAMETER, msg);
225 return NULL;
226 }
227 return drv;
228 }
229
230
231 /**
232 * Lookup and lock a display.
233 */
234 static inline _EGLDisplay *
235 _eglLockDisplay(EGLDisplay display)
236 {
237 _EGLDisplay *dpy = _eglLookupDisplay(display);
238 if (dpy)
239 mtx_lock(&dpy->Mutex);
240 return dpy;
241 }
242
243
244 /**
245 * Unlock a display.
246 */
247 static inline void
248 _eglUnlockDisplay(_EGLDisplay *dpy)
249 {
250 mtx_unlock(&dpy->Mutex);
251 }
252
253
254 static EGLint *
255 _eglConvertAttribsToInt(const EGLAttrib *attr_list)
256 {
257 EGLint *int_attribs = NULL;
258
259 /* Convert attributes from EGLAttrib[] to EGLint[] */
260 if (attr_list) {
261 int i, size = 0;
262
263 while (attr_list[size] != EGL_NONE)
264 size += 2;
265
266 size += 1; /* add space for EGL_NONE */
267
268 int_attribs = calloc(size, sizeof(int_attribs[0]));
269 if (!int_attribs)
270 return NULL;
271
272 for (i = 0; i < size; i++)
273 int_attribs[i] = attr_list[i];
274 }
275 return int_attribs;
276 }
277
278
279 /**
280 * This is typically the first EGL function that an application calls.
281 * It associates a private _EGLDisplay object to the native display.
282 */
283 EGLDisplay EGLAPIENTRY
284 eglGetDisplay(EGLNativeDisplayType nativeDisplay)
285 {
286 _EGLPlatformType plat;
287 _EGLDisplay *dpy;
288 void *native_display_ptr;
289
290 STATIC_ASSERT(sizeof(void*) == sizeof(nativeDisplay));
291 native_display_ptr = (void*) nativeDisplay;
292
293 plat = _eglGetNativePlatform(native_display_ptr);
294 dpy = _eglFindDisplay(plat, native_display_ptr);
295 return _eglGetDisplayHandle(dpy);
296 }
297
298 static EGLDisplay EGLAPIENTRY
299 eglGetPlatformDisplayEXT(EGLenum platform, void *native_display,
300 const EGLint *attrib_list)
301 {
302 _EGLDisplay *dpy;
303
304 switch (platform) {
305 #ifdef HAVE_X11_PLATFORM
306 case EGL_PLATFORM_X11_EXT:
307 dpy = _eglGetX11Display((Display*) native_display, attrib_list);
308 break;
309 #endif
310 #ifdef HAVE_DRM_PLATFORM
311 case EGL_PLATFORM_GBM_MESA:
312 dpy = _eglGetGbmDisplay((struct gbm_device*) native_display,
313 attrib_list);
314 break;
315 #endif
316 #ifdef HAVE_WAYLAND_PLATFORM
317 case EGL_PLATFORM_WAYLAND_EXT:
318 dpy = _eglGetWaylandDisplay((struct wl_display*) native_display,
319 attrib_list);
320 break;
321 #endif
322 default:
323 RETURN_EGL_ERROR(NULL, EGL_BAD_PARAMETER, NULL);
324 }
325
326 return _eglGetDisplayHandle(dpy);
327 }
328
329 EGLDisplay EGLAPIENTRY
330 eglGetPlatformDisplay(EGLenum platform, void *native_display,
331 const EGLAttrib *attrib_list)
332 {
333 EGLDisplay display;
334 EGLint *int_attribs = _eglConvertAttribsToInt(attrib_list);
335
336 if (attrib_list && !int_attribs)
337 RETURN_EGL_ERROR(NULL, EGL_BAD_ALLOC, NULL);
338
339 display = eglGetPlatformDisplayEXT(platform, native_display, int_attribs);
340 free(int_attribs);
341 return display;
342 }
343
344 /**
345 * Copy the extension into the string and update the string pointer.
346 */
347 static EGLint
348 _eglAppendExtension(char **str, const char *ext)
349 {
350 char *s = *str;
351 size_t len = strlen(ext);
352
353 if (s) {
354 memcpy(s, ext, len);
355 s[len++] = ' ';
356 s[len] = '\0';
357
358 *str += len;
359 }
360 else {
361 len++;
362 }
363
364 return (EGLint) len;
365 }
366
367 /**
368 * Examine the individual extension enable/disable flags and recompute
369 * the driver's Extensions string.
370 */
371 static void
372 _eglCreateExtensionsString(_EGLDisplay *dpy)
373 {
374 #define _EGL_CHECK_EXTENSION(ext) \
375 do { \
376 if (dpy->Extensions.ext) { \
377 _eglAppendExtension(&exts, "EGL_" #ext); \
378 assert(exts <= dpy->ExtensionsString + _EGL_MAX_EXTENSIONS_LEN); \
379 } \
380 } while (0)
381
382 char *exts = dpy->ExtensionsString;
383
384 _EGL_CHECK_EXTENSION(MESA_drm_display);
385 _EGL_CHECK_EXTENSION(MESA_drm_image);
386 _EGL_CHECK_EXTENSION(MESA_configless_context);
387
388 _EGL_CHECK_EXTENSION(WL_bind_wayland_display);
389 _EGL_CHECK_EXTENSION(WL_create_wayland_buffer_from_image);
390
391 _EGL_CHECK_EXTENSION(KHR_image_base);
392 _EGL_CHECK_EXTENSION(KHR_image_pixmap);
393 if (dpy->Extensions.KHR_image_base && dpy->Extensions.KHR_image_pixmap)
394 _eglAppendExtension(&exts, "EGL_KHR_image");
395
396 _EGL_CHECK_EXTENSION(KHR_vg_parent_image);
397 _EGL_CHECK_EXTENSION(KHR_get_all_proc_addresses);
398 _EGL_CHECK_EXTENSION(KHR_gl_texture_2D_image);
399 _EGL_CHECK_EXTENSION(KHR_gl_texture_cubemap_image);
400 _EGL_CHECK_EXTENSION(KHR_gl_texture_3D_image);
401 _EGL_CHECK_EXTENSION(KHR_gl_renderbuffer_image);
402
403 _EGL_CHECK_EXTENSION(KHR_reusable_sync);
404 _EGL_CHECK_EXTENSION(KHR_fence_sync);
405 _EGL_CHECK_EXTENSION(KHR_wait_sync);
406 _EGL_CHECK_EXTENSION(KHR_cl_event2);
407
408 _EGL_CHECK_EXTENSION(KHR_surfaceless_context);
409 _EGL_CHECK_EXTENSION(KHR_create_context);
410
411 _EGL_CHECK_EXTENSION(NOK_swap_region);
412 _EGL_CHECK_EXTENSION(NOK_texture_from_pixmap);
413
414 _EGL_CHECK_EXTENSION(ANDROID_image_native_buffer);
415
416 _EGL_CHECK_EXTENSION(CHROMIUM_sync_control);
417
418 _EGL_CHECK_EXTENSION(EXT_create_context_robustness);
419 _EGL_CHECK_EXTENSION(EXT_buffer_age);
420 _EGL_CHECK_EXTENSION(EXT_swap_buffers_with_damage);
421 _EGL_CHECK_EXTENSION(EXT_image_dma_buf_import);
422
423 _EGL_CHECK_EXTENSION(NV_post_sub_buffer);
424
425 _EGL_CHECK_EXTENSION(MESA_image_dma_buf_export);
426 #undef _EGL_CHECK_EXTENSION
427 }
428
429 static void
430 _eglCreateAPIsString(_EGLDisplay *dpy)
431 {
432 if (dpy->ClientAPIs & EGL_OPENGL_BIT)
433 strcat(dpy->ClientAPIsString, "OpenGL ");
434
435 if (dpy->ClientAPIs & EGL_OPENGL_ES_BIT)
436 strcat(dpy->ClientAPIsString, "OpenGL_ES ");
437
438 if (dpy->ClientAPIs & EGL_OPENGL_ES2_BIT)
439 strcat(dpy->ClientAPIsString, "OpenGL_ES2 ");
440
441 if (dpy->ClientAPIs & EGL_OPENGL_ES3_BIT_KHR)
442 strcat(dpy->ClientAPIsString, "OpenGL_ES3 ");
443
444 if (dpy->ClientAPIs & EGL_OPENVG_BIT)
445 strcat(dpy->ClientAPIsString, "OpenVG ");
446
447 assert(strlen(dpy->ClientAPIsString) < sizeof(dpy->ClientAPIsString));
448 }
449
450 static void
451 _eglComputeVersion(_EGLDisplay *disp)
452 {
453 disp->Version = 14;
454
455 if (disp->Extensions.KHR_fence_sync &&
456 disp->Extensions.KHR_cl_event2 &&
457 disp->Extensions.KHR_wait_sync &&
458 disp->Extensions.KHR_image_base &&
459 disp->Extensions.KHR_gl_texture_2D_image &&
460 disp->Extensions.KHR_gl_texture_3D_image &&
461 disp->Extensions.KHR_gl_texture_cubemap_image &&
462 disp->Extensions.KHR_gl_renderbuffer_image &&
463 disp->Extensions.KHR_create_context &&
464 disp->Extensions.EXT_create_context_robustness &&
465 disp->Extensions.KHR_get_all_proc_addresses &&
466 disp->Extensions.KHR_gl_colorspace &&
467 disp->Extensions.KHR_surfaceless_context)
468 disp->Version = 15;
469 }
470
471 /**
472 * This is typically the second EGL function that an application calls.
473 * Here we load/initialize the actual hardware driver.
474 */
475 EGLBoolean EGLAPIENTRY
476 eglInitialize(EGLDisplay dpy, EGLint *major, EGLint *minor)
477 {
478 _EGLDisplay *disp = _eglLockDisplay(dpy);
479
480 if (!disp)
481 RETURN_EGL_ERROR(NULL, EGL_BAD_DISPLAY, EGL_FALSE);
482
483 if (!disp->Initialized) {
484 if (!_eglMatchDriver(disp, EGL_FALSE))
485 RETURN_EGL_ERROR(disp, EGL_NOT_INITIALIZED, EGL_FALSE);
486
487 /* limit to APIs supported by core */
488 disp->ClientAPIs &= _EGL_API_ALL_BITS;
489
490 /* EGL_KHR_get_all_proc_addresses is a corner-case extension. The spec
491 * classifies it as an EGL display extension, though conceptually it's an
492 * EGL client extension.
493 *
494 * From the EGL_KHR_get_all_proc_addresses spec:
495 *
496 * The EGL implementation must expose the name
497 * EGL_KHR_client_get_all_proc_addresses if and only if it exposes
498 * EGL_KHR_get_all_proc_addresses and supports
499 * EGL_EXT_client_extensions.
500 *
501 * Mesa unconditionally exposes both client extensions mentioned above,
502 * so the spec requires that each EGLDisplay unconditionally expose
503 * EGL_KHR_get_all_proc_addresses also.
504 */
505 disp->Extensions.KHR_get_all_proc_addresses = EGL_TRUE;
506
507 _eglComputeVersion(disp);
508 _eglCreateExtensionsString(disp);
509 _eglCreateAPIsString(disp);
510 _eglsnprintf(disp->VersionString, sizeof(disp->VersionString),
511 "%d.%d (%s)", disp->Version / 10, disp->Version % 10,
512 disp->Driver->Name);
513 }
514
515 /* Update applications version of major and minor if not NULL */
516 if ((major != NULL) && (minor != NULL)) {
517 *major = disp->Version / 10;
518 *minor = disp->Version % 10;
519 }
520
521 RETURN_EGL_SUCCESS(disp, EGL_TRUE);
522 }
523
524
525 EGLBoolean EGLAPIENTRY
526 eglTerminate(EGLDisplay dpy)
527 {
528 _EGLDisplay *disp = _eglLockDisplay(dpy);
529
530 if (!disp)
531 RETURN_EGL_ERROR(NULL, EGL_BAD_DISPLAY, EGL_FALSE);
532
533 if (disp->Initialized) {
534 _EGLDriver *drv = disp->Driver;
535
536 drv->API.Terminate(drv, disp);
537 /* do not reset disp->Driver */
538 disp->ClientAPIsString[0] = 0;
539 disp->Initialized = EGL_FALSE;
540 }
541
542 RETURN_EGL_SUCCESS(disp, EGL_TRUE);
543 }
544
545
546 const char * EGLAPIENTRY
547 eglQueryString(EGLDisplay dpy, EGLint name)
548 {
549 _EGLDisplay *disp;
550 _EGLDriver *drv;
551
552 if (dpy == EGL_NO_DISPLAY && name == EGL_EXTENSIONS) {
553 RETURN_EGL_SUCCESS(NULL, _eglGlobal.ClientExtensionString);
554 }
555
556 disp = _eglLockDisplay(dpy);
557 _EGL_CHECK_DISPLAY(disp, NULL, drv);
558
559 switch (name) {
560 case EGL_VENDOR:
561 RETURN_EGL_SUCCESS(disp, _EGL_VENDOR_STRING);
562 case EGL_VERSION:
563 RETURN_EGL_SUCCESS(disp, disp->VersionString);
564 case EGL_EXTENSIONS:
565 RETURN_EGL_SUCCESS(disp, disp->ExtensionsString);
566 case EGL_CLIENT_APIS:
567 RETURN_EGL_SUCCESS(disp, disp->ClientAPIsString);
568 default:
569 RETURN_EGL_ERROR(disp, EGL_BAD_PARAMETER, NULL);
570 }
571 }
572
573
574 EGLBoolean EGLAPIENTRY
575 eglGetConfigs(EGLDisplay dpy, EGLConfig *configs,
576 EGLint config_size, EGLint *num_config)
577 {
578 _EGLDisplay *disp = _eglLockDisplay(dpy);
579 _EGLDriver *drv;
580 EGLBoolean ret;
581
582 _EGL_CHECK_DISPLAY(disp, EGL_FALSE, drv);
583 ret = drv->API.GetConfigs(drv, disp, configs, config_size, num_config);
584
585 RETURN_EGL_EVAL(disp, ret);
586 }
587
588
589 EGLBoolean EGLAPIENTRY
590 eglChooseConfig(EGLDisplay dpy, const EGLint *attrib_list, EGLConfig *configs,
591 EGLint config_size, EGLint *num_config)
592 {
593 _EGLDisplay *disp = _eglLockDisplay(dpy);
594 _EGLDriver *drv;
595 EGLBoolean ret;
596
597 _EGL_CHECK_DISPLAY(disp, EGL_FALSE, drv);
598 ret = drv->API.ChooseConfig(drv, disp, attrib_list, configs,
599 config_size, num_config);
600
601 RETURN_EGL_EVAL(disp, ret);
602 }
603
604
605 EGLBoolean EGLAPIENTRY
606 eglGetConfigAttrib(EGLDisplay dpy, EGLConfig config,
607 EGLint attribute, EGLint *value)
608 {
609 _EGLDisplay *disp = _eglLockDisplay(dpy);
610 _EGLConfig *conf = _eglLookupConfig(config, disp);
611 _EGLDriver *drv;
612 EGLBoolean ret;
613
614 _EGL_CHECK_CONFIG(disp, conf, EGL_FALSE, drv);
615 ret = drv->API.GetConfigAttrib(drv, disp, conf, attribute, value);
616
617 RETURN_EGL_EVAL(disp, ret);
618 }
619
620
621 EGLContext EGLAPIENTRY
622 eglCreateContext(EGLDisplay dpy, EGLConfig config, EGLContext share_list,
623 const EGLint *attrib_list)
624 {
625 _EGLDisplay *disp = _eglLockDisplay(dpy);
626 _EGLConfig *conf = _eglLookupConfig(config, disp);
627 _EGLContext *share = _eglLookupContext(share_list, disp);
628 _EGLDriver *drv;
629 _EGLContext *context;
630 EGLContext ret;
631
632 _EGL_CHECK_DISPLAY(disp, EGL_NO_CONTEXT, drv);
633
634 if (!config && !disp->Extensions.MESA_configless_context)
635 RETURN_EGL_ERROR(disp, EGL_BAD_CONFIG, EGL_NO_CONTEXT);
636
637 if (!share && share_list != EGL_NO_CONTEXT)
638 RETURN_EGL_ERROR(disp, EGL_BAD_CONTEXT, EGL_NO_CONTEXT);
639
640 context = drv->API.CreateContext(drv, disp, conf, share, attrib_list);
641 ret = (context) ? _eglLinkContext(context) : EGL_NO_CONTEXT;
642
643 RETURN_EGL_EVAL(disp, ret);
644 }
645
646
647 EGLBoolean EGLAPIENTRY
648 eglDestroyContext(EGLDisplay dpy, EGLContext ctx)
649 {
650 _EGLDisplay *disp = _eglLockDisplay(dpy);
651 _EGLContext *context = _eglLookupContext(ctx, disp);
652 _EGLDriver *drv;
653 EGLBoolean ret;
654
655 _EGL_CHECK_CONTEXT(disp, context, EGL_FALSE, drv);
656 _eglUnlinkContext(context);
657 ret = drv->API.DestroyContext(drv, disp, context);
658
659 RETURN_EGL_EVAL(disp, ret);
660 }
661
662
663 EGLBoolean EGLAPIENTRY
664 eglMakeCurrent(EGLDisplay dpy, EGLSurface draw, EGLSurface read,
665 EGLContext ctx)
666 {
667 _EGLDisplay *disp = _eglLockDisplay(dpy);
668 _EGLContext *context = _eglLookupContext(ctx, disp);
669 _EGLSurface *draw_surf = _eglLookupSurface(draw, disp);
670 _EGLSurface *read_surf = _eglLookupSurface(read, disp);
671 _EGLDriver *drv;
672 EGLBoolean ret;
673
674 if (!disp)
675 RETURN_EGL_ERROR(disp, EGL_BAD_DISPLAY, EGL_FALSE);
676 drv = disp->Driver;
677
678 /* display is allowed to be uninitialized under certain condition */
679 if (!disp->Initialized) {
680 if (draw != EGL_NO_SURFACE || read != EGL_NO_SURFACE ||
681 ctx != EGL_NO_CONTEXT)
682 RETURN_EGL_ERROR(disp, EGL_BAD_DISPLAY, EGL_FALSE);
683 }
684 if (!drv)
685 RETURN_EGL_SUCCESS(disp, EGL_TRUE);
686
687 if (!context && ctx != EGL_NO_CONTEXT)
688 RETURN_EGL_ERROR(disp, EGL_BAD_CONTEXT, EGL_FALSE);
689 if (!draw_surf || !read_surf) {
690 /* From the EGL 1.4 (20130211) spec:
691 *
692 * To release the current context without assigning a new one, set ctx
693 * to EGL_NO_CONTEXT and set draw and read to EGL_NO_SURFACE.
694 */
695 if (!disp->Extensions.KHR_surfaceless_context && ctx != EGL_NO_CONTEXT)
696 RETURN_EGL_ERROR(disp, EGL_BAD_SURFACE, EGL_FALSE);
697
698 if ((!draw_surf && draw != EGL_NO_SURFACE) ||
699 (!read_surf && read != EGL_NO_SURFACE))
700 RETURN_EGL_ERROR(disp, EGL_BAD_SURFACE, EGL_FALSE);
701 if (draw_surf || read_surf)
702 RETURN_EGL_ERROR(disp, EGL_BAD_MATCH, EGL_FALSE);
703 }
704
705 ret = drv->API.MakeCurrent(drv, disp, draw_surf, read_surf, context);
706
707 RETURN_EGL_EVAL(disp, ret);
708 }
709
710
711 EGLBoolean EGLAPIENTRY
712 eglQueryContext(EGLDisplay dpy, EGLContext ctx,
713 EGLint attribute, EGLint *value)
714 {
715 _EGLDisplay *disp = _eglLockDisplay(dpy);
716 _EGLContext *context = _eglLookupContext(ctx, disp);
717 _EGLDriver *drv;
718 EGLBoolean ret;
719
720 _EGL_CHECK_CONTEXT(disp, context, EGL_FALSE, drv);
721 ret = drv->API.QueryContext(drv, disp, context, attribute, value);
722
723 RETURN_EGL_EVAL(disp, ret);
724 }
725
726
727 static EGLSurface
728 _eglCreateWindowSurfaceCommon(_EGLDisplay *disp, EGLConfig config,
729 void *native_window, const EGLint *attrib_list)
730 {
731 _EGLConfig *conf = _eglLookupConfig(config, disp);
732 _EGLDriver *drv;
733 _EGLSurface *surf;
734 EGLSurface ret;
735
736 _EGL_CHECK_CONFIG(disp, conf, EGL_NO_SURFACE, drv);
737
738 if (native_window == NULL)
739 RETURN_EGL_ERROR(disp, EGL_BAD_NATIVE_WINDOW, EGL_NO_SURFACE);
740
741 surf = drv->API.CreateWindowSurface(drv, disp, conf, native_window,
742 attrib_list);
743 ret = (surf) ? _eglLinkSurface(surf) : EGL_NO_SURFACE;
744
745 RETURN_EGL_EVAL(disp, ret);
746 }
747
748
749 EGLSurface EGLAPIENTRY
750 eglCreateWindowSurface(EGLDisplay dpy, EGLConfig config,
751 EGLNativeWindowType window, const EGLint *attrib_list)
752 {
753 _EGLDisplay *disp = _eglLockDisplay(dpy);
754 STATIC_ASSERT(sizeof(void*) == sizeof(window));
755 return _eglCreateWindowSurfaceCommon(disp, config, (void*) window,
756 attrib_list);
757 }
758
759
760 static EGLSurface EGLAPIENTRY
761 eglCreatePlatformWindowSurfaceEXT(EGLDisplay dpy, EGLConfig config,
762 void *native_window,
763 const EGLint *attrib_list)
764 {
765 _EGLDisplay *disp = _eglLockDisplay(dpy);
766
767 #ifdef HAVE_X11_PLATFORM
768 if (disp->Platform == _EGL_PLATFORM_X11 && native_window != NULL) {
769 /* The `native_window` parameter for the X11 platform differs between
770 * eglCreateWindowSurface() and eglCreatePlatformPixmapSurfaceEXT(). In
771 * eglCreateWindowSurface(), the type of `native_window` is an Xlib
772 * `Window`. In eglCreatePlatformWindowSurfaceEXT(), the type is
773 * `Window*`. Convert `Window*` to `Window` because that's what
774 * dri2_x11_create_window_surface() expects.
775 */
776 native_window = (void*) (* (Window*) native_window);
777 }
778 #endif
779
780 return _eglCreateWindowSurfaceCommon(disp, config, native_window,
781 attrib_list);
782 }
783
784
785 EGLSurface EGLAPIENTRY
786 eglCreatePlatformWindowSurface(EGLDisplay dpy, EGLConfig config,
787 void *native_window,
788 const EGLAttrib *attrib_list)
789 {
790 EGLSurface surface;
791 EGLint *int_attribs = _eglConvertAttribsToInt(attrib_list);
792
793 if (attrib_list && !int_attribs)
794 RETURN_EGL_ERROR(NULL, EGL_BAD_ALLOC, EGL_NO_SURFACE);
795
796 surface = eglCreatePlatformWindowSurfaceEXT(dpy, config, native_window,
797 int_attribs);
798 free(int_attribs);
799 return surface;
800 }
801
802
803 static EGLSurface
804 _eglCreatePixmapSurfaceCommon(_EGLDisplay *disp, EGLConfig config,
805 void *native_pixmap, const EGLint *attrib_list)
806 {
807 _EGLConfig *conf = _eglLookupConfig(config, disp);
808 _EGLDriver *drv;
809 _EGLSurface *surf;
810 EGLSurface ret;
811
812 _EGL_CHECK_CONFIG(disp, conf, EGL_NO_SURFACE, drv);
813 surf = drv->API.CreatePixmapSurface(drv, disp, conf, native_pixmap,
814 attrib_list);
815 ret = (surf) ? _eglLinkSurface(surf) : EGL_NO_SURFACE;
816
817 RETURN_EGL_EVAL(disp, ret);
818 }
819
820
821 EGLSurface EGLAPIENTRY
822 eglCreatePixmapSurface(EGLDisplay dpy, EGLConfig config,
823 EGLNativePixmapType pixmap, const EGLint *attrib_list)
824 {
825 _EGLDisplay *disp = _eglLockDisplay(dpy);
826 STATIC_ASSERT(sizeof(void*) == sizeof(pixmap));
827 return _eglCreatePixmapSurfaceCommon(disp, config, (void*) pixmap,
828 attrib_list);
829 }
830
831 static EGLSurface EGLAPIENTRY
832 eglCreatePlatformPixmapSurfaceEXT(EGLDisplay dpy, EGLConfig config,
833 void *native_pixmap,
834 const EGLint *attrib_list)
835 {
836 _EGLDisplay *disp = _eglLockDisplay(dpy);
837
838 #ifdef HAVE_X11_PLATFORM
839 /* The `native_pixmap` parameter for the X11 platform differs between
840 * eglCreatePixmapSurface() and eglCreatePlatformPixmapSurfaceEXT(). In
841 * eglCreatePixmapSurface(), the type of `native_pixmap` is an Xlib
842 * `Pixmap`. In eglCreatePlatformPixmapSurfaceEXT(), the type is
843 * `Pixmap*`. Convert `Pixmap*` to `Pixmap` because that's what
844 * dri2_x11_create_pixmap_surface() expects.
845 */
846 if (disp->Platform == _EGL_PLATFORM_X11 && native_pixmap != NULL) {
847 native_pixmap = (void*) (* (Pixmap*) native_pixmap);
848 }
849 #endif
850
851 return _eglCreatePixmapSurfaceCommon(disp, config, native_pixmap,
852 attrib_list);
853 }
854
855
856 EGLSurface EGLAPIENTRY
857 eglCreatePlatformPixmapSurface(EGLDisplay dpy, EGLConfig config,
858 void *native_pixmap,
859 const EGLAttrib *attrib_list)
860 {
861 EGLSurface surface;
862 EGLint *int_attribs = _eglConvertAttribsToInt(attrib_list);
863
864 if (attrib_list && !int_attribs)
865 RETURN_EGL_ERROR(NULL, EGL_BAD_ALLOC, EGL_NO_SURFACE);
866
867 surface = eglCreatePlatformPixmapSurfaceEXT(dpy, config, native_pixmap,
868 int_attribs);
869 free(int_attribs);
870 return surface;
871 }
872
873
874 EGLSurface EGLAPIENTRY
875 eglCreatePbufferSurface(EGLDisplay dpy, EGLConfig config,
876 const EGLint *attrib_list)
877 {
878 _EGLDisplay *disp = _eglLockDisplay(dpy);
879 _EGLConfig *conf = _eglLookupConfig(config, disp);
880 _EGLDriver *drv;
881 _EGLSurface *surf;
882 EGLSurface ret;
883
884 _EGL_CHECK_CONFIG(disp, conf, EGL_NO_SURFACE, drv);
885
886 surf = drv->API.CreatePbufferSurface(drv, disp, conf, attrib_list);
887 ret = (surf) ? _eglLinkSurface(surf) : EGL_NO_SURFACE;
888
889 RETURN_EGL_EVAL(disp, ret);
890 }
891
892
893 EGLBoolean EGLAPIENTRY
894 eglDestroySurface(EGLDisplay dpy, EGLSurface surface)
895 {
896 _EGLDisplay *disp = _eglLockDisplay(dpy);
897 _EGLSurface *surf = _eglLookupSurface(surface, disp);
898 _EGLDriver *drv;
899 EGLBoolean ret;
900
901 _EGL_CHECK_SURFACE(disp, surf, EGL_FALSE, drv);
902 _eglUnlinkSurface(surf);
903 ret = drv->API.DestroySurface(drv, disp, surf);
904
905 RETURN_EGL_EVAL(disp, ret);
906 }
907
908 EGLBoolean EGLAPIENTRY
909 eglQuerySurface(EGLDisplay dpy, EGLSurface surface,
910 EGLint attribute, EGLint *value)
911 {
912 _EGLDisplay *disp = _eglLockDisplay(dpy);
913 _EGLSurface *surf = _eglLookupSurface(surface, disp);
914 _EGLDriver *drv;
915 EGLBoolean ret;
916
917 _EGL_CHECK_SURFACE(disp, surf, EGL_FALSE, drv);
918 ret = drv->API.QuerySurface(drv, disp, surf, attribute, value);
919
920 RETURN_EGL_EVAL(disp, ret);
921 }
922
923 EGLBoolean EGLAPIENTRY
924 eglSurfaceAttrib(EGLDisplay dpy, EGLSurface surface,
925 EGLint attribute, EGLint value)
926 {
927 _EGLDisplay *disp = _eglLockDisplay(dpy);
928 _EGLSurface *surf = _eglLookupSurface(surface, disp);
929 _EGLDriver *drv;
930 EGLBoolean ret;
931
932 _EGL_CHECK_SURFACE(disp, surf, EGL_FALSE, drv);
933 ret = drv->API.SurfaceAttrib(drv, disp, surf, attribute, value);
934
935 RETURN_EGL_EVAL(disp, ret);
936 }
937
938
939 EGLBoolean EGLAPIENTRY
940 eglBindTexImage(EGLDisplay dpy, EGLSurface surface, EGLint buffer)
941 {
942 _EGLDisplay *disp = _eglLockDisplay(dpy);
943 _EGLSurface *surf = _eglLookupSurface(surface, disp);
944 _EGLDriver *drv;
945 EGLBoolean ret;
946
947 _EGL_CHECK_SURFACE(disp, surf, EGL_FALSE, drv);
948 ret = drv->API.BindTexImage(drv, disp, surf, buffer);
949
950 RETURN_EGL_EVAL(disp, ret);
951 }
952
953
954 EGLBoolean EGLAPIENTRY
955 eglReleaseTexImage(EGLDisplay dpy, EGLSurface surface, EGLint buffer)
956 {
957 _EGLDisplay *disp = _eglLockDisplay(dpy);
958 _EGLSurface *surf = _eglLookupSurface(surface, disp);
959 _EGLDriver *drv;
960 EGLBoolean ret;
961
962 _EGL_CHECK_SURFACE(disp, surf, EGL_FALSE, drv);
963 ret = drv->API.ReleaseTexImage(drv, disp, surf, buffer);
964
965 RETURN_EGL_EVAL(disp, ret);
966 }
967
968
969 EGLBoolean EGLAPIENTRY
970 eglSwapInterval(EGLDisplay dpy, EGLint interval)
971 {
972 _EGLDisplay *disp = _eglLockDisplay(dpy);
973 _EGLContext *ctx = _eglGetCurrentContext();
974 _EGLSurface *surf;
975 _EGLDriver *drv;
976 EGLBoolean ret;
977
978 _EGL_CHECK_DISPLAY(disp, EGL_FALSE, drv);
979
980 if (_eglGetContextHandle(ctx) == EGL_NO_CONTEXT ||
981 ctx->Resource.Display != disp)
982 RETURN_EGL_ERROR(disp, EGL_BAD_CONTEXT, EGL_FALSE);
983
984 surf = ctx->DrawSurface;
985 if (_eglGetSurfaceHandle(surf) == EGL_NO_SURFACE)
986 RETURN_EGL_ERROR(disp, EGL_BAD_SURFACE, EGL_FALSE);
987
988 ret = drv->API.SwapInterval(drv, disp, surf, interval);
989
990 RETURN_EGL_EVAL(disp, ret);
991 }
992
993
994 EGLBoolean EGLAPIENTRY
995 eglSwapBuffers(EGLDisplay dpy, EGLSurface surface)
996 {
997 _EGLContext *ctx = _eglGetCurrentContext();
998 _EGLDisplay *disp = _eglLockDisplay(dpy);
999 _EGLSurface *surf = _eglLookupSurface(surface, disp);
1000 _EGLDriver *drv;
1001 EGLBoolean ret;
1002
1003 _EGL_CHECK_SURFACE(disp, surf, EGL_FALSE, drv);
1004
1005 /* surface must be bound to current context in EGL 1.4 */
1006 #ifndef _EGL_BUILT_IN_DRIVER_HAIKU
1007 if (_eglGetContextHandle(ctx) == EGL_NO_CONTEXT ||
1008 surf != ctx->DrawSurface)
1009 RETURN_EGL_ERROR(disp, EGL_BAD_SURFACE, EGL_FALSE);
1010 #endif
1011
1012 ret = drv->API.SwapBuffers(drv, disp, surf);
1013
1014 RETURN_EGL_EVAL(disp, ret);
1015 }
1016
1017
1018 #ifdef EGL_EXT_swap_buffers_with_damage
1019
1020 static EGLBoolean EGLAPIENTRY
1021 eglSwapBuffersWithDamageEXT(EGLDisplay dpy, EGLSurface surface,
1022 EGLint *rects, EGLint n_rects)
1023 {
1024 _EGLContext *ctx = _eglGetCurrentContext();
1025 _EGLDisplay *disp = _eglLockDisplay(dpy);
1026 _EGLSurface *surf = _eglLookupSurface(surface, disp);
1027 _EGLDriver *drv;
1028 EGLBoolean ret;
1029
1030 _EGL_CHECK_SURFACE(disp, surf, EGL_FALSE, drv);
1031
1032 /* surface must be bound to current context in EGL 1.4 */
1033 if (_eglGetContextHandle(ctx) == EGL_NO_CONTEXT ||
1034 surf != ctx->DrawSurface)
1035 RETURN_EGL_ERROR(disp, EGL_BAD_SURFACE, EGL_FALSE);
1036
1037 if ((n_rects > 0 && rects == NULL) || n_rects < 0)
1038 RETURN_EGL_ERROR(disp, EGL_BAD_PARAMETER, EGL_FALSE);
1039
1040 ret = drv->API.SwapBuffersWithDamageEXT(drv, disp, surf, rects, n_rects);
1041
1042 RETURN_EGL_EVAL(disp, ret);
1043 }
1044
1045 #endif /* EGL_EXT_swap_buffers_with_damage */
1046
1047 EGLBoolean EGLAPIENTRY
1048 eglCopyBuffers(EGLDisplay dpy, EGLSurface surface, EGLNativePixmapType target)
1049 {
1050 _EGLDisplay *disp = _eglLockDisplay(dpy);
1051 _EGLSurface *surf = _eglLookupSurface(surface, disp);
1052 _EGLDriver *drv;
1053 EGLBoolean ret;
1054 void *native_pixmap_ptr;
1055
1056 STATIC_ASSERT(sizeof(void*) == sizeof(target));
1057 native_pixmap_ptr = (void*) target;
1058
1059 _EGL_CHECK_SURFACE(disp, surf, EGL_FALSE, drv);
1060 if (disp->Platform != _eglGetNativePlatform(disp->PlatformDisplay))
1061 RETURN_EGL_ERROR(disp, EGL_BAD_NATIVE_PIXMAP, EGL_FALSE);
1062 ret = drv->API.CopyBuffers(drv, disp, surf, native_pixmap_ptr);
1063
1064 RETURN_EGL_EVAL(disp, ret);
1065 }
1066
1067
1068 EGLBoolean EGLAPIENTRY
1069 eglWaitClient(void)
1070 {
1071 _EGLContext *ctx = _eglGetCurrentContext();
1072 _EGLDisplay *disp;
1073 _EGLDriver *drv;
1074 EGLBoolean ret;
1075
1076 if (!ctx)
1077 RETURN_EGL_SUCCESS(NULL, EGL_TRUE);
1078
1079 disp = ctx->Resource.Display;
1080 mtx_lock(&disp->Mutex);
1081
1082 /* let bad current context imply bad current surface */
1083 if (_eglGetContextHandle(ctx) == EGL_NO_CONTEXT ||
1084 _eglGetSurfaceHandle(ctx->DrawSurface) == EGL_NO_SURFACE)
1085 RETURN_EGL_ERROR(disp, EGL_BAD_CURRENT_SURFACE, EGL_FALSE);
1086
1087 /* a valid current context implies an initialized current display */
1088 assert(disp->Initialized);
1089 drv = disp->Driver;
1090 ret = drv->API.WaitClient(drv, disp, ctx);
1091
1092 RETURN_EGL_EVAL(disp, ret);
1093 }
1094
1095
1096 EGLBoolean EGLAPIENTRY
1097 eglWaitGL(void)
1098 {
1099 _EGLThreadInfo *t = _eglGetCurrentThread();
1100 EGLint api_index = t->CurrentAPIIndex;
1101 EGLint es_index = _eglConvertApiToIndex(EGL_OPENGL_ES_API);
1102 EGLBoolean ret;
1103
1104 if (api_index != es_index && _eglIsCurrentThreadDummy())
1105 RETURN_EGL_ERROR(NULL, EGL_BAD_ALLOC, EGL_FALSE);
1106
1107 t->CurrentAPIIndex = es_index;
1108 ret = eglWaitClient();
1109 t->CurrentAPIIndex = api_index;
1110 return ret;
1111 }
1112
1113
1114 EGLBoolean EGLAPIENTRY
1115 eglWaitNative(EGLint engine)
1116 {
1117 _EGLContext *ctx = _eglGetCurrentContext();
1118 _EGLDisplay *disp;
1119 _EGLDriver *drv;
1120 EGLBoolean ret;
1121
1122 if (!ctx)
1123 RETURN_EGL_SUCCESS(NULL, EGL_TRUE);
1124
1125 disp = ctx->Resource.Display;
1126 mtx_lock(&disp->Mutex);
1127
1128 /* let bad current context imply bad current surface */
1129 if (_eglGetContextHandle(ctx) == EGL_NO_CONTEXT ||
1130 _eglGetSurfaceHandle(ctx->DrawSurface) == EGL_NO_SURFACE)
1131 RETURN_EGL_ERROR(disp, EGL_BAD_CURRENT_SURFACE, EGL_FALSE);
1132
1133 /* a valid current context implies an initialized current display */
1134 assert(disp->Initialized);
1135 drv = disp->Driver;
1136 ret = drv->API.WaitNative(drv, disp, engine);
1137
1138 RETURN_EGL_EVAL(disp, ret);
1139 }
1140
1141
1142 EGLDisplay EGLAPIENTRY
1143 eglGetCurrentDisplay(void)
1144 {
1145 _EGLContext *ctx = _eglGetCurrentContext();
1146 EGLDisplay ret;
1147
1148 ret = (ctx) ? _eglGetDisplayHandle(ctx->Resource.Display) : EGL_NO_DISPLAY;
1149
1150 RETURN_EGL_SUCCESS(NULL, ret);
1151 }
1152
1153
1154 EGLContext EGLAPIENTRY
1155 eglGetCurrentContext(void)
1156 {
1157 _EGLContext *ctx = _eglGetCurrentContext();
1158 EGLContext ret;
1159
1160 ret = _eglGetContextHandle(ctx);
1161
1162 RETURN_EGL_SUCCESS(NULL, ret);
1163 }
1164
1165
1166 EGLSurface EGLAPIENTRY
1167 eglGetCurrentSurface(EGLint readdraw)
1168 {
1169 _EGLContext *ctx = _eglGetCurrentContext();
1170 EGLint err = EGL_SUCCESS;
1171 _EGLSurface *surf;
1172 EGLSurface ret;
1173
1174 if (!ctx)
1175 RETURN_EGL_SUCCESS(NULL, EGL_NO_SURFACE);
1176
1177 switch (readdraw) {
1178 case EGL_DRAW:
1179 surf = ctx->DrawSurface;
1180 break;
1181 case EGL_READ:
1182 surf = ctx->ReadSurface;
1183 break;
1184 default:
1185 surf = NULL;
1186 err = EGL_BAD_PARAMETER;
1187 break;
1188 }
1189
1190 ret = _eglGetSurfaceHandle(surf);
1191
1192 RETURN_EGL_ERROR(NULL, err, ret);
1193 }
1194
1195
1196 EGLint EGLAPIENTRY
1197 eglGetError(void)
1198 {
1199 _EGLThreadInfo *t = _eglGetCurrentThread();
1200 EGLint e = t->LastError;
1201 if (!_eglIsCurrentThreadDummy())
1202 t->LastError = EGL_SUCCESS;
1203 return e;
1204 }
1205
1206
1207 #ifdef EGL_MESA_drm_display
1208
1209 static EGLDisplay EGLAPIENTRY
1210 eglGetDRMDisplayMESA(int fd)
1211 {
1212 _EGLDisplay *dpy = _eglFindDisplay(_EGL_PLATFORM_DRM, (void *) (intptr_t) fd);
1213 return _eglGetDisplayHandle(dpy);
1214 }
1215
1216 #endif /* EGL_MESA_drm_display */
1217
1218 /**
1219 ** EGL 1.2
1220 **/
1221
1222 /**
1223 * Specify the client API to use for subsequent calls including:
1224 * eglCreateContext()
1225 * eglGetCurrentContext()
1226 * eglGetCurrentDisplay()
1227 * eglGetCurrentSurface()
1228 * eglMakeCurrent(when the ctx parameter is EGL NO CONTEXT)
1229 * eglWaitClient()
1230 * eglWaitNative()
1231 * See section 3.7 "Rendering Context" in the EGL specification for details.
1232 */
1233 EGLBoolean EGLAPIENTRY
1234 eglBindAPI(EGLenum api)
1235 {
1236 _EGLThreadInfo *t = _eglGetCurrentThread();
1237
1238 if (_eglIsCurrentThreadDummy())
1239 RETURN_EGL_ERROR(NULL, EGL_BAD_ALLOC, EGL_FALSE);
1240
1241 if (!_eglIsApiValid(api))
1242 RETURN_EGL_ERROR(NULL, EGL_BAD_PARAMETER, EGL_FALSE);
1243
1244 t->CurrentAPIIndex = _eglConvertApiToIndex(api);
1245
1246 RETURN_EGL_SUCCESS(NULL, EGL_TRUE);
1247 }
1248
1249
1250 /**
1251 * Return the last value set with eglBindAPI().
1252 */
1253 EGLenum EGLAPIENTRY
1254 eglQueryAPI(void)
1255 {
1256 _EGLThreadInfo *t = _eglGetCurrentThread();
1257 EGLenum ret;
1258
1259 /* returns one of EGL_OPENGL_API, EGL_OPENGL_ES_API or EGL_OPENVG_API */
1260 ret = _eglConvertApiFromIndex(t->CurrentAPIIndex);
1261
1262 RETURN_EGL_SUCCESS(NULL, ret);
1263 }
1264
1265
1266 EGLSurface EGLAPIENTRY
1267 eglCreatePbufferFromClientBuffer(EGLDisplay dpy, EGLenum buftype,
1268 EGLClientBuffer buffer, EGLConfig config,
1269 const EGLint *attrib_list)
1270 {
1271 _EGLDisplay *disp = _eglLockDisplay(dpy);
1272 _EGLConfig *conf = _eglLookupConfig(config, disp);
1273 _EGLDriver *drv;
1274 _EGLSurface *surf;
1275 EGLSurface ret;
1276
1277 _EGL_CHECK_CONFIG(disp, conf, EGL_NO_SURFACE, drv);
1278
1279 surf = drv->API.CreatePbufferFromClientBuffer(drv, disp, buftype, buffer,
1280 conf, attrib_list);
1281 ret = (surf) ? _eglLinkSurface(surf) : EGL_NO_SURFACE;
1282
1283 RETURN_EGL_EVAL(disp, ret);
1284 }
1285
1286
1287 EGLBoolean EGLAPIENTRY
1288 eglReleaseThread(void)
1289 {
1290 /* unbind current contexts */
1291 if (!_eglIsCurrentThreadDummy()) {
1292 _EGLThreadInfo *t = _eglGetCurrentThread();
1293 EGLint api_index = t->CurrentAPIIndex;
1294 EGLint i;
1295
1296 for (i = 0; i < _EGL_API_NUM_APIS; i++) {
1297 _EGLContext *ctx = t->CurrentContexts[i];
1298 if (ctx) {
1299 _EGLDisplay *disp = ctx->Resource.Display;
1300 _EGLDriver *drv;
1301
1302 t->CurrentAPIIndex = i;
1303
1304 mtx_lock(&disp->Mutex);
1305 drv = disp->Driver;
1306 (void) drv->API.MakeCurrent(drv, disp, NULL, NULL, NULL);
1307 mtx_unlock(&disp->Mutex);
1308 }
1309 }
1310
1311 t->CurrentAPIIndex = api_index;
1312 }
1313
1314 _eglDestroyCurrentThread();
1315
1316 RETURN_EGL_SUCCESS(NULL, EGL_TRUE);
1317 }
1318
1319
1320 static EGLImage EGLAPIENTRY
1321 eglCreateImageKHR(EGLDisplay dpy, EGLContext ctx, EGLenum target,
1322 EGLClientBuffer buffer, const EGLint *attr_list)
1323 {
1324 _EGLDisplay *disp = _eglLockDisplay(dpy);
1325 _EGLContext *context = _eglLookupContext(ctx, disp);
1326 _EGLDriver *drv;
1327 _EGLImage *img;
1328 EGLImage ret;
1329
1330 _EGL_CHECK_DISPLAY(disp, EGL_NO_IMAGE_KHR, drv);
1331 if (!disp->Extensions.KHR_image_base)
1332 RETURN_EGL_EVAL(disp, EGL_NO_IMAGE_KHR);
1333 if (!context && ctx != EGL_NO_CONTEXT)
1334 RETURN_EGL_ERROR(disp, EGL_BAD_CONTEXT, EGL_NO_IMAGE_KHR);
1335 /* "If <target> is EGL_LINUX_DMA_BUF_EXT, <dpy> must be a valid display,
1336 * <ctx> must be EGL_NO_CONTEXT..."
1337 */
1338 if (ctx != EGL_NO_CONTEXT && target == EGL_LINUX_DMA_BUF_EXT)
1339 RETURN_EGL_ERROR(disp, EGL_BAD_PARAMETER, EGL_NO_IMAGE_KHR);
1340
1341 img = drv->API.CreateImageKHR(drv,
1342 disp, context, target, buffer, attr_list);
1343 ret = (img) ? _eglLinkImage(img) : EGL_NO_IMAGE_KHR;
1344
1345 RETURN_EGL_EVAL(disp, ret);
1346 }
1347
1348
1349 EGLImage EGLAPIENTRY
1350 eglCreateImage(EGLDisplay dpy, EGLContext ctx, EGLenum target,
1351 EGLClientBuffer buffer, const EGLAttrib *attr_list)
1352 {
1353 EGLImage image;
1354 EGLint *int_attribs = _eglConvertAttribsToInt(attr_list);
1355
1356 if (attr_list && !int_attribs)
1357 RETURN_EGL_ERROR(NULL, EGL_BAD_ALLOC, EGL_NO_IMAGE);
1358
1359 image = eglCreateImageKHR(dpy, ctx, target, buffer, int_attribs);
1360 free(int_attribs);
1361 return image;
1362 }
1363
1364
1365 EGLBoolean EGLAPIENTRY
1366 eglDestroyImage(EGLDisplay dpy, EGLImage image)
1367 {
1368 _EGLDisplay *disp = _eglLockDisplay(dpy);
1369 _EGLImage *img = _eglLookupImage(image, disp);
1370 _EGLDriver *drv;
1371 EGLBoolean ret;
1372
1373 _EGL_CHECK_DISPLAY(disp, EGL_FALSE, drv);
1374 if (!disp->Extensions.KHR_image_base)
1375 RETURN_EGL_EVAL(disp, EGL_FALSE);
1376 if (!img)
1377 RETURN_EGL_ERROR(disp, EGL_BAD_PARAMETER, EGL_FALSE);
1378
1379 _eglUnlinkImage(img);
1380 ret = drv->API.DestroyImageKHR(drv, disp, img);
1381
1382 RETURN_EGL_EVAL(disp, ret);
1383 }
1384
1385
1386 static EGLSync
1387 _eglCreateSync(EGLDisplay dpy, EGLenum type, const EGLint *attrib_list,
1388 const EGLAttrib *attrib_list64, EGLBoolean is64,
1389 EGLenum invalid_type_error)
1390 {
1391 _EGLDisplay *disp = _eglLockDisplay(dpy);
1392 _EGLContext *ctx = _eglGetCurrentContext();
1393 _EGLDriver *drv;
1394 _EGLSync *sync;
1395 EGLSync ret;
1396
1397 _EGL_CHECK_DISPLAY(disp, EGL_NO_SYNC_KHR, drv);
1398
1399 if (!disp->Extensions.KHR_cl_event2 && is64)
1400 RETURN_EGL_EVAL(disp, EGL_NO_SYNC_KHR);
1401
1402 /* return an error if the client API doesn't support GL_OES_EGL_sync */
1403 if (!ctx || ctx->Resource.Display != dpy ||
1404 ctx->ClientAPI != EGL_OPENGL_ES_API)
1405 RETURN_EGL_ERROR(disp, EGL_BAD_MATCH, EGL_NO_SYNC_KHR);
1406
1407 switch (type) {
1408 case EGL_SYNC_FENCE_KHR:
1409 if (!disp->Extensions.KHR_fence_sync)
1410 RETURN_EGL_ERROR(disp, invalid_type_error, EGL_NO_SYNC_KHR);
1411 break;
1412 case EGL_SYNC_REUSABLE_KHR:
1413 if (!disp->Extensions.KHR_reusable_sync)
1414 RETURN_EGL_ERROR(disp, invalid_type_error, EGL_NO_SYNC_KHR);
1415 break;
1416 case EGL_SYNC_CL_EVENT_KHR:
1417 if (!disp->Extensions.KHR_cl_event2)
1418 RETURN_EGL_ERROR(disp, invalid_type_error, EGL_NO_SYNC_KHR);
1419 break;
1420 default:
1421 RETURN_EGL_ERROR(disp, invalid_type_error, EGL_NO_SYNC_KHR);
1422 }
1423
1424 sync = drv->API.CreateSyncKHR(drv, disp, type, attrib_list, attrib_list64);
1425 ret = (sync) ? _eglLinkSync(sync) : EGL_NO_SYNC_KHR;
1426
1427 RETURN_EGL_EVAL(disp, ret);
1428 }
1429
1430
1431 static EGLSync EGLAPIENTRY
1432 eglCreateSyncKHR(EGLDisplay dpy, EGLenum type, const EGLint *attrib_list)
1433 {
1434 return _eglCreateSync(dpy, type, attrib_list, NULL, EGL_FALSE,
1435 EGL_BAD_ATTRIBUTE);
1436 }
1437
1438
1439 static EGLSync EGLAPIENTRY
1440 eglCreateSync64KHR(EGLDisplay dpy, EGLenum type, const EGLAttrib *attrib_list)
1441 {
1442 return _eglCreateSync(dpy, type, NULL, attrib_list, EGL_TRUE,
1443 EGL_BAD_ATTRIBUTE);
1444 }
1445
1446
1447 EGLSync EGLAPIENTRY
1448 eglCreateSync(EGLDisplay dpy, EGLenum type, const EGLAttrib *attrib_list)
1449 {
1450 return _eglCreateSync(dpy, type, NULL, attrib_list, EGL_TRUE,
1451 EGL_BAD_PARAMETER);
1452 }
1453
1454
1455 EGLBoolean EGLAPIENTRY
1456 eglDestroySync(EGLDisplay dpy, EGLSync sync)
1457 {
1458 _EGLDisplay *disp = _eglLockDisplay(dpy);
1459 _EGLSync *s = _eglLookupSync(sync, disp);
1460 _EGLDriver *drv;
1461 EGLBoolean ret;
1462
1463 _EGL_CHECK_SYNC(disp, s, EGL_FALSE, drv);
1464 assert(disp->Extensions.KHR_reusable_sync ||
1465 disp->Extensions.KHR_fence_sync);
1466
1467 _eglUnlinkSync(s);
1468 ret = drv->API.DestroySyncKHR(drv, disp, s);
1469
1470 RETURN_EGL_EVAL(disp, ret);
1471 }
1472
1473
1474 EGLint EGLAPIENTRY
1475 eglClientWaitSync(EGLDisplay dpy, EGLSync sync, EGLint flags, EGLTime timeout)
1476 {
1477 _EGLDisplay *disp = _eglLockDisplay(dpy);
1478 _EGLSync *s = _eglLookupSync(sync, disp);
1479 _EGLDriver *drv;
1480 EGLint ret;
1481
1482 _EGL_CHECK_SYNC(disp, s, EGL_FALSE, drv);
1483 assert(disp->Extensions.KHR_reusable_sync ||
1484 disp->Extensions.KHR_fence_sync);
1485
1486 if (s->SyncStatus == EGL_SIGNALED_KHR)
1487 RETURN_EGL_EVAL(disp, EGL_CONDITION_SATISFIED_KHR);
1488
1489 ret = drv->API.ClientWaitSyncKHR(drv, disp, s, flags, timeout);
1490
1491 RETURN_EGL_EVAL(disp, ret);
1492 }
1493
1494
1495 static EGLint EGLAPIENTRY
1496 eglWaitSyncKHR(EGLDisplay dpy, EGLSync sync, EGLint flags)
1497 {
1498 _EGLDisplay *disp = _eglLockDisplay(dpy);
1499 _EGLSync *s = _eglLookupSync(sync, disp);
1500 _EGLContext *ctx = _eglGetCurrentContext();
1501 _EGLDriver *drv;
1502 EGLint ret;
1503
1504 _EGL_CHECK_SYNC(disp, s, EGL_FALSE, drv);
1505 assert(disp->Extensions.KHR_wait_sync);
1506
1507 /* return an error if the client API doesn't support GL_OES_EGL_sync */
1508 if (ctx == EGL_NO_CONTEXT || ctx->ClientAPI != EGL_OPENGL_ES_API)
1509 RETURN_EGL_ERROR(disp, EGL_BAD_MATCH, EGL_FALSE);
1510
1511 /* the API doesn't allow any flags yet */
1512 if (flags != 0)
1513 RETURN_EGL_ERROR(disp, EGL_BAD_PARAMETER, EGL_FALSE);
1514
1515 ret = drv->API.WaitSyncKHR(drv, disp, s);
1516
1517 RETURN_EGL_EVAL(disp, ret);
1518 }
1519
1520
1521 EGLBoolean EGLAPIENTRY
1522 eglWaitSync(EGLDisplay dpy, EGLSync sync, EGLint flags)
1523 {
1524 /* The KHR version returns EGLint, while the core version returns
1525 * EGLBoolean. In both cases, the return values can only be EGL_FALSE and
1526 * EGL_TRUE.
1527 */
1528 return eglWaitSyncKHR(dpy, sync, flags);
1529 }
1530
1531
1532 static EGLBoolean EGLAPIENTRY
1533 eglSignalSyncKHR(EGLDisplay dpy, EGLSync sync, EGLenum mode)
1534 {
1535 _EGLDisplay *disp = _eglLockDisplay(dpy);
1536 _EGLSync *s = _eglLookupSync(sync, disp);
1537 _EGLDriver *drv;
1538 EGLBoolean ret;
1539
1540 _EGL_CHECK_SYNC(disp, s, EGL_FALSE, drv);
1541 assert(disp->Extensions.KHR_reusable_sync);
1542 ret = drv->API.SignalSyncKHR(drv, disp, s, mode);
1543
1544 RETURN_EGL_EVAL(disp, ret);
1545 }
1546
1547
1548 EGLBoolean EGLAPIENTRY
1549 eglGetSyncAttrib(EGLDisplay dpy, EGLSync sync, EGLint attribute, EGLAttrib *value)
1550 {
1551 _EGLDisplay *disp = _eglLockDisplay(dpy);
1552 _EGLSync *s = _eglLookupSync(sync, disp);
1553 _EGLDriver *drv;
1554 EGLBoolean ret;
1555
1556 _EGL_CHECK_SYNC(disp, s, EGL_FALSE, drv);
1557 assert(disp->Extensions.KHR_reusable_sync ||
1558 disp->Extensions.KHR_fence_sync);
1559 ret = drv->API.GetSyncAttrib(drv, disp, s, attribute, value);
1560
1561 RETURN_EGL_EVAL(disp, ret);
1562 }
1563
1564
1565 static EGLBoolean EGLAPIENTRY
1566 eglGetSyncAttribKHR(EGLDisplay dpy, EGLSync sync, EGLint attribute, EGLint *value)
1567 {
1568 EGLAttrib attrib = *value;
1569 EGLBoolean result = eglGetSyncAttrib(dpy, sync, attribute, &attrib);
1570
1571 /* The EGL_KHR_fence_sync spec says this about eglGetSyncAttribKHR:
1572 *
1573 * If any error occurs, <*value> is not modified.
1574 */
1575 if (result == EGL_FALSE)
1576 return result;
1577
1578 *value = attrib;
1579 return result;
1580 }
1581
1582
1583 #ifdef EGL_NOK_swap_region
1584
1585 static EGLBoolean EGLAPIENTRY
1586 eglSwapBuffersRegionNOK(EGLDisplay dpy, EGLSurface surface,
1587 EGLint numRects, const EGLint *rects)
1588 {
1589 _EGLContext *ctx = _eglGetCurrentContext();
1590 _EGLDisplay *disp = _eglLockDisplay(dpy);
1591 _EGLSurface *surf = _eglLookupSurface(surface, disp);
1592 _EGLDriver *drv;
1593 EGLBoolean ret;
1594
1595 _EGL_CHECK_SURFACE(disp, surf, EGL_FALSE, drv);
1596
1597 if (!disp->Extensions.NOK_swap_region)
1598 RETURN_EGL_EVAL(disp, EGL_FALSE);
1599
1600 /* surface must be bound to current context in EGL 1.4 */
1601 if (_eglGetContextHandle(ctx) == EGL_NO_CONTEXT ||
1602 surf != ctx->DrawSurface)
1603 RETURN_EGL_ERROR(disp, EGL_BAD_SURFACE, EGL_FALSE);
1604
1605 ret = drv->API.SwapBuffersRegionNOK(drv, disp, surf, numRects, rects);
1606
1607 RETURN_EGL_EVAL(disp, ret);
1608 }
1609
1610 #endif /* EGL_NOK_swap_region */
1611
1612
1613 #ifdef EGL_MESA_drm_image
1614
1615 static EGLImage EGLAPIENTRY
1616 eglCreateDRMImageMESA(EGLDisplay dpy, const EGLint *attr_list)
1617 {
1618 _EGLDisplay *disp = _eglLockDisplay(dpy);
1619 _EGLDriver *drv;
1620 _EGLImage *img;
1621 EGLImage ret;
1622
1623 _EGL_CHECK_DISPLAY(disp, EGL_NO_IMAGE_KHR, drv);
1624 if (!disp->Extensions.MESA_drm_image)
1625 RETURN_EGL_EVAL(disp, EGL_NO_IMAGE_KHR);
1626
1627 img = drv->API.CreateDRMImageMESA(drv, disp, attr_list);
1628 ret = (img) ? _eglLinkImage(img) : EGL_NO_IMAGE_KHR;
1629
1630 RETURN_EGL_EVAL(disp, ret);
1631 }
1632
1633 static EGLBoolean EGLAPIENTRY
1634 eglExportDRMImageMESA(EGLDisplay dpy, EGLImage image,
1635 EGLint *name, EGLint *handle, EGLint *stride)
1636 {
1637 _EGLDisplay *disp = _eglLockDisplay(dpy);
1638 _EGLImage *img = _eglLookupImage(image, disp);
1639 _EGLDriver *drv;
1640 EGLBoolean ret;
1641
1642 _EGL_CHECK_DISPLAY(disp, EGL_FALSE, drv);
1643 assert(disp->Extensions.MESA_drm_image);
1644
1645 if (!img)
1646 RETURN_EGL_ERROR(disp, EGL_BAD_PARAMETER, EGL_FALSE);
1647
1648 ret = drv->API.ExportDRMImageMESA(drv, disp, img, name, handle, stride);
1649
1650 RETURN_EGL_EVAL(disp, ret);
1651 }
1652
1653 #endif
1654
1655 #ifdef EGL_WL_bind_wayland_display
1656 struct wl_display;
1657
1658 static EGLBoolean EGLAPIENTRY
1659 eglBindWaylandDisplayWL(EGLDisplay dpy, struct wl_display *display)
1660 {
1661 _EGLDisplay *disp = _eglLockDisplay(dpy);
1662 _EGLDriver *drv;
1663 EGLBoolean ret;
1664
1665 _EGL_CHECK_DISPLAY(disp, EGL_FALSE, drv);
1666 assert(disp->Extensions.WL_bind_wayland_display);
1667
1668 if (!display)
1669 RETURN_EGL_ERROR(disp, EGL_BAD_PARAMETER, EGL_FALSE);
1670
1671 ret = drv->API.BindWaylandDisplayWL(drv, disp, display);
1672
1673 RETURN_EGL_EVAL(disp, ret);
1674 }
1675
1676 static EGLBoolean EGLAPIENTRY
1677 eglUnbindWaylandDisplayWL(EGLDisplay dpy, struct wl_display *display)
1678 {
1679 _EGLDisplay *disp = _eglLockDisplay(dpy);
1680 _EGLDriver *drv;
1681 EGLBoolean ret;
1682
1683 _EGL_CHECK_DISPLAY(disp, EGL_FALSE, drv);
1684 assert(disp->Extensions.WL_bind_wayland_display);
1685
1686 if (!display)
1687 RETURN_EGL_ERROR(disp, EGL_BAD_PARAMETER, EGL_FALSE);
1688
1689 ret = drv->API.UnbindWaylandDisplayWL(drv, disp, display);
1690
1691 RETURN_EGL_EVAL(disp, ret);
1692 }
1693
1694 static EGLBoolean EGLAPIENTRY
1695 eglQueryWaylandBufferWL(EGLDisplay dpy, struct wl_resource *buffer,
1696 EGLint attribute, EGLint *value)
1697 {
1698 _EGLDisplay *disp = _eglLockDisplay(dpy);
1699 _EGLDriver *drv;
1700 EGLBoolean ret;
1701
1702 _EGL_CHECK_DISPLAY(disp, EGL_FALSE, drv);
1703 assert(disp->Extensions.WL_bind_wayland_display);
1704
1705 if (!buffer)
1706 RETURN_EGL_ERROR(disp, EGL_BAD_PARAMETER, EGL_FALSE);
1707
1708 ret = drv->API.QueryWaylandBufferWL(drv, disp, buffer, attribute, value);
1709
1710 RETURN_EGL_EVAL(disp, ret);
1711 }
1712 #endif
1713
1714 #ifdef EGL_WL_create_wayland_buffer_from_image
1715 static struct wl_buffer * EGLAPIENTRY
1716 eglCreateWaylandBufferFromImageWL(EGLDisplay dpy, EGLImage image)
1717 {
1718 _EGLDisplay *disp = _eglLockDisplay(dpy);
1719 _EGLImage *img;
1720 _EGLDriver *drv;
1721 struct wl_buffer *ret;
1722
1723 _EGL_CHECK_DISPLAY(disp, NULL, drv);
1724 assert(disp->Extensions.WL_create_wayland_buffer_from_image);
1725
1726 img = _eglLookupImage(image, disp);
1727
1728 if (!img)
1729 RETURN_EGL_ERROR(disp, EGL_BAD_PARAMETER, NULL);
1730
1731 ret = drv->API.CreateWaylandBufferFromImageWL(drv, disp, img);
1732
1733 RETURN_EGL_EVAL(disp, ret);
1734 }
1735 #endif
1736
1737 static EGLBoolean EGLAPIENTRY
1738 eglPostSubBufferNV(EGLDisplay dpy, EGLSurface surface,
1739 EGLint x, EGLint y, EGLint width, EGLint height)
1740 {
1741 _EGLDisplay *disp = _eglLockDisplay(dpy);
1742 _EGLSurface *surf = _eglLookupSurface(surface, disp);
1743 _EGLDriver *drv;
1744 EGLBoolean ret;
1745
1746 _EGL_CHECK_SURFACE(disp, surf, EGL_FALSE, drv);
1747
1748 if (!disp->Extensions.NV_post_sub_buffer)
1749 RETURN_EGL_EVAL(disp, EGL_FALSE);
1750
1751 ret = drv->API.PostSubBufferNV(drv, disp, surf, x, y, width, height);
1752
1753 RETURN_EGL_EVAL(disp, ret);
1754 }
1755
1756 static EGLBoolean EGLAPIENTRY
1757 eglGetSyncValuesCHROMIUM(EGLDisplay display, EGLSurface surface,
1758 EGLuint64KHR *ust, EGLuint64KHR *msc,
1759 EGLuint64KHR *sbc)
1760 {
1761 _EGLDisplay *disp = _eglLockDisplay(display);
1762 _EGLSurface *surf = _eglLookupSurface(surface, disp);
1763 _EGLDriver *drv;
1764 EGLBoolean ret;
1765
1766 _EGL_CHECK_SURFACE(disp, surf, EGL_FALSE, drv);
1767 if (!disp->Extensions.CHROMIUM_sync_control)
1768 RETURN_EGL_EVAL(disp, EGL_FALSE);
1769
1770 if (!ust || !msc || !sbc)
1771 RETURN_EGL_ERROR(disp, EGL_BAD_PARAMETER, EGL_FALSE);
1772
1773 ret = drv->API.GetSyncValuesCHROMIUM(disp, surf, ust, msc, sbc);
1774
1775 RETURN_EGL_EVAL(disp, ret);
1776 }
1777
1778 #ifdef EGL_MESA_image_dma_buf_export
1779 static EGLBoolean EGLAPIENTRY
1780 eglExportDMABUFImageQueryMESA(EGLDisplay dpy, EGLImage image,
1781 EGLint *fourcc, EGLint *nplanes,
1782 EGLuint64KHR *modifiers)
1783 {
1784 _EGLDisplay *disp = _eglLockDisplay(dpy);
1785 _EGLImage *img = _eglLookupImage(image, disp);
1786 _EGLDriver *drv;
1787 EGLBoolean ret;
1788
1789 _EGL_CHECK_DISPLAY(disp, EGL_FALSE, drv);
1790 assert(disp->Extensions.MESA_image_dma_buf_export);
1791
1792 if (!img)
1793 RETURN_EGL_ERROR(disp, EGL_BAD_PARAMETER, EGL_FALSE);
1794
1795 ret = drv->API.ExportDMABUFImageQueryMESA(drv, disp, img, fourcc, nplanes,
1796 modifiers);
1797
1798 RETURN_EGL_EVAL(disp, ret);
1799 }
1800
1801 static EGLBoolean EGLAPIENTRY
1802 eglExportDMABUFImageMESA(EGLDisplay dpy, EGLImage image,
1803 int *fds, EGLint *strides, EGLint *offsets)
1804 {
1805 _EGLDisplay *disp = _eglLockDisplay(dpy);
1806 _EGLImage *img = _eglLookupImage(image, disp);
1807 _EGLDriver *drv;
1808 EGLBoolean ret;
1809
1810 _EGL_CHECK_DISPLAY(disp, EGL_FALSE, drv);
1811 assert(disp->Extensions.MESA_image_dma_buf_export);
1812
1813 if (!img)
1814 RETURN_EGL_ERROR(disp, EGL_BAD_PARAMETER, EGL_FALSE);
1815
1816 ret = drv->API.ExportDMABUFImageMESA(drv, disp, img, fds, strides, offsets);
1817
1818 RETURN_EGL_EVAL(disp, ret);
1819 }
1820 #endif
1821
1822 __eglMustCastToProperFunctionPointerType EGLAPIENTRY
1823 eglGetProcAddress(const char *procname)
1824 {
1825 static const struct {
1826 const char *name;
1827 _EGLProc function;
1828 } egl_functions[] = {
1829 /* core functions queryable in the presence of
1830 * EGL_KHR_get_all_proc_addresses or EGL 1.5
1831 */
1832 /* alphabetical order */
1833 { "eglBindAPI", (_EGLProc) eglBindAPI },
1834 { "eglBindTexImage", (_EGLProc) eglBindTexImage },
1835 { "eglChooseConfig", (_EGLProc) eglChooseConfig },
1836 { "eglCopyBuffers", (_EGLProc) eglCopyBuffers },
1837 { "eglCreateContext", (_EGLProc) eglCreateContext },
1838 { "eglCreatePbufferFromClientBuffer", (_EGLProc) eglCreatePbufferFromClientBuffer },
1839 { "eglCreatePbufferSurface", (_EGLProc) eglCreatePbufferSurface },
1840 { "eglCreatePixmapSurface", (_EGLProc) eglCreatePixmapSurface },
1841 { "eglCreateWindowSurface", (_EGLProc) eglCreateWindowSurface },
1842 { "eglDestroyContext", (_EGLProc) eglDestroyContext },
1843 { "eglDestroySurface", (_EGLProc) eglDestroySurface },
1844 { "eglGetConfigAttrib", (_EGLProc) eglGetConfigAttrib },
1845 { "eglGetConfigs", (_EGLProc) eglGetConfigs },
1846 { "eglGetCurrentContext", (_EGLProc) eglGetCurrentContext },
1847 { "eglGetCurrentDisplay", (_EGLProc) eglGetCurrentDisplay },
1848 { "eglGetCurrentSurface", (_EGLProc) eglGetCurrentSurface },
1849 { "eglGetDisplay", (_EGLProc) eglGetDisplay },
1850 { "eglGetError", (_EGLProc) eglGetError },
1851 { "eglGetProcAddress", (_EGLProc) eglGetProcAddress },
1852 { "eglInitialize", (_EGLProc) eglInitialize },
1853 { "eglMakeCurrent", (_EGLProc) eglMakeCurrent },
1854 { "eglQueryAPI", (_EGLProc) eglQueryAPI },
1855 { "eglQueryContext", (_EGLProc) eglQueryContext },
1856 { "eglQueryString", (_EGLProc) eglQueryString },
1857 { "eglQuerySurface", (_EGLProc) eglQuerySurface },
1858 { "eglReleaseTexImage", (_EGLProc) eglReleaseTexImage },
1859 { "eglReleaseThread", (_EGLProc) eglReleaseThread },
1860 { "eglSurfaceAttrib", (_EGLProc) eglSurfaceAttrib },
1861 { "eglSwapBuffers", (_EGLProc) eglSwapBuffers },
1862 { "eglSwapInterval", (_EGLProc) eglSwapInterval },
1863 { "eglTerminate", (_EGLProc) eglTerminate },
1864 { "eglWaitClient", (_EGLProc) eglWaitClient },
1865 { "eglWaitGL", (_EGLProc) eglWaitGL },
1866 { "eglWaitNative", (_EGLProc) eglWaitNative },
1867 { "eglCreateSync", (_EGLProc) eglCreateSync },
1868 { "eglDestroySync", (_EGLProc) eglDestroySync },
1869 { "eglClientWaitSync", (_EGLProc) eglClientWaitSync },
1870 { "eglGetSyncAttrib", (_EGLProc) eglGetSyncAttrib },
1871 { "eglWaitSync", (_EGLProc) eglWaitSync },
1872 { "eglCreateImage", (_EGLProc) eglCreateImage },
1873 { "eglDestroyImage", (_EGLProc) eglDestroyImage },
1874 { "eglGetPlatformDisplay", (_EGLProc) eglGetPlatformDisplay },
1875 { "eglCreatePlatformWindowSurface", (_EGLProc) eglCreatePlatformWindowSurface },
1876 { "eglCreatePlatformPixmapSurface", (_EGLProc) eglCreatePlatformPixmapSurface },
1877 #ifdef EGL_MESA_drm_display
1878 { "eglGetDRMDisplayMESA", (_EGLProc) eglGetDRMDisplayMESA },
1879 #endif
1880 { "eglCreateImageKHR", (_EGLProc) eglCreateImageKHR },
1881 { "eglDestroyImageKHR", (_EGLProc) eglDestroyImage },
1882 { "eglCreateSyncKHR", (_EGLProc) eglCreateSyncKHR },
1883 { "eglCreateSync64KHR", (_EGLProc) eglCreateSync64KHR },
1884 { "eglDestroySyncKHR", (_EGLProc) eglDestroySync },
1885 { "eglClientWaitSyncKHR", (_EGLProc) eglClientWaitSync },
1886 { "eglWaitSyncKHR", (_EGLProc) eglWaitSyncKHR },
1887 { "eglSignalSyncKHR", (_EGLProc) eglSignalSyncKHR },
1888 { "eglGetSyncAttribKHR", (_EGLProc) eglGetSyncAttribKHR },
1889 #ifdef EGL_NOK_swap_region
1890 { "eglSwapBuffersRegionNOK", (_EGLProc) eglSwapBuffersRegionNOK },
1891 #endif
1892 #ifdef EGL_MESA_drm_image
1893 { "eglCreateDRMImageMESA", (_EGLProc) eglCreateDRMImageMESA },
1894 { "eglExportDRMImageMESA", (_EGLProc) eglExportDRMImageMESA },
1895 #endif
1896 #ifdef EGL_WL_bind_wayland_display
1897 { "eglBindWaylandDisplayWL", (_EGLProc) eglBindWaylandDisplayWL },
1898 { "eglUnbindWaylandDisplayWL", (_EGLProc) eglUnbindWaylandDisplayWL },
1899 { "eglQueryWaylandBufferWL", (_EGLProc) eglQueryWaylandBufferWL },
1900 #endif
1901 #ifdef EGL_WL_create_wayland_buffer_from_image
1902 { "eglCreateWaylandBufferFromImageWL", (_EGLProc) eglCreateWaylandBufferFromImageWL },
1903 #endif
1904 { "eglPostSubBufferNV", (_EGLProc) eglPostSubBufferNV },
1905 #ifdef EGL_EXT_swap_buffers_with_damage
1906 { "eglSwapBuffersWithDamageEXT", (_EGLProc) eglSwapBuffersWithDamageEXT },
1907 #endif
1908 { "eglGetPlatformDisplayEXT", (_EGLProc) eglGetPlatformDisplayEXT },
1909 { "eglCreatePlatformWindowSurfaceEXT", (_EGLProc) eglCreatePlatformWindowSurfaceEXT },
1910 { "eglCreatePlatformPixmapSurfaceEXT", (_EGLProc) eglCreatePlatformPixmapSurfaceEXT },
1911 { "eglGetSyncValuesCHROMIUM", (_EGLProc) eglGetSyncValuesCHROMIUM },
1912 #ifdef EGL_MESA_image_dma_buf_export
1913 { "eglExportDMABUFImageQueryMESA", (_EGLProc) eglExportDMABUFImageQueryMESA },
1914 { "eglExportDMABUFImageMESA", (_EGLProc) eglExportDMABUFImageMESA },
1915 #endif
1916 { NULL, NULL }
1917 };
1918 EGLint i;
1919 _EGLProc ret;
1920
1921 if (!procname)
1922 RETURN_EGL_SUCCESS(NULL, NULL);
1923
1924 ret = NULL;
1925 if (strncmp(procname, "egl", 3) == 0) {
1926 for (i = 0; egl_functions[i].name; i++) {
1927 if (strcmp(egl_functions[i].name, procname) == 0) {
1928 ret = egl_functions[i].function;
1929 break;
1930 }
1931 }
1932 }
1933 if (!ret)
1934 ret = _eglGetDriverProc(procname);
1935
1936 RETURN_EGL_SUCCESS(NULL, ret);
1937 }