diff options
Diffstat (limited to 'src/egl/main/eglapi.c')
-rw-r--r-- | src/egl/main/eglapi.c | 1282 |
1 files changed, 1282 insertions, 0 deletions
diff --git a/src/egl/main/eglapi.c b/src/egl/main/eglapi.c new file mode 100644 index 0000000000..9912043e06 --- /dev/null +++ b/src/egl/main/eglapi.c @@ -0,0 +1,1282 @@ +/** + * Public EGL API entrypoints + * + * Generally, we use the EGLDisplay parameter as a key to lookup the + * appropriate device driver handle, then jump though the driver's + * dispatch table to handle the function. + * + * That allows us the option of supporting multiple, simultaneous, + * heterogeneous hardware devices in the future. + * + * The EGLDisplay, EGLConfig, EGLContext and EGLSurface types are + * opaque handles. Internal objects are linked to a display to + * create the handles. + * + * For each public API entry point, the opaque handles are looked up + * before being dispatched to the drivers. When it fails to look up + * a handle, one of + * + * EGL_BAD_DISPLAY + * EGL_BAD_CONFIG + * EGL_BAD_CONTEXT + * EGL_BAD_SURFACE + * EGL_BAD_SCREEN_MESA + * EGL_BAD_MODE_MESA + * + * is generated and the driver function is not called. An + * uninitialized EGLDisplay has no driver associated with it. When + * such display is detected, + * + * EGL_NOT_INITIALIZED + * + * is generated. + * + * Some of the entry points use current display, context, or surface + * implicitly. For such entry points, the implicit objects are also + * checked before calling the driver function. Other than the + * errors listed above, + * + * EGL_BAD_CURRENT_SURFACE + * + * may also be generated. + * + * Notes on naming conventions: + * + * eglFooBar - public EGL function + * EGL_FOO_BAR - public EGL token + * EGLDatatype - public EGL datatype + * + * _eglFooBar - private EGL function + * _EGLDatatype - private EGL datatype, typedef'd struct + * _egl_struct - private EGL struct, non-typedef'd + * + */ + + +#include <stdio.h> +#include <stdlib.h> +#include <string.h> + +#include "eglstring.h" +#include "eglcontext.h" +#include "egldisplay.h" +#include "egltypedefs.h" +#include "eglglobals.h" +#include "eglcurrent.h" +#include "egldriver.h" +#include "eglsurface.h" +#include "eglconfig.h" +#include "eglscreen.h" +#include "eglmode.h" +#include "eglimage.h" + + +/** + * Macros to help return an API entrypoint. + * + * These macros will unlock the display and record the error code. + */ +#define RETURN_EGL_ERROR(disp, err, ret) \ + do { \ + if (disp) \ + _eglUnlockDisplay(disp); \ + /* EGL error codes are non-zero */ \ + if (err) \ + _eglError(err, __FUNCTION__); \ + return ret; \ + } while (0) + +#define RETURN_EGL_SUCCESS(disp, ret) \ + RETURN_EGL_ERROR(disp, EGL_SUCCESS, ret) + +/* record EGL_SUCCESS only when ret evaluates to true */ +#define RETURN_EGL_EVAL(disp, ret) \ + RETURN_EGL_ERROR(disp, (ret) ? EGL_SUCCESS : 0, ret) + + +/* + * A bunch of macros and checks to simplify error checking. + */ + +#define _EGL_CHECK_DISPLAY(disp, ret, drv) \ + do { \ + drv = _eglCheckDisplay(disp, __FUNCTION__); \ + if (!drv) \ + RETURN_EGL_ERROR(disp, 0, ret); \ + } while (0) + +#define _EGL_CHECK_OBJECT(disp, type, obj, ret, drv) \ + do { \ + drv = _eglCheck ## type(disp, obj, __FUNCTION__); \ + if (!drv) \ + RETURN_EGL_ERROR(disp, 0, ret); \ + } while (0) + +#define _EGL_CHECK_SURFACE(disp, surf, ret, drv) \ + _EGL_CHECK_OBJECT(disp, Surface, surf, ret, drv) + +#define _EGL_CHECK_CONTEXT(disp, context, ret, drv) \ + _EGL_CHECK_OBJECT(disp, Context, context, ret, drv) + +#define _EGL_CHECK_CONFIG(disp, conf, ret, drv) \ + _EGL_CHECK_OBJECT(disp, Config, conf, ret, drv) + +#define _EGL_CHECK_SCREEN(disp, scrn, ret, drv) \ + _EGL_CHECK_OBJECT(disp, Screen, scrn, ret, drv) + +#define _EGL_CHECK_MODE(disp, m, ret, drv) \ + _EGL_CHECK_OBJECT(disp, Mode, m, ret, drv) + + + +static INLINE _EGLDriver * +_eglCheckDisplay(_EGLDisplay *disp, const char *msg) +{ + if (!disp) { + _eglError(EGL_BAD_DISPLAY, msg); + return NULL; + } + if (!disp->Initialized) { + _eglError(EGL_NOT_INITIALIZED, msg); + return NULL; + } + return disp->Driver; +} + + +static INLINE _EGLDriver * +_eglCheckSurface(_EGLDisplay *disp, _EGLSurface *surf, const char *msg) +{ + _EGLDriver *drv = _eglCheckDisplay(disp, msg); + if (!drv) + return NULL; + if (!surf) { + _eglError(EGL_BAD_SURFACE, msg); + return NULL; + } + return drv; +} + + +static INLINE _EGLDriver * +_eglCheckContext(_EGLDisplay *disp, _EGLContext *context, const char *msg) +{ + _EGLDriver *drv = _eglCheckDisplay(disp, msg); + if (!drv) + return NULL; + if (!context) { + _eglError(EGL_BAD_CONTEXT, msg); + return NULL; + } + return drv; +} + + +static INLINE _EGLDriver * +_eglCheckConfig(_EGLDisplay *disp, _EGLConfig *conf, const char *msg) +{ + _EGLDriver *drv = _eglCheckDisplay(disp, msg); + if (!drv) + return NULL; + if (!conf) { + _eglError(EGL_BAD_CONFIG, msg); + return NULL; + } + return drv; +} + + +#ifdef EGL_MESA_screen_surface + + +static INLINE _EGLDriver * +_eglCheckScreen(_EGLDisplay *disp, _EGLScreen *scrn, const char *msg) +{ + _EGLDriver *drv = _eglCheckDisplay(disp, msg); + if (!drv) + return NULL; + if (!scrn) { + _eglError(EGL_BAD_SCREEN_MESA, msg); + return NULL; + } + return drv; +} + + +static INLINE _EGLDriver * +_eglCheckMode(_EGLDisplay *disp, _EGLMode *m, const char *msg) +{ + _EGLDriver *drv = _eglCheckDisplay(disp, msg); + if (!drv) + return NULL; + if (!m) { + _eglError(EGL_BAD_MODE_MESA, msg); + return NULL; + } + return drv; +} + + +#endif /* EGL_MESA_screen_surface */ + + +/** + * Lookup and lock a display. + */ +static INLINE _EGLDisplay * +_eglLockDisplay(EGLDisplay display) +{ + _EGLDisplay *dpy = _eglLookupDisplay(display); + if (dpy) + _eglLockMutex(&dpy->Mutex); + return dpy; +} + + +/** + * Unlock a display. + */ +static INLINE void +_eglUnlockDisplay(_EGLDisplay *dpy) +{ + _eglUnlockMutex(&dpy->Mutex); +} + + +/** + * This is typically the first EGL function that an application calls. + * It associates a private _EGLDisplay object to the native display. + */ +EGLDisplay EGLAPIENTRY +eglGetDisplay(EGLNativeDisplayType nativeDisplay) +{ + _EGLDisplay *dpy = _eglFindDisplay(nativeDisplay); + return _eglGetDisplayHandle(dpy); +} + + +/** + * This is typically the second EGL function that an application calls. + * Here we load/initialize the actual hardware driver. + */ +EGLBoolean EGLAPIENTRY +eglInitialize(EGLDisplay dpy, EGLint *major, EGLint *minor) +{ + _EGLDisplay *disp = _eglLockDisplay(dpy); + EGLint major_int = 0, minor_int = 0; + + if (!disp) + RETURN_EGL_ERROR(NULL, EGL_BAD_DISPLAY, EGL_FALSE); + + if (!disp->Initialized) { + _EGLDriver *drv = disp->Driver; + + if (!drv) { + _eglPreloadDrivers(); + drv = _eglMatchDriver(disp); + /* Initialize the particular display now */ + if (drv && !drv->API.Initialize(drv, disp, &major_int, &minor_int)) + RETURN_EGL_ERROR(disp, EGL_NOT_INITIALIZED, EGL_FALSE); + } + if (!drv) + /* Load and initialize the first default driver that works */ + drv = _eglLoadDefaultDriver(disp, &major_int, &minor_int); + if (!drv) + RETURN_EGL_ERROR(disp, EGL_NOT_INITIALIZED, EGL_FALSE); + + disp->APImajor = major_int; + disp->APIminor = minor_int; + _eglsnprintf(disp->Version, sizeof(disp->Version), + "%d.%d (%s)", major_int, minor_int, drv->Name); + + /* limit to APIs supported by core */ + disp->ClientAPIsMask &= _EGL_API_ALL_BITS; + + disp->Driver = drv; + disp->Initialized = EGL_TRUE; + } else { + major_int = disp->APImajor; + minor_int = disp->APIminor; + } + + /* Update applications version of major and minor if not NULL */ + if ((major != NULL) && (minor != NULL)) { + *major = major_int; + *minor = minor_int; + } + + RETURN_EGL_SUCCESS(disp, EGL_TRUE); +} + + +EGLBoolean EGLAPIENTRY +eglTerminate(EGLDisplay dpy) +{ + _EGLDisplay *disp = _eglLockDisplay(dpy); + + if (!disp) + RETURN_EGL_ERROR(NULL, EGL_BAD_DISPLAY, EGL_FALSE); + + if (disp->Initialized) { + _EGLDriver *drv = disp->Driver; + + drv->API.Terminate(drv, disp); + /* do not reset disp->Driver */ + disp->Initialized = EGL_FALSE; + } + + RETURN_EGL_SUCCESS(disp, EGL_TRUE); +} + + +const char * EGLAPIENTRY +eglQueryString(EGLDisplay dpy, EGLint name) +{ + _EGLDisplay *disp = _eglLockDisplay(dpy); + _EGLDriver *drv; + const char *ret; + + _EGL_CHECK_DISPLAY(disp, NULL, drv); + ret = drv->API.QueryString(drv, disp, name); + + RETURN_EGL_EVAL(disp, ret); +} + + +EGLBoolean EGLAPIENTRY +eglGetConfigs(EGLDisplay dpy, EGLConfig *configs, + EGLint config_size, EGLint *num_config) +{ + _EGLDisplay *disp = _eglLockDisplay(dpy); + _EGLDriver *drv; + EGLBoolean ret; + + _EGL_CHECK_DISPLAY(disp, EGL_FALSE, drv); + ret = drv->API.GetConfigs(drv, disp, configs, config_size, num_config); + + RETURN_EGL_EVAL(disp, ret); +} + + +EGLBoolean EGLAPIENTRY +eglChooseConfig(EGLDisplay dpy, const EGLint *attrib_list, EGLConfig *configs, + EGLint config_size, EGLint *num_config) +{ + _EGLDisplay *disp = _eglLockDisplay(dpy); + _EGLDriver *drv; + EGLBoolean ret; + + _EGL_CHECK_DISPLAY(disp, EGL_FALSE, drv); + ret = drv->API.ChooseConfig(drv, disp, attrib_list, configs, + config_size, num_config); + + RETURN_EGL_EVAL(disp, ret); +} + + +EGLBoolean EGLAPIENTRY +eglGetConfigAttrib(EGLDisplay dpy, EGLConfig config, + EGLint attribute, EGLint *value) +{ + _EGLDisplay *disp = _eglLockDisplay(dpy); + _EGLConfig *conf = _eglLookupConfig(config, disp); + _EGLDriver *drv; + EGLBoolean ret; + + _EGL_CHECK_CONFIG(disp, conf, EGL_FALSE, drv); + ret = drv->API.GetConfigAttrib(drv, disp, conf, attribute, value); + + RETURN_EGL_EVAL(disp, ret); +} + + +EGLContext EGLAPIENTRY +eglCreateContext(EGLDisplay dpy, EGLConfig config, EGLContext share_list, + const EGLint *attrib_list) +{ + _EGLDisplay *disp = _eglLockDisplay(dpy); + _EGLConfig *conf = _eglLookupConfig(config, disp); + _EGLContext *share = _eglLookupContext(share_list, disp); + _EGLDriver *drv; + _EGLContext *context; + EGLContext ret; + + _EGL_CHECK_CONFIG(disp, conf, EGL_NO_CONTEXT, drv); + if (!share && share_list != EGL_NO_CONTEXT) + RETURN_EGL_ERROR(disp, EGL_BAD_CONTEXT, EGL_NO_CONTEXT); + + context = drv->API.CreateContext(drv, disp, conf, share, attrib_list); + ret = (context) ? _eglLinkContext(context, disp) : EGL_NO_CONTEXT; + + RETURN_EGL_EVAL(disp, ret); +} + + +EGLBoolean EGLAPIENTRY +eglDestroyContext(EGLDisplay dpy, EGLContext ctx) +{ + _EGLDisplay *disp = _eglLockDisplay(dpy); + _EGLContext *context = _eglLookupContext(ctx, disp); + _EGLDriver *drv; + EGLBoolean ret; + + _EGL_CHECK_CONTEXT(disp, context, EGL_FALSE, drv); + _eglUnlinkContext(context); + ret = drv->API.DestroyContext(drv, disp, context); + + RETURN_EGL_EVAL(disp, ret); +} + + +EGLBoolean EGLAPIENTRY +eglMakeCurrent(EGLDisplay dpy, EGLSurface draw, EGLSurface read, + EGLContext ctx) +{ + _EGLDisplay *disp = _eglLockDisplay(dpy); + _EGLContext *context = _eglLookupContext(ctx, disp); + _EGLSurface *draw_surf = _eglLookupSurface(draw, disp); + _EGLSurface *read_surf = _eglLookupSurface(read, disp); + _EGLDriver *drv; + EGLBoolean ret; + + if (!disp) + RETURN_EGL_ERROR(disp, EGL_BAD_DISPLAY, EGL_FALSE); + drv = disp->Driver; + + /* display is allowed to be uninitialized under certain condition */ + if (!disp->Initialized) { + if (draw != EGL_NO_SURFACE || read != EGL_NO_SURFACE || + ctx != EGL_NO_CONTEXT) + RETURN_EGL_ERROR(disp, EGL_BAD_DISPLAY, EGL_FALSE); + } + if (!drv) + RETURN_EGL_SUCCESS(disp, EGL_TRUE); + + if (!context && ctx != EGL_NO_CONTEXT) + RETURN_EGL_ERROR(disp, EGL_BAD_CONTEXT, EGL_FALSE); + if ((!draw_surf && draw != EGL_NO_SURFACE) || + (!read_surf && read != EGL_NO_SURFACE)) + RETURN_EGL_ERROR(disp, EGL_BAD_SURFACE, EGL_FALSE); + + ret = drv->API.MakeCurrent(drv, disp, draw_surf, read_surf, context); + + RETURN_EGL_EVAL(disp, ret); +} + + +EGLBoolean EGLAPIENTRY +eglQueryContext(EGLDisplay dpy, EGLContext ctx, + EGLint attribute, EGLint *value) +{ + _EGLDisplay *disp = _eglLockDisplay(dpy); + _EGLContext *context = _eglLookupContext(ctx, disp); + _EGLDriver *drv; + EGLBoolean ret; + + _EGL_CHECK_CONTEXT(disp, context, EGL_FALSE, drv); + ret = drv->API.QueryContext(drv, disp, context, attribute, value); + + RETURN_EGL_EVAL(disp, ret); +} + + +EGLSurface EGLAPIENTRY +eglCreateWindowSurface(EGLDisplay dpy, EGLConfig config, + EGLNativeWindowType window, const EGLint *attrib_list) +{ + _EGLDisplay *disp = _eglLockDisplay(dpy); + _EGLConfig *conf = _eglLookupConfig(config, disp); + _EGLDriver *drv; + _EGLSurface *surf; + EGLSurface ret; + + _EGL_CHECK_CONFIG(disp, conf, EGL_NO_SURFACE, drv); + + surf = drv->API.CreateWindowSurface(drv, disp, conf, window, attrib_list); + ret = (surf) ? _eglLinkSurface(surf, disp) : EGL_NO_SURFACE; + + RETURN_EGL_EVAL(disp, ret); +} + + +EGLSurface EGLAPIENTRY +eglCreatePixmapSurface(EGLDisplay dpy, EGLConfig config, + EGLNativePixmapType pixmap, const EGLint *attrib_list) +{ + _EGLDisplay *disp = _eglLockDisplay(dpy); + _EGLConfig *conf = _eglLookupConfig(config, disp); + _EGLDriver *drv; + _EGLSurface *surf; + EGLSurface ret; + + _EGL_CHECK_CONFIG(disp, conf, EGL_NO_SURFACE, drv); + + surf = drv->API.CreatePixmapSurface(drv, disp, conf, pixmap, attrib_list); + ret = (surf) ? _eglLinkSurface(surf, disp) : EGL_NO_SURFACE; + + RETURN_EGL_EVAL(disp, ret); +} + + +EGLSurface EGLAPIENTRY +eglCreatePbufferSurface(EGLDisplay dpy, EGLConfig config, + const EGLint *attrib_list) +{ + _EGLDisplay *disp = _eglLockDisplay(dpy); + _EGLConfig *conf = _eglLookupConfig(config, disp); + _EGLDriver *drv; + _EGLSurface *surf; + EGLSurface ret; + + _EGL_CHECK_CONFIG(disp, conf, EGL_NO_SURFACE, drv); + + surf = drv->API.CreatePbufferSurface(drv, disp, conf, attrib_list); + ret = (surf) ? _eglLinkSurface(surf, disp) : EGL_NO_SURFACE; + + RETURN_EGL_EVAL(disp, ret); +} + + +EGLBoolean EGLAPIENTRY +eglDestroySurface(EGLDisplay dpy, EGLSurface surface) +{ + _EGLDisplay *disp = _eglLockDisplay(dpy); + _EGLSurface *surf = _eglLookupSurface(surface, disp); + _EGLDriver *drv; + EGLBoolean ret; + + _EGL_CHECK_SURFACE(disp, surf, EGL_FALSE, drv); + _eglUnlinkSurface(surf); + ret = drv->API.DestroySurface(drv, disp, surf); + + RETURN_EGL_EVAL(disp, ret); +} + +EGLBoolean EGLAPIENTRY +eglQuerySurface(EGLDisplay dpy, EGLSurface surface, + EGLint attribute, EGLint *value) +{ + _EGLDisplay *disp = _eglLockDisplay(dpy); + _EGLSurface *surf = _eglLookupSurface(surface, disp); + _EGLDriver *drv; + EGLBoolean ret; + + _EGL_CHECK_SURFACE(disp, surf, EGL_FALSE, drv); + ret = drv->API.QuerySurface(drv, disp, surf, attribute, value); + + RETURN_EGL_EVAL(disp, ret); +} + +EGLBoolean EGLAPIENTRY +eglSurfaceAttrib(EGLDisplay dpy, EGLSurface surface, + EGLint attribute, EGLint value) +{ + _EGLDisplay *disp = _eglLockDisplay(dpy); + _EGLSurface *surf = _eglLookupSurface(surface, disp); + _EGLDriver *drv; + EGLBoolean ret; + + _EGL_CHECK_SURFACE(disp, surf, EGL_FALSE, drv); + ret = drv->API.SurfaceAttrib(drv, disp, surf, attribute, value); + + RETURN_EGL_EVAL(disp, ret); +} + + +EGLBoolean EGLAPIENTRY +eglBindTexImage(EGLDisplay dpy, EGLSurface surface, EGLint buffer) +{ + _EGLDisplay *disp = _eglLockDisplay(dpy); + _EGLSurface *surf = _eglLookupSurface(surface, disp); + _EGLDriver *drv; + EGLBoolean ret; + + _EGL_CHECK_SURFACE(disp, surf, EGL_FALSE, drv); + ret = drv->API.BindTexImage(drv, disp, surf, buffer); + + RETURN_EGL_EVAL(disp, ret); +} + + +EGLBoolean EGLAPIENTRY +eglReleaseTexImage(EGLDisplay dpy, EGLSurface surface, EGLint buffer) +{ + _EGLDisplay *disp = _eglLockDisplay(dpy); + _EGLSurface *surf = _eglLookupSurface(surface, disp); + _EGLDriver *drv; + EGLBoolean ret; + + _EGL_CHECK_SURFACE(disp, surf, EGL_FALSE, drv); + ret = drv->API.ReleaseTexImage(drv, disp, surf, buffer); + + RETURN_EGL_EVAL(disp, ret); +} + + +EGLBoolean EGLAPIENTRY +eglSwapInterval(EGLDisplay dpy, EGLint interval) +{ + _EGLDisplay *disp = _eglLockDisplay(dpy); + _EGLContext *ctx = _eglGetCurrentContext(); + _EGLSurface *surf; + _EGLDriver *drv; + EGLBoolean ret; + + _EGL_CHECK_DISPLAY(disp, EGL_FALSE, drv); + + if (!ctx || !_eglIsContextLinked(ctx) || ctx->Resource.Display != disp) + RETURN_EGL_ERROR(disp, EGL_BAD_CONTEXT, EGL_FALSE); + + surf = ctx->DrawSurface; + if (!_eglIsSurfaceLinked(surf)) + RETURN_EGL_ERROR(disp, EGL_BAD_SURFACE, EGL_FALSE); + + ret = drv->API.SwapInterval(drv, disp, surf, interval); + + RETURN_EGL_EVAL(disp, ret); +} + + +EGLBoolean EGLAPIENTRY +eglSwapBuffers(EGLDisplay dpy, EGLSurface surface) +{ + _EGLContext *ctx = _eglGetCurrentContext(); + _EGLDisplay *disp = _eglLockDisplay(dpy); + _EGLSurface *surf = _eglLookupSurface(surface, disp); + _EGLDriver *drv; + EGLBoolean ret; + + _EGL_CHECK_SURFACE(disp, surf, EGL_FALSE, drv); + + /* surface must be bound to current context in EGL 1.4 */ + if (!ctx || !_eglIsContextLinked(ctx) || surf != ctx->DrawSurface) + RETURN_EGL_ERROR(disp, EGL_BAD_SURFACE, EGL_FALSE); + + ret = drv->API.SwapBuffers(drv, disp, surf); + + RETURN_EGL_EVAL(disp, ret); +} + + +EGLBoolean EGLAPIENTRY +eglCopyBuffers(EGLDisplay dpy, EGLSurface surface, EGLNativePixmapType target) +{ + _EGLDisplay *disp = _eglLockDisplay(dpy); + _EGLSurface *surf = _eglLookupSurface(surface, disp); + _EGLDriver *drv; + EGLBoolean ret; + + _EGL_CHECK_SURFACE(disp, surf, EGL_FALSE, drv); + ret = drv->API.CopyBuffers(drv, disp, surf, target); + + RETURN_EGL_EVAL(disp, ret); +} + + +EGLBoolean EGLAPIENTRY +eglWaitClient(void) +{ + _EGLContext *ctx = _eglGetCurrentContext(); + _EGLDisplay *disp; + _EGLDriver *drv; + EGLBoolean ret; + + if (!ctx) + RETURN_EGL_SUCCESS(NULL, EGL_TRUE); + + disp = ctx->Resource.Display; + _eglLockMutex(&disp->Mutex); + + /* let bad current context imply bad current surface */ + if (!_eglIsContextLinked(ctx) || !_eglIsSurfaceLinked(ctx->DrawSurface)) + RETURN_EGL_ERROR(disp, EGL_BAD_CURRENT_SURFACE, EGL_FALSE); + + /* a valid current context implies an initialized current display */ + assert(disp->Initialized); + drv = disp->Driver; + ret = drv->API.WaitClient(drv, disp, ctx); + + RETURN_EGL_EVAL(disp, ret); +} + + +EGLBoolean EGLAPIENTRY +eglWaitGL(void) +{ +#ifdef EGL_VERSION_1_2 + _EGLThreadInfo *t = _eglGetCurrentThread(); + EGLint api_index = t->CurrentAPIIndex; + EGLint es_index = _eglConvertApiToIndex(EGL_OPENGL_ES_API); + EGLBoolean ret; + + if (api_index != es_index && _eglIsCurrentThreadDummy()) + RETURN_EGL_ERROR(NULL, EGL_BAD_ALLOC, EGL_FALSE); + + t->CurrentAPIIndex = es_index; + ret = eglWaitClient(); + t->CurrentAPIIndex = api_index; + return ret; +#else + return eglWaitClient(); +#endif +} + + +EGLBoolean EGLAPIENTRY +eglWaitNative(EGLint engine) +{ + _EGLContext *ctx = _eglGetCurrentContext(); + _EGLDisplay *disp; + _EGLDriver *drv; + EGLBoolean ret; + + if (!ctx) + RETURN_EGL_SUCCESS(NULL, EGL_TRUE); + + disp = ctx->Resource.Display; + _eglLockMutex(&disp->Mutex); + + /* let bad current context imply bad current surface */ + if (!_eglIsContextLinked(ctx) || !_eglIsSurfaceLinked(ctx->DrawSurface)) + RETURN_EGL_ERROR(disp, EGL_BAD_CURRENT_SURFACE, EGL_FALSE); + + /* a valid current context implies an initialized current display */ + assert(disp->Initialized); + drv = disp->Driver; + ret = drv->API.WaitNative(drv, disp, engine); + + RETURN_EGL_EVAL(disp, ret); +} + + +EGLDisplay EGLAPIENTRY +eglGetCurrentDisplay(void) +{ + _EGLContext *ctx = _eglGetCurrentContext(); + EGLDisplay ret; + + ret = (ctx) ? _eglGetDisplayHandle(ctx->Resource.Display) : EGL_NO_DISPLAY; + + RETURN_EGL_SUCCESS(NULL, ret); +} + + +EGLContext EGLAPIENTRY +eglGetCurrentContext(void) +{ + _EGLContext *ctx = _eglGetCurrentContext(); + EGLContext ret; + + ret = _eglGetContextHandle(ctx); + + RETURN_EGL_SUCCESS(NULL, ret); +} + + +EGLSurface EGLAPIENTRY +eglGetCurrentSurface(EGLint readdraw) +{ + _EGLContext *ctx = _eglGetCurrentContext(); + EGLint err = EGL_SUCCESS; + _EGLSurface *surf; + EGLSurface ret; + + if (!ctx) + RETURN_EGL_SUCCESS(NULL, EGL_NO_SURFACE); + + switch (readdraw) { + case EGL_DRAW: + surf = ctx->DrawSurface; + break; + case EGL_READ: + surf = ctx->ReadSurface; + break; + default: + surf = NULL; + err = EGL_BAD_PARAMETER; + break; + } + + ret = _eglGetSurfaceHandle(surf); + + RETURN_EGL_ERROR(NULL, err, ret); +} + + +EGLint EGLAPIENTRY +eglGetError(void) +{ + _EGLThreadInfo *t = _eglGetCurrentThread(); + EGLint e = t->LastError; + if (!_eglIsCurrentThreadDummy()) + t->LastError = EGL_SUCCESS; + return e; +} + + +__eglMustCastToProperFunctionPointerType EGLAPIENTRY +eglGetProcAddress(const char *procname) +{ + static const struct { + const char *name; + _EGLProc function; + } egl_functions[] = { + /* extensions only */ +#ifdef EGL_MESA_screen_surface + { "eglChooseModeMESA", (_EGLProc) eglChooseModeMESA }, + { "eglGetModesMESA", (_EGLProc) eglGetModesMESA }, + { "eglGetModeAttribMESA", (_EGLProc) eglGetModeAttribMESA }, + { "eglCopyContextMESA", (_EGLProc) eglCopyContextMESA }, + { "eglGetScreensMESA", (_EGLProc) eglGetScreensMESA }, + { "eglCreateScreenSurfaceMESA", (_EGLProc) eglCreateScreenSurfaceMESA }, + { "eglShowScreenSurfaceMESA", (_EGLProc) eglShowScreenSurfaceMESA }, + { "eglScreenPositionMESA", (_EGLProc) eglScreenPositionMESA }, + { "eglQueryScreenMESA", (_EGLProc) eglQueryScreenMESA }, + { "eglQueryScreenSurfaceMESA", (_EGLProc) eglQueryScreenSurfaceMESA }, + { "eglQueryScreenModeMESA", (_EGLProc) eglQueryScreenModeMESA }, + { "eglQueryModeStringMESA", (_EGLProc) eglQueryModeStringMESA }, +#endif /* EGL_MESA_screen_surface */ +#ifdef EGL_KHR_image_base + { "eglCreateImageKHR", (_EGLProc) eglCreateImageKHR }, + { "eglDestroyImageKHR", (_EGLProc) eglDestroyImageKHR }, +#endif /* EGL_KHR_image_base */ +#ifdef EGL_NOK_swap_region + { "eglSwapBuffersRegionNOK", (_EGLProc) eglSwapBuffersRegionNOK }, +#endif + { NULL, NULL } + }; + EGLint i; + _EGLProc ret; + + if (!procname) + RETURN_EGL_SUCCESS(NULL, NULL); + + ret = NULL; + if (strncmp(procname, "egl", 3) == 0) { + for (i = 0; egl_functions[i].name; i++) { + if (strcmp(egl_functions[i].name, procname) == 0) { + ret = egl_functions[i].function; + break; + } + } + } + if (ret) + RETURN_EGL_SUCCESS(NULL, ret); + + _eglPreloadDrivers(); + + /* now loop over drivers to query their procs */ + for (i = 0; i < _eglGlobal.NumDrivers; i++) { + _EGLDriver *drv = _eglGlobal.Drivers[i]; + ret = drv->API.GetProcAddress(drv, procname); + if (ret) + break; + } + + RETURN_EGL_SUCCESS(NULL, ret); +} + + +#ifdef EGL_MESA_screen_surface + + +/* + * EGL_MESA_screen extension + */ + +EGLBoolean EGLAPIENTRY +eglChooseModeMESA(EGLDisplay dpy, EGLScreenMESA screen, + const EGLint *attrib_list, EGLModeMESA *modes, + EGLint modes_size, EGLint *num_modes) +{ + _EGLDisplay *disp = _eglLockDisplay(dpy); + _EGLScreen *scrn = _eglLookupScreen(screen, disp); + _EGLDriver *drv; + EGLBoolean ret; + + _EGL_CHECK_SCREEN(disp, scrn, EGL_FALSE, drv); + ret = drv->API.ChooseModeMESA(drv, disp, scrn, attrib_list, + modes, modes_size, num_modes); + + RETURN_EGL_EVAL(disp, ret); +} + + +EGLBoolean EGLAPIENTRY +eglGetModesMESA(EGLDisplay dpy, EGLScreenMESA screen, EGLModeMESA *modes, + EGLint mode_size, EGLint *num_mode) +{ + _EGLDisplay *disp = _eglLockDisplay(dpy); + _EGLScreen *scrn = _eglLookupScreen(screen, disp); + _EGLDriver *drv; + EGLBoolean ret; + + _EGL_CHECK_SCREEN(disp, scrn, EGL_FALSE, drv); + ret = drv->API.GetModesMESA(drv, disp, scrn, modes, mode_size, num_mode); + + RETURN_EGL_EVAL(disp, ret); +} + + +EGLBoolean EGLAPIENTRY +eglGetModeAttribMESA(EGLDisplay dpy, EGLModeMESA mode, + EGLint attribute, EGLint *value) +{ + _EGLDisplay *disp = _eglLockDisplay(dpy); + _EGLMode *m = _eglLookupMode(mode, disp); + _EGLDriver *drv; + EGLBoolean ret; + + _EGL_CHECK_MODE(disp, m, EGL_FALSE, drv); + ret = drv->API.GetModeAttribMESA(drv, disp, m, attribute, value); + + RETURN_EGL_EVAL(disp, ret); +} + + +EGLBoolean EGLAPIENTRY +eglCopyContextMESA(EGLDisplay dpy, EGLContext source, EGLContext dest, + EGLint mask) +{ + _EGLDisplay *disp = _eglLockDisplay(dpy); + _EGLContext *source_context = _eglLookupContext(source, disp); + _EGLContext *dest_context = _eglLookupContext(dest, disp); + _EGLDriver *drv; + EGLBoolean ret; + + _EGL_CHECK_CONTEXT(disp, source_context, EGL_FALSE, drv); + if (!dest_context) + RETURN_EGL_ERROR(disp, EGL_BAD_CONTEXT, EGL_FALSE); + + ret = drv->API.CopyContextMESA(drv, disp, + source_context, dest_context, mask); + + RETURN_EGL_EVAL(disp, ret); +} + + +EGLBoolean +eglGetScreensMESA(EGLDisplay dpy, EGLScreenMESA *screens, + EGLint max_screens, EGLint *num_screens) +{ + _EGLDisplay *disp = _eglLockDisplay(dpy); + _EGLDriver *drv; + EGLBoolean ret; + + _EGL_CHECK_DISPLAY(disp, EGL_FALSE, drv); + ret = drv->API.GetScreensMESA(drv, disp, screens, max_screens, num_screens); + + RETURN_EGL_EVAL(disp, ret); +} + + +EGLSurface +eglCreateScreenSurfaceMESA(EGLDisplay dpy, EGLConfig config, + const EGLint *attrib_list) +{ + _EGLDisplay *disp = _eglLockDisplay(dpy); + _EGLConfig *conf = _eglLookupConfig(config, disp); + _EGLDriver *drv; + _EGLSurface *surf; + EGLSurface ret; + + _EGL_CHECK_CONFIG(disp, conf, EGL_NO_SURFACE, drv); + + surf = drv->API.CreateScreenSurfaceMESA(drv, disp, conf, attrib_list); + ret = (surf) ? _eglLinkSurface(surf, disp) : EGL_NO_SURFACE; + + RETURN_EGL_EVAL(disp, ret); +} + + +EGLBoolean +eglShowScreenSurfaceMESA(EGLDisplay dpy, EGLint screen, + EGLSurface surface, EGLModeMESA mode) +{ + _EGLDisplay *disp = _eglLockDisplay(dpy); + _EGLScreen *scrn = _eglLookupScreen((EGLScreenMESA) screen, disp); + _EGLSurface *surf = _eglLookupSurface(surface, disp); + _EGLMode *m = _eglLookupMode(mode, disp); + _EGLDriver *drv; + EGLBoolean ret; + + _EGL_CHECK_SCREEN(disp, scrn, EGL_FALSE, drv); + if (!surf && surface != EGL_NO_SURFACE) + RETURN_EGL_ERROR(disp, EGL_BAD_SURFACE, EGL_FALSE); + if (!m && mode != EGL_NO_MODE_MESA) + RETURN_EGL_ERROR(disp, EGL_BAD_MODE_MESA, EGL_FALSE); + + ret = drv->API.ShowScreenSurfaceMESA(drv, disp, scrn, surf, m); + + RETURN_EGL_EVAL(disp, ret); +} + + +EGLBoolean +eglScreenPositionMESA(EGLDisplay dpy, EGLScreenMESA screen, EGLint x, EGLint y) +{ + _EGLDisplay *disp = _eglLockDisplay(dpy); + _EGLScreen *scrn = _eglLookupScreen(screen, disp); + _EGLDriver *drv; + EGLBoolean ret; + + _EGL_CHECK_SCREEN(disp, scrn, EGL_FALSE, drv); + ret = drv->API.ScreenPositionMESA(drv, disp, scrn, x, y); + + RETURN_EGL_EVAL(disp, ret); +} + + +EGLBoolean +eglQueryScreenMESA(EGLDisplay dpy, EGLScreenMESA screen, + EGLint attribute, EGLint *value) +{ + _EGLDisplay *disp = _eglLockDisplay(dpy); + _EGLScreen *scrn = _eglLookupScreen(screen, disp); + _EGLDriver *drv; + EGLBoolean ret; + + _EGL_CHECK_SCREEN(disp, scrn, EGL_FALSE, drv); + ret = drv->API.QueryScreenMESA(drv, disp, scrn, attribute, value); + + RETURN_EGL_EVAL(disp, ret); +} + + +EGLBoolean +eglQueryScreenSurfaceMESA(EGLDisplay dpy, EGLScreenMESA screen, + EGLSurface *surface) +{ + _EGLDisplay *disp = _eglLockDisplay(dpy); + _EGLScreen *scrn = _eglLookupScreen((EGLScreenMESA) screen, disp); + _EGLDriver *drv; + _EGLSurface *surf; + EGLBoolean ret; + + _EGL_CHECK_SCREEN(disp, scrn, EGL_FALSE, drv); + ret = drv->API.QueryScreenSurfaceMESA(drv, disp, scrn, &surf); + if (ret && surface) + *surface = _eglGetSurfaceHandle(surf); + + RETURN_EGL_EVAL(disp, ret); +} + + +EGLBoolean +eglQueryScreenModeMESA(EGLDisplay dpy, EGLScreenMESA screen, EGLModeMESA *mode) +{ + _EGLDisplay *disp = _eglLockDisplay(dpy); + _EGLScreen *scrn = _eglLookupScreen((EGLScreenMESA) screen, disp); + _EGLDriver *drv; + _EGLMode *m; + EGLBoolean ret; + + _EGL_CHECK_SCREEN(disp, scrn, EGL_FALSE, drv); + ret = drv->API.QueryScreenModeMESA(drv, disp, scrn, &m); + if (ret && mode) + *mode = m->Handle; + + RETURN_EGL_EVAL(disp, ret); +} + + +const char * +eglQueryModeStringMESA(EGLDisplay dpy, EGLModeMESA mode) +{ + _EGLDisplay *disp = _eglLockDisplay(dpy); + _EGLMode *m = _eglLookupMode(mode, disp); + _EGLDriver *drv; + const char *ret; + + _EGL_CHECK_MODE(disp, m, NULL, drv); + ret = drv->API.QueryModeStringMESA(drv, disp, m); + + RETURN_EGL_EVAL(disp, ret); +} + + +#endif /* EGL_MESA_screen_surface */ + + +/** + ** EGL 1.2 + **/ + +#ifdef EGL_VERSION_1_2 + + +/** + * Specify the client API to use for subsequent calls including: + * eglCreateContext() + * eglGetCurrentContext() + * eglGetCurrentDisplay() + * eglGetCurrentSurface() + * eglMakeCurrent(when the ctx parameter is EGL NO CONTEXT) + * eglWaitClient() + * eglWaitNative() + * See section 3.7 "Rendering Context" in the EGL specification for details. + */ +EGLBoolean +eglBindAPI(EGLenum api) +{ + _EGLThreadInfo *t = _eglGetCurrentThread(); + + if (_eglIsCurrentThreadDummy()) + RETURN_EGL_ERROR(NULL, EGL_BAD_ALLOC, EGL_FALSE); + + if (!_eglIsApiValid(api)) + RETURN_EGL_ERROR(NULL, EGL_BAD_PARAMETER, EGL_FALSE); + + t->CurrentAPIIndex = _eglConvertApiToIndex(api); + + RETURN_EGL_SUCCESS(NULL, EGL_TRUE); +} + + +/** + * Return the last value set with eglBindAPI(). + */ +EGLenum +eglQueryAPI(void) +{ + _EGLThreadInfo *t = _eglGetCurrentThread(); + EGLenum ret; + + /* returns one of EGL_OPENGL_API, EGL_OPENGL_ES_API or EGL_OPENVG_API */ + ret = _eglConvertApiFromIndex(t->CurrentAPIIndex); + + RETURN_EGL_SUCCESS(NULL, ret); +} + + +EGLSurface +eglCreatePbufferFromClientBuffer(EGLDisplay dpy, EGLenum buftype, + EGLClientBuffer buffer, EGLConfig config, + const EGLint *attrib_list) +{ + _EGLDisplay *disp = _eglLockDisplay(dpy); + _EGLConfig *conf = _eglLookupConfig(config, disp); + _EGLDriver *drv; + _EGLSurface *surf; + EGLSurface ret; + + _EGL_CHECK_CONFIG(disp, conf, EGL_NO_SURFACE, drv); + + surf = drv->API.CreatePbufferFromClientBuffer(drv, disp, buftype, buffer, + conf, attrib_list); + ret = (surf) ? _eglLinkSurface(surf, disp) : EGL_NO_SURFACE; + + RETURN_EGL_EVAL(disp, ret); +} + + +EGLBoolean +eglReleaseThread(void) +{ + /* unbind current contexts */ + if (!_eglIsCurrentThreadDummy()) { + _EGLThreadInfo *t = _eglGetCurrentThread(); + EGLint api_index = t->CurrentAPIIndex; + EGLint i; + + for (i = 0; i < _EGL_API_NUM_APIS; i++) { + _EGLContext *ctx = t->CurrentContexts[i]; + if (ctx) { + _EGLDisplay *disp = ctx->Resource.Display; + _EGLDriver *drv; + + t->CurrentAPIIndex = i; + + _eglLockMutex(&disp->Mutex); + drv = disp->Driver; + (void) drv->API.MakeCurrent(drv, disp, NULL, NULL, NULL); + _eglUnlockMutex(&disp->Mutex); + } + } + + t->CurrentAPIIndex = api_index; + } + + _eglDestroyCurrentThread(); + + RETURN_EGL_SUCCESS(NULL, EGL_TRUE); +} + + +#endif /* EGL_VERSION_1_2 */ + + +#ifdef EGL_KHR_image_base + + +EGLImageKHR +eglCreateImageKHR(EGLDisplay dpy, EGLContext ctx, EGLenum target, + EGLClientBuffer buffer, const EGLint *attr_list) +{ + _EGLDisplay *disp = _eglLockDisplay(dpy); + _EGLContext *context = _eglLookupContext(ctx, disp); + _EGLDriver *drv; + _EGLImage *img; + EGLImageKHR ret; + + _EGL_CHECK_DISPLAY(disp, EGL_NO_IMAGE_KHR, drv); + if (!context && ctx != EGL_NO_CONTEXT) + RETURN_EGL_ERROR(disp, EGL_BAD_CONTEXT, EGL_NO_IMAGE_KHR); + + img = drv->API.CreateImageKHR(drv, + disp, context, target, buffer, attr_list); + ret = (img) ? _eglLinkImage(img, disp) : EGL_NO_IMAGE_KHR; + + RETURN_EGL_EVAL(disp, ret); +} + + +EGLBoolean +eglDestroyImageKHR(EGLDisplay dpy, EGLImageKHR image) +{ + _EGLDisplay *disp = _eglLockDisplay(dpy); + _EGLImage *img = _eglLookupImage(image, disp); + _EGLDriver *drv; + EGLBoolean ret; + + _EGL_CHECK_DISPLAY(disp, EGL_FALSE, drv); + if (!img) + RETURN_EGL_ERROR(disp, EGL_BAD_PARAMETER, EGL_FALSE); + + _eglUnlinkImage(img); + ret = drv->API.DestroyImageKHR(drv, disp, img); + + RETURN_EGL_EVAL(disp, ret); +} + + +#endif /* EGL_KHR_image_base */ + + +#ifdef EGL_NOK_swap_region + +EGLBoolean +eglSwapBuffersRegionNOK(EGLDisplay dpy, EGLSurface surface, + EGLint numRects, const EGLint *rects) +{ + _EGLContext *ctx = _eglGetCurrentContext(); + _EGLDisplay *disp = _eglLockDisplay(dpy); + _EGLSurface *surf = _eglLookupSurface(surface, disp); + _EGLDriver *drv; + EGLBoolean ret; + + _EGL_CHECK_SURFACE(disp, surf, EGL_FALSE, drv); + + /* surface must be bound to current context in EGL 1.4 */ + if (!ctx || !_eglIsContextLinked(ctx) || surf != ctx->DrawSurface) + RETURN_EGL_ERROR(disp, EGL_BAD_SURFACE, EGL_FALSE); + + if (drv->API.SwapBuffersRegionNOK) + ret = drv->API.SwapBuffersRegionNOK(drv, disp, surf, numRects, rects); + else + ret = drv->API.SwapBuffers(drv, disp, surf); + + RETURN_EGL_EVAL(disp, ret); +} + +#endif /* EGL_NOK_swap_region */ |