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