1848b8605Smrg/************************************************************************** 2848b8605Smrg * 3848b8605Smrg * Copyright 2008 VMware, Inc. 4848b8605Smrg * Copyright 2009-2010 Chia-I Wu <olvaffe@gmail.com> 5848b8605Smrg * Copyright 2010-2011 LunarG, Inc. 6848b8605Smrg * All Rights Reserved. 7848b8605Smrg * 8848b8605Smrg * Permission is hereby granted, free of charge, to any person obtaining a 9848b8605Smrg * copy of this software and associated documentation files (the 10848b8605Smrg * "Software"), to deal in the Software without restriction, including 11848b8605Smrg * without limitation the rights to use, copy, modify, merge, publish, 12848b8605Smrg * distribute, sub license, and/or sell copies of the Software, and to 13848b8605Smrg * permit persons to whom the Software is furnished to do so, subject to 14848b8605Smrg * the following conditions: 15848b8605Smrg * 16848b8605Smrg * The above copyright notice and this permission notice (including the 17848b8605Smrg * next paragraph) shall be included in all copies or substantial portions 18848b8605Smrg * of the Software. 19848b8605Smrg * 20848b8605Smrg * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 21848b8605Smrg * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 22848b8605Smrg * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL 23848b8605Smrg * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 24848b8605Smrg * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING 25848b8605Smrg * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER 26848b8605Smrg * DEALINGS IN THE SOFTWARE. 27848b8605Smrg * 28848b8605Smrg **************************************************************************/ 29848b8605Smrg 30848b8605Smrg 31848b8605Smrg/** 32848b8605Smrg * Public EGL API entrypoints 33848b8605Smrg * 34848b8605Smrg * Generally, we use the EGLDisplay parameter as a key to lookup the 35848b8605Smrg * appropriate device driver handle, then jump though the driver's 36848b8605Smrg * dispatch table to handle the function. 37848b8605Smrg * 38848b8605Smrg * That allows us the option of supporting multiple, simultaneous, 39848b8605Smrg * heterogeneous hardware devices in the future. 40848b8605Smrg * 41848b8605Smrg * The EGLDisplay, EGLConfig, EGLContext and EGLSurface types are 42848b8605Smrg * opaque handles. Internal objects are linked to a display to 43848b8605Smrg * create the handles. 44848b8605Smrg * 45848b8605Smrg * For each public API entry point, the opaque handles are looked up 46848b8605Smrg * before being dispatched to the drivers. When it fails to look up 47848b8605Smrg * a handle, one of 48848b8605Smrg * 49848b8605Smrg * EGL_BAD_DISPLAY 50848b8605Smrg * EGL_BAD_CONFIG 51848b8605Smrg * EGL_BAD_CONTEXT 52848b8605Smrg * EGL_BAD_SURFACE 53848b8605Smrg * EGL_BAD_SCREEN_MESA 54848b8605Smrg * EGL_BAD_MODE_MESA 55848b8605Smrg * 56848b8605Smrg * is generated and the driver function is not called. An 57848b8605Smrg * uninitialized EGLDisplay has no driver associated with it. When 58848b8605Smrg * such display is detected, 59848b8605Smrg * 60848b8605Smrg * EGL_NOT_INITIALIZED 61848b8605Smrg * 62848b8605Smrg * is generated. 63848b8605Smrg * 64848b8605Smrg * Some of the entry points use current display, context, or surface 65848b8605Smrg * implicitly. For such entry points, the implicit objects are also 66848b8605Smrg * checked before calling the driver function. Other than the 67848b8605Smrg * errors listed above, 68848b8605Smrg * 69848b8605Smrg * EGL_BAD_CURRENT_SURFACE 70848b8605Smrg * 71848b8605Smrg * may also be generated. 72848b8605Smrg * 73848b8605Smrg * Notes on naming conventions: 74848b8605Smrg * 75848b8605Smrg * eglFooBar - public EGL function 76848b8605Smrg * EGL_FOO_BAR - public EGL token 77848b8605Smrg * EGLDatatype - public EGL datatype 78848b8605Smrg * 79848b8605Smrg * _eglFooBar - private EGL function 80848b8605Smrg * _EGLDatatype - private EGL datatype, typedef'd struct 81848b8605Smrg * _egl_struct - private EGL struct, non-typedef'd 82848b8605Smrg * 83848b8605Smrg */ 84848b8605Smrg 85848b8605Smrg 86b8e80941Smrg#ifdef USE_LIBGLVND 87b8e80941Smrg#define EGLAPI 88b8e80941Smrg#undef PUBLIC 89b8e80941Smrg#define PUBLIC 90b8e80941Smrg#endif 91b8e80941Smrg 92848b8605Smrg#include <stdio.h> 93848b8605Smrg#include <stdlib.h> 94848b8605Smrg#include <string.h> 95b8e80941Smrg#include "c99_compat.h" 96b8e80941Smrg#include "c11/threads.h" 97b8e80941Smrg#include "util/macros.h" 98848b8605Smrg 99b8e80941Smrg#include "eglapi.h" 100b8e80941Smrg#include "egldefines.h" 101848b8605Smrg#include "eglglobals.h" 102848b8605Smrg#include "eglcontext.h" 103848b8605Smrg#include "egldisplay.h" 104848b8605Smrg#include "egltypedefs.h" 105848b8605Smrg#include "eglcurrent.h" 106b8e80941Smrg#include "egldevice.h" 107848b8605Smrg#include "egldriver.h" 108848b8605Smrg#include "eglsurface.h" 109848b8605Smrg#include "eglconfig.h" 110848b8605Smrg#include "eglimage.h" 111848b8605Smrg#include "eglsync.h" 112848b8605Smrg 113b8e80941Smrg#include "GL/mesa_glinterop.h" 114848b8605Smrg 115848b8605Smrg/** 116848b8605Smrg * Macros to help return an API entrypoint. 117848b8605Smrg * 118848b8605Smrg * These macros will unlock the display and record the error code. 119848b8605Smrg */ 120848b8605Smrg#define RETURN_EGL_ERROR(disp, err, ret) \ 121848b8605Smrg do { \ 122848b8605Smrg if (disp) \ 123848b8605Smrg _eglUnlockDisplay(disp); \ 124848b8605Smrg /* EGL error codes are non-zero */ \ 125848b8605Smrg if (err) \ 126b8e80941Smrg _eglError(err, __func__); \ 127848b8605Smrg return ret; \ 128848b8605Smrg } while (0) 129848b8605Smrg 130848b8605Smrg#define RETURN_EGL_SUCCESS(disp, ret) \ 131848b8605Smrg RETURN_EGL_ERROR(disp, EGL_SUCCESS, ret) 132848b8605Smrg 133848b8605Smrg/* record EGL_SUCCESS only when ret evaluates to true */ 134848b8605Smrg#define RETURN_EGL_EVAL(disp, ret) \ 135848b8605Smrg RETURN_EGL_ERROR(disp, (ret) ? EGL_SUCCESS : 0, ret) 136848b8605Smrg 137848b8605Smrg 138848b8605Smrg/* 139848b8605Smrg * A bunch of macros and checks to simplify error checking. 140848b8605Smrg */ 141848b8605Smrg 142848b8605Smrg#define _EGL_CHECK_DISPLAY(disp, ret, drv) \ 143848b8605Smrg do { \ 144b8e80941Smrg drv = _eglCheckDisplay(disp, __func__); \ 145848b8605Smrg if (!drv) \ 146848b8605Smrg RETURN_EGL_ERROR(disp, 0, ret); \ 147848b8605Smrg } while (0) 148848b8605Smrg 149848b8605Smrg#define _EGL_CHECK_OBJECT(disp, type, obj, ret, drv) \ 150848b8605Smrg do { \ 151b8e80941Smrg drv = _eglCheck ## type(disp, obj, __func__); \ 152848b8605Smrg if (!drv) \ 153848b8605Smrg RETURN_EGL_ERROR(disp, 0, ret); \ 154848b8605Smrg } while (0) 155848b8605Smrg 156848b8605Smrg#define _EGL_CHECK_SURFACE(disp, surf, ret, drv) \ 157848b8605Smrg _EGL_CHECK_OBJECT(disp, Surface, surf, ret, drv) 158848b8605Smrg 159848b8605Smrg#define _EGL_CHECK_CONTEXT(disp, context, ret, drv) \ 160848b8605Smrg _EGL_CHECK_OBJECT(disp, Context, context, ret, drv) 161848b8605Smrg 162848b8605Smrg#define _EGL_CHECK_CONFIG(disp, conf, ret, drv) \ 163848b8605Smrg _EGL_CHECK_OBJECT(disp, Config, conf, ret, drv) 164848b8605Smrg 165848b8605Smrg#define _EGL_CHECK_SYNC(disp, s, ret, drv) \ 166848b8605Smrg _EGL_CHECK_OBJECT(disp, Sync, s, ret, drv) 167848b8605Smrg 168848b8605Smrg 169b8e80941Smrgstruct _egl_entrypoint { 170b8e80941Smrg const char *name; 171b8e80941Smrg _EGLProc function; 172b8e80941Smrg}; 173b8e80941Smrg 174b8e80941Smrg 175b8e80941Smrgstatic inline _EGLDriver * 176848b8605Smrg_eglCheckDisplay(_EGLDisplay *disp, const char *msg) 177848b8605Smrg{ 178848b8605Smrg if (!disp) { 179848b8605Smrg _eglError(EGL_BAD_DISPLAY, msg); 180848b8605Smrg return NULL; 181848b8605Smrg } 182848b8605Smrg if (!disp->Initialized) { 183848b8605Smrg _eglError(EGL_NOT_INITIALIZED, msg); 184848b8605Smrg return NULL; 185848b8605Smrg } 186848b8605Smrg return disp->Driver; 187848b8605Smrg} 188848b8605Smrg 189848b8605Smrg 190b8e80941Smrgstatic inline _EGLDriver * 191848b8605Smrg_eglCheckSurface(_EGLDisplay *disp, _EGLSurface *surf, const char *msg) 192848b8605Smrg{ 193848b8605Smrg _EGLDriver *drv = _eglCheckDisplay(disp, msg); 194848b8605Smrg if (!drv) 195848b8605Smrg return NULL; 196848b8605Smrg if (!surf) { 197848b8605Smrg _eglError(EGL_BAD_SURFACE, msg); 198848b8605Smrg return NULL; 199848b8605Smrg } 200848b8605Smrg return drv; 201848b8605Smrg} 202848b8605Smrg 203848b8605Smrg 204b8e80941Smrgstatic inline _EGLDriver * 205848b8605Smrg_eglCheckContext(_EGLDisplay *disp, _EGLContext *context, const char *msg) 206848b8605Smrg{ 207848b8605Smrg _EGLDriver *drv = _eglCheckDisplay(disp, msg); 208848b8605Smrg if (!drv) 209848b8605Smrg return NULL; 210848b8605Smrg if (!context) { 211848b8605Smrg _eglError(EGL_BAD_CONTEXT, msg); 212848b8605Smrg return NULL; 213848b8605Smrg } 214848b8605Smrg return drv; 215848b8605Smrg} 216848b8605Smrg 217848b8605Smrg 218b8e80941Smrgstatic inline _EGLDriver * 219848b8605Smrg_eglCheckConfig(_EGLDisplay *disp, _EGLConfig *conf, const char *msg) 220848b8605Smrg{ 221848b8605Smrg _EGLDriver *drv = _eglCheckDisplay(disp, msg); 222848b8605Smrg if (!drv) 223848b8605Smrg return NULL; 224848b8605Smrg if (!conf) { 225848b8605Smrg _eglError(EGL_BAD_CONFIG, msg); 226848b8605Smrg return NULL; 227848b8605Smrg } 228848b8605Smrg return drv; 229848b8605Smrg} 230848b8605Smrg 231848b8605Smrg 232b8e80941Smrgstatic inline _EGLDriver * 233848b8605Smrg_eglCheckSync(_EGLDisplay *disp, _EGLSync *s, const char *msg) 234848b8605Smrg{ 235848b8605Smrg _EGLDriver *drv = _eglCheckDisplay(disp, msg); 236848b8605Smrg if (!drv) 237848b8605Smrg return NULL; 238848b8605Smrg if (!s) { 239848b8605Smrg _eglError(EGL_BAD_PARAMETER, msg); 240848b8605Smrg return NULL; 241848b8605Smrg } 242848b8605Smrg return drv; 243848b8605Smrg} 244848b8605Smrg 245848b8605Smrg 246b8e80941Smrg/** 247b8e80941Smrg * Lookup and lock a display. 248b8e80941Smrg */ 249b8e80941Smrgstatic inline _EGLDisplay * 250b8e80941Smrg_eglLockDisplay(EGLDisplay dpy) 251848b8605Smrg{ 252b8e80941Smrg _EGLDisplay *disp = _eglLookupDisplay(dpy); 253b8e80941Smrg if (disp) 254b8e80941Smrg mtx_lock(&disp->Mutex); 255b8e80941Smrg return disp; 256848b8605Smrg} 257848b8605Smrg 258848b8605Smrg 259b8e80941Smrg/** 260b8e80941Smrg * Unlock a display. 261b8e80941Smrg */ 262b8e80941Smrgstatic inline void 263b8e80941Smrg_eglUnlockDisplay(_EGLDisplay *disp) 264848b8605Smrg{ 265b8e80941Smrg mtx_unlock(&disp->Mutex); 266848b8605Smrg} 267848b8605Smrg 268b8e80941Smrgstatic EGLBoolean 269b8e80941Smrg_eglSetFuncName(const char *funcName, _EGLDisplay *disp, EGLenum objectType, _EGLResource *object) 270b8e80941Smrg{ 271b8e80941Smrg _EGLThreadInfo *thr = _eglGetCurrentThread(); 272b8e80941Smrg if (!_eglIsCurrentThreadDummy()) { 273b8e80941Smrg thr->CurrentFuncName = funcName; 274b8e80941Smrg thr->CurrentObjectLabel = NULL; 275b8e80941Smrg 276b8e80941Smrg if (objectType == EGL_OBJECT_THREAD_KHR) 277b8e80941Smrg thr->CurrentObjectLabel = thr->Label; 278b8e80941Smrg else if (objectType == EGL_OBJECT_DISPLAY_KHR && disp) 279b8e80941Smrg thr->CurrentObjectLabel = disp->Label; 280b8e80941Smrg else if (object) 281b8e80941Smrg thr->CurrentObjectLabel = object->Label; 282b8e80941Smrg 283b8e80941Smrg return EGL_TRUE; 284b8e80941Smrg } 285848b8605Smrg 286b8e80941Smrg _eglDebugReport(EGL_BAD_ALLOC, funcName, EGL_DEBUG_MSG_CRITICAL_KHR, NULL); 287b8e80941Smrg return EGL_FALSE; 288b8e80941Smrg} 289848b8605Smrg 290b8e80941Smrg#define _EGL_FUNC_START(disp, objectType, object, ret) \ 291b8e80941Smrg do { \ 292b8e80941Smrg if (!_eglSetFuncName(__func__, disp, objectType, (_EGLResource *) object)) { \ 293b8e80941Smrg if (disp) \ 294b8e80941Smrg _eglUnlockDisplay(disp); \ 295b8e80941Smrg return ret; \ 296b8e80941Smrg } \ 297b8e80941Smrg } while(0) 298848b8605Smrg 299848b8605Smrg/** 300b8e80941Smrg * Convert an attribute list from EGLint[] to EGLAttrib[]. 301b8e80941Smrg * 302b8e80941Smrg * Return an EGL error code. The output parameter out_attrib_list is modified 303b8e80941Smrg * only on success. 304848b8605Smrg */ 305b8e80941Smrgstatic EGLint 306b8e80941Smrg_eglConvertIntsToAttribs(const EGLint *int_list, EGLAttrib **out_attrib_list) 307848b8605Smrg{ 308b8e80941Smrg size_t len = 0; 309b8e80941Smrg EGLAttrib *attrib_list; 310b8e80941Smrg 311b8e80941Smrg if (int_list) { 312b8e80941Smrg while (int_list[2*len] != EGL_NONE) 313b8e80941Smrg ++len; 314b8e80941Smrg } 315b8e80941Smrg 316b8e80941Smrg if (len == 0) { 317b8e80941Smrg *out_attrib_list = NULL; 318b8e80941Smrg return EGL_SUCCESS; 319b8e80941Smrg } 320b8e80941Smrg 321b8e80941Smrg if (2*len + 1 > SIZE_MAX / sizeof(EGLAttrib)) 322b8e80941Smrg return EGL_BAD_ALLOC; 323b8e80941Smrg 324b8e80941Smrg attrib_list = malloc((2*len + 1) * sizeof(EGLAttrib)); 325b8e80941Smrg if (!attrib_list) 326b8e80941Smrg return EGL_BAD_ALLOC; 327b8e80941Smrg 328b8e80941Smrg for (size_t i = 0; i < len; ++i) { 329b8e80941Smrg attrib_list[2*i + 0] = int_list[2*i + 0]; 330b8e80941Smrg attrib_list[2*i + 1] = int_list[2*i + 1]; 331b8e80941Smrg } 332b8e80941Smrg 333b8e80941Smrg attrib_list[2*len] = EGL_NONE; 334b8e80941Smrg 335b8e80941Smrg *out_attrib_list = attrib_list; 336b8e80941Smrg return EGL_SUCCESS; 337848b8605Smrg} 338848b8605Smrg 339848b8605Smrg 340b8e80941Smrgstatic EGLint * 341b8e80941Smrg_eglConvertAttribsToInt(const EGLAttrib *attr_list) 342848b8605Smrg{ 343b8e80941Smrg EGLint *int_attribs = NULL; 344b8e80941Smrg 345b8e80941Smrg /* Convert attributes from EGLAttrib[] to EGLint[] */ 346b8e80941Smrg if (attr_list) { 347b8e80941Smrg int i, size = 0; 348b8e80941Smrg 349b8e80941Smrg while (attr_list[size] != EGL_NONE) 350b8e80941Smrg size += 2; 351b8e80941Smrg 352b8e80941Smrg size += 1; /* add space for EGL_NONE */ 353b8e80941Smrg 354b8e80941Smrg int_attribs = calloc(size, sizeof(int_attribs[0])); 355b8e80941Smrg if (!int_attribs) 356b8e80941Smrg return NULL; 357b8e80941Smrg 358b8e80941Smrg for (i = 0; i < size; i++) 359b8e80941Smrg int_attribs[i] = attr_list[i]; 360b8e80941Smrg } 361b8e80941Smrg return int_attribs; 362848b8605Smrg} 363848b8605Smrg 364848b8605Smrg 365848b8605Smrg/** 366848b8605Smrg * This is typically the first EGL function that an application calls. 367848b8605Smrg * It associates a private _EGLDisplay object to the native display. 368848b8605Smrg */ 369848b8605SmrgEGLDisplay EGLAPIENTRY 370848b8605SmrgeglGetDisplay(EGLNativeDisplayType nativeDisplay) 371848b8605Smrg{ 372848b8605Smrg _EGLPlatformType plat; 373b8e80941Smrg _EGLDisplay *disp; 374848b8605Smrg void *native_display_ptr; 375848b8605Smrg 376b8e80941Smrg _EGL_FUNC_START(NULL, EGL_OBJECT_THREAD_KHR, NULL, EGL_NO_DISPLAY); 377b8e80941Smrg 378848b8605Smrg STATIC_ASSERT(sizeof(void*) == sizeof(nativeDisplay)); 379848b8605Smrg native_display_ptr = (void*) nativeDisplay; 380848b8605Smrg 381848b8605Smrg plat = _eglGetNativePlatform(native_display_ptr); 382b8e80941Smrg disp = _eglFindDisplay(plat, native_display_ptr); 383b8e80941Smrg return _eglGetDisplayHandle(disp); 384848b8605Smrg} 385848b8605Smrg 386b8e80941Smrgstatic EGLDisplay 387b8e80941Smrg_eglGetPlatformDisplayCommon(EGLenum platform, void *native_display, 388b8e80941Smrg const EGLAttrib *attrib_list) 389848b8605Smrg{ 390b8e80941Smrg _EGLDisplay *disp; 391848b8605Smrg 392848b8605Smrg switch (platform) { 393848b8605Smrg#ifdef HAVE_X11_PLATFORM 394848b8605Smrg case EGL_PLATFORM_X11_EXT: 395b8e80941Smrg disp = _eglGetX11Display((Display*) native_display, attrib_list); 396848b8605Smrg break; 397848b8605Smrg#endif 398848b8605Smrg#ifdef HAVE_DRM_PLATFORM 399848b8605Smrg case EGL_PLATFORM_GBM_MESA: 400b8e80941Smrg disp = _eglGetGbmDisplay((struct gbm_device*) native_display, 401848b8605Smrg attrib_list); 402848b8605Smrg break; 403848b8605Smrg#endif 404848b8605Smrg#ifdef HAVE_WAYLAND_PLATFORM 405848b8605Smrg case EGL_PLATFORM_WAYLAND_EXT: 406b8e80941Smrg disp = _eglGetWaylandDisplay((struct wl_display*) native_display, 407848b8605Smrg attrib_list); 408848b8605Smrg break; 409b8e80941Smrg#endif 410b8e80941Smrg#ifdef HAVE_SURFACELESS_PLATFORM 411b8e80941Smrg case EGL_PLATFORM_SURFACELESS_MESA: 412b8e80941Smrg disp = _eglGetSurfacelessDisplay(native_display, attrib_list); 413b8e80941Smrg break; 414848b8605Smrg#endif 415848b8605Smrg default: 416848b8605Smrg RETURN_EGL_ERROR(NULL, EGL_BAD_PARAMETER, NULL); 417848b8605Smrg } 418848b8605Smrg 419b8e80941Smrg return _eglGetDisplayHandle(disp); 420b8e80941Smrg} 421b8e80941Smrg 422b8e80941Smrgstatic EGLDisplay EGLAPIENTRY 423b8e80941SmrgeglGetPlatformDisplayEXT(EGLenum platform, void *native_display, 424b8e80941Smrg const EGLint *int_attribs) 425b8e80941Smrg{ 426b8e80941Smrg EGLAttrib *attrib_list; 427b8e80941Smrg EGLDisplay disp; 428b8e80941Smrg 429b8e80941Smrg _EGL_FUNC_START(NULL, EGL_OBJECT_THREAD_KHR, NULL, EGL_NO_DISPLAY); 430b8e80941Smrg 431b8e80941Smrg if (_eglConvertIntsToAttribs(int_attribs, &attrib_list) != EGL_SUCCESS) 432b8e80941Smrg RETURN_EGL_ERROR(NULL, EGL_BAD_ALLOC, NULL); 433b8e80941Smrg 434b8e80941Smrg disp = _eglGetPlatformDisplayCommon(platform, native_display, attrib_list); 435b8e80941Smrg free(attrib_list); 436b8e80941Smrg return disp; 437b8e80941Smrg} 438b8e80941Smrg 439b8e80941SmrgEGLDisplay EGLAPIENTRY 440b8e80941SmrgeglGetPlatformDisplay(EGLenum platform, void *native_display, 441b8e80941Smrg const EGLAttrib *attrib_list) 442b8e80941Smrg{ 443b8e80941Smrg _EGL_FUNC_START(NULL, EGL_OBJECT_THREAD_KHR, NULL, EGL_NO_DISPLAY); 444b8e80941Smrg return _eglGetPlatformDisplayCommon(platform, native_display, attrib_list); 445b8e80941Smrg} 446b8e80941Smrg 447b8e80941Smrg/** 448b8e80941Smrg * Copy the extension into the string and update the string pointer. 449b8e80941Smrg */ 450b8e80941Smrgstatic EGLint 451b8e80941Smrg_eglAppendExtension(char **str, const char *ext) 452b8e80941Smrg{ 453b8e80941Smrg char *s = *str; 454b8e80941Smrg size_t len = strlen(ext); 455b8e80941Smrg 456b8e80941Smrg if (s) { 457b8e80941Smrg memcpy(s, ext, len); 458b8e80941Smrg s[len++] = ' '; 459b8e80941Smrg s[len] = '\0'; 460b8e80941Smrg 461b8e80941Smrg *str += len; 462b8e80941Smrg } 463b8e80941Smrg else { 464b8e80941Smrg len++; 465b8e80941Smrg } 466b8e80941Smrg 467b8e80941Smrg return (EGLint) len; 468b8e80941Smrg} 469b8e80941Smrg 470b8e80941Smrg/** 471b8e80941Smrg * Examine the individual extension enable/disable flags and recompute 472b8e80941Smrg * the driver's Extensions string. 473b8e80941Smrg */ 474b8e80941Smrgstatic void 475b8e80941Smrg_eglCreateExtensionsString(_EGLDisplay *disp) 476b8e80941Smrg{ 477b8e80941Smrg#define _EGL_CHECK_EXTENSION(ext) \ 478b8e80941Smrg do { \ 479b8e80941Smrg if (disp->Extensions.ext) { \ 480b8e80941Smrg _eglAppendExtension(&exts, "EGL_" #ext); \ 481b8e80941Smrg assert(exts <= disp->ExtensionsString + _EGL_MAX_EXTENSIONS_LEN); \ 482b8e80941Smrg } \ 483b8e80941Smrg } while (0) 484b8e80941Smrg 485b8e80941Smrg char *exts = disp->ExtensionsString; 486b8e80941Smrg 487b8e80941Smrg /* Please keep these sorted alphabetically. */ 488b8e80941Smrg _EGL_CHECK_EXTENSION(ANDROID_blob_cache); 489b8e80941Smrg _EGL_CHECK_EXTENSION(ANDROID_framebuffer_target); 490b8e80941Smrg _EGL_CHECK_EXTENSION(ANDROID_image_native_buffer); 491b8e80941Smrg _EGL_CHECK_EXTENSION(ANDROID_native_fence_sync); 492b8e80941Smrg _EGL_CHECK_EXTENSION(ANDROID_recordable); 493b8e80941Smrg 494b8e80941Smrg _EGL_CHECK_EXTENSION(CHROMIUM_sync_control); 495b8e80941Smrg 496b8e80941Smrg _EGL_CHECK_EXTENSION(EXT_buffer_age); 497b8e80941Smrg _EGL_CHECK_EXTENSION(EXT_create_context_robustness); 498b8e80941Smrg _EGL_CHECK_EXTENSION(EXT_image_dma_buf_import); 499b8e80941Smrg _EGL_CHECK_EXTENSION(EXT_image_dma_buf_import_modifiers); 500b8e80941Smrg _EGL_CHECK_EXTENSION(EXT_surface_CTA861_3_metadata); 501b8e80941Smrg _EGL_CHECK_EXTENSION(EXT_surface_SMPTE2086_metadata); 502b8e80941Smrg _EGL_CHECK_EXTENSION(EXT_swap_buffers_with_damage); 503b8e80941Smrg 504b8e80941Smrg _EGL_CHECK_EXTENSION(IMG_context_priority); 505b8e80941Smrg 506b8e80941Smrg _EGL_CHECK_EXTENSION(KHR_cl_event2); 507b8e80941Smrg _EGL_CHECK_EXTENSION(KHR_config_attribs); 508b8e80941Smrg _EGL_CHECK_EXTENSION(KHR_context_flush_control); 509b8e80941Smrg _EGL_CHECK_EXTENSION(KHR_create_context); 510b8e80941Smrg _EGL_CHECK_EXTENSION(KHR_create_context_no_error); 511b8e80941Smrg _EGL_CHECK_EXTENSION(KHR_fence_sync); 512b8e80941Smrg _EGL_CHECK_EXTENSION(KHR_get_all_proc_addresses); 513b8e80941Smrg _EGL_CHECK_EXTENSION(KHR_gl_colorspace); 514b8e80941Smrg _EGL_CHECK_EXTENSION(KHR_gl_renderbuffer_image); 515b8e80941Smrg _EGL_CHECK_EXTENSION(KHR_gl_texture_2D_image); 516b8e80941Smrg _EGL_CHECK_EXTENSION(KHR_gl_texture_3D_image); 517b8e80941Smrg _EGL_CHECK_EXTENSION(KHR_gl_texture_cubemap_image); 518b8e80941Smrg if (disp->Extensions.KHR_image_base && disp->Extensions.KHR_image_pixmap) 519b8e80941Smrg disp->Extensions.KHR_image = EGL_TRUE; 520b8e80941Smrg _EGL_CHECK_EXTENSION(KHR_image); 521b8e80941Smrg _EGL_CHECK_EXTENSION(KHR_image_base); 522b8e80941Smrg _EGL_CHECK_EXTENSION(KHR_image_pixmap); 523b8e80941Smrg _EGL_CHECK_EXTENSION(KHR_mutable_render_buffer); 524b8e80941Smrg _EGL_CHECK_EXTENSION(KHR_no_config_context); 525b8e80941Smrg _EGL_CHECK_EXTENSION(KHR_partial_update); 526b8e80941Smrg _EGL_CHECK_EXTENSION(KHR_reusable_sync); 527b8e80941Smrg _EGL_CHECK_EXTENSION(KHR_surfaceless_context); 528b8e80941Smrg if (disp->Extensions.EXT_swap_buffers_with_damage) 529b8e80941Smrg _eglAppendExtension(&exts, "EGL_KHR_swap_buffers_with_damage"); 530b8e80941Smrg _EGL_CHECK_EXTENSION(EXT_pixel_format_float); 531b8e80941Smrg _EGL_CHECK_EXTENSION(KHR_wait_sync); 532b8e80941Smrg 533b8e80941Smrg if (disp->Extensions.KHR_no_config_context) 534b8e80941Smrg _eglAppendExtension(&exts, "EGL_MESA_configless_context"); 535b8e80941Smrg _EGL_CHECK_EXTENSION(MESA_drm_image); 536b8e80941Smrg _EGL_CHECK_EXTENSION(MESA_image_dma_buf_export); 537b8e80941Smrg _EGL_CHECK_EXTENSION(MESA_query_driver); 538b8e80941Smrg 539b8e80941Smrg _EGL_CHECK_EXTENSION(NOK_swap_region); 540b8e80941Smrg _EGL_CHECK_EXTENSION(NOK_texture_from_pixmap); 541b8e80941Smrg 542b8e80941Smrg _EGL_CHECK_EXTENSION(NV_post_sub_buffer); 543b8e80941Smrg 544b8e80941Smrg _EGL_CHECK_EXTENSION(WL_bind_wayland_display); 545b8e80941Smrg _EGL_CHECK_EXTENSION(WL_create_wayland_buffer_from_image); 546b8e80941Smrg 547b8e80941Smrg#undef _EGL_CHECK_EXTENSION 548b8e80941Smrg} 549b8e80941Smrg 550b8e80941Smrgstatic void 551b8e80941Smrg_eglCreateAPIsString(_EGLDisplay *disp) 552b8e80941Smrg{ 553b8e80941Smrg#define addstr(str) \ 554b8e80941Smrg { \ 555b8e80941Smrg const size_t old_len = strlen(disp->ClientAPIsString); \ 556b8e80941Smrg const size_t add_len = sizeof(str); \ 557b8e80941Smrg const size_t max_len = sizeof(disp->ClientAPIsString) - 1; \ 558b8e80941Smrg if (old_len + add_len <= max_len) \ 559b8e80941Smrg strcat(disp->ClientAPIsString, str " "); \ 560b8e80941Smrg else \ 561b8e80941Smrg assert(!"disp->ClientAPIsString is not large enough"); \ 562b8e80941Smrg } 563b8e80941Smrg 564b8e80941Smrg if (disp->ClientAPIs & EGL_OPENGL_BIT) 565b8e80941Smrg addstr("OpenGL"); 566b8e80941Smrg 567b8e80941Smrg if (disp->ClientAPIs & EGL_OPENGL_ES_BIT || 568b8e80941Smrg disp->ClientAPIs & EGL_OPENGL_ES2_BIT || 569b8e80941Smrg disp->ClientAPIs & EGL_OPENGL_ES3_BIT_KHR) { 570b8e80941Smrg addstr("OpenGL_ES"); 571b8e80941Smrg } 572b8e80941Smrg 573b8e80941Smrg if (disp->ClientAPIs & EGL_OPENVG_BIT) 574b8e80941Smrg addstr("OpenVG"); 575b8e80941Smrg 576b8e80941Smrg#undef addstr 577b8e80941Smrg} 578b8e80941Smrg 579b8e80941Smrgstatic void 580b8e80941Smrg_eglComputeVersion(_EGLDisplay *disp) 581b8e80941Smrg{ 582b8e80941Smrg disp->Version = 14; 583b8e80941Smrg 584b8e80941Smrg if (disp->Extensions.KHR_fence_sync && 585b8e80941Smrg disp->Extensions.KHR_cl_event2 && 586b8e80941Smrg disp->Extensions.KHR_wait_sync && 587b8e80941Smrg disp->Extensions.KHR_image_base && 588b8e80941Smrg disp->Extensions.KHR_gl_texture_2D_image && 589b8e80941Smrg disp->Extensions.KHR_gl_texture_3D_image && 590b8e80941Smrg disp->Extensions.KHR_gl_texture_cubemap_image && 591b8e80941Smrg disp->Extensions.KHR_gl_renderbuffer_image && 592b8e80941Smrg disp->Extensions.KHR_create_context && 593b8e80941Smrg disp->Extensions.EXT_create_context_robustness && 594b8e80941Smrg disp->Extensions.KHR_get_all_proc_addresses && 595b8e80941Smrg disp->Extensions.KHR_gl_colorspace && 596b8e80941Smrg disp->Extensions.KHR_surfaceless_context) 597b8e80941Smrg disp->Version = 15; 598848b8605Smrg} 599848b8605Smrg 600848b8605Smrg/** 601848b8605Smrg * This is typically the second EGL function that an application calls. 602848b8605Smrg * Here we load/initialize the actual hardware driver. 603848b8605Smrg */ 604848b8605SmrgEGLBoolean EGLAPIENTRY 605848b8605SmrgeglInitialize(EGLDisplay dpy, EGLint *major, EGLint *minor) 606848b8605Smrg{ 607848b8605Smrg _EGLDisplay *disp = _eglLockDisplay(dpy); 608848b8605Smrg 609b8e80941Smrg _EGL_FUNC_START(disp, EGL_OBJECT_DISPLAY_KHR, NULL, EGL_FALSE); 610b8e80941Smrg 611848b8605Smrg if (!disp) 612848b8605Smrg RETURN_EGL_ERROR(NULL, EGL_BAD_DISPLAY, EGL_FALSE); 613848b8605Smrg 614848b8605Smrg if (!disp->Initialized) { 615b8e80941Smrg if (!_eglMatchDriver(disp)) 616848b8605Smrg RETURN_EGL_ERROR(disp, EGL_NOT_INITIALIZED, EGL_FALSE); 617848b8605Smrg 618848b8605Smrg /* limit to APIs supported by core */ 619848b8605Smrg disp->ClientAPIs &= _EGL_API_ALL_BITS; 620b8e80941Smrg 621b8e80941Smrg /* EGL_KHR_get_all_proc_addresses is a corner-case extension. The spec 622b8e80941Smrg * classifies it as an EGL display extension, though conceptually it's an 623b8e80941Smrg * EGL client extension. 624b8e80941Smrg * 625b8e80941Smrg * From the EGL_KHR_get_all_proc_addresses spec: 626b8e80941Smrg * 627b8e80941Smrg * The EGL implementation must expose the name 628b8e80941Smrg * EGL_KHR_client_get_all_proc_addresses if and only if it exposes 629b8e80941Smrg * EGL_KHR_get_all_proc_addresses and supports 630b8e80941Smrg * EGL_EXT_client_extensions. 631b8e80941Smrg * 632b8e80941Smrg * Mesa unconditionally exposes both client extensions mentioned above, 633b8e80941Smrg * so the spec requires that each EGLDisplay unconditionally expose 634b8e80941Smrg * EGL_KHR_get_all_proc_addresses also. 635b8e80941Smrg */ 636b8e80941Smrg disp->Extensions.KHR_get_all_proc_addresses = EGL_TRUE; 637b8e80941Smrg 638b8e80941Smrg /* Extensions is used to provide EGL 1.3 functionality for 1.2 aware 639b8e80941Smrg * programs. It is driver agnostic and handled in the main EGL code. 640b8e80941Smrg */ 641b8e80941Smrg disp->Extensions.KHR_config_attribs = EGL_TRUE; 642b8e80941Smrg 643b8e80941Smrg _eglComputeVersion(disp); 644b8e80941Smrg _eglCreateExtensionsString(disp); 645b8e80941Smrg _eglCreateAPIsString(disp); 646b8e80941Smrg snprintf(disp->VersionString, sizeof(disp->VersionString), 647b8e80941Smrg "%d.%d", disp->Version / 10, disp->Version % 10); 648848b8605Smrg } 649848b8605Smrg 650848b8605Smrg /* Update applications version of major and minor if not NULL */ 651848b8605Smrg if ((major != NULL) && (minor != NULL)) { 652b8e80941Smrg *major = disp->Version / 10; 653b8e80941Smrg *minor = disp->Version % 10; 654848b8605Smrg } 655848b8605Smrg 656848b8605Smrg RETURN_EGL_SUCCESS(disp, EGL_TRUE); 657848b8605Smrg} 658848b8605Smrg 659848b8605Smrg 660848b8605SmrgEGLBoolean EGLAPIENTRY 661848b8605SmrgeglTerminate(EGLDisplay dpy) 662848b8605Smrg{ 663848b8605Smrg _EGLDisplay *disp = _eglLockDisplay(dpy); 664848b8605Smrg 665b8e80941Smrg _EGL_FUNC_START(disp, EGL_OBJECT_DISPLAY_KHR, NULL, EGL_FALSE); 666b8e80941Smrg 667848b8605Smrg if (!disp) 668848b8605Smrg RETURN_EGL_ERROR(NULL, EGL_BAD_DISPLAY, EGL_FALSE); 669848b8605Smrg 670848b8605Smrg if (disp->Initialized) { 671848b8605Smrg _EGLDriver *drv = disp->Driver; 672848b8605Smrg 673848b8605Smrg drv->API.Terminate(drv, disp); 674848b8605Smrg /* do not reset disp->Driver */ 675b8e80941Smrg disp->ClientAPIsString[0] = 0; 676848b8605Smrg disp->Initialized = EGL_FALSE; 677b8e80941Smrg 678b8e80941Smrg /* Reset blob cache funcs on terminate. */ 679b8e80941Smrg disp->BlobCacheSet = NULL; 680b8e80941Smrg disp->BlobCacheGet = NULL; 681848b8605Smrg } 682848b8605Smrg 683848b8605Smrg RETURN_EGL_SUCCESS(disp, EGL_TRUE); 684848b8605Smrg} 685848b8605Smrg 686848b8605Smrg 687848b8605Smrgconst char * EGLAPIENTRY 688848b8605SmrgeglQueryString(EGLDisplay dpy, EGLint name) 689848b8605Smrg{ 690848b8605Smrg _EGLDisplay *disp; 691848b8605Smrg _EGLDriver *drv; 692848b8605Smrg 693848b8605Smrg if (dpy == EGL_NO_DISPLAY && name == EGL_EXTENSIONS) { 694b8e80941Smrg const char *ret = _eglGetClientExtensionString(); 695b8e80941Smrg if (ret != NULL) 696b8e80941Smrg RETURN_EGL_SUCCESS(NULL, ret); 697b8e80941Smrg else 698b8e80941Smrg RETURN_EGL_ERROR(NULL, EGL_BAD_ALLOC, NULL); 699848b8605Smrg } 700848b8605Smrg 701848b8605Smrg disp = _eglLockDisplay(dpy); 702b8e80941Smrg _EGL_FUNC_START(disp, EGL_OBJECT_DISPLAY_KHR, NULL, NULL); 703848b8605Smrg _EGL_CHECK_DISPLAY(disp, NULL, drv); 704848b8605Smrg 705b8e80941Smrg switch (name) { 706b8e80941Smrg case EGL_VENDOR: 707b8e80941Smrg RETURN_EGL_SUCCESS(disp, _EGL_VENDOR_STRING); 708b8e80941Smrg case EGL_VERSION: 709b8e80941Smrg RETURN_EGL_SUCCESS(disp, disp->VersionString); 710b8e80941Smrg case EGL_EXTENSIONS: 711b8e80941Smrg RETURN_EGL_SUCCESS(disp, disp->ExtensionsString); 712b8e80941Smrg case EGL_CLIENT_APIS: 713b8e80941Smrg RETURN_EGL_SUCCESS(disp, disp->ClientAPIsString); 714b8e80941Smrg default: 715b8e80941Smrg RETURN_EGL_ERROR(disp, EGL_BAD_PARAMETER, NULL); 716b8e80941Smrg } 717848b8605Smrg} 718848b8605Smrg 719848b8605Smrg 720848b8605SmrgEGLBoolean EGLAPIENTRY 721848b8605SmrgeglGetConfigs(EGLDisplay dpy, EGLConfig *configs, 722848b8605Smrg EGLint config_size, EGLint *num_config) 723848b8605Smrg{ 724848b8605Smrg _EGLDisplay *disp = _eglLockDisplay(dpy); 725848b8605Smrg _EGLDriver *drv; 726848b8605Smrg EGLBoolean ret; 727848b8605Smrg 728b8e80941Smrg _EGL_FUNC_START(disp, EGL_OBJECT_DISPLAY_KHR, NULL, EGL_FALSE); 729b8e80941Smrg 730848b8605Smrg _EGL_CHECK_DISPLAY(disp, EGL_FALSE, drv); 731848b8605Smrg ret = drv->API.GetConfigs(drv, disp, configs, config_size, num_config); 732848b8605Smrg 733848b8605Smrg RETURN_EGL_EVAL(disp, ret); 734848b8605Smrg} 735848b8605Smrg 736848b8605Smrg 737848b8605SmrgEGLBoolean EGLAPIENTRY 738848b8605SmrgeglChooseConfig(EGLDisplay dpy, const EGLint *attrib_list, EGLConfig *configs, 739848b8605Smrg EGLint config_size, EGLint *num_config) 740848b8605Smrg{ 741848b8605Smrg _EGLDisplay *disp = _eglLockDisplay(dpy); 742848b8605Smrg _EGLDriver *drv; 743848b8605Smrg EGLBoolean ret; 744848b8605Smrg 745b8e80941Smrg _EGL_FUNC_START(disp, EGL_OBJECT_DISPLAY_KHR, NULL, EGL_FALSE); 746b8e80941Smrg 747848b8605Smrg _EGL_CHECK_DISPLAY(disp, EGL_FALSE, drv); 748848b8605Smrg ret = drv->API.ChooseConfig(drv, disp, attrib_list, configs, 749b8e80941Smrg config_size, num_config); 750848b8605Smrg 751848b8605Smrg RETURN_EGL_EVAL(disp, ret); 752848b8605Smrg} 753848b8605Smrg 754848b8605Smrg 755848b8605SmrgEGLBoolean EGLAPIENTRY 756848b8605SmrgeglGetConfigAttrib(EGLDisplay dpy, EGLConfig config, 757848b8605Smrg EGLint attribute, EGLint *value) 758848b8605Smrg{ 759848b8605Smrg _EGLDisplay *disp = _eglLockDisplay(dpy); 760848b8605Smrg _EGLConfig *conf = _eglLookupConfig(config, disp); 761848b8605Smrg _EGLDriver *drv; 762848b8605Smrg EGLBoolean ret; 763848b8605Smrg 764b8e80941Smrg _EGL_FUNC_START(disp, EGL_OBJECT_DISPLAY_KHR, NULL, EGL_FALSE); 765b8e80941Smrg 766848b8605Smrg _EGL_CHECK_CONFIG(disp, conf, EGL_FALSE, drv); 767848b8605Smrg ret = drv->API.GetConfigAttrib(drv, disp, conf, attribute, value); 768848b8605Smrg 769848b8605Smrg RETURN_EGL_EVAL(disp, ret); 770848b8605Smrg} 771848b8605Smrg 772848b8605Smrg 773848b8605SmrgEGLContext EGLAPIENTRY 774848b8605SmrgeglCreateContext(EGLDisplay dpy, EGLConfig config, EGLContext share_list, 775848b8605Smrg const EGLint *attrib_list) 776848b8605Smrg{ 777848b8605Smrg _EGLDisplay *disp = _eglLockDisplay(dpy); 778848b8605Smrg _EGLConfig *conf = _eglLookupConfig(config, disp); 779848b8605Smrg _EGLContext *share = _eglLookupContext(share_list, disp); 780848b8605Smrg _EGLDriver *drv; 781848b8605Smrg _EGLContext *context; 782848b8605Smrg EGLContext ret; 783848b8605Smrg 784b8e80941Smrg _EGL_FUNC_START(disp, EGL_OBJECT_DISPLAY_KHR, NULL, EGL_NO_CONTEXT); 785b8e80941Smrg 786848b8605Smrg _EGL_CHECK_DISPLAY(disp, EGL_NO_CONTEXT, drv); 787848b8605Smrg 788b8e80941Smrg if (config != EGL_NO_CONFIG_KHR) 789b8e80941Smrg _EGL_CHECK_CONFIG(disp, conf, EGL_NO_CONTEXT, drv); 790b8e80941Smrg else if (!disp->Extensions.KHR_no_config_context) 791848b8605Smrg RETURN_EGL_ERROR(disp, EGL_BAD_CONFIG, EGL_NO_CONTEXT); 792848b8605Smrg 793848b8605Smrg if (!share && share_list != EGL_NO_CONTEXT) 794848b8605Smrg RETURN_EGL_ERROR(disp, EGL_BAD_CONTEXT, EGL_NO_CONTEXT); 795848b8605Smrg 796848b8605Smrg context = drv->API.CreateContext(drv, disp, conf, share, attrib_list); 797848b8605Smrg ret = (context) ? _eglLinkContext(context) : EGL_NO_CONTEXT; 798848b8605Smrg 799848b8605Smrg RETURN_EGL_EVAL(disp, ret); 800848b8605Smrg} 801848b8605Smrg 802848b8605Smrg 803848b8605SmrgEGLBoolean EGLAPIENTRY 804848b8605SmrgeglDestroyContext(EGLDisplay dpy, EGLContext ctx) 805848b8605Smrg{ 806848b8605Smrg _EGLDisplay *disp = _eglLockDisplay(dpy); 807848b8605Smrg _EGLContext *context = _eglLookupContext(ctx, disp); 808848b8605Smrg _EGLDriver *drv; 809848b8605Smrg EGLBoolean ret; 810848b8605Smrg 811b8e80941Smrg _EGL_FUNC_START(disp, EGL_OBJECT_CONTEXT_KHR, context, EGL_FALSE); 812b8e80941Smrg 813848b8605Smrg _EGL_CHECK_CONTEXT(disp, context, EGL_FALSE, drv); 814848b8605Smrg _eglUnlinkContext(context); 815848b8605Smrg ret = drv->API.DestroyContext(drv, disp, context); 816848b8605Smrg 817848b8605Smrg RETURN_EGL_EVAL(disp, ret); 818848b8605Smrg} 819848b8605Smrg 820848b8605Smrg 821848b8605SmrgEGLBoolean EGLAPIENTRY 822848b8605SmrgeglMakeCurrent(EGLDisplay dpy, EGLSurface draw, EGLSurface read, 823848b8605Smrg EGLContext ctx) 824848b8605Smrg{ 825848b8605Smrg _EGLDisplay *disp = _eglLockDisplay(dpy); 826848b8605Smrg _EGLContext *context = _eglLookupContext(ctx, disp); 827848b8605Smrg _EGLSurface *draw_surf = _eglLookupSurface(draw, disp); 828848b8605Smrg _EGLSurface *read_surf = _eglLookupSurface(read, disp); 829848b8605Smrg _EGLDriver *drv; 830848b8605Smrg EGLBoolean ret; 831848b8605Smrg 832b8e80941Smrg _EGL_FUNC_START(disp, EGL_OBJECT_CONTEXT_KHR, context, EGL_FALSE); 833b8e80941Smrg 834848b8605Smrg if (!disp) 835848b8605Smrg RETURN_EGL_ERROR(disp, EGL_BAD_DISPLAY, EGL_FALSE); 836848b8605Smrg drv = disp->Driver; 837848b8605Smrg 838848b8605Smrg /* display is allowed to be uninitialized under certain condition */ 839848b8605Smrg if (!disp->Initialized) { 840848b8605Smrg if (draw != EGL_NO_SURFACE || read != EGL_NO_SURFACE || 841848b8605Smrg ctx != EGL_NO_CONTEXT) 842848b8605Smrg RETURN_EGL_ERROR(disp, EGL_BAD_DISPLAY, EGL_FALSE); 843848b8605Smrg } 844848b8605Smrg if (!drv) 845848b8605Smrg RETURN_EGL_SUCCESS(disp, EGL_TRUE); 846848b8605Smrg 847848b8605Smrg if (!context && ctx != EGL_NO_CONTEXT) 848848b8605Smrg RETURN_EGL_ERROR(disp, EGL_BAD_CONTEXT, EGL_FALSE); 849848b8605Smrg if (!draw_surf || !read_surf) { 850848b8605Smrg /* From the EGL 1.4 (20130211) spec: 851848b8605Smrg * 852848b8605Smrg * To release the current context without assigning a new one, set ctx 853848b8605Smrg * to EGL_NO_CONTEXT and set draw and read to EGL_NO_SURFACE. 854848b8605Smrg */ 855848b8605Smrg if (!disp->Extensions.KHR_surfaceless_context && ctx != EGL_NO_CONTEXT) 856848b8605Smrg RETURN_EGL_ERROR(disp, EGL_BAD_SURFACE, EGL_FALSE); 857848b8605Smrg 858848b8605Smrg if ((!draw_surf && draw != EGL_NO_SURFACE) || 859848b8605Smrg (!read_surf && read != EGL_NO_SURFACE)) 860848b8605Smrg RETURN_EGL_ERROR(disp, EGL_BAD_SURFACE, EGL_FALSE); 861848b8605Smrg if (draw_surf || read_surf) 862848b8605Smrg RETURN_EGL_ERROR(disp, EGL_BAD_MATCH, EGL_FALSE); 863848b8605Smrg } 864848b8605Smrg 865b8e80941Smrg /* If a native window underlying either draw or read is no longer valid, 866b8e80941Smrg * an EGL_BAD_NATIVE_WINDOW error is generated. 867b8e80941Smrg */ 868b8e80941Smrg if (draw_surf && draw_surf->Lost) 869b8e80941Smrg RETURN_EGL_ERROR(disp, EGL_BAD_NATIVE_WINDOW, EGL_FALSE); 870b8e80941Smrg if (read_surf && read_surf->Lost) 871b8e80941Smrg RETURN_EGL_ERROR(disp, EGL_BAD_NATIVE_WINDOW, EGL_FALSE); 872b8e80941Smrg 873848b8605Smrg ret = drv->API.MakeCurrent(drv, disp, draw_surf, read_surf, context); 874848b8605Smrg 875848b8605Smrg RETURN_EGL_EVAL(disp, ret); 876848b8605Smrg} 877848b8605Smrg 878848b8605Smrg 879848b8605SmrgEGLBoolean EGLAPIENTRY 880848b8605SmrgeglQueryContext(EGLDisplay dpy, EGLContext ctx, 881848b8605Smrg EGLint attribute, EGLint *value) 882848b8605Smrg{ 883848b8605Smrg _EGLDisplay *disp = _eglLockDisplay(dpy); 884848b8605Smrg _EGLContext *context = _eglLookupContext(ctx, disp); 885848b8605Smrg _EGLDriver *drv; 886848b8605Smrg EGLBoolean ret; 887848b8605Smrg 888b8e80941Smrg _EGL_FUNC_START(disp, EGL_OBJECT_CONTEXT_KHR, context, EGL_FALSE); 889b8e80941Smrg 890848b8605Smrg _EGL_CHECK_CONTEXT(disp, context, EGL_FALSE, drv); 891848b8605Smrg ret = drv->API.QueryContext(drv, disp, context, attribute, value); 892848b8605Smrg 893848b8605Smrg RETURN_EGL_EVAL(disp, ret); 894848b8605Smrg} 895848b8605Smrg 896848b8605Smrg 897848b8605Smrgstatic EGLSurface 898848b8605Smrg_eglCreateWindowSurfaceCommon(_EGLDisplay *disp, EGLConfig config, 899848b8605Smrg void *native_window, const EGLint *attrib_list) 900848b8605Smrg{ 901848b8605Smrg _EGLConfig *conf = _eglLookupConfig(config, disp); 902848b8605Smrg _EGLDriver *drv; 903848b8605Smrg _EGLSurface *surf; 904848b8605Smrg EGLSurface ret; 905848b8605Smrg 906848b8605Smrg 907848b8605Smrg if (native_window == NULL) 908848b8605Smrg RETURN_EGL_ERROR(disp, EGL_BAD_NATIVE_WINDOW, EGL_NO_SURFACE); 909848b8605Smrg 910b8e80941Smrg#ifdef HAVE_SURFACELESS_PLATFORM 911b8e80941Smrg if (disp && disp->Platform == _EGL_PLATFORM_SURFACELESS) { 912b8e80941Smrg /* From the EGL_MESA_platform_surfaceless spec (v1): 913b8e80941Smrg * 914b8e80941Smrg * eglCreatePlatformWindowSurface fails when called with a <display> 915b8e80941Smrg * that belongs to the surfaceless platform. It returns 916b8e80941Smrg * EGL_NO_SURFACE and generates EGL_BAD_NATIVE_WINDOW. The 917b8e80941Smrg * justification for this unconditional failure is that the 918b8e80941Smrg * surfaceless platform has no native windows, and therefore the 919b8e80941Smrg * <native_window> parameter is always invalid. 920b8e80941Smrg * 921b8e80941Smrg * This check must occur before checking the EGLConfig, which emits 922b8e80941Smrg * EGL_BAD_CONFIG. 923b8e80941Smrg */ 924b8e80941Smrg RETURN_EGL_ERROR(disp, EGL_BAD_NATIVE_WINDOW, EGL_NO_SURFACE); 925b8e80941Smrg } 926b8e80941Smrg#endif 927b8e80941Smrg 928b8e80941Smrg _EGL_CHECK_CONFIG(disp, conf, EGL_NO_SURFACE, drv); 929b8e80941Smrg 930b8e80941Smrg if ((conf->SurfaceType & EGL_WINDOW_BIT) == 0) 931b8e80941Smrg RETURN_EGL_ERROR(disp, EGL_BAD_MATCH, EGL_NO_SURFACE); 932b8e80941Smrg 933848b8605Smrg surf = drv->API.CreateWindowSurface(drv, disp, conf, native_window, 934848b8605Smrg attrib_list); 935848b8605Smrg ret = (surf) ? _eglLinkSurface(surf) : EGL_NO_SURFACE; 936848b8605Smrg 937848b8605Smrg RETURN_EGL_EVAL(disp, ret); 938848b8605Smrg} 939848b8605Smrg 940848b8605Smrg 941848b8605SmrgEGLSurface EGLAPIENTRY 942848b8605SmrgeglCreateWindowSurface(EGLDisplay dpy, EGLConfig config, 943848b8605Smrg EGLNativeWindowType window, const EGLint *attrib_list) 944848b8605Smrg{ 945848b8605Smrg _EGLDisplay *disp = _eglLockDisplay(dpy); 946b8e80941Smrg 947b8e80941Smrg _EGL_FUNC_START(disp, EGL_OBJECT_DISPLAY_KHR, NULL, EGL_NO_SURFACE); 948848b8605Smrg STATIC_ASSERT(sizeof(void*) == sizeof(window)); 949848b8605Smrg return _eglCreateWindowSurfaceCommon(disp, config, (void*) window, 950848b8605Smrg attrib_list); 951848b8605Smrg} 952848b8605Smrg 953b8e80941Smrgstatic void * 954b8e80941Smrg_fixupNativeWindow(_EGLDisplay *disp, void *native_window) 955848b8605Smrg{ 956848b8605Smrg#ifdef HAVE_X11_PLATFORM 957b8e80941Smrg if (disp && disp->Platform == _EGL_PLATFORM_X11 && native_window != NULL) { 958848b8605Smrg /* The `native_window` parameter for the X11 platform differs between 959848b8605Smrg * eglCreateWindowSurface() and eglCreatePlatformPixmapSurfaceEXT(). In 960848b8605Smrg * eglCreateWindowSurface(), the type of `native_window` is an Xlib 961848b8605Smrg * `Window`. In eglCreatePlatformWindowSurfaceEXT(), the type is 962848b8605Smrg * `Window*`. Convert `Window*` to `Window` because that's what 963848b8605Smrg * dri2_x11_create_window_surface() expects. 964848b8605Smrg */ 965b8e80941Smrg return (void *)(* (Window*) native_window); 966848b8605Smrg } 967848b8605Smrg#endif 968b8e80941Smrg return native_window; 969b8e80941Smrg} 970b8e80941Smrg 971b8e80941Smrgstatic EGLSurface EGLAPIENTRY 972b8e80941SmrgeglCreatePlatformWindowSurfaceEXT(EGLDisplay dpy, EGLConfig config, 973b8e80941Smrg void *native_window, 974b8e80941Smrg const EGLint *attrib_list) 975b8e80941Smrg{ 976b8e80941Smrg _EGLDisplay *disp = _eglLockDisplay(dpy); 977b8e80941Smrg 978b8e80941Smrg native_window = _fixupNativeWindow(disp, native_window); 979848b8605Smrg 980b8e80941Smrg _EGL_FUNC_START(disp, EGL_OBJECT_DISPLAY_KHR, NULL, EGL_NO_SURFACE); 981848b8605Smrg return _eglCreateWindowSurfaceCommon(disp, config, native_window, 982848b8605Smrg attrib_list); 983848b8605Smrg} 984848b8605Smrg 985848b8605Smrg 986b8e80941SmrgEGLSurface EGLAPIENTRY 987b8e80941SmrgeglCreatePlatformWindowSurface(EGLDisplay dpy, EGLConfig config, 988b8e80941Smrg void *native_window, 989b8e80941Smrg const EGLAttrib *attrib_list) 990b8e80941Smrg{ 991b8e80941Smrg _EGLDisplay *disp = _eglLockDisplay(dpy); 992b8e80941Smrg EGLSurface surface; 993b8e80941Smrg EGLint *int_attribs; 994b8e80941Smrg 995b8e80941Smrg _EGL_FUNC_START(disp, EGL_OBJECT_DISPLAY_KHR, NULL, EGL_NO_SURFACE); 996b8e80941Smrg 997b8e80941Smrg int_attribs = _eglConvertAttribsToInt(attrib_list); 998b8e80941Smrg if (attrib_list && !int_attribs) 999b8e80941Smrg RETURN_EGL_ERROR(disp, EGL_BAD_ALLOC, EGL_NO_SURFACE); 1000b8e80941Smrg 1001b8e80941Smrg native_window = _fixupNativeWindow(disp, native_window); 1002b8e80941Smrg surface = _eglCreateWindowSurfaceCommon(disp, config, native_window, 1003b8e80941Smrg int_attribs); 1004b8e80941Smrg free(int_attribs); 1005b8e80941Smrg return surface; 1006b8e80941Smrg} 1007b8e80941Smrg 1008b8e80941Smrgstatic void * 1009b8e80941Smrg_fixupNativePixmap(_EGLDisplay *disp, void *native_pixmap) 1010b8e80941Smrg{ 1011b8e80941Smrg#ifdef HAVE_X11_PLATFORM 1012b8e80941Smrg /* The `native_pixmap` parameter for the X11 platform differs between 1013b8e80941Smrg * eglCreatePixmapSurface() and eglCreatePlatformPixmapSurfaceEXT(). In 1014b8e80941Smrg * eglCreatePixmapSurface(), the type of `native_pixmap` is an Xlib 1015b8e80941Smrg * `Pixmap`. In eglCreatePlatformPixmapSurfaceEXT(), the type is 1016b8e80941Smrg * `Pixmap*`. Convert `Pixmap*` to `Pixmap` because that's what 1017b8e80941Smrg * dri2_x11_create_pixmap_surface() expects. 1018b8e80941Smrg */ 1019b8e80941Smrg if (disp && disp->Platform == _EGL_PLATFORM_X11 && native_pixmap != NULL) 1020b8e80941Smrg return (void *)(* (Pixmap*) native_pixmap); 1021b8e80941Smrg#endif 1022b8e80941Smrg return native_pixmap; 1023b8e80941Smrg} 1024b8e80941Smrg 1025848b8605Smrgstatic EGLSurface 1026848b8605Smrg_eglCreatePixmapSurfaceCommon(_EGLDisplay *disp, EGLConfig config, 1027848b8605Smrg void *native_pixmap, const EGLint *attrib_list) 1028848b8605Smrg{ 1029848b8605Smrg _EGLConfig *conf = _eglLookupConfig(config, disp); 1030848b8605Smrg _EGLDriver *drv; 1031848b8605Smrg _EGLSurface *surf; 1032848b8605Smrg EGLSurface ret; 1033848b8605Smrg 1034b8e80941Smrg#if HAVE_SURFACELESS_PLATFORM 1035b8e80941Smrg if (disp && disp->Platform == _EGL_PLATFORM_SURFACELESS) { 1036b8e80941Smrg /* From the EGL_MESA_platform_surfaceless spec (v1): 1037b8e80941Smrg * 1038b8e80941Smrg * [Like eglCreatePlatformWindowSurface,] eglCreatePlatformPixmapSurface 1039b8e80941Smrg * also fails when called with a <display> that belongs to the 1040b8e80941Smrg * surfaceless platform. It returns EGL_NO_SURFACE and generates 1041b8e80941Smrg * EGL_BAD_NATIVE_PIXMAP. 1042b8e80941Smrg * 1043b8e80941Smrg * This check must occur before checking the EGLConfig, which emits 1044b8e80941Smrg * EGL_BAD_CONFIG. 1045b8e80941Smrg */ 1046b8e80941Smrg RETURN_EGL_ERROR(disp, EGL_BAD_NATIVE_PIXMAP, EGL_NO_SURFACE); 1047b8e80941Smrg } 1048b8e80941Smrg#endif 1049b8e80941Smrg 1050848b8605Smrg _EGL_CHECK_CONFIG(disp, conf, EGL_NO_SURFACE, drv); 1051b8e80941Smrg 1052b8e80941Smrg if ((conf->SurfaceType & EGL_PIXMAP_BIT) == 0) 1053b8e80941Smrg RETURN_EGL_ERROR(disp, EGL_BAD_MATCH, EGL_NO_SURFACE); 1054b8e80941Smrg 1055b8e80941Smrg if (native_pixmap == NULL) 1056b8e80941Smrg RETURN_EGL_ERROR(disp, EGL_BAD_NATIVE_PIXMAP, EGL_NO_SURFACE); 1057b8e80941Smrg 1058848b8605Smrg surf = drv->API.CreatePixmapSurface(drv, disp, conf, native_pixmap, 1059848b8605Smrg attrib_list); 1060848b8605Smrg ret = (surf) ? _eglLinkSurface(surf) : EGL_NO_SURFACE; 1061848b8605Smrg 1062848b8605Smrg RETURN_EGL_EVAL(disp, ret); 1063848b8605Smrg} 1064848b8605Smrg 1065848b8605Smrg 1066848b8605SmrgEGLSurface EGLAPIENTRY 1067848b8605SmrgeglCreatePixmapSurface(EGLDisplay dpy, EGLConfig config, 1068848b8605Smrg EGLNativePixmapType pixmap, const EGLint *attrib_list) 1069848b8605Smrg{ 1070848b8605Smrg _EGLDisplay *disp = _eglLockDisplay(dpy); 1071b8e80941Smrg 1072b8e80941Smrg _EGL_FUNC_START(disp, EGL_OBJECT_DISPLAY_KHR, NULL, EGL_NO_SURFACE); 1073848b8605Smrg STATIC_ASSERT(sizeof(void*) == sizeof(pixmap)); 1074848b8605Smrg return _eglCreatePixmapSurfaceCommon(disp, config, (void*) pixmap, 1075b8e80941Smrg attrib_list); 1076848b8605Smrg} 1077848b8605Smrg 1078b8e80941Smrgstatic EGLSurface EGLAPIENTRY 1079848b8605SmrgeglCreatePlatformPixmapSurfaceEXT(EGLDisplay dpy, EGLConfig config, 1080b8e80941Smrg void *native_pixmap, 1081b8e80941Smrg const EGLint *attrib_list) 1082848b8605Smrg{ 1083848b8605Smrg _EGLDisplay *disp = _eglLockDisplay(dpy); 1084848b8605Smrg 1085b8e80941Smrg _EGL_FUNC_START(disp, EGL_OBJECT_DISPLAY_KHR, NULL, EGL_NO_SURFACE); 1086b8e80941Smrg native_pixmap = _fixupNativePixmap(disp, native_pixmap); 1087848b8605Smrg return _eglCreatePixmapSurfaceCommon(disp, config, native_pixmap, 1088848b8605Smrg attrib_list); 1089848b8605Smrg} 1090848b8605Smrg 1091848b8605Smrg 1092b8e80941SmrgEGLSurface EGLAPIENTRY 1093b8e80941SmrgeglCreatePlatformPixmapSurface(EGLDisplay dpy, EGLConfig config, 1094b8e80941Smrg void *native_pixmap, 1095b8e80941Smrg const EGLAttrib *attrib_list) 1096b8e80941Smrg{ 1097b8e80941Smrg _EGLDisplay *disp = _eglLockDisplay(dpy); 1098b8e80941Smrg EGLSurface surface; 1099b8e80941Smrg EGLint *int_attribs; 1100b8e80941Smrg 1101b8e80941Smrg _EGL_FUNC_START(disp, EGL_OBJECT_DISPLAY_KHR, NULL, EGL_NO_SURFACE); 1102b8e80941Smrg 1103b8e80941Smrg int_attribs = _eglConvertAttribsToInt(attrib_list); 1104b8e80941Smrg if (attrib_list && !int_attribs) 1105b8e80941Smrg RETURN_EGL_ERROR(disp, EGL_BAD_ALLOC, EGL_NO_SURFACE); 1106b8e80941Smrg 1107b8e80941Smrg native_pixmap = _fixupNativePixmap(disp, native_pixmap); 1108b8e80941Smrg surface = _eglCreatePixmapSurfaceCommon(disp, config, native_pixmap, 1109b8e80941Smrg int_attribs); 1110b8e80941Smrg free(int_attribs); 1111b8e80941Smrg return surface; 1112b8e80941Smrg} 1113b8e80941Smrg 1114b8e80941Smrg 1115848b8605SmrgEGLSurface EGLAPIENTRY 1116848b8605SmrgeglCreatePbufferSurface(EGLDisplay dpy, EGLConfig config, 1117848b8605Smrg const EGLint *attrib_list) 1118848b8605Smrg{ 1119848b8605Smrg _EGLDisplay *disp = _eglLockDisplay(dpy); 1120848b8605Smrg _EGLConfig *conf = _eglLookupConfig(config, disp); 1121848b8605Smrg _EGLDriver *drv; 1122848b8605Smrg _EGLSurface *surf; 1123848b8605Smrg EGLSurface ret; 1124848b8605Smrg 1125b8e80941Smrg _EGL_FUNC_START(disp, EGL_OBJECT_DISPLAY_KHR, NULL, EGL_NO_SURFACE); 1126848b8605Smrg _EGL_CHECK_CONFIG(disp, conf, EGL_NO_SURFACE, drv); 1127848b8605Smrg 1128b8e80941Smrg if ((conf->SurfaceType & EGL_PBUFFER_BIT) == 0) 1129b8e80941Smrg RETURN_EGL_ERROR(disp, EGL_BAD_MATCH, EGL_NO_SURFACE); 1130b8e80941Smrg 1131848b8605Smrg surf = drv->API.CreatePbufferSurface(drv, disp, conf, attrib_list); 1132848b8605Smrg ret = (surf) ? _eglLinkSurface(surf) : EGL_NO_SURFACE; 1133848b8605Smrg 1134848b8605Smrg RETURN_EGL_EVAL(disp, ret); 1135848b8605Smrg} 1136848b8605Smrg 1137848b8605Smrg 1138848b8605SmrgEGLBoolean EGLAPIENTRY 1139848b8605SmrgeglDestroySurface(EGLDisplay dpy, EGLSurface surface) 1140848b8605Smrg{ 1141848b8605Smrg _EGLDisplay *disp = _eglLockDisplay(dpy); 1142848b8605Smrg _EGLSurface *surf = _eglLookupSurface(surface, disp); 1143848b8605Smrg _EGLDriver *drv; 1144848b8605Smrg EGLBoolean ret; 1145848b8605Smrg 1146b8e80941Smrg _EGL_FUNC_START(disp, EGL_OBJECT_SURFACE_KHR, surf, EGL_FALSE); 1147848b8605Smrg _EGL_CHECK_SURFACE(disp, surf, EGL_FALSE, drv); 1148848b8605Smrg _eglUnlinkSurface(surf); 1149848b8605Smrg ret = drv->API.DestroySurface(drv, disp, surf); 1150848b8605Smrg 1151848b8605Smrg RETURN_EGL_EVAL(disp, ret); 1152848b8605Smrg} 1153848b8605Smrg 1154848b8605SmrgEGLBoolean EGLAPIENTRY 1155848b8605SmrgeglQuerySurface(EGLDisplay dpy, EGLSurface surface, 1156848b8605Smrg EGLint attribute, EGLint *value) 1157848b8605Smrg{ 1158848b8605Smrg _EGLDisplay *disp = _eglLockDisplay(dpy); 1159848b8605Smrg _EGLSurface *surf = _eglLookupSurface(surface, disp); 1160848b8605Smrg _EGLDriver *drv; 1161848b8605Smrg EGLBoolean ret; 1162848b8605Smrg 1163b8e80941Smrg _EGL_FUNC_START(disp, EGL_OBJECT_SURFACE_KHR, surf, EGL_FALSE); 1164848b8605Smrg _EGL_CHECK_SURFACE(disp, surf, EGL_FALSE, drv); 1165848b8605Smrg ret = drv->API.QuerySurface(drv, disp, surf, attribute, value); 1166848b8605Smrg 1167848b8605Smrg RETURN_EGL_EVAL(disp, ret); 1168848b8605Smrg} 1169848b8605Smrg 1170848b8605SmrgEGLBoolean EGLAPIENTRY 1171848b8605SmrgeglSurfaceAttrib(EGLDisplay dpy, EGLSurface surface, 1172848b8605Smrg EGLint attribute, EGLint value) 1173848b8605Smrg{ 1174848b8605Smrg _EGLDisplay *disp = _eglLockDisplay(dpy); 1175848b8605Smrg _EGLSurface *surf = _eglLookupSurface(surface, disp); 1176848b8605Smrg _EGLDriver *drv; 1177848b8605Smrg EGLBoolean ret; 1178848b8605Smrg 1179b8e80941Smrg _EGL_FUNC_START(disp, EGL_OBJECT_SURFACE_KHR, surf, EGL_FALSE); 1180848b8605Smrg _EGL_CHECK_SURFACE(disp, surf, EGL_FALSE, drv); 1181848b8605Smrg ret = drv->API.SurfaceAttrib(drv, disp, surf, attribute, value); 1182848b8605Smrg 1183848b8605Smrg RETURN_EGL_EVAL(disp, ret); 1184848b8605Smrg} 1185848b8605Smrg 1186848b8605Smrg 1187848b8605SmrgEGLBoolean EGLAPIENTRY 1188848b8605SmrgeglBindTexImage(EGLDisplay dpy, EGLSurface surface, EGLint buffer) 1189848b8605Smrg{ 1190848b8605Smrg _EGLDisplay *disp = _eglLockDisplay(dpy); 1191848b8605Smrg _EGLSurface *surf = _eglLookupSurface(surface, disp); 1192848b8605Smrg _EGLDriver *drv; 1193848b8605Smrg EGLBoolean ret; 1194848b8605Smrg 1195b8e80941Smrg _EGL_FUNC_START(disp, EGL_OBJECT_SURFACE_KHR, surf, EGL_FALSE); 1196848b8605Smrg _EGL_CHECK_SURFACE(disp, surf, EGL_FALSE, drv); 1197848b8605Smrg ret = drv->API.BindTexImage(drv, disp, surf, buffer); 1198848b8605Smrg 1199848b8605Smrg RETURN_EGL_EVAL(disp, ret); 1200848b8605Smrg} 1201848b8605Smrg 1202848b8605Smrg 1203848b8605SmrgEGLBoolean EGLAPIENTRY 1204848b8605SmrgeglReleaseTexImage(EGLDisplay dpy, EGLSurface surface, EGLint buffer) 1205848b8605Smrg{ 1206848b8605Smrg _EGLDisplay *disp = _eglLockDisplay(dpy); 1207848b8605Smrg _EGLSurface *surf = _eglLookupSurface(surface, disp); 1208848b8605Smrg _EGLDriver *drv; 1209848b8605Smrg EGLBoolean ret; 1210848b8605Smrg 1211b8e80941Smrg _EGL_FUNC_START(disp, EGL_OBJECT_SURFACE_KHR, surf, EGL_FALSE); 1212848b8605Smrg _EGL_CHECK_SURFACE(disp, surf, EGL_FALSE, drv); 1213848b8605Smrg ret = drv->API.ReleaseTexImage(drv, disp, surf, buffer); 1214848b8605Smrg 1215848b8605Smrg RETURN_EGL_EVAL(disp, ret); 1216848b8605Smrg} 1217848b8605Smrg 1218848b8605Smrg 1219848b8605SmrgEGLBoolean EGLAPIENTRY 1220848b8605SmrgeglSwapInterval(EGLDisplay dpy, EGLint interval) 1221848b8605Smrg{ 1222848b8605Smrg _EGLDisplay *disp = _eglLockDisplay(dpy); 1223848b8605Smrg _EGLContext *ctx = _eglGetCurrentContext(); 1224b8e80941Smrg _EGLSurface *surf = ctx ? ctx->DrawSurface : NULL; 1225848b8605Smrg _EGLDriver *drv; 1226848b8605Smrg EGLBoolean ret; 1227848b8605Smrg 1228b8e80941Smrg _EGL_FUNC_START(disp, EGL_OBJECT_SURFACE_KHR, surf, EGL_FALSE); 1229848b8605Smrg _EGL_CHECK_DISPLAY(disp, EGL_FALSE, drv); 1230848b8605Smrg 1231848b8605Smrg if (_eglGetContextHandle(ctx) == EGL_NO_CONTEXT || 1232848b8605Smrg ctx->Resource.Display != disp) 1233848b8605Smrg RETURN_EGL_ERROR(disp, EGL_BAD_CONTEXT, EGL_FALSE); 1234848b8605Smrg 1235848b8605Smrg if (_eglGetSurfaceHandle(surf) == EGL_NO_SURFACE) 1236848b8605Smrg RETURN_EGL_ERROR(disp, EGL_BAD_SURFACE, EGL_FALSE); 1237848b8605Smrg 1238b8e80941Smrg if (surf->Type != EGL_WINDOW_BIT) 1239b8e80941Smrg RETURN_EGL_EVAL(disp, EGL_TRUE); 1240b8e80941Smrg 1241b8e80941Smrg interval = CLAMP(interval, 1242b8e80941Smrg surf->Config->MinSwapInterval, 1243b8e80941Smrg surf->Config->MaxSwapInterval); 1244b8e80941Smrg 1245b8e80941Smrg if (surf->SwapInterval != interval) 1246b8e80941Smrg ret = drv->API.SwapInterval(drv, disp, surf, interval); 1247b8e80941Smrg else 1248b8e80941Smrg ret = EGL_TRUE; 1249b8e80941Smrg 1250b8e80941Smrg if (ret) 1251b8e80941Smrg surf->SwapInterval = interval; 1252848b8605Smrg 1253848b8605Smrg RETURN_EGL_EVAL(disp, ret); 1254848b8605Smrg} 1255848b8605Smrg 1256848b8605Smrg 1257848b8605SmrgEGLBoolean EGLAPIENTRY 1258848b8605SmrgeglSwapBuffers(EGLDisplay dpy, EGLSurface surface) 1259848b8605Smrg{ 1260848b8605Smrg _EGLContext *ctx = _eglGetCurrentContext(); 1261848b8605Smrg _EGLDisplay *disp = _eglLockDisplay(dpy); 1262848b8605Smrg _EGLSurface *surf = _eglLookupSurface(surface, disp); 1263848b8605Smrg _EGLDriver *drv; 1264848b8605Smrg EGLBoolean ret; 1265848b8605Smrg 1266b8e80941Smrg _EGL_FUNC_START(disp, EGL_OBJECT_SURFACE_KHR, surf, EGL_FALSE); 1267848b8605Smrg _EGL_CHECK_SURFACE(disp, surf, EGL_FALSE, drv); 1268848b8605Smrg 1269848b8605Smrg /* surface must be bound to current context in EGL 1.4 */ 1270b8e80941Smrg #ifndef _EGL_BUILT_IN_DRIVER_HAIKU 1271848b8605Smrg if (_eglGetContextHandle(ctx) == EGL_NO_CONTEXT || 1272848b8605Smrg surf != ctx->DrawSurface) 1273848b8605Smrg RETURN_EGL_ERROR(disp, EGL_BAD_SURFACE, EGL_FALSE); 1274b8e80941Smrg #endif 1275b8e80941Smrg 1276b8e80941Smrg if (surf->Type != EGL_WINDOW_BIT) 1277b8e80941Smrg RETURN_EGL_EVAL(disp, EGL_TRUE); 1278b8e80941Smrg 1279b8e80941Smrg /* From the EGL 1.5 spec: 1280b8e80941Smrg * 1281b8e80941Smrg * If eglSwapBuffers is called and the native window associated with 1282b8e80941Smrg * surface is no longer valid, an EGL_BAD_NATIVE_WINDOW error is 1283b8e80941Smrg * generated. 1284b8e80941Smrg */ 1285b8e80941Smrg if (surf->Lost) 1286b8e80941Smrg RETURN_EGL_ERROR(disp, EGL_BAD_NATIVE_WINDOW, EGL_FALSE); 1287848b8605Smrg 1288848b8605Smrg ret = drv->API.SwapBuffers(drv, disp, surf); 1289848b8605Smrg 1290b8e80941Smrg /* EGL_KHR_partial_update 1291b8e80941Smrg * Frame boundary successfully reached, 1292b8e80941Smrg * reset damage region and reset BufferAgeRead 1293b8e80941Smrg */ 1294b8e80941Smrg if (ret) { 1295b8e80941Smrg surf->SetDamageRegionCalled = EGL_FALSE; 1296b8e80941Smrg surf->BufferAgeRead = EGL_FALSE; 1297b8e80941Smrg } 1298b8e80941Smrg 1299848b8605Smrg RETURN_EGL_EVAL(disp, ret); 1300848b8605Smrg} 1301848b8605Smrg 1302848b8605Smrg 1303b8e80941Smrgstatic EGLBoolean 1304b8e80941Smrg_eglSwapBuffersWithDamageCommon(_EGLDisplay *disp, _EGLSurface *surf, 1305b8e80941Smrg EGLint *rects, EGLint n_rects) 1306848b8605Smrg{ 1307848b8605Smrg _EGLContext *ctx = _eglGetCurrentContext(); 1308848b8605Smrg _EGLDriver *drv; 1309848b8605Smrg EGLBoolean ret; 1310848b8605Smrg 1311848b8605Smrg _EGL_CHECK_SURFACE(disp, surf, EGL_FALSE, drv); 1312848b8605Smrg 1313848b8605Smrg /* surface must be bound to current context in EGL 1.4 */ 1314848b8605Smrg if (_eglGetContextHandle(ctx) == EGL_NO_CONTEXT || 1315848b8605Smrg surf != ctx->DrawSurface) 1316848b8605Smrg RETURN_EGL_ERROR(disp, EGL_BAD_SURFACE, EGL_FALSE); 1317848b8605Smrg 1318b8e80941Smrg if (surf->Type != EGL_WINDOW_BIT) 1319b8e80941Smrg RETURN_EGL_EVAL(disp, EGL_TRUE); 1320b8e80941Smrg 1321848b8605Smrg if ((n_rects > 0 && rects == NULL) || n_rects < 0) 1322848b8605Smrg RETURN_EGL_ERROR(disp, EGL_BAD_PARAMETER, EGL_FALSE); 1323848b8605Smrg 1324848b8605Smrg ret = drv->API.SwapBuffersWithDamageEXT(drv, disp, surf, rects, n_rects); 1325848b8605Smrg 1326b8e80941Smrg /* EGL_KHR_partial_update 1327b8e80941Smrg * Frame boundary successfully reached, 1328b8e80941Smrg * reset damage region and reset BufferAgeRead 1329b8e80941Smrg */ 1330b8e80941Smrg if (ret) { 1331b8e80941Smrg surf->SetDamageRegionCalled = EGL_FALSE; 1332b8e80941Smrg surf->BufferAgeRead = EGL_FALSE; 1333b8e80941Smrg } 1334b8e80941Smrg 1335848b8605Smrg RETURN_EGL_EVAL(disp, ret); 1336848b8605Smrg} 1337848b8605Smrg 1338b8e80941Smrgstatic EGLBoolean EGLAPIENTRY 1339b8e80941SmrgeglSwapBuffersWithDamageEXT(EGLDisplay dpy, EGLSurface surface, 1340b8e80941Smrg EGLint *rects, EGLint n_rects) 1341b8e80941Smrg{ 1342b8e80941Smrg _EGLDisplay *disp = _eglLockDisplay(dpy); 1343b8e80941Smrg _EGLSurface *surf = _eglLookupSurface(surface, disp); 1344b8e80941Smrg _EGL_FUNC_START(disp, EGL_OBJECT_SURFACE_KHR, surf, EGL_FALSE); 1345b8e80941Smrg return _eglSwapBuffersWithDamageCommon(disp, surf, rects, n_rects); 1346b8e80941Smrg} 1347b8e80941Smrg 1348b8e80941Smrgstatic EGLBoolean EGLAPIENTRY 1349b8e80941SmrgeglSwapBuffersWithDamageKHR(EGLDisplay dpy, EGLSurface surface, 1350b8e80941Smrg EGLint *rects, EGLint n_rects) 1351b8e80941Smrg{ 1352b8e80941Smrg _EGLDisplay *disp = _eglLockDisplay(dpy); 1353b8e80941Smrg _EGLSurface *surf = _eglLookupSurface(surface, disp); 1354b8e80941Smrg _EGL_FUNC_START(disp, EGL_OBJECT_SURFACE_KHR, surf, EGL_FALSE); 1355b8e80941Smrg return _eglSwapBuffersWithDamageCommon(disp, surf, rects, n_rects); 1356b8e80941Smrg} 1357b8e80941Smrg 1358b8e80941Smrg/** 1359b8e80941Smrg * Clamp the rectangles so that they lie within the surface. 1360b8e80941Smrg */ 1361b8e80941Smrg 1362b8e80941Smrgstatic void 1363b8e80941Smrg_eglSetDamageRegionKHRClampRects(_EGLDisplay* disp, _EGLSurface* surf, 1364b8e80941Smrg EGLint *rects, EGLint n_rects) 1365b8e80941Smrg{ 1366b8e80941Smrg EGLint i; 1367b8e80941Smrg EGLint surf_height = surf->Height; 1368b8e80941Smrg EGLint surf_width = surf->Width; 1369b8e80941Smrg 1370b8e80941Smrg for (i = 0; i < (4 * n_rects); i += 4) { 1371b8e80941Smrg EGLint x1, y1, x2, y2; 1372b8e80941Smrg x1 = rects[i]; 1373b8e80941Smrg y1 = rects[i + 1]; 1374b8e80941Smrg x2 = rects[i + 2] + x1; 1375b8e80941Smrg y2 = rects[i + 3] + y1; 1376b8e80941Smrg 1377b8e80941Smrg rects[i] = CLAMP(x1, 0, surf_width); 1378b8e80941Smrg rects[i + 1] = CLAMP(y1, 0, surf_height); 1379b8e80941Smrg rects[i + 2] = CLAMP(x2, 0, surf_width) - rects[i]; 1380b8e80941Smrg rects[i + 3] = CLAMP(y2, 0, surf_height) - rects[i + 1]; 1381b8e80941Smrg } 1382b8e80941Smrg} 1383b8e80941Smrg 1384b8e80941Smrgstatic EGLBoolean EGLAPIENTRY 1385b8e80941SmrgeglSetDamageRegionKHR(EGLDisplay dpy, EGLSurface surface, 1386b8e80941Smrg EGLint *rects, EGLint n_rects) 1387b8e80941Smrg{ 1388b8e80941Smrg _EGLDisplay *disp = _eglLockDisplay(dpy); 1389b8e80941Smrg _EGLSurface *surf = _eglLookupSurface(surface, disp); 1390b8e80941Smrg _EGL_FUNC_START(disp, EGL_OBJECT_SURFACE_KHR, surf, EGL_FALSE); 1391b8e80941Smrg _EGLContext *ctx = _eglGetCurrentContext(); 1392b8e80941Smrg _EGLDriver *drv; 1393b8e80941Smrg EGLBoolean ret; 1394b8e80941Smrg _EGL_CHECK_SURFACE(disp, surf, EGL_FALSE, drv); 1395b8e80941Smrg 1396b8e80941Smrg if (_eglGetContextHandle(ctx) == EGL_NO_CONTEXT || 1397b8e80941Smrg surf->Type != EGL_WINDOW_BIT || 1398b8e80941Smrg ctx->DrawSurface != surf || 1399b8e80941Smrg surf->SwapBehavior != EGL_BUFFER_DESTROYED) 1400b8e80941Smrg RETURN_EGL_ERROR(disp, EGL_BAD_MATCH, EGL_FALSE); 1401b8e80941Smrg 1402b8e80941Smrg /* If the damage region is already set or 1403b8e80941Smrg * buffer age is not queried between 1404b8e80941Smrg * frame boundaries, throw bad access error 1405b8e80941Smrg */ 1406b8e80941Smrg 1407b8e80941Smrg if (surf->SetDamageRegionCalled || !surf->BufferAgeRead) 1408b8e80941Smrg RETURN_EGL_ERROR(disp, EGL_BAD_ACCESS, EGL_FALSE); 1409b8e80941Smrg 1410b8e80941Smrg _eglSetDamageRegionKHRClampRects(disp, surf, rects, n_rects); 1411b8e80941Smrg ret = drv->API.SetDamageRegion(drv, disp, surf, rects, n_rects); 1412b8e80941Smrg 1413b8e80941Smrg if (ret) 1414b8e80941Smrg surf->SetDamageRegionCalled = EGL_TRUE; 1415b8e80941Smrg 1416b8e80941Smrg RETURN_EGL_EVAL(disp, ret); 1417b8e80941Smrg} 1418848b8605Smrg 1419848b8605SmrgEGLBoolean EGLAPIENTRY 1420848b8605SmrgeglCopyBuffers(EGLDisplay dpy, EGLSurface surface, EGLNativePixmapType target) 1421848b8605Smrg{ 1422848b8605Smrg _EGLDisplay *disp = _eglLockDisplay(dpy); 1423848b8605Smrg _EGLSurface *surf = _eglLookupSurface(surface, disp); 1424848b8605Smrg _EGLDriver *drv; 1425848b8605Smrg EGLBoolean ret; 1426848b8605Smrg void *native_pixmap_ptr; 1427848b8605Smrg 1428b8e80941Smrg _EGL_FUNC_START(disp, EGL_OBJECT_SURFACE_KHR, surf, EGL_FALSE); 1429848b8605Smrg STATIC_ASSERT(sizeof(void*) == sizeof(target)); 1430848b8605Smrg native_pixmap_ptr = (void*) target; 1431848b8605Smrg 1432848b8605Smrg _EGL_CHECK_SURFACE(disp, surf, EGL_FALSE, drv); 1433848b8605Smrg ret = drv->API.CopyBuffers(drv, disp, surf, native_pixmap_ptr); 1434848b8605Smrg 1435848b8605Smrg RETURN_EGL_EVAL(disp, ret); 1436848b8605Smrg} 1437848b8605Smrg 1438848b8605Smrg 1439b8e80941Smrgstatic EGLBoolean 1440b8e80941Smrg_eglWaitClientCommon(void) 1441848b8605Smrg{ 1442848b8605Smrg _EGLContext *ctx = _eglGetCurrentContext(); 1443848b8605Smrg _EGLDisplay *disp; 1444848b8605Smrg _EGLDriver *drv; 1445848b8605Smrg EGLBoolean ret; 1446848b8605Smrg 1447848b8605Smrg if (!ctx) 1448848b8605Smrg RETURN_EGL_SUCCESS(NULL, EGL_TRUE); 1449848b8605Smrg 1450848b8605Smrg disp = ctx->Resource.Display; 1451b8e80941Smrg mtx_lock(&disp->Mutex); 1452848b8605Smrg 1453848b8605Smrg /* let bad current context imply bad current surface */ 1454848b8605Smrg if (_eglGetContextHandle(ctx) == EGL_NO_CONTEXT || 1455848b8605Smrg _eglGetSurfaceHandle(ctx->DrawSurface) == EGL_NO_SURFACE) 1456848b8605Smrg RETURN_EGL_ERROR(disp, EGL_BAD_CURRENT_SURFACE, EGL_FALSE); 1457848b8605Smrg 1458848b8605Smrg /* a valid current context implies an initialized current display */ 1459848b8605Smrg assert(disp->Initialized); 1460848b8605Smrg drv = disp->Driver; 1461848b8605Smrg ret = drv->API.WaitClient(drv, disp, ctx); 1462848b8605Smrg 1463848b8605Smrg RETURN_EGL_EVAL(disp, ret); 1464848b8605Smrg} 1465848b8605Smrg 1466b8e80941SmrgEGLBoolean EGLAPIENTRY 1467b8e80941SmrgeglWaitClient(void) 1468b8e80941Smrg{ 1469b8e80941Smrg _EGL_FUNC_START(NULL, EGL_OBJECT_CONTEXT_KHR, _eglGetCurrentContext(), EGL_FALSE); 1470b8e80941Smrg return _eglWaitClientCommon(); 1471b8e80941Smrg} 1472848b8605Smrg 1473848b8605SmrgEGLBoolean EGLAPIENTRY 1474848b8605SmrgeglWaitGL(void) 1475848b8605Smrg{ 1476b8e80941Smrg /* Since we only support OpenGL and GLES, eglWaitGL is equivalent to eglWaitClient. */ 1477b8e80941Smrg _EGL_FUNC_START(NULL, EGL_OBJECT_CONTEXT_KHR, _eglGetCurrentContext(), EGL_FALSE); 1478b8e80941Smrg return _eglWaitClientCommon(); 1479b8e80941Smrg} 1480848b8605Smrg 1481848b8605Smrg 1482848b8605SmrgEGLBoolean EGLAPIENTRY 1483848b8605SmrgeglWaitNative(EGLint engine) 1484848b8605Smrg{ 1485848b8605Smrg _EGLContext *ctx = _eglGetCurrentContext(); 1486848b8605Smrg _EGLDisplay *disp; 1487848b8605Smrg _EGLDriver *drv; 1488848b8605Smrg EGLBoolean ret; 1489848b8605Smrg 1490848b8605Smrg if (!ctx) 1491848b8605Smrg RETURN_EGL_SUCCESS(NULL, EGL_TRUE); 1492848b8605Smrg 1493b8e80941Smrg _EGL_FUNC_START(NULL, EGL_OBJECT_THREAD_KHR, NULL, EGL_FALSE); 1494b8e80941Smrg 1495848b8605Smrg disp = ctx->Resource.Display; 1496b8e80941Smrg mtx_lock(&disp->Mutex); 1497848b8605Smrg 1498848b8605Smrg /* let bad current context imply bad current surface */ 1499848b8605Smrg if (_eglGetContextHandle(ctx) == EGL_NO_CONTEXT || 1500848b8605Smrg _eglGetSurfaceHandle(ctx->DrawSurface) == EGL_NO_SURFACE) 1501848b8605Smrg RETURN_EGL_ERROR(disp, EGL_BAD_CURRENT_SURFACE, EGL_FALSE); 1502848b8605Smrg 1503848b8605Smrg /* a valid current context implies an initialized current display */ 1504848b8605Smrg assert(disp->Initialized); 1505848b8605Smrg drv = disp->Driver; 1506848b8605Smrg ret = drv->API.WaitNative(drv, disp, engine); 1507848b8605Smrg 1508848b8605Smrg RETURN_EGL_EVAL(disp, ret); 1509848b8605Smrg} 1510848b8605Smrg 1511848b8605Smrg 1512848b8605SmrgEGLDisplay EGLAPIENTRY 1513848b8605SmrgeglGetCurrentDisplay(void) 1514848b8605Smrg{ 1515848b8605Smrg _EGLContext *ctx = _eglGetCurrentContext(); 1516848b8605Smrg EGLDisplay ret; 1517848b8605Smrg 1518848b8605Smrg ret = (ctx) ? _eglGetDisplayHandle(ctx->Resource.Display) : EGL_NO_DISPLAY; 1519848b8605Smrg 1520848b8605Smrg RETURN_EGL_SUCCESS(NULL, ret); 1521848b8605Smrg} 1522848b8605Smrg 1523848b8605Smrg 1524848b8605SmrgEGLContext EGLAPIENTRY 1525848b8605SmrgeglGetCurrentContext(void) 1526848b8605Smrg{ 1527848b8605Smrg _EGLContext *ctx = _eglGetCurrentContext(); 1528848b8605Smrg EGLContext ret; 1529848b8605Smrg 1530848b8605Smrg ret = _eglGetContextHandle(ctx); 1531848b8605Smrg 1532848b8605Smrg RETURN_EGL_SUCCESS(NULL, ret); 1533848b8605Smrg} 1534848b8605Smrg 1535848b8605Smrg 1536848b8605SmrgEGLSurface EGLAPIENTRY 1537848b8605SmrgeglGetCurrentSurface(EGLint readdraw) 1538848b8605Smrg{ 1539848b8605Smrg _EGLContext *ctx = _eglGetCurrentContext(); 1540848b8605Smrg EGLint err = EGL_SUCCESS; 1541848b8605Smrg _EGLSurface *surf; 1542848b8605Smrg EGLSurface ret; 1543848b8605Smrg 1544b8e80941Smrg _EGL_FUNC_START(NULL, EGL_NONE, NULL, EGL_NO_SURFACE); 1545b8e80941Smrg 1546848b8605Smrg if (!ctx) 1547848b8605Smrg RETURN_EGL_SUCCESS(NULL, EGL_NO_SURFACE); 1548848b8605Smrg 1549848b8605Smrg switch (readdraw) { 1550848b8605Smrg case EGL_DRAW: 1551848b8605Smrg surf = ctx->DrawSurface; 1552848b8605Smrg break; 1553848b8605Smrg case EGL_READ: 1554848b8605Smrg surf = ctx->ReadSurface; 1555848b8605Smrg break; 1556848b8605Smrg default: 1557848b8605Smrg surf = NULL; 1558848b8605Smrg err = EGL_BAD_PARAMETER; 1559848b8605Smrg break; 1560848b8605Smrg } 1561848b8605Smrg 1562848b8605Smrg ret = _eglGetSurfaceHandle(surf); 1563848b8605Smrg 1564848b8605Smrg RETURN_EGL_ERROR(NULL, err, ret); 1565848b8605Smrg} 1566848b8605Smrg 1567848b8605Smrg 1568848b8605SmrgEGLint EGLAPIENTRY 1569848b8605SmrgeglGetError(void) 1570848b8605Smrg{ 1571848b8605Smrg _EGLThreadInfo *t = _eglGetCurrentThread(); 1572848b8605Smrg EGLint e = t->LastError; 1573848b8605Smrg if (!_eglIsCurrentThreadDummy()) 1574848b8605Smrg t->LastError = EGL_SUCCESS; 1575848b8605Smrg return e; 1576848b8605Smrg} 1577848b8605Smrg 1578848b8605Smrg 1579848b8605Smrg/** 1580848b8605Smrg ** EGL 1.2 1581848b8605Smrg **/ 1582848b8605Smrg 1583848b8605Smrg/** 1584848b8605Smrg * Specify the client API to use for subsequent calls including: 1585848b8605Smrg * eglCreateContext() 1586848b8605Smrg * eglGetCurrentContext() 1587848b8605Smrg * eglGetCurrentDisplay() 1588848b8605Smrg * eglGetCurrentSurface() 1589848b8605Smrg * eglMakeCurrent(when the ctx parameter is EGL NO CONTEXT) 1590848b8605Smrg * eglWaitClient() 1591848b8605Smrg * eglWaitNative() 1592848b8605Smrg * See section 3.7 "Rendering Context" in the EGL specification for details. 1593848b8605Smrg */ 1594848b8605SmrgEGLBoolean EGLAPIENTRY 1595848b8605SmrgeglBindAPI(EGLenum api) 1596848b8605Smrg{ 1597b8e80941Smrg _EGLThreadInfo *t; 1598848b8605Smrg 1599b8e80941Smrg _EGL_FUNC_START(NULL, EGL_OBJECT_THREAD_KHR, NULL, EGL_FALSE); 1600b8e80941Smrg 1601b8e80941Smrg t = _eglGetCurrentThread(); 1602848b8605Smrg if (_eglIsCurrentThreadDummy()) 1603848b8605Smrg RETURN_EGL_ERROR(NULL, EGL_BAD_ALLOC, EGL_FALSE); 1604848b8605Smrg 1605848b8605Smrg if (!_eglIsApiValid(api)) 1606848b8605Smrg RETURN_EGL_ERROR(NULL, EGL_BAD_PARAMETER, EGL_FALSE); 1607848b8605Smrg 1608b8e80941Smrg t->CurrentAPI = api; 1609848b8605Smrg 1610848b8605Smrg RETURN_EGL_SUCCESS(NULL, EGL_TRUE); 1611848b8605Smrg} 1612848b8605Smrg 1613848b8605Smrg 1614848b8605Smrg/** 1615848b8605Smrg * Return the last value set with eglBindAPI(). 1616848b8605Smrg */ 1617848b8605SmrgEGLenum EGLAPIENTRY 1618848b8605SmrgeglQueryAPI(void) 1619848b8605Smrg{ 1620848b8605Smrg _EGLThreadInfo *t = _eglGetCurrentThread(); 1621848b8605Smrg EGLenum ret; 1622848b8605Smrg 1623848b8605Smrg /* returns one of EGL_OPENGL_API, EGL_OPENGL_ES_API or EGL_OPENVG_API */ 1624b8e80941Smrg ret = t->CurrentAPI; 1625848b8605Smrg 1626848b8605Smrg RETURN_EGL_SUCCESS(NULL, ret); 1627848b8605Smrg} 1628848b8605Smrg 1629848b8605Smrg 1630848b8605SmrgEGLSurface EGLAPIENTRY 1631848b8605SmrgeglCreatePbufferFromClientBuffer(EGLDisplay dpy, EGLenum buftype, 1632848b8605Smrg EGLClientBuffer buffer, EGLConfig config, 1633848b8605Smrg const EGLint *attrib_list) 1634848b8605Smrg{ 1635848b8605Smrg _EGLDisplay *disp = _eglLockDisplay(dpy); 1636848b8605Smrg _EGLConfig *conf = _eglLookupConfig(config, disp); 1637848b8605Smrg _EGLDriver *drv; 1638848b8605Smrg _EGLSurface *surf; 1639848b8605Smrg EGLSurface ret; 1640848b8605Smrg 1641b8e80941Smrg _EGL_FUNC_START(disp, EGL_OBJECT_DISPLAY_KHR, NULL, EGL_NO_SURFACE); 1642b8e80941Smrg 1643848b8605Smrg _EGL_CHECK_CONFIG(disp, conf, EGL_NO_SURFACE, drv); 1644848b8605Smrg 1645848b8605Smrg surf = drv->API.CreatePbufferFromClientBuffer(drv, disp, buftype, buffer, 1646848b8605Smrg conf, attrib_list); 1647848b8605Smrg ret = (surf) ? _eglLinkSurface(surf) : EGL_NO_SURFACE; 1648848b8605Smrg 1649848b8605Smrg RETURN_EGL_EVAL(disp, ret); 1650848b8605Smrg} 1651848b8605Smrg 1652848b8605Smrg 1653848b8605SmrgEGLBoolean EGLAPIENTRY 1654848b8605SmrgeglReleaseThread(void) 1655848b8605Smrg{ 1656848b8605Smrg /* unbind current contexts */ 1657848b8605Smrg if (!_eglIsCurrentThreadDummy()) { 1658848b8605Smrg _EGLThreadInfo *t = _eglGetCurrentThread(); 1659b8e80941Smrg _EGLContext *ctx = t->CurrentContext; 1660848b8605Smrg 1661b8e80941Smrg _EGL_FUNC_START(NULL, EGL_OBJECT_THREAD_KHR, NULL, EGL_FALSE); 1662848b8605Smrg 1663b8e80941Smrg if (ctx) { 1664b8e80941Smrg _EGLDisplay *disp = ctx->Resource.Display; 1665b8e80941Smrg _EGLDriver *drv; 1666848b8605Smrg 1667b8e80941Smrg mtx_lock(&disp->Mutex); 1668b8e80941Smrg drv = disp->Driver; 1669b8e80941Smrg (void) drv->API.MakeCurrent(drv, disp, NULL, NULL, NULL); 1670b8e80941Smrg mtx_unlock(&disp->Mutex); 1671848b8605Smrg } 1672848b8605Smrg } 1673848b8605Smrg 1674848b8605Smrg _eglDestroyCurrentThread(); 1675848b8605Smrg 1676848b8605Smrg RETURN_EGL_SUCCESS(NULL, EGL_TRUE); 1677848b8605Smrg} 1678848b8605Smrg 1679848b8605Smrg 1680b8e80941Smrgstatic EGLImage 1681b8e80941Smrg_eglCreateImageCommon(_EGLDisplay *disp, EGLContext ctx, EGLenum target, 1682b8e80941Smrg EGLClientBuffer buffer, const EGLint *attr_list) 1683848b8605Smrg{ 1684848b8605Smrg _EGLContext *context = _eglLookupContext(ctx, disp); 1685848b8605Smrg _EGLDriver *drv; 1686848b8605Smrg _EGLImage *img; 1687b8e80941Smrg EGLImage ret; 1688848b8605Smrg 1689848b8605Smrg _EGL_CHECK_DISPLAY(disp, EGL_NO_IMAGE_KHR, drv); 1690848b8605Smrg if (!disp->Extensions.KHR_image_base) 1691848b8605Smrg RETURN_EGL_EVAL(disp, EGL_NO_IMAGE_KHR); 1692848b8605Smrg if (!context && ctx != EGL_NO_CONTEXT) 1693848b8605Smrg RETURN_EGL_ERROR(disp, EGL_BAD_CONTEXT, EGL_NO_IMAGE_KHR); 1694848b8605Smrg /* "If <target> is EGL_LINUX_DMA_BUF_EXT, <dpy> must be a valid display, 1695848b8605Smrg * <ctx> must be EGL_NO_CONTEXT..." 1696848b8605Smrg */ 1697848b8605Smrg if (ctx != EGL_NO_CONTEXT && target == EGL_LINUX_DMA_BUF_EXT) 1698848b8605Smrg RETURN_EGL_ERROR(disp, EGL_BAD_PARAMETER, EGL_NO_IMAGE_KHR); 1699848b8605Smrg 1700b8e80941Smrg img = drv->API.CreateImageKHR(drv, disp, context, target, 1701b8e80941Smrg buffer, attr_list); 1702848b8605Smrg ret = (img) ? _eglLinkImage(img) : EGL_NO_IMAGE_KHR; 1703848b8605Smrg 1704848b8605Smrg RETURN_EGL_EVAL(disp, ret); 1705848b8605Smrg} 1706848b8605Smrg 1707b8e80941Smrgstatic EGLImage EGLAPIENTRY 1708b8e80941SmrgeglCreateImageKHR(EGLDisplay dpy, EGLContext ctx, EGLenum target, 1709b8e80941Smrg EGLClientBuffer buffer, const EGLint *attr_list) 1710b8e80941Smrg{ 1711b8e80941Smrg _EGLDisplay *disp = _eglLockDisplay(dpy); 1712b8e80941Smrg _EGL_FUNC_START(disp, EGL_OBJECT_DISPLAY_KHR, NULL, EGL_NO_IMAGE_KHR); 1713b8e80941Smrg return _eglCreateImageCommon(disp, ctx, target, buffer, attr_list); 1714b8e80941Smrg} 1715b8e80941Smrg 1716848b8605Smrg 1717b8e80941SmrgEGLImage EGLAPIENTRY 1718b8e80941SmrgeglCreateImage(EGLDisplay dpy, EGLContext ctx, EGLenum target, 1719b8e80941Smrg EGLClientBuffer buffer, const EGLAttrib *attr_list) 1720848b8605Smrg{ 1721848b8605Smrg _EGLDisplay *disp = _eglLockDisplay(dpy); 1722b8e80941Smrg EGLImage image; 1723b8e80941Smrg EGLint *int_attribs; 1724b8e80941Smrg 1725b8e80941Smrg _EGL_FUNC_START(disp, EGL_OBJECT_DISPLAY_KHR, NULL, EGL_NO_IMAGE_KHR); 1726b8e80941Smrg 1727b8e80941Smrg int_attribs = _eglConvertAttribsToInt(attr_list); 1728b8e80941Smrg if (attr_list && !int_attribs) 1729b8e80941Smrg RETURN_EGL_ERROR(disp, EGL_BAD_ALLOC, EGL_NO_IMAGE); 1730b8e80941Smrg 1731b8e80941Smrg image = _eglCreateImageCommon(disp, ctx, target, buffer, int_attribs); 1732b8e80941Smrg free(int_attribs); 1733b8e80941Smrg return image; 1734b8e80941Smrg} 1735b8e80941Smrg 1736b8e80941Smrg 1737b8e80941Smrgstatic EGLBoolean 1738b8e80941Smrg_eglDestroyImageCommon(_EGLDisplay *disp, _EGLImage *img) 1739b8e80941Smrg{ 1740848b8605Smrg _EGLDriver *drv; 1741848b8605Smrg EGLBoolean ret; 1742848b8605Smrg 1743848b8605Smrg _EGL_CHECK_DISPLAY(disp, EGL_FALSE, drv); 1744848b8605Smrg if (!disp->Extensions.KHR_image_base) 1745848b8605Smrg RETURN_EGL_EVAL(disp, EGL_FALSE); 1746848b8605Smrg if (!img) 1747848b8605Smrg RETURN_EGL_ERROR(disp, EGL_BAD_PARAMETER, EGL_FALSE); 1748848b8605Smrg 1749848b8605Smrg _eglUnlinkImage(img); 1750848b8605Smrg ret = drv->API.DestroyImageKHR(drv, disp, img); 1751848b8605Smrg 1752848b8605Smrg RETURN_EGL_EVAL(disp, ret); 1753848b8605Smrg} 1754848b8605Smrg 1755b8e80941SmrgEGLBoolean EGLAPIENTRY 1756b8e80941SmrgeglDestroyImage(EGLDisplay dpy, EGLImage image) 1757b8e80941Smrg{ 1758b8e80941Smrg _EGLDisplay *disp = _eglLockDisplay(dpy); 1759b8e80941Smrg _EGLImage *img = _eglLookupImage(image, disp); 1760b8e80941Smrg _EGL_FUNC_START(disp, EGL_OBJECT_IMAGE_KHR, img, EGL_FALSE); 1761b8e80941Smrg return _eglDestroyImageCommon(disp, img); 1762b8e80941Smrg} 1763848b8605Smrg 1764b8e80941Smrgstatic EGLBoolean EGLAPIENTRY 1765b8e80941SmrgeglDestroyImageKHR(EGLDisplay dpy, EGLImage image) 1766848b8605Smrg{ 1767848b8605Smrg _EGLDisplay *disp = _eglLockDisplay(dpy); 1768b8e80941Smrg _EGLImage *img = _eglLookupImage(image, disp); 1769b8e80941Smrg _EGL_FUNC_START(disp, EGL_OBJECT_IMAGE_KHR, img, EGL_FALSE); 1770b8e80941Smrg return _eglDestroyImageCommon(disp, img); 1771b8e80941Smrg} 1772b8e80941Smrg 1773b8e80941Smrg 1774b8e80941Smrgstatic EGLSync 1775b8e80941Smrg_eglCreateSync(_EGLDisplay *disp, EGLenum type, const EGLAttrib *attrib_list, 1776b8e80941Smrg EGLBoolean orig_is_EGLAttrib, 1777b8e80941Smrg EGLenum invalid_type_error) 1778b8e80941Smrg{ 1779b8e80941Smrg _EGLContext *ctx = _eglGetCurrentContext(); 1780848b8605Smrg _EGLDriver *drv; 1781848b8605Smrg _EGLSync *sync; 1782b8e80941Smrg EGLSync ret; 1783848b8605Smrg 1784848b8605Smrg _EGL_CHECK_DISPLAY(disp, EGL_NO_SYNC_KHR, drv); 1785b8e80941Smrg 1786b8e80941Smrg if (!disp->Extensions.KHR_cl_event2 && orig_is_EGLAttrib) { 1787b8e80941Smrg /* There exist two EGLAttrib variants of eglCreateSync*: 1788b8e80941Smrg * eglCreateSync64KHR which requires EGL_KHR_cl_event2, and eglCreateSync 1789b8e80941Smrg * which requires EGL 1.5. Here we use the presence of EGL_KHR_cl_event2 1790b8e80941Smrg * support as a proxy for EGL 1.5 support, even though that's not 1791b8e80941Smrg * entirely correct (though _eglComputeVersion does the same). 1792b8e80941Smrg * 1793b8e80941Smrg * The EGL spec provides no guidance on how to handle unsupported 1794b8e80941Smrg * functions. EGL_BAD_MATCH seems reasonable. 1795b8e80941Smrg */ 1796b8e80941Smrg RETURN_EGL_ERROR(disp, EGL_BAD_MATCH, EGL_NO_SYNC_KHR); 1797b8e80941Smrg } 1798b8e80941Smrg 1799b8e80941Smrg /* If type is EGL_SYNC_FENCE and no context is current for the bound API 1800b8e80941Smrg * (i.e., eglGetCurrentContext returns EGL_NO_CONTEXT ), an EGL_BAD_MATCH 1801b8e80941Smrg * error is generated. 1802b8e80941Smrg */ 1803b8e80941Smrg if (!ctx && 1804b8e80941Smrg (type == EGL_SYNC_FENCE_KHR || type == EGL_SYNC_NATIVE_FENCE_ANDROID)) 1805b8e80941Smrg RETURN_EGL_ERROR(disp, EGL_BAD_MATCH, EGL_NO_SYNC_KHR); 1806b8e80941Smrg 1807b8e80941Smrg /* return an error if the client API doesn't support GL_OES_EGL_sync */ 1808b8e80941Smrg if (ctx && (ctx->Resource.Display != disp || 1809b8e80941Smrg ctx->ClientAPI != EGL_OPENGL_ES_API)) 1810b8e80941Smrg RETURN_EGL_ERROR(disp, EGL_BAD_MATCH, EGL_NO_SYNC_KHR); 1811b8e80941Smrg 1812b8e80941Smrg switch (type) { 1813b8e80941Smrg case EGL_SYNC_FENCE_KHR: 1814b8e80941Smrg if (!disp->Extensions.KHR_fence_sync) 1815b8e80941Smrg RETURN_EGL_ERROR(disp, invalid_type_error, EGL_NO_SYNC_KHR); 1816b8e80941Smrg break; 1817b8e80941Smrg case EGL_SYNC_REUSABLE_KHR: 1818b8e80941Smrg if (!disp->Extensions.KHR_reusable_sync) 1819b8e80941Smrg RETURN_EGL_ERROR(disp, invalid_type_error, EGL_NO_SYNC_KHR); 1820b8e80941Smrg break; 1821b8e80941Smrg case EGL_SYNC_CL_EVENT_KHR: 1822b8e80941Smrg if (!disp->Extensions.KHR_cl_event2) 1823b8e80941Smrg RETURN_EGL_ERROR(disp, invalid_type_error, EGL_NO_SYNC_KHR); 1824b8e80941Smrg break; 1825b8e80941Smrg case EGL_SYNC_NATIVE_FENCE_ANDROID: 1826b8e80941Smrg if (!disp->Extensions.ANDROID_native_fence_sync) 1827b8e80941Smrg RETURN_EGL_ERROR(disp, invalid_type_error, EGL_NO_SYNC_KHR); 1828b8e80941Smrg break; 1829b8e80941Smrg default: 1830b8e80941Smrg RETURN_EGL_ERROR(disp, invalid_type_error, EGL_NO_SYNC_KHR); 1831b8e80941Smrg } 1832848b8605Smrg 1833848b8605Smrg sync = drv->API.CreateSyncKHR(drv, disp, type, attrib_list); 1834848b8605Smrg ret = (sync) ? _eglLinkSync(sync) : EGL_NO_SYNC_KHR; 1835848b8605Smrg 1836848b8605Smrg RETURN_EGL_EVAL(disp, ret); 1837848b8605Smrg} 1838848b8605Smrg 1839848b8605Smrg 1840b8e80941Smrgstatic EGLSync EGLAPIENTRY 1841b8e80941SmrgeglCreateSyncKHR(EGLDisplay dpy, EGLenum type, const EGLint *int_list) 1842848b8605Smrg{ 1843848b8605Smrg _EGLDisplay *disp = _eglLockDisplay(dpy); 1844b8e80941Smrg _EGL_FUNC_START(disp, EGL_OBJECT_DISPLAY_KHR, NULL, EGL_FALSE); 1845b8e80941Smrg 1846b8e80941Smrg EGLSync sync; 1847b8e80941Smrg EGLAttrib *attrib_list; 1848b8e80941Smrg EGLint err; 1849b8e80941Smrg 1850b8e80941Smrg if (sizeof(int_list[0]) == sizeof(attrib_list[0])) { 1851b8e80941Smrg attrib_list = (EGLAttrib *) int_list; 1852b8e80941Smrg } else { 1853b8e80941Smrg err = _eglConvertIntsToAttribs(int_list, &attrib_list); 1854b8e80941Smrg if (err != EGL_SUCCESS) 1855b8e80941Smrg RETURN_EGL_ERROR(disp, err, EGL_NO_SYNC); 1856b8e80941Smrg } 1857848b8605Smrg 1858b8e80941Smrg sync = _eglCreateSync(disp, type, attrib_list, EGL_FALSE, 1859b8e80941Smrg EGL_BAD_ATTRIBUTE); 1860848b8605Smrg 1861b8e80941Smrg if (sizeof(int_list[0]) != sizeof(attrib_list[0])) 1862b8e80941Smrg free(attrib_list); 1863848b8605Smrg 1864b8e80941Smrg /* Don't double-unlock the display. _eglCreateSync already unlocked it. */ 1865b8e80941Smrg return sync; 1866848b8605Smrg} 1867848b8605Smrg 1868848b8605Smrg 1869b8e80941Smrgstatic EGLSync EGLAPIENTRY 1870b8e80941SmrgeglCreateSync64KHR(EGLDisplay dpy, EGLenum type, const EGLAttrib *attrib_list) 1871848b8605Smrg{ 1872848b8605Smrg _EGLDisplay *disp = _eglLockDisplay(dpy); 1873b8e80941Smrg _EGL_FUNC_START(disp, EGL_OBJECT_DISPLAY_KHR, NULL, EGL_FALSE); 1874b8e80941Smrg return _eglCreateSync(disp, type, attrib_list, EGL_TRUE, 1875b8e80941Smrg EGL_BAD_ATTRIBUTE); 1876b8e80941Smrg} 1877848b8605Smrg 1878848b8605Smrg 1879b8e80941SmrgEGLSync EGLAPIENTRY 1880b8e80941SmrgeglCreateSync(EGLDisplay dpy, EGLenum type, const EGLAttrib *attrib_list) 1881b8e80941Smrg{ 1882b8e80941Smrg _EGLDisplay *disp = _eglLockDisplay(dpy); 1883b8e80941Smrg _EGL_FUNC_START(disp, EGL_OBJECT_DISPLAY_KHR, NULL, EGL_FALSE); 1884b8e80941Smrg return _eglCreateSync(disp, type, attrib_list, EGL_TRUE, 1885b8e80941Smrg EGL_BAD_PARAMETER); 1886848b8605Smrg} 1887848b8605Smrg 1888848b8605Smrg 1889b8e80941Smrgstatic EGLBoolean 1890b8e80941Smrg_eglDestroySync(_EGLDisplay *disp, _EGLSync *s) 1891b8e80941Smrg{ 1892b8e80941Smrg _EGLDriver *drv; 1893b8e80941Smrg EGLBoolean ret; 1894b8e80941Smrg 1895b8e80941Smrg _EGL_CHECK_SYNC(disp, s, EGL_FALSE, drv); 1896b8e80941Smrg assert(disp->Extensions.KHR_reusable_sync || 1897b8e80941Smrg disp->Extensions.KHR_fence_sync || 1898b8e80941Smrg disp->Extensions.ANDROID_native_fence_sync); 1899b8e80941Smrg 1900b8e80941Smrg _eglUnlinkSync(s); 1901b8e80941Smrg ret = drv->API.DestroySyncKHR(drv, disp, s); 1902b8e80941Smrg 1903b8e80941Smrg RETURN_EGL_EVAL(disp, ret); 1904b8e80941Smrg} 1905b8e80941Smrg 1906848b8605SmrgEGLBoolean EGLAPIENTRY 1907b8e80941SmrgeglDestroySync(EGLDisplay dpy, EGLSync sync) 1908848b8605Smrg{ 1909848b8605Smrg _EGLDisplay *disp = _eglLockDisplay(dpy); 1910848b8605Smrg _EGLSync *s = _eglLookupSync(sync, disp); 1911b8e80941Smrg _EGL_FUNC_START(disp, EGL_OBJECT_SYNC_KHR, s, EGL_FALSE); 1912b8e80941Smrg return _eglDestroySync(disp, s); 1913b8e80941Smrg} 1914b8e80941Smrg 1915b8e80941Smrgstatic EGLBoolean EGLAPIENTRY 1916b8e80941SmrgeglDestroySyncKHR(EGLDisplay dpy, EGLSync sync) 1917b8e80941Smrg{ 1918b8e80941Smrg _EGLDisplay *disp = _eglLockDisplay(dpy); 1919b8e80941Smrg _EGLSync *s = _eglLookupSync(sync, disp); 1920b8e80941Smrg _EGL_FUNC_START(disp, EGL_OBJECT_SYNC_KHR, s, EGL_FALSE); 1921b8e80941Smrg return _eglDestroySync(disp, s); 1922b8e80941Smrg} 1923b8e80941Smrg 1924b8e80941Smrg 1925b8e80941Smrgstatic EGLint 1926b8e80941Smrg_eglClientWaitSyncCommon(_EGLDisplay *disp, EGLDisplay dpy, 1927b8e80941Smrg _EGLSync *s, EGLint flags, EGLTime timeout) 1928b8e80941Smrg{ 1929848b8605Smrg _EGLDriver *drv; 1930b8e80941Smrg EGLint ret; 1931848b8605Smrg 1932848b8605Smrg _EGL_CHECK_SYNC(disp, s, EGL_FALSE, drv); 1933b8e80941Smrg assert(disp->Extensions.KHR_reusable_sync || 1934b8e80941Smrg disp->Extensions.KHR_fence_sync || 1935b8e80941Smrg disp->Extensions.ANDROID_native_fence_sync); 1936b8e80941Smrg 1937b8e80941Smrg if (s->SyncStatus == EGL_SIGNALED_KHR) 1938b8e80941Smrg RETURN_EGL_EVAL(disp, EGL_CONDITION_SATISFIED_KHR); 1939b8e80941Smrg 1940b8e80941Smrg /* if sync type is EGL_SYNC_REUSABLE_KHR, dpy should be 1941b8e80941Smrg * unlocked here to allow other threads also to be able to 1942b8e80941Smrg * go into waiting state. 1943b8e80941Smrg */ 1944b8e80941Smrg 1945b8e80941Smrg if (s->Type == EGL_SYNC_REUSABLE_KHR) 1946b8e80941Smrg _eglUnlockDisplay(dpy); 1947b8e80941Smrg 1948b8e80941Smrg ret = drv->API.ClientWaitSyncKHR(drv, disp, s, flags, timeout); 1949b8e80941Smrg 1950b8e80941Smrg /* 1951b8e80941Smrg * 'disp' is already unlocked for reusable sync type, 1952b8e80941Smrg * so passing 'NULL' to bypass unlocking display. 1953b8e80941Smrg */ 1954b8e80941Smrg if (s->Type == EGL_SYNC_REUSABLE_KHR) 1955b8e80941Smrg RETURN_EGL_EVAL(NULL, ret); 1956b8e80941Smrg else 1957b8e80941Smrg RETURN_EGL_EVAL(disp, ret); 1958b8e80941Smrg} 1959b8e80941Smrg 1960b8e80941SmrgEGLint EGLAPIENTRY 1961b8e80941SmrgeglClientWaitSync(EGLDisplay dpy, EGLSync sync, 1962b8e80941Smrg EGLint flags, EGLTime timeout) 1963b8e80941Smrg{ 1964b8e80941Smrg _EGLDisplay *disp = _eglLockDisplay(dpy); 1965b8e80941Smrg _EGLSync *s = _eglLookupSync(sync, disp); 1966b8e80941Smrg _EGL_FUNC_START(disp, EGL_OBJECT_SYNC_KHR, s, EGL_FALSE); 1967b8e80941Smrg return _eglClientWaitSyncCommon(disp, dpy, s, flags, timeout); 1968b8e80941Smrg} 1969b8e80941Smrg 1970b8e80941Smrgstatic EGLint EGLAPIENTRY 1971b8e80941SmrgeglClientWaitSyncKHR(EGLDisplay dpy, EGLSync sync, 1972b8e80941Smrg EGLint flags, EGLTime timeout) 1973b8e80941Smrg{ 1974b8e80941Smrg _EGLDisplay *disp = _eglLockDisplay(dpy); 1975b8e80941Smrg _EGLSync *s = _eglLookupSync(sync, disp); 1976b8e80941Smrg _EGL_FUNC_START(disp, EGL_OBJECT_SYNC_KHR, s, EGL_FALSE); 1977b8e80941Smrg return _eglClientWaitSyncCommon(disp, dpy, s, flags, timeout); 1978b8e80941Smrg} 1979b8e80941Smrg 1980b8e80941Smrg 1981b8e80941Smrgstatic EGLint 1982b8e80941Smrg_eglWaitSyncCommon(_EGLDisplay *disp, _EGLSync *s, EGLint flags) 1983b8e80941Smrg{ 1984b8e80941Smrg _EGLContext *ctx = _eglGetCurrentContext(); 1985b8e80941Smrg _EGLDriver *drv; 1986b8e80941Smrg EGLint ret; 1987b8e80941Smrg 1988b8e80941Smrg _EGL_CHECK_SYNC(disp, s, EGL_FALSE, drv); 1989b8e80941Smrg assert(disp->Extensions.KHR_wait_sync); 1990b8e80941Smrg 1991b8e80941Smrg /* return an error if the client API doesn't support GL_OES_EGL_sync */ 1992b8e80941Smrg if (ctx == EGL_NO_CONTEXT || ctx->ClientAPI != EGL_OPENGL_ES_API) 1993b8e80941Smrg RETURN_EGL_ERROR(disp, EGL_BAD_MATCH, EGL_FALSE); 1994b8e80941Smrg 1995b8e80941Smrg /* the API doesn't allow any flags yet */ 1996b8e80941Smrg if (flags != 0) 1997b8e80941Smrg RETURN_EGL_ERROR(disp, EGL_BAD_PARAMETER, EGL_FALSE); 1998b8e80941Smrg 1999b8e80941Smrg ret = drv->API.WaitSyncKHR(drv, disp, s); 2000848b8605Smrg 2001848b8605Smrg RETURN_EGL_EVAL(disp, ret); 2002848b8605Smrg} 2003848b8605Smrg 2004b8e80941Smrgstatic EGLint EGLAPIENTRY 2005b8e80941SmrgeglWaitSyncKHR(EGLDisplay dpy, EGLSync sync, EGLint flags) 2006b8e80941Smrg{ 2007b8e80941Smrg _EGLDisplay *disp = _eglLockDisplay(dpy); 2008b8e80941Smrg _EGLSync *s = _eglLookupSync(sync, disp); 2009b8e80941Smrg _EGL_FUNC_START(disp, EGL_OBJECT_SYNC_KHR, s, EGL_FALSE); 2010b8e80941Smrg return _eglWaitSyncCommon(disp, s, flags); 2011b8e80941Smrg} 2012b8e80941Smrg 2013848b8605Smrg 2014848b8605SmrgEGLBoolean EGLAPIENTRY 2015b8e80941SmrgeglWaitSync(EGLDisplay dpy, EGLSync sync, EGLint flags) 2016b8e80941Smrg{ 2017b8e80941Smrg /* The KHR version returns EGLint, while the core version returns 2018b8e80941Smrg * EGLBoolean. In both cases, the return values can only be EGL_FALSE and 2019b8e80941Smrg * EGL_TRUE. 2020b8e80941Smrg */ 2021b8e80941Smrg _EGLDisplay *disp = _eglLockDisplay(dpy); 2022b8e80941Smrg _EGLSync *s = _eglLookupSync(sync, disp); 2023b8e80941Smrg _EGL_FUNC_START(disp, EGL_OBJECT_SYNC_KHR, s, EGL_FALSE); 2024b8e80941Smrg return _eglWaitSyncCommon(disp, s, flags); 2025b8e80941Smrg} 2026b8e80941Smrg 2027b8e80941Smrg 2028b8e80941Smrgstatic EGLBoolean EGLAPIENTRY 2029b8e80941SmrgeglSignalSyncKHR(EGLDisplay dpy, EGLSync sync, EGLenum mode) 2030848b8605Smrg{ 2031848b8605Smrg _EGLDisplay *disp = _eglLockDisplay(dpy); 2032848b8605Smrg _EGLSync *s = _eglLookupSync(sync, disp); 2033848b8605Smrg _EGLDriver *drv; 2034848b8605Smrg EGLBoolean ret; 2035848b8605Smrg 2036b8e80941Smrg _EGL_FUNC_START(disp, EGL_OBJECT_SYNC_KHR, s, EGL_FALSE); 2037b8e80941Smrg 2038848b8605Smrg _EGL_CHECK_SYNC(disp, s, EGL_FALSE, drv); 2039848b8605Smrg assert(disp->Extensions.KHR_reusable_sync); 2040b8e80941Smrg ret = drv->API.SignalSyncKHR(drv, disp, s, mode); 2041848b8605Smrg 2042848b8605Smrg RETURN_EGL_EVAL(disp, ret); 2043848b8605Smrg} 2044848b8605Smrg 2045848b8605Smrg 2046b8e80941Smrgstatic EGLBoolean 2047b8e80941Smrg_eglGetSyncAttribCommon(_EGLDisplay *disp, _EGLSync *s, EGLint attribute, EGLAttrib *value) 2048b8e80941Smrg{ 2049b8e80941Smrg _EGLDriver *drv; 2050b8e80941Smrg EGLBoolean ret; 2051b8e80941Smrg 2052b8e80941Smrg _EGL_CHECK_SYNC(disp, s, EGL_FALSE, drv); 2053b8e80941Smrg assert(disp->Extensions.KHR_reusable_sync || 2054b8e80941Smrg disp->Extensions.KHR_fence_sync || 2055b8e80941Smrg disp->Extensions.ANDROID_native_fence_sync); 2056b8e80941Smrg ret = drv->API.GetSyncAttrib(drv, disp, s, attribute, value); 2057b8e80941Smrg 2058b8e80941Smrg RETURN_EGL_EVAL(disp, ret); 2059b8e80941Smrg} 2060848b8605Smrg 2061848b8605SmrgEGLBoolean EGLAPIENTRY 2062b8e80941SmrgeglGetSyncAttrib(EGLDisplay dpy, EGLSync sync, EGLint attribute, EGLAttrib *value) 2063b8e80941Smrg{ 2064b8e80941Smrg _EGLDisplay *disp = _eglLockDisplay(dpy); 2065b8e80941Smrg _EGLSync *s = _eglLookupSync(sync, disp); 2066b8e80941Smrg _EGL_FUNC_START(disp, EGL_OBJECT_SYNC_KHR, s, EGL_FALSE); 2067b8e80941Smrg return _eglGetSyncAttribCommon(disp, s, attribute, value); 2068b8e80941Smrg} 2069b8e80941Smrg 2070b8e80941Smrg 2071b8e80941Smrgstatic EGLBoolean EGLAPIENTRY 2072b8e80941SmrgeglGetSyncAttribKHR(EGLDisplay dpy, EGLSync sync, EGLint attribute, EGLint *value) 2073b8e80941Smrg{ 2074b8e80941Smrg _EGLDisplay *disp = _eglLockDisplay(dpy); 2075b8e80941Smrg _EGLSync *s = _eglLookupSync(sync, disp); 2076b8e80941Smrg EGLAttrib attrib; 2077b8e80941Smrg EGLBoolean result; 2078b8e80941Smrg 2079b8e80941Smrg _EGL_FUNC_START(disp, EGL_OBJECT_SYNC_KHR, s, EGL_FALSE); 2080b8e80941Smrg 2081b8e80941Smrg if (!value) 2082b8e80941Smrg RETURN_EGL_ERROR(disp, EGL_BAD_PARAMETER, EGL_FALSE); 2083b8e80941Smrg 2084b8e80941Smrg attrib = *value; 2085b8e80941Smrg result = _eglGetSyncAttribCommon(disp, s, attribute, &attrib); 2086b8e80941Smrg 2087b8e80941Smrg /* The EGL_KHR_fence_sync spec says this about eglGetSyncAttribKHR: 2088b8e80941Smrg * 2089b8e80941Smrg * If any error occurs, <*value> is not modified. 2090b8e80941Smrg */ 2091b8e80941Smrg if (result == EGL_FALSE) 2092b8e80941Smrg return result; 2093b8e80941Smrg 2094b8e80941Smrg *value = attrib; 2095b8e80941Smrg return result; 2096b8e80941Smrg} 2097b8e80941Smrg 2098b8e80941Smrgstatic EGLint EGLAPIENTRY 2099b8e80941SmrgeglDupNativeFenceFDANDROID(EGLDisplay dpy, EGLSync sync) 2100b8e80941Smrg{ 2101b8e80941Smrg _EGLDisplay *disp = _eglLockDisplay(dpy); 2102b8e80941Smrg _EGLSync *s = _eglLookupSync(sync, disp); 2103b8e80941Smrg _EGLDriver *drv; 2104b8e80941Smrg EGLBoolean ret; 2105b8e80941Smrg 2106b8e80941Smrg _EGL_FUNC_START(disp, EGL_OBJECT_SYNC_KHR, s, EGL_FALSE); 2107b8e80941Smrg 2108b8e80941Smrg /* the spec doesn't seem to specify what happens if the fence 2109b8e80941Smrg * type is not EGL_SYNC_NATIVE_FENCE_ANDROID, but this seems 2110b8e80941Smrg * sensible: 2111b8e80941Smrg */ 2112b8e80941Smrg if (!(s && (s->Type == EGL_SYNC_NATIVE_FENCE_ANDROID))) 2113b8e80941Smrg RETURN_EGL_ERROR(disp, EGL_BAD_PARAMETER, EGL_NO_NATIVE_FENCE_FD_ANDROID); 2114b8e80941Smrg 2115b8e80941Smrg _EGL_CHECK_SYNC(disp, s, EGL_NO_NATIVE_FENCE_FD_ANDROID, drv); 2116b8e80941Smrg assert(disp->Extensions.ANDROID_native_fence_sync); 2117b8e80941Smrg ret = drv->API.DupNativeFenceFDANDROID(drv, disp, s); 2118b8e80941Smrg 2119b8e80941Smrg RETURN_EGL_EVAL(disp, ret); 2120b8e80941Smrg} 2121b8e80941Smrg 2122b8e80941Smrgstatic EGLBoolean EGLAPIENTRY 2123848b8605SmrgeglSwapBuffersRegionNOK(EGLDisplay dpy, EGLSurface surface, 2124b8e80941Smrg EGLint numRects, const EGLint *rects) 2125848b8605Smrg{ 2126848b8605Smrg _EGLContext *ctx = _eglGetCurrentContext(); 2127848b8605Smrg _EGLDisplay *disp = _eglLockDisplay(dpy); 2128848b8605Smrg _EGLSurface *surf = _eglLookupSurface(surface, disp); 2129848b8605Smrg _EGLDriver *drv; 2130848b8605Smrg EGLBoolean ret; 2131848b8605Smrg 2132b8e80941Smrg _EGL_FUNC_START(disp, EGL_OBJECT_SURFACE_KHR, surf, EGL_FALSE); 2133b8e80941Smrg 2134848b8605Smrg _EGL_CHECK_SURFACE(disp, surf, EGL_FALSE, drv); 2135848b8605Smrg 2136848b8605Smrg if (!disp->Extensions.NOK_swap_region) 2137848b8605Smrg RETURN_EGL_EVAL(disp, EGL_FALSE); 2138848b8605Smrg 2139848b8605Smrg /* surface must be bound to current context in EGL 1.4 */ 2140848b8605Smrg if (_eglGetContextHandle(ctx) == EGL_NO_CONTEXT || 2141848b8605Smrg surf != ctx->DrawSurface) 2142848b8605Smrg RETURN_EGL_ERROR(disp, EGL_BAD_SURFACE, EGL_FALSE); 2143848b8605Smrg 2144848b8605Smrg ret = drv->API.SwapBuffersRegionNOK(drv, disp, surf, numRects, rects); 2145848b8605Smrg 2146848b8605Smrg RETURN_EGL_EVAL(disp, ret); 2147848b8605Smrg} 2148848b8605Smrg 2149848b8605Smrg 2150b8e80941Smrgstatic EGLImage EGLAPIENTRY 2151848b8605SmrgeglCreateDRMImageMESA(EGLDisplay dpy, const EGLint *attr_list) 2152848b8605Smrg{ 2153848b8605Smrg _EGLDisplay *disp = _eglLockDisplay(dpy); 2154848b8605Smrg _EGLDriver *drv; 2155848b8605Smrg _EGLImage *img; 2156b8e80941Smrg EGLImage ret; 2157b8e80941Smrg 2158b8e80941Smrg _EGL_FUNC_START(disp, EGL_OBJECT_DISPLAY_KHR, NULL, EGL_FALSE); 2159848b8605Smrg 2160848b8605Smrg _EGL_CHECK_DISPLAY(disp, EGL_NO_IMAGE_KHR, drv); 2161848b8605Smrg if (!disp->Extensions.MESA_drm_image) 2162848b8605Smrg RETURN_EGL_EVAL(disp, EGL_NO_IMAGE_KHR); 2163848b8605Smrg 2164848b8605Smrg img = drv->API.CreateDRMImageMESA(drv, disp, attr_list); 2165848b8605Smrg ret = (img) ? _eglLinkImage(img) : EGL_NO_IMAGE_KHR; 2166848b8605Smrg 2167848b8605Smrg RETURN_EGL_EVAL(disp, ret); 2168848b8605Smrg} 2169848b8605Smrg 2170b8e80941Smrgstatic EGLBoolean EGLAPIENTRY 2171b8e80941SmrgeglExportDRMImageMESA(EGLDisplay dpy, EGLImage image, 2172b8e80941Smrg EGLint *name, EGLint *handle, EGLint *stride) 2173848b8605Smrg{ 2174848b8605Smrg _EGLDisplay *disp = _eglLockDisplay(dpy); 2175848b8605Smrg _EGLImage *img = _eglLookupImage(image, disp); 2176848b8605Smrg _EGLDriver *drv; 2177848b8605Smrg EGLBoolean ret; 2178848b8605Smrg 2179b8e80941Smrg _EGL_FUNC_START(disp, EGL_OBJECT_IMAGE_KHR, img, EGL_FALSE); 2180b8e80941Smrg 2181848b8605Smrg _EGL_CHECK_DISPLAY(disp, EGL_FALSE, drv); 2182848b8605Smrg assert(disp->Extensions.MESA_drm_image); 2183848b8605Smrg 2184848b8605Smrg if (!img) 2185848b8605Smrg RETURN_EGL_ERROR(disp, EGL_BAD_PARAMETER, EGL_FALSE); 2186848b8605Smrg 2187848b8605Smrg ret = drv->API.ExportDRMImageMESA(drv, disp, img, name, handle, stride); 2188848b8605Smrg 2189848b8605Smrg RETURN_EGL_EVAL(disp, ret); 2190848b8605Smrg} 2191848b8605Smrg 2192848b8605Smrg 2193848b8605Smrgstruct wl_display; 2194848b8605Smrg 2195b8e80941Smrgstatic EGLBoolean EGLAPIENTRY 2196848b8605SmrgeglBindWaylandDisplayWL(EGLDisplay dpy, struct wl_display *display) 2197848b8605Smrg{ 2198848b8605Smrg _EGLDisplay *disp = _eglLockDisplay(dpy); 2199848b8605Smrg _EGLDriver *drv; 2200848b8605Smrg EGLBoolean ret; 2201848b8605Smrg 2202b8e80941Smrg _EGL_FUNC_START(disp, EGL_OBJECT_DISPLAY_KHR, NULL, EGL_FALSE); 2203b8e80941Smrg 2204848b8605Smrg _EGL_CHECK_DISPLAY(disp, EGL_FALSE, drv); 2205848b8605Smrg assert(disp->Extensions.WL_bind_wayland_display); 2206848b8605Smrg 2207848b8605Smrg if (!display) 2208848b8605Smrg RETURN_EGL_ERROR(disp, EGL_BAD_PARAMETER, EGL_FALSE); 2209848b8605Smrg 2210848b8605Smrg ret = drv->API.BindWaylandDisplayWL(drv, disp, display); 2211848b8605Smrg 2212848b8605Smrg RETURN_EGL_EVAL(disp, ret); 2213848b8605Smrg} 2214848b8605Smrg 2215b8e80941Smrgstatic EGLBoolean EGLAPIENTRY 2216848b8605SmrgeglUnbindWaylandDisplayWL(EGLDisplay dpy, struct wl_display *display) 2217848b8605Smrg{ 2218848b8605Smrg _EGLDisplay *disp = _eglLockDisplay(dpy); 2219848b8605Smrg _EGLDriver *drv; 2220848b8605Smrg EGLBoolean ret; 2221848b8605Smrg 2222b8e80941Smrg _EGL_FUNC_START(disp, EGL_OBJECT_DISPLAY_KHR, NULL, EGL_FALSE); 2223b8e80941Smrg 2224848b8605Smrg _EGL_CHECK_DISPLAY(disp, EGL_FALSE, drv); 2225848b8605Smrg assert(disp->Extensions.WL_bind_wayland_display); 2226848b8605Smrg 2227848b8605Smrg if (!display) 2228848b8605Smrg RETURN_EGL_ERROR(disp, EGL_BAD_PARAMETER, EGL_FALSE); 2229848b8605Smrg 2230848b8605Smrg ret = drv->API.UnbindWaylandDisplayWL(drv, disp, display); 2231848b8605Smrg 2232848b8605Smrg RETURN_EGL_EVAL(disp, ret); 2233848b8605Smrg} 2234848b8605Smrg 2235b8e80941Smrgstatic EGLBoolean EGLAPIENTRY 2236848b8605SmrgeglQueryWaylandBufferWL(EGLDisplay dpy, struct wl_resource *buffer, 2237848b8605Smrg EGLint attribute, EGLint *value) 2238848b8605Smrg{ 2239848b8605Smrg _EGLDisplay *disp = _eglLockDisplay(dpy); 2240848b8605Smrg _EGLDriver *drv; 2241848b8605Smrg EGLBoolean ret; 2242848b8605Smrg 2243b8e80941Smrg _EGL_FUNC_START(disp, EGL_OBJECT_DISPLAY_KHR, NULL, EGL_FALSE); 2244b8e80941Smrg 2245848b8605Smrg _EGL_CHECK_DISPLAY(disp, EGL_FALSE, drv); 2246848b8605Smrg assert(disp->Extensions.WL_bind_wayland_display); 2247848b8605Smrg 2248848b8605Smrg if (!buffer) 2249848b8605Smrg RETURN_EGL_ERROR(disp, EGL_BAD_PARAMETER, EGL_FALSE); 2250848b8605Smrg 2251848b8605Smrg ret = drv->API.QueryWaylandBufferWL(drv, disp, buffer, attribute, value); 2252848b8605Smrg 2253848b8605Smrg RETURN_EGL_EVAL(disp, ret); 2254848b8605Smrg} 2255848b8605Smrg 2256b8e80941Smrg 2257b8e80941Smrgstatic struct wl_buffer * EGLAPIENTRY 2258b8e80941SmrgeglCreateWaylandBufferFromImageWL(EGLDisplay dpy, EGLImage image) 2259848b8605Smrg{ 2260848b8605Smrg _EGLDisplay *disp = _eglLockDisplay(dpy); 2261848b8605Smrg _EGLImage *img; 2262848b8605Smrg _EGLDriver *drv; 2263848b8605Smrg struct wl_buffer *ret; 2264848b8605Smrg 2265b8e80941Smrg _EGL_FUNC_START(disp, EGL_OBJECT_DISPLAY_KHR, NULL, EGL_FALSE); 2266b8e80941Smrg 2267848b8605Smrg _EGL_CHECK_DISPLAY(disp, NULL, drv); 2268b8e80941Smrg if (!disp->Extensions.WL_create_wayland_buffer_from_image) 2269b8e80941Smrg RETURN_EGL_EVAL(disp, NULL); 2270848b8605Smrg 2271848b8605Smrg img = _eglLookupImage(image, disp); 2272848b8605Smrg 2273848b8605Smrg if (!img) 2274848b8605Smrg RETURN_EGL_ERROR(disp, EGL_BAD_PARAMETER, NULL); 2275848b8605Smrg 2276848b8605Smrg ret = drv->API.CreateWaylandBufferFromImageWL(drv, disp, img); 2277848b8605Smrg 2278848b8605Smrg RETURN_EGL_EVAL(disp, ret); 2279848b8605Smrg} 2280848b8605Smrg 2281b8e80941Smrgstatic EGLBoolean EGLAPIENTRY 2282848b8605SmrgeglPostSubBufferNV(EGLDisplay dpy, EGLSurface surface, 2283848b8605Smrg EGLint x, EGLint y, EGLint width, EGLint height) 2284848b8605Smrg{ 2285848b8605Smrg _EGLDisplay *disp = _eglLockDisplay(dpy); 2286848b8605Smrg _EGLSurface *surf = _eglLookupSurface(surface, disp); 2287848b8605Smrg _EGLDriver *drv; 2288848b8605Smrg EGLBoolean ret; 2289848b8605Smrg 2290b8e80941Smrg _EGL_FUNC_START(disp, EGL_OBJECT_SURFACE_KHR, surf, EGL_FALSE); 2291b8e80941Smrg 2292848b8605Smrg _EGL_CHECK_SURFACE(disp, surf, EGL_FALSE, drv); 2293848b8605Smrg 2294848b8605Smrg if (!disp->Extensions.NV_post_sub_buffer) 2295848b8605Smrg RETURN_EGL_EVAL(disp, EGL_FALSE); 2296848b8605Smrg 2297848b8605Smrg ret = drv->API.PostSubBufferNV(drv, disp, surf, x, y, width, height); 2298848b8605Smrg 2299848b8605Smrg RETURN_EGL_EVAL(disp, ret); 2300848b8605Smrg} 2301848b8605Smrg 2302b8e80941Smrgstatic EGLBoolean EGLAPIENTRY 2303b8e80941SmrgeglGetSyncValuesCHROMIUM(EGLDisplay dpy, EGLSurface surface, 2304848b8605Smrg EGLuint64KHR *ust, EGLuint64KHR *msc, 2305848b8605Smrg EGLuint64KHR *sbc) 2306848b8605Smrg{ 2307b8e80941Smrg _EGLDisplay *disp = _eglLockDisplay(dpy); 2308848b8605Smrg _EGLSurface *surf = _eglLookupSurface(surface, disp); 2309848b8605Smrg _EGLDriver *drv; 2310848b8605Smrg EGLBoolean ret; 2311848b8605Smrg 2312b8e80941Smrg _EGL_FUNC_START(disp, EGL_OBJECT_SURFACE_KHR, surf, EGL_FALSE); 2313b8e80941Smrg 2314848b8605Smrg _EGL_CHECK_SURFACE(disp, surf, EGL_FALSE, drv); 2315848b8605Smrg if (!disp->Extensions.CHROMIUM_sync_control) 2316848b8605Smrg RETURN_EGL_EVAL(disp, EGL_FALSE); 2317848b8605Smrg 2318848b8605Smrg if (!ust || !msc || !sbc) 2319848b8605Smrg RETURN_EGL_ERROR(disp, EGL_BAD_PARAMETER, EGL_FALSE); 2320848b8605Smrg 2321848b8605Smrg ret = drv->API.GetSyncValuesCHROMIUM(disp, surf, ust, msc, sbc); 2322848b8605Smrg 2323848b8605Smrg RETURN_EGL_EVAL(disp, ret); 2324848b8605Smrg} 2325b8e80941Smrg 2326b8e80941Smrgstatic EGLBoolean EGLAPIENTRY 2327b8e80941SmrgeglExportDMABUFImageQueryMESA(EGLDisplay dpy, EGLImage image, 2328b8e80941Smrg EGLint *fourcc, EGLint *nplanes, 2329b8e80941Smrg EGLuint64KHR *modifiers) 2330b8e80941Smrg{ 2331b8e80941Smrg _EGLDisplay *disp = _eglLockDisplay(dpy); 2332b8e80941Smrg _EGLImage *img = _eglLookupImage(image, disp); 2333b8e80941Smrg _EGLDriver *drv; 2334b8e80941Smrg EGLBoolean ret; 2335b8e80941Smrg 2336b8e80941Smrg _EGL_FUNC_START(disp, EGL_OBJECT_IMAGE_KHR, img, EGL_FALSE); 2337b8e80941Smrg 2338b8e80941Smrg _EGL_CHECK_DISPLAY(disp, EGL_FALSE, drv); 2339b8e80941Smrg assert(disp->Extensions.MESA_image_dma_buf_export); 2340b8e80941Smrg 2341b8e80941Smrg if (!img) 2342b8e80941Smrg RETURN_EGL_ERROR(disp, EGL_BAD_PARAMETER, EGL_FALSE); 2343b8e80941Smrg 2344b8e80941Smrg ret = drv->API.ExportDMABUFImageQueryMESA(drv, disp, img, fourcc, nplanes, 2345b8e80941Smrg modifiers); 2346b8e80941Smrg 2347b8e80941Smrg RETURN_EGL_EVAL(disp, ret); 2348b8e80941Smrg} 2349b8e80941Smrg 2350b8e80941Smrgstatic EGLBoolean EGLAPIENTRY 2351b8e80941SmrgeglExportDMABUFImageMESA(EGLDisplay dpy, EGLImage image, 2352b8e80941Smrg int *fds, EGLint *strides, EGLint *offsets) 2353b8e80941Smrg{ 2354b8e80941Smrg _EGLDisplay *disp = _eglLockDisplay(dpy); 2355b8e80941Smrg _EGLImage *img = _eglLookupImage(image, disp); 2356b8e80941Smrg _EGLDriver *drv; 2357b8e80941Smrg EGLBoolean ret; 2358b8e80941Smrg 2359b8e80941Smrg _EGL_FUNC_START(disp, EGL_OBJECT_IMAGE_KHR, img, EGL_FALSE); 2360b8e80941Smrg 2361b8e80941Smrg _EGL_CHECK_DISPLAY(disp, EGL_FALSE, drv); 2362b8e80941Smrg assert(disp->Extensions.MESA_image_dma_buf_export); 2363b8e80941Smrg 2364b8e80941Smrg if (!img) 2365b8e80941Smrg RETURN_EGL_ERROR(disp, EGL_BAD_PARAMETER, EGL_FALSE); 2366b8e80941Smrg 2367b8e80941Smrg ret = drv->API.ExportDMABUFImageMESA(drv, disp, img, fds, strides, offsets); 2368b8e80941Smrg 2369b8e80941Smrg RETURN_EGL_EVAL(disp, ret); 2370b8e80941Smrg} 2371b8e80941Smrg 2372b8e80941Smrgstatic EGLint EGLAPIENTRY 2373b8e80941SmrgeglLabelObjectKHR(EGLDisplay dpy, EGLenum objectType, EGLObjectKHR object, 2374b8e80941Smrg EGLLabelKHR label) 2375b8e80941Smrg{ 2376b8e80941Smrg _EGLDisplay *disp = NULL; 2377b8e80941Smrg _EGLResourceType type; 2378b8e80941Smrg 2379b8e80941Smrg _EGL_FUNC_START(NULL, EGL_NONE, NULL, EGL_BAD_ALLOC); 2380b8e80941Smrg 2381b8e80941Smrg if (objectType == EGL_OBJECT_THREAD_KHR) { 2382b8e80941Smrg _EGLThreadInfo *t = _eglGetCurrentThread(); 2383b8e80941Smrg 2384b8e80941Smrg if (!_eglIsCurrentThreadDummy()) { 2385b8e80941Smrg t->Label = label; 2386b8e80941Smrg return EGL_SUCCESS; 2387b8e80941Smrg } 2388b8e80941Smrg 2389b8e80941Smrg RETURN_EGL_ERROR(NULL, EGL_BAD_ALLOC, EGL_BAD_ALLOC); 2390b8e80941Smrg } 2391b8e80941Smrg 2392b8e80941Smrg disp = _eglLockDisplay(dpy); 2393b8e80941Smrg if (disp == NULL) 2394b8e80941Smrg RETURN_EGL_ERROR(disp, EGL_BAD_DISPLAY, EGL_BAD_DISPLAY); 2395b8e80941Smrg 2396b8e80941Smrg if (objectType == EGL_OBJECT_DISPLAY_KHR) { 2397b8e80941Smrg if (dpy != (EGLDisplay) object) 2398b8e80941Smrg RETURN_EGL_ERROR(disp, EGL_BAD_PARAMETER, EGL_BAD_PARAMETER); 2399b8e80941Smrg 2400b8e80941Smrg disp->Label = label; 2401b8e80941Smrg RETURN_EGL_EVAL(disp, EGL_SUCCESS); 2402b8e80941Smrg } 2403b8e80941Smrg 2404b8e80941Smrg switch (objectType) { 2405b8e80941Smrg case EGL_OBJECT_CONTEXT_KHR: 2406b8e80941Smrg type = _EGL_RESOURCE_CONTEXT; 2407b8e80941Smrg break; 2408b8e80941Smrg case EGL_OBJECT_SURFACE_KHR: 2409b8e80941Smrg type = _EGL_RESOURCE_SURFACE; 2410b8e80941Smrg break; 2411b8e80941Smrg case EGL_OBJECT_IMAGE_KHR: 2412b8e80941Smrg type = _EGL_RESOURCE_IMAGE; 2413b8e80941Smrg break; 2414b8e80941Smrg case EGL_OBJECT_SYNC_KHR: 2415b8e80941Smrg type = _EGL_RESOURCE_SYNC; 2416b8e80941Smrg break; 2417b8e80941Smrg case EGL_OBJECT_STREAM_KHR: 2418b8e80941Smrg default: 2419b8e80941Smrg RETURN_EGL_ERROR(disp, EGL_BAD_PARAMETER, EGL_BAD_PARAMETER); 2420b8e80941Smrg } 2421b8e80941Smrg 2422b8e80941Smrg if (_eglCheckResource(object, type, disp)) { 2423b8e80941Smrg _EGLResource *res = (_EGLResource *) object; 2424b8e80941Smrg 2425b8e80941Smrg res->Label = label; 2426b8e80941Smrg RETURN_EGL_EVAL(disp, EGL_SUCCESS); 2427b8e80941Smrg } 2428b8e80941Smrg 2429b8e80941Smrg RETURN_EGL_ERROR(disp, EGL_BAD_PARAMETER, EGL_BAD_PARAMETER); 2430b8e80941Smrg} 2431b8e80941Smrg 2432b8e80941Smrgstatic EGLint EGLAPIENTRY 2433b8e80941SmrgeglDebugMessageControlKHR(EGLDEBUGPROCKHR callback, 2434b8e80941Smrg const EGLAttrib *attrib_list) 2435b8e80941Smrg{ 2436b8e80941Smrg unsigned int newEnabled; 2437b8e80941Smrg 2438b8e80941Smrg _EGL_FUNC_START(NULL, EGL_NONE, NULL, EGL_BAD_ALLOC); 2439b8e80941Smrg 2440b8e80941Smrg mtx_lock(_eglGlobal.Mutex); 2441b8e80941Smrg 2442b8e80941Smrg newEnabled = _eglGlobal.debugTypesEnabled; 2443b8e80941Smrg if (attrib_list != NULL) { 2444b8e80941Smrg int i; 2445b8e80941Smrg 2446b8e80941Smrg for (i = 0; attrib_list[i] != EGL_NONE; i += 2) { 2447b8e80941Smrg switch (attrib_list[i]) { 2448b8e80941Smrg case EGL_DEBUG_MSG_CRITICAL_KHR: 2449b8e80941Smrg case EGL_DEBUG_MSG_ERROR_KHR: 2450b8e80941Smrg case EGL_DEBUG_MSG_WARN_KHR: 2451b8e80941Smrg case EGL_DEBUG_MSG_INFO_KHR: 2452b8e80941Smrg if (attrib_list[i + 1]) 2453b8e80941Smrg newEnabled |= DebugBitFromType(attrib_list[i]); 2454b8e80941Smrg else 2455b8e80941Smrg newEnabled &= ~DebugBitFromType(attrib_list[i]); 2456b8e80941Smrg break; 2457b8e80941Smrg default: 2458b8e80941Smrg // On error, set the last error code, call the current 2459b8e80941Smrg // debug callback, and return the error code. 2460b8e80941Smrg mtx_unlock(_eglGlobal.Mutex); 2461b8e80941Smrg _eglReportError(EGL_BAD_ATTRIBUTE, NULL, 2462b8e80941Smrg "Invalid attribute 0x%04lx", (unsigned long) attrib_list[i]); 2463b8e80941Smrg return EGL_BAD_ATTRIBUTE; 2464b8e80941Smrg } 2465b8e80941Smrg } 2466b8e80941Smrg } 2467b8e80941Smrg 2468b8e80941Smrg if (callback != NULL) { 2469b8e80941Smrg _eglGlobal.debugCallback = callback; 2470b8e80941Smrg _eglGlobal.debugTypesEnabled = newEnabled; 2471b8e80941Smrg } else { 2472b8e80941Smrg _eglGlobal.debugCallback = NULL; 2473b8e80941Smrg _eglGlobal.debugTypesEnabled = _EGL_DEBUG_BIT_CRITICAL | _EGL_DEBUG_BIT_ERROR; 2474b8e80941Smrg } 2475b8e80941Smrg 2476b8e80941Smrg mtx_unlock(_eglGlobal.Mutex); 2477b8e80941Smrg return EGL_SUCCESS; 2478b8e80941Smrg} 2479b8e80941Smrg 2480b8e80941Smrgstatic EGLBoolean EGLAPIENTRY 2481b8e80941SmrgeglQueryDebugKHR(EGLint attribute, EGLAttrib *value) 2482b8e80941Smrg{ 2483b8e80941Smrg _EGL_FUNC_START(NULL, EGL_NONE, NULL, EGL_BAD_ALLOC); 2484b8e80941Smrg 2485b8e80941Smrg mtx_lock(_eglGlobal.Mutex); 2486b8e80941Smrg 2487b8e80941Smrg switch (attribute) { 2488b8e80941Smrg case EGL_DEBUG_MSG_CRITICAL_KHR: 2489b8e80941Smrg case EGL_DEBUG_MSG_ERROR_KHR: 2490b8e80941Smrg case EGL_DEBUG_MSG_WARN_KHR: 2491b8e80941Smrg case EGL_DEBUG_MSG_INFO_KHR: 2492b8e80941Smrg if (_eglGlobal.debugTypesEnabled & DebugBitFromType(attribute)) 2493b8e80941Smrg *value = EGL_TRUE; 2494b8e80941Smrg else 2495b8e80941Smrg *value = EGL_FALSE; 2496b8e80941Smrg break; 2497b8e80941Smrg case EGL_DEBUG_CALLBACK_KHR: 2498b8e80941Smrg *value = (EGLAttrib) _eglGlobal.debugCallback; 2499b8e80941Smrg break; 2500b8e80941Smrg default: 2501b8e80941Smrg mtx_unlock(_eglGlobal.Mutex); 2502b8e80941Smrg _eglReportError(EGL_BAD_ATTRIBUTE, NULL, 2503b8e80941Smrg "Invalid attribute 0x%04lx", (unsigned long) attribute); 2504b8e80941Smrg return EGL_FALSE; 2505b8e80941Smrg } 2506b8e80941Smrg 2507b8e80941Smrg mtx_unlock(_eglGlobal.Mutex); 2508b8e80941Smrg return EGL_TRUE; 2509b8e80941Smrg} 2510b8e80941Smrg 2511b8e80941Smrgstatic int 2512b8e80941Smrg_eglFunctionCompare(const void *key, const void *elem) 2513b8e80941Smrg{ 2514b8e80941Smrg const char *procname = key; 2515b8e80941Smrg const struct _egl_entrypoint *entrypoint = elem; 2516b8e80941Smrg return strcmp(procname, entrypoint->name); 2517b8e80941Smrg} 2518b8e80941Smrg 2519b8e80941Smrgstatic EGLBoolean EGLAPIENTRY 2520b8e80941SmrgeglQueryDmaBufFormatsEXT(EGLDisplay dpy, EGLint max_formats, 2521b8e80941Smrg EGLint *formats, EGLint *num_formats) 2522b8e80941Smrg{ 2523b8e80941Smrg _EGLDisplay *disp = _eglLockDisplay(dpy); 2524b8e80941Smrg _EGLDriver *drv; 2525b8e80941Smrg EGLBoolean ret; 2526b8e80941Smrg 2527b8e80941Smrg _EGL_FUNC_START(NULL, EGL_NONE, NULL, EGL_FALSE); 2528b8e80941Smrg 2529b8e80941Smrg _EGL_CHECK_DISPLAY(disp, EGL_FALSE, drv); 2530b8e80941Smrg 2531b8e80941Smrg ret = drv->API.QueryDmaBufFormatsEXT(drv, disp, max_formats, formats, 2532b8e80941Smrg num_formats); 2533b8e80941Smrg 2534b8e80941Smrg RETURN_EGL_EVAL(disp, ret); 2535b8e80941Smrg} 2536b8e80941Smrg 2537b8e80941Smrgstatic EGLBoolean EGLAPIENTRY 2538b8e80941SmrgeglQueryDmaBufModifiersEXT(EGLDisplay dpy, EGLint format, EGLint max_modifiers, 2539b8e80941Smrg EGLuint64KHR *modifiers, EGLBoolean *external_only, 2540b8e80941Smrg EGLint *num_modifiers) 2541b8e80941Smrg{ 2542b8e80941Smrg _EGLDisplay *disp = _eglLockDisplay(dpy); 2543b8e80941Smrg _EGLDriver *drv; 2544b8e80941Smrg EGLBoolean ret; 2545b8e80941Smrg 2546b8e80941Smrg _EGL_FUNC_START(NULL, EGL_NONE, NULL, EGL_FALSE); 2547b8e80941Smrg 2548b8e80941Smrg _EGL_CHECK_DISPLAY(disp, EGL_FALSE, drv); 2549b8e80941Smrg 2550b8e80941Smrg ret = drv->API.QueryDmaBufModifiersEXT(drv, disp, format, max_modifiers, 2551b8e80941Smrg modifiers, external_only, 2552b8e80941Smrg num_modifiers); 2553b8e80941Smrg 2554b8e80941Smrg RETURN_EGL_EVAL(disp, ret); 2555b8e80941Smrg} 2556b8e80941Smrg 2557b8e80941Smrgstatic void EGLAPIENTRY 2558b8e80941SmrgeglSetBlobCacheFuncsANDROID(EGLDisplay *dpy, EGLSetBlobFuncANDROID set, 2559b8e80941Smrg EGLGetBlobFuncANDROID get) 2560b8e80941Smrg{ 2561b8e80941Smrg /* This function does not return anything so we cannot 2562b8e80941Smrg * utilize the helper macros _EGL_FUNC_START or _EGL_CHECK_DISPLAY. 2563b8e80941Smrg */ 2564b8e80941Smrg _EGLDisplay *disp = _eglLockDisplay(dpy); 2565b8e80941Smrg if (!_eglSetFuncName(__func__, disp, EGL_OBJECT_DISPLAY_KHR, NULL)) { 2566b8e80941Smrg if (disp) 2567b8e80941Smrg _eglUnlockDisplay(disp); 2568b8e80941Smrg return; 2569b8e80941Smrg } 2570b8e80941Smrg 2571b8e80941Smrg _EGLDriver *drv = _eglCheckDisplay(disp, __func__); 2572b8e80941Smrg if (!drv) { 2573b8e80941Smrg if (disp) 2574b8e80941Smrg _eglUnlockDisplay(disp); 2575b8e80941Smrg return; 2576b8e80941Smrg } 2577b8e80941Smrg 2578b8e80941Smrg if (!set || !get) { 2579b8e80941Smrg _eglError(EGL_BAD_PARAMETER, 2580b8e80941Smrg "eglSetBlobCacheFuncsANDROID: NULL handler given"); 2581b8e80941Smrg _eglUnlockDisplay(disp); 2582b8e80941Smrg return; 2583b8e80941Smrg } 2584b8e80941Smrg 2585b8e80941Smrg if (disp->BlobCacheSet) { 2586b8e80941Smrg _eglError(EGL_BAD_PARAMETER, 2587b8e80941Smrg "eglSetBlobCacheFuncsANDROID: functions already set"); 2588b8e80941Smrg _eglUnlockDisplay(disp); 2589b8e80941Smrg return; 2590b8e80941Smrg } 2591b8e80941Smrg 2592b8e80941Smrg disp->BlobCacheSet = set; 2593b8e80941Smrg disp->BlobCacheGet = get; 2594b8e80941Smrg 2595b8e80941Smrg drv->API.SetBlobCacheFuncsANDROID(drv, disp, set, get); 2596b8e80941Smrg 2597b8e80941Smrg _eglUnlockDisplay(disp); 2598b8e80941Smrg} 2599b8e80941Smrg 2600b8e80941Smrgstatic EGLBoolean EGLAPIENTRY 2601b8e80941SmrgeglQueryDeviceAttribEXT(EGLDeviceEXT device, 2602b8e80941Smrg EGLint attribute, 2603b8e80941Smrg EGLAttrib *value) 2604b8e80941Smrg{ 2605b8e80941Smrg _EGLDevice *dev = _eglLookupDevice(device); 2606b8e80941Smrg EGLBoolean ret; 2607b8e80941Smrg 2608b8e80941Smrg _EGL_FUNC_START(NULL, EGL_NONE, NULL, EGL_FALSE); 2609b8e80941Smrg if (!dev) 2610b8e80941Smrg RETURN_EGL_ERROR(NULL, EGL_BAD_DEVICE_EXT, EGL_FALSE); 2611b8e80941Smrg 2612b8e80941Smrg ret = _eglQueryDeviceAttribEXT(dev, attribute, value); 2613b8e80941Smrg RETURN_EGL_EVAL(NULL, ret); 2614b8e80941Smrg} 2615b8e80941Smrg 2616b8e80941Smrgstatic const char * EGLAPIENTRY 2617b8e80941SmrgeglQueryDeviceStringEXT(EGLDeviceEXT device, 2618b8e80941Smrg EGLint name) 2619b8e80941Smrg{ 2620b8e80941Smrg _EGLDevice *dev = _eglLookupDevice(device); 2621b8e80941Smrg 2622b8e80941Smrg _EGL_FUNC_START(NULL, EGL_NONE, NULL, NULL); 2623b8e80941Smrg if (!dev) 2624b8e80941Smrg RETURN_EGL_ERROR(NULL, EGL_BAD_DEVICE_EXT, NULL); 2625b8e80941Smrg 2626b8e80941Smrg RETURN_EGL_EVAL(NULL, _eglQueryDeviceStringEXT(dev, name)); 2627b8e80941Smrg} 2628b8e80941Smrg 2629b8e80941Smrgstatic EGLBoolean EGLAPIENTRY 2630b8e80941SmrgeglQueryDevicesEXT(EGLint max_devices, 2631b8e80941Smrg EGLDeviceEXT *devices, 2632b8e80941Smrg EGLint *num_devices) 2633b8e80941Smrg{ 2634b8e80941Smrg EGLBoolean ret; 2635b8e80941Smrg 2636b8e80941Smrg _EGL_FUNC_START(NULL, EGL_NONE, NULL, EGL_FALSE); 2637b8e80941Smrg ret = _eglQueryDevicesEXT(max_devices, (_EGLDevice **) devices, 2638b8e80941Smrg num_devices); 2639b8e80941Smrg RETURN_EGL_EVAL(NULL, ret); 2640b8e80941Smrg} 2641b8e80941Smrg 2642b8e80941Smrgstatic EGLBoolean EGLAPIENTRY 2643b8e80941SmrgeglQueryDisplayAttribEXT(EGLDisplay dpy, 2644b8e80941Smrg EGLint attribute, 2645b8e80941Smrg EGLAttrib *value) 2646b8e80941Smrg{ 2647b8e80941Smrg _EGLDisplay *disp = _eglLockDisplay(dpy); 2648b8e80941Smrg _EGLDriver *drv; 2649b8e80941Smrg 2650b8e80941Smrg _EGL_FUNC_START(NULL, EGL_NONE, NULL, EGL_FALSE); 2651b8e80941Smrg _EGL_CHECK_DISPLAY(disp, EGL_FALSE, drv); 2652b8e80941Smrg 2653b8e80941Smrg switch (attribute) { 2654b8e80941Smrg case EGL_DEVICE_EXT: 2655b8e80941Smrg *value = (EGLAttrib) disp->Device; 2656b8e80941Smrg break; 2657b8e80941Smrg default: 2658b8e80941Smrg RETURN_EGL_ERROR(disp, EGL_BAD_ATTRIBUTE, EGL_FALSE); 2659b8e80941Smrg } 2660b8e80941Smrg RETURN_EGL_SUCCESS(disp, EGL_TRUE); 2661b8e80941Smrg} 2662b8e80941Smrg 2663b8e80941Smrgstatic char * EGLAPIENTRY 2664b8e80941SmrgeglGetDisplayDriverConfig(EGLDisplay dpy) 2665b8e80941Smrg{ 2666b8e80941Smrg _EGLDisplay *disp = _eglLockDisplay(dpy); 2667b8e80941Smrg _EGLDriver *drv; 2668b8e80941Smrg char *ret; 2669b8e80941Smrg 2670b8e80941Smrg _EGL_FUNC_START(disp, EGL_NONE, NULL, NULL); 2671b8e80941Smrg _EGL_CHECK_DISPLAY(disp, NULL, drv); 2672b8e80941Smrg 2673b8e80941Smrg assert(disp->Extensions.MESA_query_driver); 2674b8e80941Smrg 2675b8e80941Smrg ret = drv->API.QueryDriverConfig(disp); 2676b8e80941Smrg RETURN_EGL_EVAL(disp, ret); 2677b8e80941Smrg} 2678b8e80941Smrg 2679b8e80941Smrgstatic const char * EGLAPIENTRY 2680b8e80941SmrgeglGetDisplayDriverName(EGLDisplay dpy) 2681b8e80941Smrg{ 2682b8e80941Smrg _EGLDisplay *disp = _eglLockDisplay(dpy); 2683b8e80941Smrg _EGLDriver *drv; 2684b8e80941Smrg const char *ret; 2685b8e80941Smrg 2686b8e80941Smrg _EGL_FUNC_START(disp, EGL_NONE, NULL, NULL); 2687b8e80941Smrg _EGL_CHECK_DISPLAY(disp, NULL, drv); 2688b8e80941Smrg 2689b8e80941Smrg assert(disp->Extensions.MESA_query_driver); 2690b8e80941Smrg 2691b8e80941Smrg ret = drv->API.QueryDriverName(disp); 2692b8e80941Smrg RETURN_EGL_EVAL(disp, ret); 2693b8e80941Smrg} 2694b8e80941Smrg 2695b8e80941Smrg__eglMustCastToProperFunctionPointerType EGLAPIENTRY 2696b8e80941SmrgeglGetProcAddress(const char *procname) 2697b8e80941Smrg{ 2698b8e80941Smrg static const struct _egl_entrypoint egl_functions[] = { 2699b8e80941Smrg#define EGL_ENTRYPOINT(f) { .name = #f, .function = (_EGLProc) f }, 2700b8e80941Smrg#include "eglentrypoint.h" 2701b8e80941Smrg#undef EGL_ENTRYPOINT 2702b8e80941Smrg }; 2703b8e80941Smrg _EGLProc ret = NULL; 2704b8e80941Smrg 2705b8e80941Smrg if (!procname) 2706b8e80941Smrg RETURN_EGL_SUCCESS(NULL, NULL); 2707b8e80941Smrg 2708b8e80941Smrg _EGL_FUNC_START(NULL, EGL_NONE, NULL, NULL); 2709b8e80941Smrg 2710b8e80941Smrg if (strncmp(procname, "egl", 3) == 0) { 2711b8e80941Smrg const struct _egl_entrypoint *entrypoint = 2712b8e80941Smrg bsearch(procname, 2713b8e80941Smrg egl_functions, ARRAY_SIZE(egl_functions), 2714b8e80941Smrg sizeof(egl_functions[0]), 2715b8e80941Smrg _eglFunctionCompare); 2716b8e80941Smrg if (entrypoint) 2717b8e80941Smrg ret = entrypoint->function; 2718b8e80941Smrg } 2719b8e80941Smrg 2720b8e80941Smrg if (!ret) 2721b8e80941Smrg ret = _eglGetDriverProc(procname); 2722b8e80941Smrg 2723b8e80941Smrg RETURN_EGL_SUCCESS(NULL, ret); 2724b8e80941Smrg} 2725b8e80941Smrg 2726b8e80941Smrgstatic int 2727b8e80941Smrg_eglLockDisplayInterop(EGLDisplay dpy, EGLContext context, 2728b8e80941Smrg _EGLDisplay **disp, _EGLDriver **drv, 2729b8e80941Smrg _EGLContext **ctx) 2730b8e80941Smrg{ 2731b8e80941Smrg 2732b8e80941Smrg *disp = _eglLockDisplay(dpy); 2733b8e80941Smrg if (!*disp || !(*disp)->Initialized || !(*disp)->Driver) { 2734b8e80941Smrg if (*disp) 2735b8e80941Smrg _eglUnlockDisplay(*disp); 2736b8e80941Smrg return MESA_GLINTEROP_INVALID_DISPLAY; 2737b8e80941Smrg } 2738b8e80941Smrg 2739b8e80941Smrg *drv = (*disp)->Driver; 2740b8e80941Smrg 2741b8e80941Smrg *ctx = _eglLookupContext(context, *disp); 2742b8e80941Smrg if (!*ctx || 2743b8e80941Smrg ((*ctx)->ClientAPI != EGL_OPENGL_API && 2744b8e80941Smrg (*ctx)->ClientAPI != EGL_OPENGL_ES_API)) { 2745b8e80941Smrg _eglUnlockDisplay(*disp); 2746b8e80941Smrg return MESA_GLINTEROP_INVALID_CONTEXT; 2747b8e80941Smrg } 2748b8e80941Smrg 2749b8e80941Smrg return MESA_GLINTEROP_SUCCESS; 2750b8e80941Smrg} 2751b8e80941Smrg 2752b8e80941SmrgPUBLIC int 2753b8e80941SmrgMesaGLInteropEGLQueryDeviceInfo(EGLDisplay dpy, EGLContext context, 2754b8e80941Smrg struct mesa_glinterop_device_info *out) 2755b8e80941Smrg{ 2756b8e80941Smrg _EGLDisplay *disp; 2757b8e80941Smrg _EGLDriver *drv; 2758b8e80941Smrg _EGLContext *ctx; 2759b8e80941Smrg int ret; 2760b8e80941Smrg 2761b8e80941Smrg ret = _eglLockDisplayInterop(dpy, context, &disp, &drv, &ctx); 2762b8e80941Smrg if (ret != MESA_GLINTEROP_SUCCESS) 2763b8e80941Smrg return ret; 2764b8e80941Smrg 2765b8e80941Smrg if (drv->API.GLInteropQueryDeviceInfo) 2766b8e80941Smrg ret = drv->API.GLInteropQueryDeviceInfo(disp, ctx, out); 2767b8e80941Smrg else 2768b8e80941Smrg ret = MESA_GLINTEROP_UNSUPPORTED; 2769b8e80941Smrg 2770b8e80941Smrg _eglUnlockDisplay(disp); 2771b8e80941Smrg return ret; 2772b8e80941Smrg} 2773b8e80941Smrg 2774b8e80941SmrgPUBLIC int 2775b8e80941SmrgMesaGLInteropEGLExportObject(EGLDisplay dpy, EGLContext context, 2776b8e80941Smrg struct mesa_glinterop_export_in *in, 2777b8e80941Smrg struct mesa_glinterop_export_out *out) 2778b8e80941Smrg{ 2779b8e80941Smrg _EGLDisplay *disp; 2780b8e80941Smrg _EGLDriver *drv; 2781b8e80941Smrg _EGLContext *ctx; 2782b8e80941Smrg int ret; 2783b8e80941Smrg 2784b8e80941Smrg ret = _eglLockDisplayInterop(dpy, context, &disp, &drv, &ctx); 2785b8e80941Smrg if (ret != MESA_GLINTEROP_SUCCESS) 2786b8e80941Smrg return ret; 2787b8e80941Smrg 2788b8e80941Smrg if (drv->API.GLInteropExportObject) 2789b8e80941Smrg ret = drv->API.GLInteropExportObject(disp, ctx, in, out); 2790b8e80941Smrg else 2791b8e80941Smrg ret = MESA_GLINTEROP_UNSUPPORTED; 2792b8e80941Smrg 2793b8e80941Smrg _eglUnlockDisplay(disp); 2794b8e80941Smrg return ret; 2795b8e80941Smrg} 2796