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