diff options
Diffstat (limited to 'src/egl/main')
29 files changed, 1689 insertions, 1261 deletions
diff --git a/src/egl/main/Makefile b/src/egl/main/Makefile index ec326a845df..31f214cf6f2 100644 --- a/src/egl/main/Makefile +++ b/src/egl/main/Makefile @@ -19,6 +19,7 @@ HEADERS = \ egldisplay.h \ egldriver.h \ eglglobals.h \ + eglimage.h \ egllog.h \ eglmisc.h \ eglmode.h \ @@ -36,6 +37,7 @@ SOURCES = \ egldisplay.c \ egldriver.c \ eglglobals.c \ + eglimage.c \ egllog.c \ eglmisc.c \ eglmode.c \ @@ -47,8 +49,13 @@ OBJECTS = $(SOURCES:.c=.o) # use dl*() to load drivers -LOCAL_CFLAGS = -D_EGL_PLATFORM_X=1 +LOCAL_CFLAGS = -D_EGL_PLATFORM_POSIX=1 +EGL_DEFAULT_DISPLAY = $(word 1, $(EGL_DISPLAYS)) + +LOCAL_CFLAGS += \ + -D_EGL_DEFAULT_DISPLAY=\"$(EGL_DEFAULT_DISPLAY)\" \ + -D_EGL_DRIVER_SEARCH_DIR=\"$(EGL_DRIVER_INSTALL_DIR)\" .c.o: $(CC) -c $(INCLUDE_DIRS) $(CFLAGS) $(LOCAL_CFLAGS) $< -o $@ @@ -67,7 +74,15 @@ $(TOP)/$(LIB_DIR)/$(EGL_LIB_NAME): $(OBJECTS) -install $(TOP)/$(LIB_DIR) $(MKLIB_OPTIONS) \ $(EGL_LIB_DEPS) $(OBJECTS) -install: default +install-headers: + $(INSTALL) -d $(DESTDIR)$(INSTALL_INC_DIR)/KHR + $(INSTALL) -m 644 $(TOP)/include/KHR/*.h \ + $(DESTDIR)$(INSTALL_INC_DIR)/KHR + $(INSTALL) -d $(DESTDIR)$(INSTALL_INC_DIR)/EGL + $(INSTALL) -m 644 $(TOP)/include/EGL/*.h \ + $(DESTDIR)$(INSTALL_INC_DIR)/EGL + +install: default install-headers $(INSTALL) -d $(DESTDIR)$(INSTALL_LIB_DIR) $(MINSTALL) $(TOP)/$(LIB_DIR)/$(EGL_LIB_GLOB) \ $(DESTDIR)$(INSTALL_LIB_DIR) diff --git a/src/egl/main/eglapi.c b/src/egl/main/eglapi.c index 14cc5fa6137..364ad9c4585 100644 --- a/src/egl/main/eglapi.c +++ b/src/egl/main/eglapi.c @@ -60,11 +60,13 @@ #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" /** @@ -72,7 +74,7 @@ * We initialize our global vars and create a private _EGLDisplay object. */ EGLDisplay EGLAPIENTRY -eglGetDisplay(NativeDisplayType nativeDisplay) +eglGetDisplay(EGLNativeDisplayType nativeDisplay) { _EGLDisplay *dpy; dpy = _eglFindDisplay(nativeDisplay); @@ -93,23 +95,24 @@ EGLBoolean EGLAPIENTRY eglInitialize(EGLDisplay dpy, EGLint *major, EGLint *minor) { _EGLDisplay *disp = _eglLookupDisplay(dpy); - _EGLDriver *drv; EGLint major_int, minor_int; if (!disp) return _eglError(EGL_BAD_DISPLAY, __FUNCTION__); - drv = disp->Driver; - if (!drv) { - drv = _eglOpenDriver(disp); - if (!drv) - return _eglError(EGL_NOT_INITIALIZED, __FUNCTION__); + if (!disp->Initialized) { + _EGLDriver *drv = disp->Driver; + + if (!drv) { + _eglPreloadDrivers(); + drv = _eglMatchDriver(disp); + if (!drv) + return _eglError(EGL_NOT_INITIALIZED, __FUNCTION__); + } /* Initialize the particular display now */ - if (!drv->API.Initialize(drv, disp, &major_int, &minor_int)) { - _eglCloseDriver(drv, disp); + if (!drv->API.Initialize(drv, disp, &major_int, &minor_int)) return _eglError(EGL_NOT_INITIALIZED, __FUNCTION__); - } disp->APImajor = major_int; disp->APIminor = minor_int; @@ -120,6 +123,7 @@ eglInitialize(EGLDisplay dpy, EGLint *major, EGLint *minor) disp->ClientAPIsMask &= _EGL_API_ALL_BITS; disp->Driver = drv; + disp->Initialized = EGL_TRUE; } else { major_int = disp->APImajor; minor_int = disp->APIminor; @@ -139,16 +143,16 @@ EGLBoolean EGLAPIENTRY eglTerminate(EGLDisplay dpy) { _EGLDisplay *disp = _eglLookupDisplay(dpy); - _EGLDriver *drv; if (!disp) return _eglError(EGL_BAD_DISPLAY, __FUNCTION__); - drv = disp->Driver; - if (drv) { + if (disp->Initialized) { + _EGLDriver *drv = disp->Driver; + drv->API.Terminate(drv, disp); - _eglCloseDriver(drv, disp); - disp->Driver = NULL; + /* do not reset disp->Driver */ + disp->Initialized = EGL_FALSE; } return EGL_TRUE; @@ -165,7 +169,7 @@ _eglCheckDisplay(_EGLDisplay *disp, const char *msg) _eglError(EGL_BAD_DISPLAY, msg); return NULL; } - if (!disp->Driver) { + if (!disp->Initialized) { _eglError(EGL_NOT_INITIALIZED, msg); return NULL; } @@ -391,9 +395,19 @@ eglMakeCurrent(EGLDisplay dpy, EGLSurface draw, EGLSurface read, _EGLSurface *read_surf = _eglLookupSurface(read, disp); _EGLDriver *drv; - drv = _eglCheckDisplay(disp, __FUNCTION__); + if (!disp) + return _eglError(EGL_BAD_DISPLAY, __FUNCTION__); + 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 _eglError(EGL_BAD_DISPLAY, __FUNCTION__); + } if (!drv) - return EGL_FALSE; + return EGL_TRUE; + if (!context && ctx != EGL_NO_CONTEXT) return _eglError(EGL_BAD_CONTEXT, __FUNCTION__); if ((!draw_surf && draw != EGL_NO_SURFACE) || @@ -415,7 +429,7 @@ eglQueryContext(EGLDisplay dpy, EGLContext ctx, EGLSurface EGLAPIENTRY eglCreateWindowSurface(EGLDisplay dpy, EGLConfig config, - NativeWindowType window, const EGLint *attrib_list) + EGLNativeWindowType window, const EGLint *attrib_list) { _EGLDisplay *disp = _eglLookupDisplay(dpy); _EGLConfig *conf = _eglLookupConfig(config, disp); @@ -436,7 +450,7 @@ eglCreateWindowSurface(EGLDisplay dpy, EGLConfig config, EGLSurface EGLAPIENTRY eglCreatePixmapSurface(EGLDisplay dpy, EGLConfig config, - NativePixmapType pixmap, const EGLint *attrib_list) + EGLNativePixmapType pixmap, const EGLint *attrib_list) { _EGLDisplay *disp = _eglLookupDisplay(dpy); _EGLConfig *conf = _eglLookupConfig(config, disp); @@ -524,7 +538,7 @@ eglSwapInterval(EGLDisplay dpy, EGLint interval) _EGLSurface *surf; _EGL_DECLARE_DD(dpy); - if (!ctx || !_eglIsContextLinked(ctx) || ctx->Display != disp) + if (!ctx || !_eglIsContextLinked(ctx) || ctx->Resource.Display != disp) return _eglError(EGL_BAD_CONTEXT, __FUNCTION__); surf = ctx->DrawSurface; @@ -550,7 +564,7 @@ eglSwapBuffers(EGLDisplay dpy, EGLSurface surface) EGLBoolean EGLAPIENTRY -eglCopyBuffers(EGLDisplay dpy, EGLSurface surface, NativePixmapType target) +eglCopyBuffers(EGLDisplay dpy, EGLSurface surface, EGLNativePixmapType target) { _EGL_DECLARE_DD_AND_SURFACE(dpy, surface); return drv->API.CopyBuffers(drv, disp, surf, target); @@ -571,9 +585,9 @@ eglWaitClient(void) return _eglError(EGL_BAD_CURRENT_SURFACE, __FUNCTION__); /* a valid current context implies an initialized current display */ - disp = ctx->Display; + disp = ctx->Resource.Display; + assert(disp->Initialized); drv = disp->Driver; - assert(drv); return drv->API.WaitClient(drv, disp, ctx); } @@ -615,9 +629,9 @@ eglWaitNative(EGLint engine) return _eglError(EGL_BAD_CURRENT_SURFACE, __FUNCTION__); /* a valid current context implies an initialized current display */ - disp = ctx->Display; + disp = ctx->Resource.Display; + assert(disp->Initialized); drv = disp->Driver; - assert(drv); return drv->API.WaitNative(drv, disp, engine); } @@ -626,8 +640,8 @@ eglWaitNative(EGLint engine) EGLDisplay EGLAPIENTRY eglGetCurrentDisplay(void) { - _EGLDisplay *dpy = _eglGetCurrentDisplay(); - return _eglGetDisplayHandle(dpy); + _EGLContext *ctx = _eglGetCurrentContext(); + return (ctx) ? _eglGetDisplayHandle(ctx->Resource.Display) : EGL_NO_DISPLAY; } @@ -676,7 +690,8 @@ eglGetError(void) } -void (* EGLAPIENTRY eglGetProcAddress(const char *procname))() +__eglMustCastToProperFunctionPointerType EGLAPIENTRY +eglGetProcAddress(const char *procname) { static const struct { const char *name; @@ -697,6 +712,10 @@ void (* EGLAPIENTRY eglGetProcAddress(const char *procname))() { "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 */ { NULL, NULL } }; EGLint i; @@ -710,13 +729,12 @@ void (* EGLAPIENTRY eglGetProcAddress(const char *procname))() } } - /* preload a driver if there isn't one */ - if (!_eglGlobal.NumDrivers) - _eglPreloadDriver(NULL); + _eglPreloadDrivers(); /* now loop over drivers to query their procs */ for (i = 0; i < _eglGlobal.NumDrivers; i++) { - _EGLProc p = _eglGlobal.Drivers[i]->API.GetProcAddress(procname); + _EGLDriver *drv = _eglGlobal.Drivers[i]; + _EGLProc p = drv->API.GetProcAddress(drv, procname); if (p) return p; } @@ -977,14 +995,23 @@ eglCreatePbufferFromClientBuffer(EGLDisplay dpy, EGLenum buftype, EGLBoolean eglReleaseThread(void) { - /* unbind current context */ + /* unbind current contexts */ if (!_eglIsCurrentThreadDummy()) { - _EGLDisplay *disp = _eglGetCurrentDisplay(); - _EGLDriver *drv; - if (disp) { - drv = disp->Driver; - (void) drv->API.MakeCurrent(drv, disp, NULL, NULL, NULL); + _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 = disp->Driver; + t->CurrentAPIIndex = i; + (void) drv->API.MakeCurrent(drv, disp, NULL, NULL, NULL); + } } + + t->CurrentAPIIndex = api_index; } _eglDestroyCurrentThread(); @@ -993,3 +1020,52 @@ eglReleaseThread(void) #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 = _eglLookupDisplay(dpy); + _EGLContext *context = _eglLookupContext(ctx, disp); + _EGLDriver *drv; + _EGLImage *img; + + drv = _eglCheckDisplay(disp, __FUNCTION__); + if (!drv) + return EGL_NO_IMAGE_KHR; + if (!context && ctx != EGL_NO_CONTEXT) { + _eglError(EGL_BAD_CONTEXT, __FUNCTION__); + return EGL_NO_IMAGE_KHR; + } + + img = drv->API.CreateImageKHR(drv, + disp, context, target, buffer, attr_list); + if (img) + return _eglLinkImage(img, disp); + else + return EGL_NO_IMAGE_KHR; +} + + +EGLBoolean eglDestroyImageKHR(EGLDisplay dpy, EGLImageKHR image) +{ + _EGLDisplay *disp = _eglLookupDisplay(dpy); + _EGLImage *img = _eglLookupImage(image, disp); + _EGLDriver *drv; + + drv = _eglCheckDisplay(disp, __FUNCTION__); + if (!drv) + return EGL_FALSE; + if (!img) + return _eglError(EGL_BAD_PARAMETER, __FUNCTION__); + + _eglUnlinkImage(img); + return drv->API.DestroyImageKHR(drv, disp, img); +} + + +#endif /* EGL_KHR_image_base */ diff --git a/src/egl/main/eglapi.h b/src/egl/main/eglapi.h index aa0abe3eb6b..c3676ec56a1 100644 --- a/src/egl/main/eglapi.h +++ b/src/egl/main/eglapi.h @@ -4,7 +4,7 @@ /** * A generic function ptr type */ -typedef void (*_EGLProc)(); +typedef void (*_EGLProc)(void); /** @@ -23,12 +23,13 @@ typedef EGLBoolean (*GetConfigAttrib_t)(_EGLDriver *drv, _EGLDisplay *dpy, _EGLC /* context funcs */ typedef _EGLContext *(*CreateContext_t)(_EGLDriver *drv, _EGLDisplay *dpy, _EGLConfig *config, _EGLContext *share_list, const EGLint *attrib_list); typedef EGLBoolean (*DestroyContext_t)(_EGLDriver *drv, _EGLDisplay *dpy, _EGLContext *ctx); +/* this is the only function (other than Initialize) that may be called with an uninitialized display */ typedef EGLBoolean (*MakeCurrent_t)(_EGLDriver *drv, _EGLDisplay *dpy, _EGLSurface *draw, _EGLSurface *read, _EGLContext *ctx); typedef EGLBoolean (*QueryContext_t)(_EGLDriver *drv, _EGLDisplay *dpy, _EGLContext *ctx, EGLint attribute, EGLint *value); /* surface funcs */ -typedef _EGLSurface *(*CreateWindowSurface_t)(_EGLDriver *drv, _EGLDisplay *dpy, _EGLConfig *config, NativeWindowType window, const EGLint *attrib_list); -typedef _EGLSurface *(*CreatePixmapSurface_t)(_EGLDriver *drv, _EGLDisplay *dpy, _EGLConfig *config, NativePixmapType pixmap, const EGLint *attrib_list); +typedef _EGLSurface *(*CreateWindowSurface_t)(_EGLDriver *drv, _EGLDisplay *dpy, _EGLConfig *config, EGLNativeWindowType window, const EGLint *attrib_list); +typedef _EGLSurface *(*CreatePixmapSurface_t)(_EGLDriver *drv, _EGLDisplay *dpy, _EGLConfig *config, EGLNativePixmapType pixmap, const EGLint *attrib_list); typedef _EGLSurface *(*CreatePbufferSurface_t)(_EGLDriver *drv, _EGLDisplay *dpy, _EGLConfig *config, const EGLint *attrib_list); typedef EGLBoolean (*DestroySurface_t)(_EGLDriver *drv, _EGLDisplay *dpy, _EGLSurface *surface); typedef EGLBoolean (*QuerySurface_t)(_EGLDriver *drv, _EGLDisplay *dpy, _EGLSurface *surface, EGLint attribute, EGLint *value); @@ -37,14 +38,14 @@ typedef EGLBoolean (*BindTexImage_t)(_EGLDriver *drv, _EGLDisplay *dpy, _EGLSurf typedef EGLBoolean (*ReleaseTexImage_t)(_EGLDriver *drv, _EGLDisplay *dpy, _EGLSurface *surface, EGLint buffer); typedef EGLBoolean (*SwapInterval_t)(_EGLDriver *drv, _EGLDisplay *dpy, _EGLSurface *surf, EGLint interval); typedef EGLBoolean (*SwapBuffers_t)(_EGLDriver *drv, _EGLDisplay *dpy, _EGLSurface *draw); -typedef EGLBoolean (*CopyBuffers_t)(_EGLDriver *drv, _EGLDisplay *dpy, _EGLSurface *surface, NativePixmapType target); +typedef EGLBoolean (*CopyBuffers_t)(_EGLDriver *drv, _EGLDisplay *dpy, _EGLSurface *surface, EGLNativePixmapType target); /* misc funcs */ typedef const char *(*QueryString_t)(_EGLDriver *drv, _EGLDisplay *dpy, EGLint name); typedef EGLBoolean (*WaitClient_t)(_EGLDriver *drv, _EGLDisplay *dpy, _EGLContext *ctx); typedef EGLBoolean (*WaitNative_t)(_EGLDriver *drv, _EGLDisplay *dpy, EGLint engine); -typedef _EGLProc (*GetProcAddress_t)(const char *procname); +typedef _EGLProc (*GetProcAddress_t)(_EGLDriver *drv, const char *procname); @@ -69,6 +70,11 @@ typedef _EGLSurface *(*CreatePbufferFromClientBuffer_t)(_EGLDriver *drv, _EGLDis #endif /* EGL_VERSION_1_2 */ +#ifdef EGL_KHR_image_base +typedef _EGLImage *(*CreateImageKHR_t)(_EGLDriver *drv, _EGLDisplay *dpy, _EGLContext *ctx, EGLenum target, EGLClientBuffer buffer, const EGLint *attr_list); +typedef EGLBoolean (*DestroyImageKHR_t)(_EGLDriver *drv, _EGLDisplay *dpy, _EGLImage *image); +#endif /* EGL_KHR_image_base */ + /** * The API dispatcher jumps through these functions @@ -104,7 +110,7 @@ struct _egl_api WaitNative_t WaitNative; GetProcAddress_t GetProcAddress; - /* EGL_MESA_screen extension */ +#ifdef EGL_MESA_screen_surface ChooseModeMESA_t ChooseModeMESA; GetModesMESA_t GetModesMESA; GetModeAttribMESA_t GetModeAttribMESA; @@ -117,10 +123,16 @@ struct _egl_api QueryScreenSurfaceMESA_t QueryScreenSurfaceMESA; QueryScreenModeMESA_t QueryScreenModeMESA; QueryModeStringMESA_t QueryModeStringMESA; +#endif /* EGL_MESA_screen_surface */ #ifdef EGL_VERSION_1_2 CreatePbufferFromClientBuffer_t CreatePbufferFromClientBuffer; #endif + +#ifdef EGL_KHR_image_base + CreateImageKHR_t CreateImageKHR; + DestroyImageKHR_t DestroyImageKHR; +#endif /* EGL_KHR_image_base */ }; #endif /* EGLAPI_INCLUDED */ diff --git a/src/egl/main/eglcompiler.h b/src/egl/main/eglcompiler.h index f7c93f14ce2..d844fbb0efb 100644 --- a/src/egl/main/eglcompiler.h +++ b/src/egl/main/eglcompiler.h @@ -64,11 +64,30 @@ /** * Function visibility */ -#if defined(__GNUC__) && (__GNUC__ * 100 + __GNUC_MINOR__) >= 303 +#if (defined(__GNUC__) && (__GNUC__ * 100 + __GNUC_MINOR__) >= 303) \ + || (defined(__SUNPRO_C) && (__SUNPRO_C >= 0x590)) # define PUBLIC __attribute__((visibility("default"))) #else # define PUBLIC #endif +/** + * The __FUNCTION__ gcc variable is generally only used for debugging. + * If we're not using gcc, define __FUNCTION__ as a cpp symbol here. + * Don't define it if using a newer Windows compiler. + */ +#ifndef __FUNCTION__ +# if defined(__VMS) +# define __FUNCTION__ "VMS$NL:" +# elif ((!defined __GNUC__) || (__GNUC__ < 2)) && (!defined __xlC__) && \ + (!defined(_MSC_VER) || _MSC_VER < 1300) +# if (__STDC_VERSION__ >= 199901L) /* C99 */ || \ + (defined(__SUNPRO_C) && defined(__C99FEATURES__)) +# define __FUNCTION__ __func__ +# else +# define __FUNCTION__ "<unknown>" +# endif +# endif +#endif #endif /* EGLCOMPILER_INCLUDED */ diff --git a/src/egl/main/eglconfig.c b/src/egl/main/eglconfig.c index 31d69a77080..1190f8cdd57 100644 --- a/src/egl/main/eglconfig.c +++ b/src/egl/main/eglconfig.c @@ -4,13 +4,11 @@ #include <stdlib.h> -#include <stdio.h> #include <string.h> #include <assert.h> #include "eglconfig.h" #include "egldisplay.h" -#include "egldriver.h" -#include "eglglobals.h" +#include "eglcurrent.h" #include "egllog.h" @@ -27,10 +25,12 @@ * IDs are from 1 to N respectively. */ void -_eglInitConfig(_EGLConfig *config, EGLint id) +_eglInitConfig(_EGLConfig *config, _EGLDisplay *dpy, EGLint id) { memset(config, 0, sizeof(*config)); + config->Display = dpy; + /* some attributes take non-zero default values */ SET_CONFIG_ATTRIB(config, EGL_CONFIG_ID, id); SET_CONFIG_ATTRIB(config, EGL_CONFIG_CAVEAT, EGL_NONE); @@ -224,7 +224,8 @@ static const struct { { EGL_MATCH_NATIVE_PIXMAP, ATTRIB_TYPE_PSEUDO, ATTRIB_CRITERION_SPECIAL, EGL_NONE }, - { EGL_PRESERVED_RESOURCES, ATTRIB_TYPE_PSEUDO, + /* there is a gap before EGL_SAMPLES */ + { 0x3030, ATTRIB_TYPE_PSEUDO, ATTRIB_CRITERION_IGNORE, 0 }, { EGL_NONE, ATTRIB_TYPE_PSEUDO, @@ -328,6 +329,8 @@ _eglValidateConfig(const _EGLConfig *conf, EGLBoolean for_matching) EGL_VG_ALPHA_FORMAT_PRE_BIT | EGL_MULTISAMPLE_RESOLVE_BOX_BIT | EGL_SWAP_BEHAVIOR_PRESERVED_BIT; + if (conf->Display->Extensions.MESA_screen_surface) + mask |= EGL_SCREEN_BIT_MESA; break; case EGL_RENDERABLE_TYPE: case EGL_CONFORMANT: @@ -363,8 +366,11 @@ _eglValidateConfig(const _EGLConfig *conf, EGLBoolean for_matching) if (_eglValidationTable[i].criterion == ATTRIB_CRITERION_SPECIAL) valid = EGL_TRUE; } - if (!valid) + if (!valid) { + _eglLog(_EGL_DEBUG, + "attribute 0x%04x has an invalid value 0x%x", attr, val); break; + } } /* any invalid attribute value should have been catched */ @@ -387,10 +393,18 @@ _eglValidateConfig(const _EGLConfig *conf, EGLBoolean for_matching) valid = EGL_FALSE; break; } + if (!valid) { + _eglLog(_EGL_DEBUG, "conflicting color buffer type and channel sizes"); + return EGL_FALSE; + } val = GET_CONFIG_ATTRIB(conf, EGL_SAMPLE_BUFFERS); if (!val && GET_CONFIG_ATTRIB(conf, EGL_SAMPLES)) valid = EGL_FALSE; + if (!valid) { + _eglLog(_EGL_DEBUG, "conflicting samples and sample buffers"); + return EGL_FALSE; + } val = GET_CONFIG_ATTRIB(conf, EGL_SURFACE_TYPE); if (!(val & EGL_WINDOW_BIT)) { @@ -403,6 +417,10 @@ _eglValidateConfig(const _EGLConfig *conf, EGLBoolean for_matching) GET_CONFIG_ATTRIB(conf, EGL_BIND_TO_TEXTURE_RGBA)) valid = EGL_FALSE; } + if (!valid) { + _eglLog(_EGL_DEBUG, "conflicting surface type and native visual/texture binding"); + return EGL_FALSE; + } return valid; } @@ -454,8 +472,14 @@ _eglMatchConfig(const _EGLConfig *conf, const _EGLConfig *criteria) break; } - if (!matched) + if (!matched) { +#ifdef DEBUG + _eglLog(_EGL_DEBUG, + "the value (0x%x) of attribute 0x%04x did not meet the criteria (0x%x)", + val, attr, cmp); +#endif break; + } } return matched; @@ -730,7 +754,7 @@ _eglChooseConfig(_EGLDriver *drv, _EGLDisplay *disp, const EGLint *attrib_list, if (!num_configs) return _eglError(EGL_BAD_PARAMETER, "eglChooseConfigs"); - _eglInitConfig(&criteria, 0); + _eglInitConfig(&criteria, disp, 0); if (!_eglParseConfigAttribList(&criteria, attrib_list)) return _eglError(EGL_BAD_ATTRIBUTE, "eglChooseConfig"); @@ -772,7 +796,7 @@ _eglIsConfigAttribValid(_EGLConfig *conf, EGLint attr) /* there are some holes in the range */ switch (attr) { - case EGL_PRESERVED_RESOURCES: + case 0x3030 /* a gap before EGL_SAMPLES */: case EGL_NONE: #ifdef EGL_VERSION_1_4 case EGL_MATCH_NATIVE_PIXMAP: diff --git a/src/egl/main/eglconfig.h b/src/egl/main/eglconfig.h index 799bf4ee242..56ec95fe9ad 100644 --- a/src/egl/main/eglconfig.h +++ b/src/egl/main/eglconfig.h @@ -21,6 +21,9 @@ struct _egl_config }; +/** + * Macros for source level compatibility. + */ #define SET_CONFIG_ATTRIB(CONF, ATTR, VAL) _eglSetConfigKey(CONF, ATTR, VAL) #define GET_CONFIG_ATTRIB(CONF, ATTR) _eglGetConfigKey(CONF, ATTR) @@ -55,6 +58,10 @@ _eglResetConfigKeys(_EGLConfig *conf, EGLint val) /** * Update a config for a given key. + * + * Note that a valid key is not necessarily a valid attribute. There are gaps + * in the attribute enums. The separation is to catch application errors. + * Drivers should never set a key that is an invalid attribute. */ static INLINE void _eglSetConfigKey(_EGLConfig *conf, EGLint key, EGLint val) @@ -77,22 +84,8 @@ _eglGetConfigKey(const _EGLConfig *conf, EGLint key) } -/** - * Set a given attribute. - * - * Because _eglGetConfigAttrib is already used as a fallback driver - * function, this function is not considered to have a good name. - * SET_CONFIG_ATTRIB is preferred over this function. - */ -static INLINE void -_eglSetConfigAttrib(_EGLConfig *conf, EGLint attr, EGLint val) -{ - SET_CONFIG_ATTRIB(conf, attr, val); -} - - PUBLIC void -_eglInitConfig(_EGLConfig *config, EGLint id); +_eglInitConfig(_EGLConfig *config, _EGLDisplay *dpy, EGLint id); PUBLIC EGLConfig diff --git a/src/egl/main/eglconfigutil.c b/src/egl/main/eglconfigutil.c index 36e94f0d2de..e416b190f0a 100644 --- a/src/egl/main/eglconfigutil.c +++ b/src/egl/main/eglconfigutil.c @@ -4,10 +4,8 @@ #include <stdlib.h> -#include <stdio.h> #include <string.h> #include "eglconfigutil.h" -#include "egllog.h" /** @@ -128,210 +126,3 @@ _eglConfigFromContextModesRec(_EGLConfig *conf, const __GLcontextModes *m, return EGL_TRUE; } - - -/** - * Creates a set of \c _EGLConfigs that a driver will expose. - * - * A set of \c __GLcontextModes will be created based on the supplied - * parameters. The number of modes processed will be 2 * - * \c num_depth_stencil_bits * \c num_db_modes. - * - * For the most part, data is just copied from \c depth_bits, \c stencil_bits, - * \c db_modes, and \c visType into each \c __GLcontextModes element. - * However, the meanings of \c fb_format and \c fb_type require further - * explanation. The \c fb_format specifies which color components are in - * each pixel and what the default order is. For example, \c GL_RGB specifies - * that red, green, blue are available and red is in the "most significant" - * position and blue is in the "least significant". The \c fb_type specifies - * the bit sizes of each component and the actual ordering. For example, if - * \c GL_UNSIGNED_SHORT_5_6_5_REV is specified with \c GL_RGB, bits [15:11] - * are the blue value, bits [10:5] are the green value, and bits [4:0] are - * the red value. - * - * One sublte issue is the combination of \c GL_RGB or \c GL_BGR and either - * of the \c GL_UNSIGNED_INT_8_8_8_8 modes. The resulting mask values in the - * \c __GLcontextModes structure is \b identical to the \c GL_RGBA or - * \c GL_BGRA case, except the \c alphaMask is zero. This means that, as - * far as this routine is concerned, \c GL_RGB with \c GL_UNSIGNED_INT_8_8_8_8 - * still uses 32-bits. - * - * If in doubt, look at the tables used in the function. - * - * \param configs the array of configs generated - * \param fb_format Format of the framebuffer. Currently only \c GL_RGB, - * \c GL_RGBA, \c GL_BGR, and \c GL_BGRA are supported. - * \param fb_type Type of the pixels in the framebuffer. Currently only - * \c GL_UNSIGNED_SHORT_5_6_5, - * \c GL_UNSIGNED_SHORT_5_6_5_REV, - * \c GL_UNSIGNED_INT_8_8_8_8, and - * \c GL_UNSIGNED_INT_8_8_8_8_REV are supported. - * \param depth_bits Array of depth buffer sizes to be exposed. - * \param stencil_bits Array of stencil buffer sizes to be exposed. - * \param num_depth_stencil_bits Number of entries in both \c depth_bits and - * \c stencil_bits. - * \param db_modes Array of buffer swap modes. If an element has a - * value of \c GLX_NONE, then it represents a - * single-buffered mode. Other valid values are - * \c GLX_SWAP_EXCHANGE_OML, \c GLX_SWAP_COPY_OML, and - * \c GLX_SWAP_UNDEFINED_OML. See the - * GLX_OML_swap_method extension spec for more details. - * \param num_db_modes Number of entries in \c db_modes. - * \param visType GLX visual type. Usually either \c GLX_TRUE_COLOR or - * \c GLX_DIRECT_COLOR. - * - * \returns - * \c GL_TRUE on success or \c GL_FALSE on failure. Currently the only - * cause of failure is a bad parameter (i.e., unsupported \c fb_format or - * \c fb_type). - * - * \todo - * There is currently no way to support packed RGB modes (i.e., modes with - * exactly 3 bytes per pixel) or floating-point modes. This could probably - * be done by creating some new, private enums with clever names likes - * \c GL_UNSIGNED_3BYTE_8_8_8, \c GL_4FLOAT_32_32_32_32, - * \c GL_4HALF_16_16_16_16, etc. We can cross that bridge when we come to it. - */ -EGLBoolean -_eglFillInConfigs(_EGLConfig * configs, - GLenum fb_format, GLenum fb_type, - const uint8_t * depth_bits, const uint8_t * stencil_bits, - unsigned num_depth_stencil_bits, - const GLenum * db_modes, unsigned num_db_modes, - int visType) -{ - static const uint8_t bits_table[3][4] = { - /* R G B A */ - { 5, 6, 5, 0 }, /* Any GL_UNSIGNED_SHORT_5_6_5 */ - { 8, 8, 8, 0 }, /* Any RGB with any GL_UNSIGNED_INT_8_8_8_8 */ - { 8, 8, 8, 8 } /* Any RGBA with any GL_UNSIGNED_INT_8_8_8_8 */ - }; - - /* The following arrays are all indexed by the fb_type masked with 0x07. - * Given the four supported fb_type values, this results in valid array - * indices of 3, 4, 5, and 7. - */ - static const uint32_t masks_table_rgb[8][4] = { - {0x00000000, 0x00000000, 0x00000000, 0x00000000}, - {0x00000000, 0x00000000, 0x00000000, 0x00000000}, - {0x00000000, 0x00000000, 0x00000000, 0x00000000}, - {0x0000F800, 0x000007E0, 0x0000001F, 0x00000000}, /* 5_6_5 */ - {0x0000001F, 0x000007E0, 0x0000F800, 0x00000000}, /* 5_6_5_REV */ - {0xFF000000, 0x00FF0000, 0x0000FF00, 0x00000000}, /* 8_8_8_8 */ - {0x00000000, 0x00000000, 0x00000000, 0x00000000}, - {0x000000FF, 0x0000FF00, 0x00FF0000, 0x00000000} /* 8_8_8_8_REV */ - }; - - static const uint32_t masks_table_rgba[8][4] = { - {0x00000000, 0x00000000, 0x00000000, 0x00000000}, - {0x00000000, 0x00000000, 0x00000000, 0x00000000}, - {0x00000000, 0x00000000, 0x00000000, 0x00000000}, - {0x0000F800, 0x000007E0, 0x0000001F, 0x00000000}, /* 5_6_5 */ - {0x0000001F, 0x000007E0, 0x0000F800, 0x00000000}, /* 5_6_5_REV */ - {0xFF000000, 0x00FF0000, 0x0000FF00, 0x000000FF}, /* 8_8_8_8 */ - {0x00000000, 0x00000000, 0x00000000, 0x00000000}, - {0x000000FF, 0x0000FF00, 0x00FF0000, 0xFF000000}, /* 8_8_8_8_REV */ - }; - -#if 0 - static const uint32_t masks_table_bgr[8][4] = { - {0x00000000, 0x00000000, 0x00000000, 0x00000000}, - {0x00000000, 0x00000000, 0x00000000, 0x00000000}, - {0x00000000, 0x00000000, 0x00000000, 0x00000000}, - {0x0000001F, 0x000007E0, 0x0000F800, 0x00000000}, /* 5_6_5 */ - {0x0000F800, 0x000007E0, 0x0000001F, 0x00000000}, /* 5_6_5_REV */ - {0x0000FF00, 0x00FF0000, 0xFF000000, 0x00000000}, /* 8_8_8_8 */ - {0x00000000, 0x00000000, 0x00000000, 0x00000000}, - {0x00FF0000, 0x0000FF00, 0x000000FF, 0x00000000}, /* 8_8_8_8_REV */ - }; - - static const uint32_t masks_table_bgra[8][4] = { - {0x00000000, 0x00000000, 0x00000000, 0x00000000}, - {0x00000000, 0x00000000, 0x00000000, 0x00000000}, - {0x00000000, 0x00000000, 0x00000000, 0x00000000}, - {0x0000001F, 0x000007E0, 0x0000F800, 0x00000000}, /* 5_6_5 */ - {0x0000F800, 0x000007E0, 0x0000001F, 0x00000000}, /* 5_6_5_REV */ - {0x0000FF00, 0x00FF0000, 0xFF000000, 0x000000FF}, /* 8_8_8_8 */ - {0x00000000, 0x00000000, 0x00000000, 0x00000000}, - {0x00FF0000, 0x0000FF00, 0x000000FF, 0xFF000000}, /* 8_8_8_8_REV */ - }; -#endif - - static const uint8_t bytes_per_pixel[8] = { - 0, 0, 0, 2, 2, 4, 0, 4 - }; - - const uint8_t * bits; - const uint32_t * masks; - const int index = fb_type & 0x07; - _EGLConfig *config; - unsigned i; - unsigned j; - unsigned k; - - if ( bytes_per_pixel[index] == 0 ) { - _eglLog(_EGL_INFO, - "[_eglFillInConfigs:%u] Framebuffer type 0x%04x has 0 bytes per pixel.", - __LINE__, fb_type); - return GL_FALSE; - } - - /* Valid types are GL_UNSIGNED_SHORT_5_6_5 and GL_UNSIGNED_INT_8_8_8_8 and - * the _REV versions. - * - * Valid formats are GL_RGBA, GL_RGB, and GL_BGRA. - */ - switch ( fb_format ) { - case GL_RGB: - bits = (bytes_per_pixel[index] == 2) ? bits_table[0] : bits_table[1]; - masks = masks_table_rgb[index]; - break; - - case GL_RGBA: - bits = (bytes_per_pixel[index] == 2) ? bits_table[0] : bits_table[2]; - masks = masks_table_rgba[index]; - break; - -#if 0 - case GL_BGR: - bits = (bytes_per_pixel[index] == 2) ? bits_table[0] : bits_table[1]; - masks = masks_table_bgr[index]; - break; - - case GL_BGRA: - bits = (bytes_per_pixel[index] == 2) ? bits_table[0] : bits_table[2]; - masks = masks_table_bgra[index]; - break; -#endif - - default: - _eglLog(_EGL_WARNING, - "[_eglFillInConfigs:%u] Framebuffer format 0x%04x is not GL_RGB, GL_RGBA, GL_BGR, or GL_BGRA.", - __LINE__, fb_format); - return GL_FALSE; - } - - config = configs; - for (k = 0; k < num_depth_stencil_bits; k++) { - for (i = 0; i < num_db_modes; i++) { - for (j = 0; j < 2; j++) { - _eglSetConfigAttrib(config, EGL_RED_SIZE, bits[0]); - _eglSetConfigAttrib(config, EGL_GREEN_SIZE, bits[1]); - _eglSetConfigAttrib(config, EGL_BLUE_SIZE, bits[2]); - _eglSetConfigAttrib(config, EGL_ALPHA_SIZE, bits[3]); - _eglSetConfigAttrib(config, EGL_BUFFER_SIZE, - bits[0] + bits[1] + bits[2] + bits[3]); - - _eglSetConfigAttrib(config, EGL_STENCIL_SIZE, stencil_bits[k]); - _eglSetConfigAttrib(config, EGL_DEPTH_SIZE, depth_bits[i]); - - _eglSetConfigAttrib(config, EGL_SURFACE_TYPE, EGL_SCREEN_BIT_MESA | - EGL_PBUFFER_BIT | EGL_PIXMAP_BIT | EGL_WINDOW_BIT); - - config++; - } - } - } - return GL_TRUE; -} - diff --git a/src/egl/main/eglconfigutil.h b/src/egl/main/eglconfigutil.h index 9f8906dedb6..c6f48199605 100644 --- a/src/egl/main/eglconfigutil.h +++ b/src/egl/main/eglconfigutil.h @@ -16,14 +16,4 @@ _eglConfigFromContextModesRec(_EGLConfig *conf, const __GLcontextModes *m, EGLint conformant, EGLint renderable_type); -PUBLIC EGLBoolean -_eglFillInConfigs( _EGLConfig *configs, - EGLenum fb_format, EGLenum fb_type, - const uint8_t * depth_bits, const uint8_t * stencil_bits, - unsigned num_depth_stencil_bits, - const EGLenum * db_modes, unsigned num_db_modes, - int visType ); - - - #endif /* EGLCONFIGUTIL_INCLUDED */ diff --git a/src/egl/main/eglcontext.c b/src/egl/main/eglcontext.c index ee4b1b59f5b..012d8dfe1f4 100644 --- a/src/egl/main/eglcontext.c +++ b/src/egl/main/eglcontext.c @@ -4,9 +4,96 @@ #include "eglconfig.h" #include "eglcontext.h" #include "egldisplay.h" -#include "egldriver.h" -#include "eglglobals.h" +#include "eglcurrent.h" #include "eglsurface.h" +#include "egllog.h" + + +/** + * Return the API bit (one of EGL_xxx_BIT) of the context. + */ +static EGLint +_eglGetContextAPIBit(_EGLContext *ctx) +{ + EGLint bit = 0; + + switch (ctx->ClientAPI) { + case EGL_OPENGL_ES_API: + switch (ctx->ClientVersion) { + case 1: + bit = EGL_OPENGL_ES_BIT; + break; + case 2: + bit = EGL_OPENGL_ES2_BIT; + break; + default: + break; + } + break; + case EGL_OPENVG_API: + bit = EGL_OPENVG_BIT; + break; + case EGL_OPENGL_API: + bit = EGL_OPENGL_BIT; + break; + default: + break; + } + + return bit; +} + + +/** + * Parse the list of context attributes and return the proper error code. + */ +static EGLint +_eglParseContextAttribList(_EGLContext *ctx, const EGLint *attrib_list) +{ + EGLenum api = ctx->ClientAPI; + EGLint i, err = EGL_SUCCESS; + + if (!attrib_list) + return EGL_SUCCESS; + + for (i = 0; attrib_list[i] != EGL_NONE; i++) { + EGLint attr = attrib_list[i++]; + EGLint val = attrib_list[i]; + + switch (attr) { + case EGL_CONTEXT_CLIENT_VERSION: + if (api != EGL_OPENGL_ES_API) { + err = EGL_BAD_ATTRIBUTE; + break; + } + if (val != 1 && val != 2) { + err = EGL_BAD_ATTRIBUTE; + break; + } + ctx->ClientVersion = val; + break; + default: + err = EGL_BAD_ATTRIBUTE; + break; + } + + if (err != EGL_SUCCESS) { + _eglLog(_EGL_DEBUG, "bad context attribute 0x%04x", attr); + break; + } + } + + if (err == EGL_SUCCESS) { + EGLint renderable_type, api_bit; + + renderable_type = GET_CONFIG_ATTRIB(ctx->Config, EGL_RENDERABLE_TYPE); + api_bit = _eglGetContextAPIBit(ctx); + if (!(renderable_type & api_bit)) + err = EGL_BAD_CONFIG; + } + + return err; +} /** @@ -14,11 +101,11 @@ * in the attrib_list. */ EGLBoolean -_eglInitContext(_EGLDriver *drv, _EGLContext *ctx, - _EGLConfig *conf, const EGLint *attrib_list) +_eglInitContext(_EGLContext *ctx, _EGLDisplay *dpy, _EGLConfig *conf, + const EGLint *attrib_list) { - EGLint i; const EGLenum api = eglQueryAPI(); + EGLint err; if (api == EGL_NONE) { _eglError(EGL_BAD_MATCH, "eglCreateContext(no client API)"); @@ -26,26 +113,16 @@ _eglInitContext(_EGLDriver *drv, _EGLContext *ctx, } memset(ctx, 0, sizeof(_EGLContext)); + ctx->Resource.Display = dpy; + ctx->ClientAPI = api; + ctx->Config = conf; + ctx->WindowRenderBuffer = EGL_NONE; ctx->ClientVersion = 1; /* the default, per EGL spec */ - for (i = 0; attrib_list && attrib_list[i] != EGL_NONE; i++) { - switch (attrib_list[i]) { - case EGL_CONTEXT_CLIENT_VERSION: - i++; - ctx->ClientVersion = attrib_list[i]; - break; - default: - _eglError(EGL_BAD_ATTRIBUTE, "_eglInitContext"); - return EGL_FALSE; - } - } - - ctx->Config = conf; - ctx->DrawSurface = EGL_NO_SURFACE; - ctx->ReadSurface = EGL_NO_SURFACE; - ctx->ClientAPI = api; - ctx->WindowRenderBuffer = EGL_NONE; + err = _eglParseContextAttribList(ctx, attrib_list); + if (err != EGL_SUCCESS) + return _eglError(err, "eglCreateContext"); return EGL_TRUE; } @@ -58,20 +135,6 @@ _EGLContext * _eglCreateContext(_EGLDriver *drv, _EGLDisplay *dpy, _EGLConfig *conf, _EGLContext *share_list, const EGLint *attrib_list) { -#if 0 /* example code */ - _EGLContext *context; - - context = (_EGLContext *) calloc(1, sizeof(_EGLContext)); - if (!context) - return NULL; - - if (!_eglInitContext(drv, context, conf, attrib_list)) { - free(context); - return NULL; - } - - return context; -#endif return NULL; } @@ -140,99 +203,169 @@ _eglQueryContext(_EGLDriver *drv, _EGLDisplay *dpy, _EGLContext *c, /** - * Drivers will typically call this to do the error checking and - * update the various flags. - * Then, the driver will do its device-dependent Make-Current stuff. + * Bind the context to the surfaces. Return the surfaces that are "orphaned". + * That is, when the context is not NULL, return the surfaces it previously + * bound to; when the context is NULL, the same surfaces are returned. */ -EGLBoolean -_eglMakeCurrent(_EGLDriver *drv, _EGLDisplay *dpy, _EGLSurface *draw, - _EGLSurface *read, _EGLContext *ctx) +static void +_eglBindContextToSurfaces(_EGLContext *ctx, + _EGLSurface **draw, _EGLSurface **read) +{ + _EGLSurface *newDraw = *draw, *newRead = *read; + + if (newDraw->CurrentContext) + newDraw->CurrentContext->DrawSurface = NULL; + newDraw->CurrentContext = ctx; + + if (newRead->CurrentContext) + newRead->CurrentContext->ReadSurface = NULL; + newRead->CurrentContext = ctx; + + if (ctx) { + *draw = ctx->DrawSurface; + ctx->DrawSurface = newDraw; + + *read = ctx->ReadSurface; + ctx->ReadSurface = newRead; + } +} + + +/** + * Bind the context to the thread and return the previous context. + * + * Note that the context may be NULL. + */ +static _EGLContext * +_eglBindContextToThread(_EGLContext *ctx, _EGLThreadInfo *t) { - _EGLThreadInfo *t = _eglGetCurrentThread(); - _EGLContext *oldContext = NULL; - _EGLSurface *oldDrawSurface = NULL; - _EGLSurface *oldReadSurface = NULL; EGLint apiIndex; + _EGLContext *oldCtx; + + apiIndex = (ctx) ? + _eglConvertApiToIndex(ctx->ClientAPI) : t->CurrentAPIIndex; + + oldCtx = t->CurrentContexts[apiIndex]; + if (ctx == oldCtx) + return NULL; + + if (oldCtx) + oldCtx->Binding = NULL; + if (ctx) + ctx->Binding = t; + + t->CurrentContexts[apiIndex] = ctx; + + return oldCtx; +} + + +/** + * Return true if the given context and surfaces can be made current. + */ +static EGLBoolean +_eglCheckMakeCurrent(_EGLContext *ctx, _EGLSurface *draw, _EGLSurface *read) +{ + _EGLThreadInfo *t = _eglGetCurrentThread(); + EGLint conflict_api; if (_eglIsCurrentThreadDummy()) return _eglError(EGL_BAD_ALLOC, "eglMakeCurrent"); - if (ctx) { - /* error checking */ - if (ctx->Binding && ctx->Binding != t) - return _eglError(EGL_BAD_ACCESS, "eglMakeCurrent"); - if (draw == NULL || read == NULL) + /* this is easy */ + if (!ctx) { + if (draw || read) return _eglError(EGL_BAD_MATCH, "eglMakeCurrent"); - if (draw->Config != ctx->Config || read->Config != ctx->Config) - return _eglError(EGL_BAD_MATCH, "eglMakeCurrent"); - if ((draw->Binding && draw->Binding->Binding != t) || - (read->Binding && read->Binding->Binding != t)) - return _eglError(EGL_BAD_ACCESS, "eglMakeCurrent"); + return EGL_TRUE; + } + + /* ctx/draw/read must be all given */ + if (draw == NULL || read == NULL) + return _eglError(EGL_BAD_MATCH, "eglMakeCurrent"); + + /* context stealing from another thread is not allowed */ + if (ctx->Binding && ctx->Binding != t) + return _eglError(EGL_BAD_ACCESS, "eglMakeCurrent"); + + /* + * The spec says + * + * "If ctx is current to some other thread, or if either draw or read are + * bound to contexts in another thread, an EGL_BAD_ACCESS error is + * generated." + * + * But it also says + * + * "at most one context may be bound to a particular surface at a given + * time" + * + * The latter is more restrictive so we can check only the latter case. + */ + if ((draw->CurrentContext && draw->CurrentContext != ctx) || + (read->CurrentContext && read->CurrentContext != ctx)) + return _eglError(EGL_BAD_ACCESS, "eglMakeCurrent"); + /* simply require the configs to be equal */ + if (draw->Config != ctx->Config || read->Config != ctx->Config) + return _eglError(EGL_BAD_MATCH, "eglMakeCurrent"); + + switch (ctx->ClientAPI) { #ifdef EGL_VERSION_1_4 - /* OpenGL and OpenGL ES are conflicting */ - switch (ctx->ClientAPI) { - case EGL_OPENGL_ES_API: - if (t->CurrentContexts[_eglConvertApiToIndex(EGL_OPENGL_API)]) - return _eglError(EGL_BAD_ACCESS, "eglMakeCurrent"); - break; - case EGL_OPENGL_API: - if (t->CurrentContexts[_eglConvertApiToIndex(EGL_OPENGL_ES_API)]) - return _eglError(EGL_BAD_ACCESS, "eglMakeCurrent"); - break; - default: - break; - } + /* OpenGL and OpenGL ES are conflicting */ + case EGL_OPENGL_ES_API: + conflict_api = EGL_OPENGL_API; + break; + case EGL_OPENGL_API: + conflict_api = EGL_OPENGL_ES_API; + break; #endif - apiIndex = _eglConvertApiToIndex(ctx->ClientAPI); - } - else { - if (draw != NULL || read != NULL) - return _eglError(EGL_BAD_MATCH, "eglMakeCurrent"); - apiIndex = t->CurrentAPIIndex; + default: + conflict_api = -1; + break; } - oldContext = t->CurrentContexts[apiIndex]; - if (oldContext) { - oldDrawSurface = oldContext->DrawSurface; - oldReadSurface = oldContext->ReadSurface; - assert(oldDrawSurface); - assert(oldReadSurface); - - /* break old bindings */ - t->CurrentContexts[apiIndex] = NULL; - oldContext->Binding = NULL; - oldContext->DrawSurface = NULL; - oldContext->ReadSurface = NULL; - oldDrawSurface->Binding = NULL; - oldReadSurface->Binding = NULL; + if (conflict_api >= 0 && _eglGetAPIContext(conflict_api)) + return _eglError(EGL_BAD_ACCESS, "eglMakeCurrent"); + + return EGL_TRUE; +} + + +/** + * Bind the context to the current thread and given surfaces. Return the + * previously bound context and the surfaces it bound to. Each argument is + * both input and output. + */ +EGLBoolean +_eglBindContext(_EGLContext **ctx, _EGLSurface **draw, _EGLSurface **read) +{ + _EGLThreadInfo *t = _eglGetCurrentThread(); + _EGLContext *newCtx = *ctx, *oldCtx; + + if (!_eglCheckMakeCurrent(newCtx, *draw, *read)) + return EGL_FALSE; + + /* bind the new context */ + oldCtx = _eglBindContextToThread(newCtx, t); + *ctx = oldCtx; + if (newCtx) + _eglBindContextToSurfaces(newCtx, draw, read); + /* unbind the old context from its binding surfaces */ + if (oldCtx) { /* - * check if the old context or surfaces need to be deleted + * If the new context replaces some old context, the new one should not + * be current before the replacement and it should not be bound to any + * surface. */ - if (!_eglIsSurfaceLinked(oldDrawSurface)) { - assert(draw != oldDrawSurface && read != oldDrawSurface); - drv->API.DestroySurface(drv, dpy, oldDrawSurface); - } - if (oldReadSurface != oldDrawSurface && - !_eglIsSurfaceLinked(oldReadSurface)) { - assert(draw != oldReadSurface && read != oldReadSurface); - drv->API.DestroySurface(drv, dpy, oldReadSurface); - } - if (!_eglIsContextLinked(oldContext)) { - assert(ctx != oldContext); - drv->API.DestroyContext(drv, dpy, oldContext); - } - } + if (newCtx) + assert(!*draw && !*read); - /* build new bindings */ - if (ctx) { - t->CurrentContexts[apiIndex] = ctx; - ctx->Binding = t; - ctx->DrawSurface = draw; - ctx->ReadSurface = read; - draw->Binding = ctx; - read->Binding = ctx; + *draw = oldCtx->DrawSurface; + *read = oldCtx->ReadSurface; + assert(*draw && *read); + + _eglBindContextToSurfaces(NULL, draw, read); } return EGL_TRUE; @@ -240,6 +373,17 @@ _eglMakeCurrent(_EGLDriver *drv, _EGLDisplay *dpy, _EGLSurface *draw, /** + * Just a placeholder/demo function. Drivers should override this. + */ +EGLBoolean +_eglMakeCurrent(_EGLDriver *drv, _EGLDisplay *dpy, _EGLSurface *draw, + _EGLSurface *read, _EGLContext *ctx) +{ + return EGL_FALSE; +} + + +/** * This is defined by the EGL_MESA_copy_context extension. */ EGLBoolean diff --git a/src/egl/main/eglcontext.h b/src/egl/main/eglcontext.h index cb9e3f4a892..cfe92dd9f5c 100644 --- a/src/egl/main/eglcontext.h +++ b/src/egl/main/eglcontext.h @@ -1,9 +1,9 @@ - #ifndef EGLCONTEXT_INCLUDED #define EGLCONTEXT_INCLUDED #include "egltypedefs.h" +#include "egldisplay.h" /** @@ -11,9 +11,8 @@ */ struct _egl_context { - /* Managed by EGLDisplay for linking */ - _EGLDisplay *Display; - _EGLContext *Next; + /* A context is a display resource */ + _EGLResource Resource; /* The bound status of the context */ _EGLThreadInfo *Binding; @@ -31,7 +30,7 @@ struct _egl_context PUBLIC EGLBoolean -_eglInitContext(_EGLDriver *drv, _EGLContext *ctx, +_eglInitContext(_EGLContext *ctx, _EGLDisplay *dpy, _EGLConfig *config, const EGLint *attrib_list); @@ -48,6 +47,10 @@ _eglQueryContext(_EGLDriver *drv, _EGLDisplay *dpy, _EGLContext *ctx, EGLint att PUBLIC EGLBoolean +_eglBindContext(_EGLContext **ctx, _EGLSurface **draw, _EGLSurface **read); + + +extern EGLBoolean _eglMakeCurrent(_EGLDriver *drv, _EGLDisplay *dpy, _EGLSurface *draw, _EGLSurface *read, _EGLContext *ctx); @@ -57,6 +60,9 @@ _eglCopyContextMESA(_EGLDriver *drv, EGLDisplay dpy, EGLContext source, EGLConte /** * Return true if the context is bound to a thread. + * + * The binding is considered a reference to the context. Drivers should not + * destroy a context when it is bound. */ static INLINE EGLBoolean _eglIsContextBound(_EGLContext *ctx) @@ -65,4 +71,67 @@ _eglIsContextBound(_EGLContext *ctx) } +/** + * Link a context to a display and return the handle of the link. + * The handle can be passed to client directly. + */ +static INLINE EGLContext +_eglLinkContext(_EGLContext *ctx, _EGLDisplay *dpy) +{ + _eglLinkResource(&ctx->Resource, _EGL_RESOURCE_CONTEXT, dpy); + return (EGLContext) ctx; +} + + +/** + * Unlink a linked context from its display. + * Accessing an unlinked context should generate EGL_BAD_CONTEXT error. + */ +static INLINE void +_eglUnlinkContext(_EGLContext *ctx) +{ + _eglUnlinkResource(&ctx->Resource, _EGL_RESOURCE_CONTEXT); +} + + +/** + * Lookup a handle to find the linked context. + * Return NULL if the handle has no corresponding linked context. + */ +static INLINE _EGLContext * +_eglLookupContext(EGLContext context, _EGLDisplay *dpy) +{ + _EGLContext *ctx = (_EGLContext *) context; + if (!dpy || !_eglCheckResource((void *) ctx, _EGL_RESOURCE_CONTEXT, dpy)) + ctx = NULL; + return ctx; +} + + +/** + * Return the handle of a linked context, or EGL_NO_CONTEXT. + */ +static INLINE EGLContext +_eglGetContextHandle(_EGLContext *ctx) +{ + _EGLResource *res = (_EGLResource *) ctx; + return (res && _eglIsResourceLinked(res)) ? + (EGLContext) ctx : EGL_NO_CONTEXT; +} + + +/** + * Return true if the context is linked to a display. + * + * The link is considered a reference to the context (the display is owning the + * context). Drivers should not destroy a context when it is linked. + */ +static INLINE EGLBoolean +_eglIsContextLinked(_EGLContext *ctx) +{ + _EGLResource *res = (_EGLResource *) ctx; + return (res && _eglIsResourceLinked(res)); +} + + #endif /* EGLCONTEXT_INCLUDED */ diff --git a/src/egl/main/eglcurrent.c b/src/egl/main/eglcurrent.c index df506151b58..989c19a2fa5 100644 --- a/src/egl/main/eglcurrent.c +++ b/src/egl/main/eglcurrent.c @@ -1,10 +1,9 @@ #include <stdlib.h> #include <string.h> -#include "eglcurrent.h" -#include "eglcontext.h" +#include "eglglobals.h" #include "egllog.h" #include "eglmutex.h" -#include "eglglobals.h" +#include "eglcurrent.h" /* This should be kept in sync with _eglInitThreadInfo() */ @@ -227,50 +226,24 @@ _eglIsCurrentThreadDummy(void) /** - * Return the currently bound context, or NULL. - */ -_EGLContext * -_eglGetCurrentContext(void) -{ - _EGLThreadInfo *t = _eglGetCurrentThread(); - return t->CurrentContexts[t->CurrentAPIIndex]; -} - - -/** - * Return the display of the currently bound context, or NULL. + * Return the currently bound context of the given API, or NULL. */ -_EGLDisplay * -_eglGetCurrentDisplay(void) +PUBLIC _EGLContext * +_eglGetAPIContext(EGLenum api) { _EGLThreadInfo *t = _eglGetCurrentThread(); - _EGLContext *ctx = t->CurrentContexts[t->CurrentAPIIndex]; - if (ctx) - return ctx->Display; - else - return NULL; + return t->CurrentContexts[_eglConvertApiToIndex(api)]; } /** - * Return the read or write surface of the currently bound context, or NULL. + * Return the currently bound context of the current API, or NULL. */ -_EGLSurface * -_eglGetCurrentSurface(EGLint readdraw) +_EGLContext * +_eglGetCurrentContext(void) { _EGLThreadInfo *t = _eglGetCurrentThread(); - _EGLContext *ctx = t->CurrentContexts[t->CurrentAPIIndex]; - if (ctx) { - switch (readdraw) { - case EGL_DRAW: - return ctx->DrawSurface; - case EGL_READ: - return ctx->ReadSurface; - default: - return NULL; - } - } - return NULL; + return t->CurrentContexts[t->CurrentAPIIndex]; } diff --git a/src/egl/main/eglcurrent.h b/src/egl/main/eglcurrent.h index c4478b38914..e5c94ce60ab 100644 --- a/src/egl/main/eglcurrent.h +++ b/src/egl/main/eglcurrent.h @@ -1,6 +1,7 @@ #ifndef EGLCURRENT_INCLUDED #define EGLCURRENT_INCLUDED + #include "egltypedefs.h" @@ -73,15 +74,11 @@ _eglIsCurrentThreadDummy(void); PUBLIC _EGLContext * -_eglGetCurrentContext(void); - +_eglGetAPIContext(EGLenum api); -PUBLIC _EGLDisplay * -_eglGetCurrentDisplay(void); - -PUBLIC _EGLSurface * -_eglGetCurrentSurface(EGLint readdraw); +PUBLIC _EGLContext * +_eglGetCurrentContext(void); PUBLIC EGLBoolean diff --git a/src/egl/main/egldisplay.c b/src/egl/main/egldisplay.c index 896d60dbe10..d7a8d142929 100644 --- a/src/egl/main/egldisplay.c +++ b/src/egl/main/egldisplay.c @@ -10,7 +10,6 @@ #include "egldisplay.h" #include "egldriver.h" #include "eglglobals.h" -#include "eglstring.h" #include "eglmutex.h" #include "egllog.h" @@ -26,12 +25,18 @@ _eglFiniDisplay(void) /* atexit function is called with global mutex locked */ dpyList = _eglGlobal.DisplayList; while (dpyList) { + EGLint i; + /* pop list head */ dpy = dpyList; dpyList = dpyList->Next; - if (dpy->ContextList || dpy->SurfaceList) - _eglLog(_EGL_DEBUG, "Display %p is destroyed with resources", dpy); + for (i = 0; i < _EGL_NUM_RESOURCES; i++) { + if (dpy->ResourceLists[i]) { + _eglLog(_EGL_DEBUG, "Display %p is destroyed with resources", dpy); + break; + } + } free(dpy); } @@ -40,53 +45,17 @@ _eglFiniDisplay(void) /** - * If the first character is '!' we interpret it as specific driver name - * (i.e. "!r200" or "!i830"). Whatever follows ':' is interpreted as - * arguments. - * - * The caller may free() the returned driver name. - */ -char * -_eglSplitDisplayString(const char *dpyString, const char **args) -{ - char *drv, *p; - - if (!dpyString || dpyString[0] != '!') - return NULL; - drv = _eglstrdup(dpyString + 1); - if (!drv) - return NULL; - - p = strchr(dpyString, ':'); - if (p) { - drv[p - dpyString] = '\0'; - p++; - } - if (args) - *args = p; - - return drv; -} - - -/** * Allocate a new _EGLDisplay object for the given nativeDisplay handle. * We'll also try to determine the device driver name at this time. * * Note that nativeDisplay may be an X Display ptr, or a string. */ _EGLDisplay * -_eglNewDisplay(NativeDisplayType nativeDisplay) +_eglNewDisplay(EGLNativeDisplayType nativeDisplay) { _EGLDisplay *dpy = (_EGLDisplay *) calloc(1, sizeof(_EGLDisplay)); if (dpy) { dpy->NativeDisplay = nativeDisplay; - - dpy->DriverName = _eglPreloadDriver(dpy); - if (!dpy->DriverName) { - free(dpy); - return NULL; - } } return dpy; } @@ -144,7 +113,7 @@ _eglUnlinkDisplay(_EGLDisplay *dpy) * linked displays. */ _EGLDisplay * -_eglFindDisplay(NativeDisplayType nativeDisplay) +_eglFindDisplay(EGLNativeDisplayType nativeDisplay) { _EGLDisplay *dpy; @@ -171,29 +140,27 @@ _eglFindDisplay(NativeDisplayType nativeDisplay) void _eglReleaseDisplayResources(_EGLDriver *drv, _EGLDisplay *display) { - _EGLContext *contexts; - _EGLSurface *surfaces; - - contexts = display->ContextList; - surfaces = display->SurfaceList; + _EGLResource *list; - while (contexts) { - _EGLContext *ctx = contexts; - contexts = contexts->Next; + list = display->ResourceLists[_EGL_RESOURCE_CONTEXT]; + while (list) { + _EGLContext *ctx = (_EGLContext *) list; + list = list->Next; _eglUnlinkContext(ctx); drv->API.DestroyContext(drv, display, ctx); } - assert(!display->ContextList); + assert(!display->ResourceLists[_EGL_RESOURCE_CONTEXT]); - while (surfaces) { - _EGLSurface *surf = surfaces; - surfaces = surfaces->Next; + list = display->ResourceLists[_EGL_RESOURCE_SURFACE]; + while (list) { + _EGLSurface *surf = (_EGLSurface *) list; + list = list->Next; _eglUnlinkSurface(surf); drv->API.DestroySurface(drv, display, surf); } - assert(!display->SurfaceList); + assert(!display->ResourceLists[_EGL_RESOURCE_SURFACE]); } @@ -212,97 +179,13 @@ _eglCleanupDisplay(_EGLDisplay *disp) free(disp->Configs); disp->Configs = NULL; disp->NumConfigs = 0; + disp->MaxConfigs = 0; } /* XXX incomplete */ } -/** - * Link a context to a display and return the handle of the link. - * The handle can be passed to client directly. - */ -EGLContext -_eglLinkContext(_EGLContext *ctx, _EGLDisplay *dpy) -{ - ctx->Display = dpy; - ctx->Next = dpy->ContextList; - dpy->ContextList = ctx; - return (EGLContext) ctx; -} - - -/** - * Unlink a linked context from its display. - * Accessing an unlinked context should generate EGL_BAD_CONTEXT error. - */ -void -_eglUnlinkContext(_EGLContext *ctx) -{ - _EGLContext *prev; - - prev = ctx->Display->ContextList; - if (prev != ctx) { - while (prev) { - if (prev->Next == ctx) - break; - prev = prev->Next; - } - assert(prev); - prev->Next = ctx->Next; - } - else { - ctx->Display->ContextList = ctx->Next; - } - - ctx->Next = NULL; - ctx->Display = NULL; -} - - -/** - * Link a surface to a display and return the handle of the link. - * The handle can be passed to client directly. - */ -EGLSurface -_eglLinkSurface(_EGLSurface *surf, _EGLDisplay *dpy) -{ - surf->Display = dpy; - surf->Next = dpy->SurfaceList; - dpy->SurfaceList = surf; - return (EGLSurface) surf; -} - - -/** - * Unlink a linked surface from its display. - * Accessing an unlinked surface should generate EGL_BAD_SURFACE error. - */ -void -_eglUnlinkSurface(_EGLSurface *surf) -{ - _EGLSurface *prev; - - prev = surf->Display->SurfaceList; - if (prev != surf) { - while (prev) { - if (prev->Next == surf) - break; - prev = prev->Next; - } - assert(prev); - prev->Next = surf->Next; - } - else { - prev = NULL; - surf->Display->SurfaceList = surf->Next; - } - - surf->Next = NULL; - surf->Display = NULL; -} - - #ifndef _EGL_SKIP_HANDLE_CHECK @@ -327,45 +210,70 @@ _eglCheckDisplayHandle(EGLDisplay dpy) /** - * Return EGL_TRUE if the given handle is a valid handle to a context. + * Return EGL_TRUE if the given resource is valid. That is, the display does + * own the resource. */ EGLBoolean -_eglCheckContextHandle(EGLContext ctx, _EGLDisplay *dpy) +_eglCheckResource(void *res, _EGLResourceType type, _EGLDisplay *dpy) { - _EGLContext *cur = NULL; - - if (dpy) - cur = dpy->ContextList; - while (cur) { - if (cur == (_EGLContext *) ctx) { - assert(cur->Display == dpy); + _EGLResource *list = dpy->ResourceLists[type]; + + if (!res) + return EGL_FALSE; + + while (list) { + if (res == (void *) list) { + assert(list->Display == dpy); break; } - cur = cur->Next; + list = list->Next; } - return (cur != NULL); + + return (list != NULL); } +#endif /* !_EGL_SKIP_HANDLE_CHECK */ + + /** - * Return EGL_TRUE if the given handle is a valid handle to a surface. + * Link a resource to a display. */ -EGLBoolean -_eglCheckSurfaceHandle(EGLSurface surf, _EGLDisplay *dpy) +void +_eglLinkResource(_EGLResource *res, _EGLResourceType type, _EGLDisplay *dpy) { - _EGLSurface *cur = NULL; + assert(!res->Display || res->Display == dpy); - if (dpy) - cur = dpy->SurfaceList; - while (cur) { - if (cur == (_EGLSurface *) surf) { - assert(cur->Display == dpy); - break; - } - cur = cur->Next; - } - return (cur != NULL); + res->Display = dpy; + res->IsLinked = EGL_TRUE; + res->Next = dpy->ResourceLists[type]; + dpy->ResourceLists[type] = res; } -#endif /* !_EGL_SKIP_HANDLE_CHECK */ +/** + * Unlink a linked resource from its display. + */ +void +_eglUnlinkResource(_EGLResource *res, _EGLResourceType type) +{ + _EGLResource *prev; + + prev = res->Display->ResourceLists[type]; + if (prev != res) { + while (prev) { + if (prev->Next == res) + break; + prev = prev->Next; + } + assert(prev); + prev->Next = res->Next; + } + else { + res->Display->ResourceLists[type] = res->Next; + } + + res->Next = NULL; + /* do not reset res->Display */ + res->IsLinked = EGL_FALSE; +} diff --git a/src/egl/main/egldisplay.h b/src/egl/main/egldisplay.h index 4f619e53710..03903290fdd 100644 --- a/src/egl/main/egldisplay.h +++ b/src/egl/main/egldisplay.h @@ -1,10 +1,32 @@ #ifndef EGLDISPLAY_INCLUDED #define EGLDISPLAY_INCLUDED + #include "egltypedefs.h" #include "egldefines.h" -#include "eglcontext.h" -#include "eglsurface.h" + + +enum _egl_resource_type { + _EGL_RESOURCE_CONTEXT, + _EGL_RESOURCE_SURFACE, + _EGL_RESOURCE_IMAGE, + + _EGL_NUM_RESOURCES +}; + + +/** + * A resource of a display. + */ +struct _egl_resource +{ + /* which display the resource belongs to */ + _EGLDisplay *Display; + EGLBoolean IsLinked; + + /* used to link resources of the same type */ + _EGLResource *Next; +}; /** @@ -14,6 +36,13 @@ struct _egl_extensions { EGLBoolean MESA_screen_surface; EGLBoolean MESA_copy_context; + EGLBoolean KHR_image_base; + EGLBoolean KHR_image_pixmap; + EGLBoolean KHR_vg_parent_image; + EGLBoolean KHR_gl_texture_2D_image; + EGLBoolean KHR_gl_texture_cubemap_image; + EGLBoolean KHR_gl_texture_3D_image; + EGLBoolean KHR_gl_renderbuffer_image; char String[_EGL_MAX_EXTENSIONS_LEN]; }; @@ -26,7 +55,7 @@ struct _egl_display EGLNativeDisplayType NativeDisplay; - const char *DriverName; + EGLBoolean Initialized; /**< True if the display is initialized */ _EGLDriver *Driver; void *DriverData; /* private to driver */ @@ -39,8 +68,6 @@ struct _egl_display _EGLExtensions Extensions; - int LargestPbuffer; - EGLint NumScreens; _EGLScreen **Screens; /* array [NumScreens] */ @@ -48,9 +75,8 @@ struct _egl_display EGLint NumConfigs; _EGLConfig **Configs; /* array [NumConfigs] of ptr to _EGLConfig */ - /* lists of linked contexts and surface */ - _EGLContext *ContextList; - _EGLSurface *SurfaceList; + /* lists of resources */ + _EGLResource *ResourceLists[_EGL_NUM_RESOURCES]; }; @@ -58,12 +84,8 @@ extern void _eglFiniDisplay(void); -extern char * -_eglSplitDisplayString(const char *dpyString, const char **args); - - extern _EGLDisplay * -_eglNewDisplay(NativeDisplayType displayName); +_eglNewDisplay(EGLNativeDisplayType displayName); extern EGLDisplay @@ -75,7 +97,7 @@ _eglUnlinkDisplay(_EGLDisplay *dpy); extern _EGLDisplay * -_eglFindDisplay(NativeDisplayType nativeDisplay); +_eglFindDisplay(EGLNativeDisplayType nativeDisplay); PUBLIC void @@ -86,22 +108,6 @@ PUBLIC void _eglCleanupDisplay(_EGLDisplay *disp); -extern EGLContext -_eglLinkContext(_EGLContext *ctx, _EGLDisplay *dpy); - - -extern void -_eglUnlinkContext(_EGLContext *ctx); - - -extern EGLSurface -_eglLinkSurface(_EGLSurface *surf, _EGLDisplay *dpy); - - -extern void -_eglUnlinkSurface(_EGLSurface *surf); - - #ifndef _EGL_SKIP_HANDLE_CHECK @@ -109,12 +115,8 @@ extern EGLBoolean _eglCheckDisplayHandle(EGLDisplay dpy); -extern EGLBoolean -_eglCheckContextHandle(EGLContext ctx, _EGLDisplay *dpy); - - -extern EGLBoolean -_eglCheckSurfaceHandle(EGLSurface surf, _EGLDisplay *dpy); +PUBLIC EGLBoolean +_eglCheckResource(void *res, _EGLResourceType type, _EGLDisplay *dpy); #else /* !_EGL_SKIP_HANDLE_CHECK */ @@ -129,18 +131,9 @@ _eglCheckDisplayHandle(EGLDisplay dpy) static INLINE EGLBoolean -_eglCheckContextHandle(EGLContext ctx, _EGLDisplay *dpy) +_eglCheckResource(void *res, _EGLResourceType type, _EGLDisplay *dpy); { - _EGLContext *c = (_EGLContext *) ctx; - return (dpy && c && c->Display == dpy); -} - - -static INLINE EGLBoolean -_eglCheckSurfaceHandle(EGLSurface surf, _EGLDisplay *dpy) -{ - _EGLSurface *s = (_EGLSurface *) surf; - return (dpy && s && s->Display == dpy); + return (((_EGLResource *) res)->Display == dpy); } @@ -181,92 +174,21 @@ _eglIsDisplayLinked(_EGLDisplay *dpy) } -/** - * Lookup a handle to find the linked context. - * Return NULL if the handle has no corresponding linked context. - */ -static INLINE _EGLContext * -_eglLookupContext(EGLContext context, _EGLDisplay *dpy) -{ - _EGLContext *ctx = (_EGLContext *) context; - if (!_eglCheckContextHandle(context, dpy)) - ctx = NULL; - return ctx; -} - - -/** - * Return the handle of a linked context, or EGL_NO_CONTEXT. - */ -static INLINE EGLContext -_eglGetContextHandle(_EGLContext *ctx) -{ - return (EGLContext) ((ctx && ctx->Display) ? ctx : EGL_NO_CONTEXT); -} - - -/** - * Return true if the context is linked to a display. - */ -static INLINE EGLBoolean -_eglIsContextLinked(_EGLContext *ctx) -{ - return (EGLBoolean) (_eglGetContextHandle(ctx) != EGL_NO_CONTEXT); -} - - -/** - * Lookup a handle to find the linked surface. - * Return NULL if the handle has no corresponding linked surface. - */ -static INLINE _EGLSurface * -_eglLookupSurface(EGLSurface surface, _EGLDisplay *dpy) -{ - _EGLSurface *surf = (_EGLSurface *) surface; - if (!_eglCheckSurfaceHandle(surf, dpy)) - surf = NULL; - return surf; -} +extern void +_eglLinkResource(_EGLResource *res, _EGLResourceType type, _EGLDisplay *dpy); -/** - * Return the handle of a linked surface, or EGL_NO_SURFACE. - */ -static INLINE EGLSurface -_eglGetSurfaceHandle(_EGLSurface *surf) -{ - return (EGLSurface) ((surf && surf->Display) ? surf : EGL_NO_SURFACE); -} +extern void +_eglUnlinkResource(_EGLResource *res, _EGLResourceType type); /** - * Return true if the surface is linked to a display. + * Return true if the resource is linked. */ static INLINE EGLBoolean -_eglIsSurfaceLinked(_EGLSurface *surf) -{ - return (EGLBoolean) (_eglGetSurfaceHandle(surf) != EGL_NO_SURFACE); -} - - -/** - * Cast an unsigned int to a pointer. - */ -static INLINE void * -_eglUIntToPointer(unsigned int v) -{ - return (void *) ((uintptr_t) v); -} - - -/** - * Cast a pointer to an unsigned int. The pointer must be one that is - * returned by _eglUIntToPointer. - */ -static INLINE unsigned int -_eglPointerToUInt(const void *p) +_eglIsResourceLinked(_EGLResource *res) { - return (unsigned int) ((uintptr_t) p); + return res->IsLinked; } diff --git a/src/egl/main/egldriver.c b/src/egl/main/egldriver.c index 018b06d3bea..a87c697b113 100644 --- a/src/egl/main/egldriver.c +++ b/src/egl/main/egldriver.c @@ -19,9 +19,13 @@ #include "eglscreen.h" #include "eglstring.h" #include "eglsurface.h" +#include "eglimage.h" -#if defined(_EGL_PLATFORM_X) +#if defined(_EGL_PLATFORM_POSIX) #include <dlfcn.h> +#include <sys/types.h> +#include <dirent.h> +#include <unistd.h> #endif @@ -49,10 +53,17 @@ close_library(HMODULE lib) } -#elif defined(_EGL_PLATFORM_X) +static const char * +library_suffix(void) +{ + return ".dll"; +} + + +#elif defined(_EGL_PLATFORM_POSIX) -static const char DefaultDriverName[] = "egl_softpipe"; +static const char DefaultDriverName[] = "egl_glx"; typedef void * lib_handle; @@ -68,8 +79,17 @@ close_library(void *lib) dlclose(lib); } + +static const char * +library_suffix(void) +{ + return ".so"; +} + + #else /* _EGL_PLATFORM_NO_OS */ + static const char DefaultDriverName[] = "builtin"; typedef void *lib_handle; @@ -86,67 +106,21 @@ close_library(void *lib) } -#endif +static const char * +library_suffix(void) +{ + return NULL; +} -/** - * Choose a driver for a given display. - * The caller may free() the returned strings. - */ -static char * -_eglChooseDriver(_EGLDisplay *dpy, char **argsRet) -{ - char *path = NULL; - const char *args = NULL; - const char *suffix = NULL; - const char *p; - - path = getenv("EGL_DRIVER"); - if (path) - path = _eglstrdup(path); - -#if defined(_EGL_PLATFORM_X) - if (!path && dpy && dpy->NativeDisplay) { - /* assume (wrongly!) that the native display is a display string */ - path = _eglSplitDisplayString((const char *) dpy->NativeDisplay, &args); - } - suffix = "so"; -#elif defined(_EGL_PLATFORM_WINDOWS) - suffix = "dll"; -#else /* _EGL_PLATFORM_NO_OS */ - if (path) { - /* force the use of the default driver */ - _eglLog(_EGL_DEBUG, "ignore EGL_DRIVER"); - free(path); - path = NULL; - } - suffix = NULL; #endif - if (!path) - path = _eglstrdup(DefaultDriverName); - - /* append suffix if there isn't */ - p = strrchr(path, '.'); - if (!p && suffix) { - size_t len = strlen(path); - char *tmp = malloc(len + strlen(suffix) + 2); - if (tmp) { - memcpy(tmp, path, len); - tmp[len++] = '.'; - tmp[len] = '\0'; - strcat(tmp + len, suffix); - - free(path); - path = tmp; - } - } - - if (argsRet) - *argsRet = (args) ? _eglstrdup(args) : NULL; - return path; -} +#define NUM_PROBE_CACHE_SLOTS 8 +static struct { + EGLint keys[NUM_PROBE_CACHE_SLOTS]; + const void *values[NUM_PROBE_CACHE_SLOTS]; +} _eglProbeCache; /** @@ -168,7 +142,7 @@ _eglOpenLibrary(const char *driverPath, lib_handle *handle) /* XXX untested */ if (lib) mainFunc = (_EGLMain_t) GetProcAddress(lib, "_eglMain"); -#elif defined(_EGL_PLATFORM_X) +#elif defined(_EGL_PLATFORM_POSIX) if (lib) { mainFunc = (_EGLMain_t) dlsym(lib, "_eglMain"); if (!mainFunc) @@ -208,11 +182,10 @@ _eglOpenLibrary(const char *driverPath, lib_handle *handle) /** - * Load the named driver. The path and args passed will be - * owned by the driver and freed. + * Load the named driver. */ static _EGLDriver * -_eglLoadDriver(char *path, char *args) +_eglLoadDriver(const char *path, const char *args) { _EGLMain_t mainFunc; lib_handle lib; @@ -234,8 +207,19 @@ _eglLoadDriver(char *path, char *args) drv->Name = "UNNAMED"; } - drv->Path = path; - drv->Args = args; + drv->Path = _eglstrdup(path); + drv->Args = (args) ? _eglstrdup(args) : NULL; + if (!drv->Path || (args && !drv->Args)) { + if (drv->Path) + free((char *) drv->Path); + if (drv->Args) + free((char *) drv->Args); + drv->Unload(drv); + if (lib) + close_library(lib); + return NULL; + } + drv->LibHandle = lib; return drv; @@ -244,89 +228,316 @@ _eglLoadDriver(char *path, char *args) /** * Match a display to a preloaded driver. + * + * The matching is done by finding the driver with the highest score. */ -static _EGLDriver * +_EGLDriver * _eglMatchDriver(_EGLDisplay *dpy) { - _EGLDriver *defaultDriver = NULL; - EGLint i; + _EGLDriver *best_drv = NULL; + EGLint best_score = -1, i; for (i = 0; i < _eglGlobal.NumDrivers; i++) { _EGLDriver *drv = _eglGlobal.Drivers[i]; + EGLint score; + + score = (drv->Probe) ? drv->Probe(drv, dpy) : 0; + if (score > best_score) { + if (best_drv) { + _eglLog(_EGL_DEBUG, "driver %s has higher score than %s", + drv->Name, best_drv->Name); + } + + best_drv = drv; + best_score = score; + /* perfect match */ + if (score >= 100) + break; + } + } + + return best_drv; +} - /* display specifies a driver */ - if (dpy->DriverName) { - if (strcmp(dpy->DriverName, drv->Name) == 0) - return drv; + +/** + * A loader function for use with _eglPreloadForEach. The loader data is the + * filename of the driver. This function stops on the first valid driver. + */ +static EGLBoolean +_eglLoaderFile(const char *dir, size_t len, void *loader_data) +{ + _EGLDriver *drv; + char path[1024]; + const char *filename = (const char *) loader_data; + size_t flen = strlen(filename); + + /* make a full path */ + if (len + flen + 2 > sizeof(path)) + return EGL_TRUE; + if (len) { + memcpy(path, dir, len); + path[len++] = '/'; + } + memcpy(path + len, filename, flen); + len += flen; + path[len] = '\0'; + + drv = _eglLoadDriver(path, NULL); + /* fix the path and load again */ + if (!drv && library_suffix()) { + const char *suffix = library_suffix(); + size_t slen = strlen(suffix); + const char *p; + EGLBoolean need_suffix; + + p = filename + flen - slen; + need_suffix = (p < filename || strcmp(p, suffix) != 0); + if (need_suffix && len + slen + 1 <= sizeof(path)) { + strcpy(path + len, suffix); + drv = _eglLoadDriver(path, NULL); } - else if (drv->Probe) { - if (drv->Probe(drv, dpy)) - return drv; + } + if (!drv) + return EGL_TRUE; + + /* remember the driver and stop */ + _eglGlobal.Drivers[_eglGlobal.NumDrivers++] = drv; + return EGL_FALSE; +} + + +/** + * A loader function for use with _eglPreloadForEach. The loader data is the + * pattern (prefix) of the files to look for. + */ +static EGLBoolean +_eglLoaderPattern(const char *dir, size_t len, void *loader_data) +{ +#if defined(_EGL_PLATFORM_POSIX) + const char *prefix, *suffix; + size_t prefix_len, suffix_len; + DIR *dirp; + struct dirent *dirent; + char path[1024]; + + if (len + 2 > sizeof(path)) + return EGL_TRUE; + if (len) { + memcpy(path, dir, len); + path[len++] = '/'; + } + path[len] = '\0'; + + dirp = opendir(path); + if (!dirp) + return EGL_TRUE; + + prefix = (const char *) loader_data; + prefix_len = strlen(prefix); + suffix = library_suffix(); + suffix_len = (suffix) ? strlen(suffix) : 0; + + while ((dirent = readdir(dirp))) { + _EGLDriver *drv; + size_t dirent_len = strlen(dirent->d_name); + const char *p; + + /* match the prefix */ + if (strncmp(dirent->d_name, prefix, prefix_len) != 0) + continue; + /* match the suffix */ + if (suffix) { + p = dirent->d_name + dirent_len - suffix_len; + if (p < dirent->d_name || strcmp(p, suffix) != 0) + continue; } - else { - if (!defaultDriver) - defaultDriver = drv; + + /* make a full path and load the driver */ + if (len + dirent_len + 1 <= sizeof(path)) { + strcpy(path + len, dirent->d_name); + drv = _eglLoadDriver(path, NULL); + if (drv) + _eglGlobal.Drivers[_eglGlobal.NumDrivers++] = drv; } } - return defaultDriver; + closedir(dirp); + + return EGL_TRUE; +#else /* _EGL_PLATFORM_POSIX */ + /* stop immediately */ + return EGL_FALSE; +#endif } /** - * Load a driver and save it. + * Run the preload function on each driver directory and return the number of + * drivers loaded. + * + * The process may end prematurely if the callback function returns false. */ -const char * -_eglPreloadDriver(_EGLDisplay *dpy) +static EGLint +_eglPreloadForEach(const char *search_path, + EGLBoolean (*loader)(const char *, size_t, void *), + void *loader_data) { - char *path, *args; - _EGLDriver *drv; - EGLint i; + const char *cur, *next; + size_t len; + EGLint num_drivers = _eglGlobal.NumDrivers; - path = _eglChooseDriver(dpy, &args); - if (!path) - return NULL; + cur = search_path; + while (cur) { + next = strchr(cur, ':'); + len = (next) ? next - cur : strlen(cur); - for (i = 0; i < _eglGlobal.NumDrivers; i++) { - drv = _eglGlobal.Drivers[i]; - if (strcmp(drv->Path, path) == 0) { - _eglLog(_EGL_DEBUG, "Driver %s is already preloaded", - drv->Name); - free(path); - if (args) - free(args); - return drv->Name; + if (!loader(cur, len, loader_data)) + break; + + cur = (next) ? next + 1 : NULL; + } + + return (_eglGlobal.NumDrivers - num_drivers); +} + + +/** + * Return a list of colon-separated driver directories. + */ +static const char * +_eglGetSearchPath(void) +{ + static const char *search_path; + +#if defined(_EGL_PLATFORM_POSIX) || defined(_EGL_PLATFORM_WINDOWS) + if (!search_path) { + static char buffer[1024]; + const char *p; + int ret; + + p = getenv("EGL_DRIVERS_PATH"); +#if defined(_EGL_PLATFORM_POSIX) + if (p && (geteuid() != getuid() || getegid() != getgid())) { + _eglLog(_EGL_DEBUG, + "ignore EGL_DRIVERS_PATH for setuid/setgid binaries"); + p = NULL; + } +#endif /* _EGL_PLATFORM_POSIX */ + + if (p) { + ret = snprintf(buffer, sizeof(buffer), + "%s:%s", p, _EGL_DRIVER_SEARCH_DIR); + if (ret > 0 && ret < sizeof(buffer)) + search_path = buffer; } } + if (!search_path) + search_path = _EGL_DRIVER_SEARCH_DIR; +#else + search_path = ""; +#endif - drv = _eglLoadDriver(path, args); - if (!drv) - return NULL; + return search_path; +} - _eglGlobal.Drivers[_eglGlobal.NumDrivers++] = drv; - return drv->Name; +/** + * Preload a user driver. + * + * A user driver can be specified by EGL_DRIVER. + */ +static EGLBoolean +_eglPreloadUserDriver(void) +{ + const char *search_path = _eglGetSearchPath(); + char *env; + + env = getenv("EGL_DRIVER"); +#if defined(_EGL_PLATFORM_POSIX) + if (env && strchr(env, '/')) { + search_path = ""; + if ((geteuid() != getuid() || getegid() != getgid())) { + _eglLog(_EGL_DEBUG, + "ignore EGL_DRIVER for setuid/setgid binaries"); + env = NULL; + } + } +#endif /* _EGL_PLATFORM_POSIX */ + if (!env) + return EGL_FALSE; + + if (!_eglPreloadForEach(search_path, _eglLoaderFile, (void *) env)) { + _eglLog(_EGL_WARNING, "EGL_DRIVER is set to an invalid driver"); + return EGL_FALSE; + } + + return EGL_TRUE; } /** - * Open a preloaded driver. + * Preload display drivers. + * + * Display drivers are a set of drivers that support a certain display system. + * The display system may be specified by EGL_DISPLAY. + * + * FIXME This makes libEGL a memory hog if an user driver is not specified and + * there are many display drivers. */ -_EGLDriver * -_eglOpenDriver(_EGLDisplay *dpy) +static EGLBoolean +_eglPreloadDisplayDrivers(void) { - _EGLDriver *drv = _eglMatchDriver(dpy); - return drv; + const char *dpy; + char prefix[32]; + int ret; + + dpy = getenv("EGL_DISPLAY"); + if (!dpy || !dpy[0]) + dpy = _EGL_DEFAULT_DISPLAY; + if (!dpy || !dpy[0]) + return EGL_FALSE; + + ret = snprintf(prefix, sizeof(prefix), "egl_%s_", dpy); + if (ret < 0 || ret >= sizeof(prefix)) + return EGL_FALSE; + + return (_eglPreloadForEach(_eglGetSearchPath(), + _eglLoaderPattern, (void *) prefix) > 0); +} + + +/** + * Preload the default driver. + */ +static EGLBoolean +_eglPreloadDefaultDriver(void) +{ + return (_eglPreloadForEach(_eglGetSearchPath(), + _eglLoaderFile, (void *) DefaultDriverName) > 0); } /** - * Close a preloaded driver. + * Preload drivers. + * + * This function loads the driver modules and creates the corresponding + * _EGLDriver objects. */ EGLBoolean -_eglCloseDriver(_EGLDriver *drv, _EGLDisplay *dpy) +_eglPreloadDrivers(void) { - return EGL_TRUE; + EGLBoolean loaded; + + /* already preloaded */ + if (_eglGlobal.NumDrivers) + return EGL_TRUE; + + loaded = (_eglPreloadUserDriver() || + _eglPreloadDisplayDrivers() || + _eglPreloadDefaultDriver()); + + return loaded; } @@ -360,20 +571,6 @@ _eglUnloadDrivers(void) /** - * Given a display handle, return the _EGLDriver for that display. - */ -_EGLDriver * -_eglLookupDriver(EGLDisplay dpy) -{ - _EGLDisplay *d = _eglLookupDisplay(dpy); - if (d) - return d->Driver; - else - return NULL; -} - - -/** * Plug all the available fallback routines into the given driver's * dispatch table. */ @@ -428,56 +625,50 @@ _eglInitDriverFallbacks(_EGLDriver *drv) #ifdef EGL_VERSION_1_2 drv->API.CreatePbufferFromClientBuffer = _eglCreatePbufferFromClientBuffer; #endif /* EGL_VERSION_1_2 */ -} +#ifdef EGL_KHR_image_base + drv->API.CreateImageKHR = _eglCreateImageKHR; + drv->API.DestroyImageKHR = _eglDestroyImageKHR; +#endif /* EGL_KHR_image_base */ +} /** - * Try to determine which EGL APIs (OpenGL, OpenGL ES, OpenVG, etc) - * are supported on the system by looking for standard library names. + * Set the probe cache at the given key. + * + * A key, instead of a _EGLDriver, is used to allow the probe cache to be share + * by multiple drivers. */ -EGLint -_eglFindAPIs(void) +void +_eglSetProbeCache(EGLint key, const void *val) { - EGLint mask = 0x0; - lib_handle lib; -#if defined(_EGL_PLATFORM_WINDOWS) - /* XXX not sure about these names */ - const char *es1_libname = "libGLESv1_CM.dll"; - const char *es2_libname = "libGLESv2.dll"; - const char *gl_libname = "OpenGL32.dll"; - const char *vg_libname = "libOpenVG.dll"; -#elif defined(_EGL_PLATFORM_X) - const char *es1_libname = "libGLESv1_CM.so"; - const char *es2_libname = "libGLESv2.so"; - const char *gl_libname = "libGL.so"; - const char *vg_libname = "libOpenVG.so"; -#else /* _EGL_PLATFORM_NO_OS */ - const char *es1_libname = NULL; - const char *es2_libname = NULL; - const char *gl_libname = NULL; - const char *vg_libname = NULL; -#endif + EGLint idx; - if ((lib = open_library(es1_libname))) { - close_library(lib); - mask |= EGL_OPENGL_ES_BIT; + for (idx = 0; idx < NUM_PROBE_CACHE_SLOTS; idx++) { + if (!_eglProbeCache.keys[idx] || _eglProbeCache.keys[idx] == key) + break; } + assert(key > 0); + assert(idx < NUM_PROBE_CACHE_SLOTS); - if ((lib = open_library(es2_libname))) { - close_library(lib); - mask |= EGL_OPENGL_ES2_BIT; - } + _eglProbeCache.keys[idx] = key; + _eglProbeCache.values[idx] = val; +} - if ((lib = open_library(gl_libname))) { - close_library(lib); - mask |= EGL_OPENGL_BIT; - } - if ((lib = open_library(vg_libname))) { - close_library(lib); - mask |= EGL_OPENVG_BIT; +/** + * Return the probe cache at the given key. + */ +const void * +_eglGetProbeCache(EGLint key) +{ + EGLint idx; + + for (idx = 0; idx < NUM_PROBE_CACHE_SLOTS; idx++) { + if (!_eglProbeCache.keys[idx] || _eglProbeCache.keys[idx] == key) + break; } - return mask; + return (idx < NUM_PROBE_CACHE_SLOTS && _eglProbeCache.keys[idx] == key) ? + _eglProbeCache.values[idx] : NULL; } diff --git a/src/egl/main/egldriver.h b/src/egl/main/egldriver.h index 59bd1954aa8..55686681dcb 100644 --- a/src/egl/main/egldriver.h +++ b/src/egl/main/egldriver.h @@ -7,6 +7,36 @@ /** + * Define an inline driver typecast function. + * + * Note that this macro defines a function and should not be ended with a + * semicolon when used. + */ +#define _EGL_DRIVER_TYPECAST(drvtype, egltype, code) \ + static INLINE struct drvtype *drvtype(const egltype *obj) \ + { return (struct drvtype *) code; } + + +/** + * Define the driver typecast functions for _EGLDriver, _EGLDisplay, + * _EGLContext, _EGLSurface, and _EGLConfig. + * + * Note that this macro defines several functions and should not be ended with + * a semicolon when used. + */ +#define _EGL_DRIVER_STANDARD_TYPECASTS(drvname) \ + _EGL_DRIVER_TYPECAST(drvname ## _driver, _EGLDriver, obj) \ + /* note that this is not a direct cast */ \ + _EGL_DRIVER_TYPECAST(drvname ## _display, _EGLDisplay, obj->DriverData) \ + _EGL_DRIVER_TYPECAST(drvname ## _context, _EGLContext, obj) \ + _EGL_DRIVER_TYPECAST(drvname ## _surface, _EGLSurface, obj) \ + _EGL_DRIVER_TYPECAST(drvname ## _config, _EGLConfig, obj) + + +typedef _EGLDriver *(*_EGLMain_t)(const char *args); + + +/** * Base class for device drivers. */ struct _egl_driver @@ -16,9 +46,22 @@ struct _egl_driver const char *Args; /**< args to load this driver */ const char *Name; /**< name of this driver */ - /**< probe a display to see if it is supported */ - EGLBoolean (*Probe)(_EGLDriver *drv, _EGLDisplay *dpy); - /**< called before dlclose to release this driver */ + + /** + * Probe a display and return a score. + * + * Roughly, + * 50 means the driver supports the display; + * 90 means the driver can accelerate the display; + * 100 means a perfect match. + */ + EGLint (*Probe)(_EGLDriver *drv, _EGLDisplay *dpy); + + /** + * Release the driver resource. + * + * It is called before dlclose(). + */ void (*Unload)(_EGLDriver *drv); _EGLAPI API; /**< EGL API dispatch table */ @@ -29,32 +72,28 @@ PUBLIC _EGLDriver * _eglMain(const char *args); -extern const char * -_eglPreloadDriver(_EGLDisplay *dpy); - - extern _EGLDriver * -_eglOpenDriver(_EGLDisplay *dpy); +_eglMatchDriver(_EGLDisplay *dpy); extern EGLBoolean -_eglCloseDriver(_EGLDriver *drv, _EGLDisplay *dpy); +_eglPreloadDrivers(void); -void +extern void _eglUnloadDrivers(void); -extern _EGLDriver * -_eglLookupDriver(EGLDisplay d); +PUBLIC void +_eglInitDriverFallbacks(_EGLDriver *drv); PUBLIC void -_eglInitDriverFallbacks(_EGLDriver *drv); +_eglSetProbeCache(EGLint key, const void *val); -PUBLIC EGLint -_eglFindAPIs(void); +PUBLIC const void * +_eglGetProbeCache(EGLint key); #endif /* EGLDRIVER_INCLUDED */ diff --git a/src/egl/main/eglglobals.c b/src/egl/main/eglglobals.c index 443d0f072cf..5182b18e226 100644 --- a/src/egl/main/eglglobals.c +++ b/src/egl/main/eglglobals.c @@ -1,8 +1,8 @@ #include <stdlib.h> #include <assert.h> #include "eglglobals.h" +#include "egldisplay.h" #include "egldriver.h" -#include "egllog.h" #include "eglmutex.h" diff --git a/src/egl/main/eglglobals.h b/src/egl/main/eglglobals.h index 5ebb914ca72..cd1dd5851b9 100644 --- a/src/egl/main/eglglobals.h +++ b/src/egl/main/eglglobals.h @@ -1,9 +1,8 @@ #ifndef EGLGLOBALS_INCLUDED #define EGLGLOBALS_INCLUDED + #include "egltypedefs.h" -#include "egldisplay.h" -#include "eglcurrent.h" #include "eglmutex.h" diff --git a/src/egl/main/eglimage.c b/src/egl/main/eglimage.c new file mode 100644 index 00000000000..5732ef35ecd --- /dev/null +++ b/src/egl/main/eglimage.c @@ -0,0 +1,90 @@ +#include <assert.h> +#include <string.h> + +#include "eglimage.h" +#include "eglcurrent.h" +#include "egllog.h" + + +#ifdef EGL_KHR_image_base + + +/** + * Parse the list of image attributes and return the proper error code. + */ +static EGLint +_eglParseImageAttribList(_EGLImage *img, const EGLint *attrib_list) +{ + EGLint i, err = EGL_SUCCESS; + + if (!attrib_list) + return EGL_SUCCESS; + + for (i = 0; attrib_list[i] != EGL_NONE; i++) { + EGLint attr = attrib_list[i++]; + EGLint val = attrib_list[i]; + + switch (attr) { + case EGL_IMAGE_PRESERVED_KHR: + img->Preserved = val; + break; + case EGL_GL_TEXTURE_LEVEL_KHR: + img->GLTextureLevel = val; + break; + case EGL_GL_TEXTURE_ZOFFSET_KHR: + img->GLTextureZOffset = val; + break; + default: + /* unknown attrs are ignored */ + break; + } + + if (err != EGL_SUCCESS) { + _eglLog(_EGL_DEBUG, "bad image attribute 0x%04x", attr); + break; + } + } + + return err; +} + + +EGLBoolean +_eglInitImage(_EGLImage *img, _EGLDisplay *dpy, const EGLint *attrib_list) +{ + EGLint err; + + memset(img, 0, sizeof(_EGLImage)); + img->Resource.Display = dpy; + + img->Preserved = EGL_FALSE; + img->GLTextureLevel = 0; + img->GLTextureZOffset = 0; + + err = _eglParseImageAttribList(img, attrib_list); + if (err != EGL_SUCCESS) + return _eglError(err, "eglCreateImageKHR"); + + return EGL_TRUE; +} + + +_EGLImage * +_eglCreateImageKHR(_EGLDriver *drv, _EGLDisplay *dpy, _EGLContext *ctx, + EGLenum target, EGLClientBuffer buffer, + const EGLint *attr_list) +{ + /* driver should override this function */ + return NULL; +} + + +EGLBoolean +_eglDestroyImageKHR(_EGLDriver *drv, _EGLDisplay *dpy, _EGLImage *image) +{ + /* driver should override this function */ + return EGL_FALSE; +} + + +#endif /* EGL_KHR_image_base */ diff --git a/src/egl/main/eglimage.h b/src/egl/main/eglimage.h new file mode 100644 index 00000000000..2c0fb16d1d3 --- /dev/null +++ b/src/egl/main/eglimage.h @@ -0,0 +1,96 @@ +#ifndef EGLIMAGE_INCLUDED +#define EGLIMAGE_INCLUDED + + +#include "egltypedefs.h" +#include "egldisplay.h" + + +/** + * "Base" class for device driver images. + */ +struct _egl_image +{ + /* An image is a display resource */ + _EGLResource Resource; + + EGLBoolean Preserved; + EGLint GLTextureLevel; + EGLint GLTextureZOffset; +}; + + +PUBLIC EGLBoolean +_eglInitImage(_EGLImage *img, _EGLDisplay *dpy, const EGLint *attrib_list); + + +extern _EGLImage * +_eglCreateImageKHR(_EGLDriver *drv, _EGLDisplay *dpy, _EGLContext *ctx, + EGLenum target, EGLClientBuffer buffer, const EGLint *attr_list); + + +extern EGLBoolean +_eglDestroyImageKHR(_EGLDriver *drv, _EGLDisplay *dpy, _EGLImage *image); + + +/** + * Link an image to a display and return the handle of the link. + * The handle can be passed to client directly. + */ +static INLINE EGLImageKHR +_eglLinkImage(_EGLImage *img, _EGLDisplay *dpy) +{ + _eglLinkResource(&img->Resource, _EGL_RESOURCE_IMAGE, dpy); + return (EGLImageKHR) img; +} + + +/** + * Unlink a linked image from its display. + * Accessing an unlinked image should generate EGL_BAD_PARAMETER error. + */ +static INLINE void +_eglUnlinkImage(_EGLImage *img) +{ + _eglUnlinkResource(&img->Resource, _EGL_RESOURCE_IMAGE); +} + + +/** + * Lookup a handle to find the linked image. + * Return NULL if the handle has no corresponding linked image. + */ +static INLINE _EGLImage * +_eglLookupImage(EGLImageKHR image, _EGLDisplay *dpy) +{ + _EGLImage *img = (_EGLImage *) image; + if (!dpy || !_eglCheckResource((void *) img, _EGL_RESOURCE_IMAGE, dpy)) + img = NULL; + return img; +} + + +/** + * Return the handle of a linked image, or EGL_NO_IMAGE_KHR. + */ +static INLINE EGLImageKHR +_eglGetImageHandle(_EGLImage *img) +{ + _EGLResource *res = (_EGLResource *) img; + return (res && _eglIsResourceLinked(res)) ? + (EGLImageKHR) img : EGL_NO_IMAGE_KHR; +} + + +/** + * Return true if the image is linked to a display. + */ +static INLINE EGLBoolean +_eglIsImageLinked(_EGLImage *img) +{ + _EGLResource *res = (_EGLResource *) img; + return (res && _eglIsResourceLinked(res)); +} + + +#endif /* EGLIMAGE_INCLUDED */ diff --git a/src/egl/main/egllog.h b/src/egl/main/egllog.h index 3a99bfea4b7..03bef2670f1 100644 --- a/src/egl/main/egllog.h +++ b/src/egl/main/egllog.h @@ -1,8 +1,10 @@ #ifndef EGLLOG_INCLUDED #define EGLLOG_INCLUDED + #include "egltypedefs.h" + #define _EGL_FATAL 0 /* unrecoverable error */ #define _EGL_WARNING 1 /* recoverable error/problem */ #define _EGL_INFO 2 /* just useful info */ diff --git a/src/egl/main/eglmisc.c b/src/egl/main/eglmisc.c index e66913320b2..984e426686e 100644 --- a/src/egl/main/eglmisc.c +++ b/src/egl/main/eglmisc.c @@ -33,28 +33,70 @@ #include <assert.h> #include <string.h> -#include "eglglobals.h" +#include "eglcurrent.h" #include "eglmisc.h" #include "egldisplay.h" /** + * Copy the extension into the string and update the string pointer. + */ +static EGLint +_eglAppendExtension(char **str, const char *ext) +{ + char *s = *str; + EGLint len = strlen(ext); + + if (s) { + memcpy(s, ext, len); + s[len++] = ' '; + s[len] = '\0'; + + *str += len; + } + else { + len++; + } + + return len; +} + + +/** * Examine the individual extension enable/disable flags and recompute * the driver's Extensions string. */ static void _eglUpdateExtensionsString(_EGLDisplay *dpy) { +#define _EGL_CHECK_EXTENSION(ext) \ + do { \ + if (dpy->Extensions.ext) { \ + _eglAppendExtension(&exts, "EGL_" #ext); \ + assert(exts <= dpy->Extensions.String + _EGL_MAX_EXTENSIONS_LEN); \ + } \ + } while (0) + char *exts = dpy->Extensions.String; if (exts[0]) return; - if (dpy->Extensions.MESA_screen_surface) - strcat(exts, "EGL_MESA_screen_surface "); - if (dpy->Extensions.MESA_copy_context) - strcat(exts, "EGL_MESA_copy_context "); - assert(strlen(exts) < _EGL_MAX_EXTENSIONS_LEN); + _EGL_CHECK_EXTENSION(MESA_screen_surface); + _EGL_CHECK_EXTENSION(MESA_copy_context); + + _EGL_CHECK_EXTENSION(KHR_image_base); + _EGL_CHECK_EXTENSION(KHR_image_pixmap); + if (dpy->Extensions.KHR_image_base && dpy->Extensions.KHR_image_pixmap) + _eglAppendExtension(&exts, "EGL_KHR_image"); + + _EGL_CHECK_EXTENSION(KHR_vg_parent_image); + _EGL_CHECK_EXTENSION(KHR_gl_texture_2D_image); + _EGL_CHECK_EXTENSION(KHR_gl_texture_cubemap_image); + _EGL_CHECK_EXTENSION(KHR_gl_texture_3D_image); + _EGL_CHECK_EXTENSION(KHR_gl_renderbuffer_image); + +#undef _EGL_CHECK_EXTENSION } diff --git a/src/egl/main/eglmisc.h b/src/egl/main/eglmisc.h index 829d4cde792..5e6a2d41df6 100644 --- a/src/egl/main/eglmisc.h +++ b/src/egl/main/eglmisc.h @@ -29,7 +29,8 @@ #ifndef EGLMISC_INCLUDED #define EGLMISC_INCLUDED -#include "egldriver.h" + +#include "egltypedefs.h" extern const char * diff --git a/src/egl/main/eglmode.c b/src/egl/main/eglmode.c index 0f3ba6e5c08..66446c0495d 100644 --- a/src/egl/main/eglmode.c +++ b/src/egl/main/eglmode.c @@ -1,4 +1,3 @@ -#include <stdio.h> #include <assert.h> #include <stdlib.h> #include <string.h> @@ -6,29 +5,14 @@ #include "egldisplay.h" #include "egldriver.h" #include "eglmode.h" -#include "eglglobals.h" +#include "eglcurrent.h" #include "eglscreen.h" +#include "eglstring.h" #define MIN2(A, B) (((A) < (B)) ? (A) : (B)) -static char * -my_strdup(const char *s) -{ - if (s) { - int l = strlen(s); - char *s2 = malloc(l + 1); - if (s2) - strcpy(s2, s); - return s2; - } - else { - return NULL; - } -} - - /** * Given an EGLModeMESA handle, return the corresponding _EGLMode object * or null if non-existant. @@ -82,7 +66,7 @@ _eglAddNewMode(_EGLScreen *screen, EGLint width, EGLint height, screen->Modes[n].RefreshRate = refreshRate; screen->Modes[n].Optimal = EGL_FALSE; screen->Modes[n].Interlaced = EGL_FALSE; - screen->Modes[n].Name = my_strdup(name); + screen->Modes[n].Name = _eglstrdup(name); screen->NumModes++; return screen->Modes + n; } @@ -366,41 +350,3 @@ _eglQueryModeStringMESA(_EGLDriver *drv, _EGLDisplay *dpy, _EGLMode *m) { return m->Name; } - - -#if 0 -static int -_eglRand(int max) -{ - return rand() % max; -} - -void -_eglTestModeModule(void) -{ - EGLint count = 30; - _EGLMode *modes = (_EGLMode *) malloc(count * sizeof(_EGLMode)); - _EGLMode **modeList = (_EGLMode **) malloc(count * sizeof(_EGLMode*)); - EGLint i; - - for (i = 0; i < count; i++) { - modes[i].Handle = _eglRand(20); - modes[i].Width = 512 + 256 * _eglRand(2); - modes[i].Height = 512 + 256 * _eglRand(2); - modes[i].RefreshRate = 50 + 5 * _eglRand(3); - modes[i].Interlaced = _eglRand(2); - modes[i].Optimal = _eglRand(4) == 0; - modeList[i] = modes + i; - } - - /* sort array of pointers */ - qsort(modeList, count, sizeof(_EGLMode *), compareModes); - - for (i = 0; i < count; i++) { - _EGLMode *m = modeList[i]; - printf("%2d: %3d %4d x %4d @ %3d opt %d int %d\n", i, - m->Handle, m->Width, m->Height, m->RefreshRate, - m->Optimal, m->Interlaced); - } -} -#endif diff --git a/src/egl/main/eglscreen.c b/src/egl/main/eglscreen.c index 14a1e9f8fe3..97a405a4b4b 100644 --- a/src/egl/main/eglscreen.c +++ b/src/egl/main/eglscreen.c @@ -17,6 +17,7 @@ #include "egldisplay.h" #include "eglglobals.h" +#include "eglcurrent.h" #include "eglmode.h" #include "eglconfig.h" #include "eglsurface.h" @@ -110,27 +111,12 @@ _eglGetScreensMESA(_EGLDriver *drv, _EGLDisplay *display, EGLScreenMESA *screens /** - * Example function - drivers should do a proper implementation. + * Drivers should do a proper implementation. */ _EGLSurface * _eglCreateScreenSurfaceMESA(_EGLDriver *drv, _EGLDisplay *dpy, _EGLConfig *conf, const EGLint *attrib_list) { -#if 0 /* THIS IS JUST EXAMPLE CODE */ - _EGLSurface *surf; - - surf = (_EGLSurface *) calloc(1, sizeof(_EGLSurface)); - if (!surf) - return NULL; - - if (!_eglInitSurface(drv, surf, EGL_SCREEN_BIT_MESA, - conf, attrib_list)) { - free(surf); - return NULL; - } - - return surf; -#endif return NULL; } diff --git a/src/egl/main/eglscreen.h b/src/egl/main/eglscreen.h index d52e5388c34..c400ac3d15e 100644 --- a/src/egl/main/eglscreen.h +++ b/src/egl/main/eglscreen.h @@ -2,6 +2,9 @@ #define EGLSCREEN_INCLUDED +#include "egltypedefs.h" + + /** * Per-screen information. * Note that an EGL screen doesn't have a size. A screen may be set to diff --git a/src/egl/main/eglsurface.c b/src/egl/main/eglsurface.c index 940a1b760cf..8026a6314d3 100644 --- a/src/egl/main/eglsurface.c +++ b/src/egl/main/eglsurface.c @@ -9,8 +9,7 @@ #include "egldisplay.h" #include "eglcontext.h" #include "eglconfig.h" -#include "egldriver.h" -#include "eglglobals.h" +#include "eglcurrent.h" #include "egllog.h" #include "eglsurface.h" @@ -32,23 +31,168 @@ _eglClampSwapInterval(_EGLSurface *surf, EGLint interval) /** + * Parse the list of surface attributes and return the proper error code. + */ +static EGLint +_eglParseSurfaceAttribList(_EGLSurface *surf, const EGLint *attrib_list) +{ + EGLint type = surf->Type; + EGLint i, err = EGL_SUCCESS; + + if (!attrib_list) + return EGL_SUCCESS; + + for (i = 0; attrib_list[i] != EGL_NONE; i++) { + EGLint attr = attrib_list[i++]; + EGLint val = attrib_list[i]; + + switch (attr) { + /* common (except for screen surfaces) attributes */ + case EGL_VG_COLORSPACE: + if (type == EGL_SCREEN_BIT_MESA) { + err = EGL_BAD_ATTRIBUTE; + break; + } + switch (val) { + case EGL_VG_COLORSPACE_sRGB: + case EGL_VG_COLORSPACE_LINEAR: + break; + default: + err = EGL_BAD_ATTRIBUTE; + break; + } + if (err != EGL_SUCCESS) + break; + surf->VGColorspace = val; + break; + case EGL_VG_ALPHA_FORMAT: + if (type == EGL_SCREEN_BIT_MESA) { + err = EGL_BAD_ATTRIBUTE; + break; + } + switch (val) { + case EGL_VG_ALPHA_FORMAT_NONPRE: + case EGL_VG_ALPHA_FORMAT_PRE: + break; + default: + err = EGL_BAD_ATTRIBUTE; + break; + } + if (err != EGL_SUCCESS) + break; + surf->VGAlphaFormat = val; + break; + /* window surface attributes */ + case EGL_RENDER_BUFFER: + if (type != EGL_WINDOW_BIT) { + err = EGL_BAD_ATTRIBUTE; + break; + } + if (val != EGL_BACK_BUFFER && val != EGL_SINGLE_BUFFER) { + err = EGL_BAD_ATTRIBUTE; + break; + } + surf->RenderBuffer = val; + break; + /* pbuffer surface attributes */ + case EGL_WIDTH: + if (type != EGL_PBUFFER_BIT && type != EGL_SCREEN_BIT_MESA) { + err = EGL_BAD_ATTRIBUTE; + break; + } + if (val < 0) { + err = EGL_BAD_PARAMETER; + break; + } + surf->Width = val; + break; + case EGL_HEIGHT: + if (type != EGL_PBUFFER_BIT && type != EGL_SCREEN_BIT_MESA) { + err = EGL_BAD_ATTRIBUTE; + break; + } + if (val < 0) { + err = EGL_BAD_PARAMETER; + break; + } + surf->Height = val; + break; + case EGL_LARGEST_PBUFFER: + if (type != EGL_PBUFFER_BIT) { + err = EGL_BAD_ATTRIBUTE; + break; + } + surf->LargestPbuffer = !!val; + break; + case EGL_TEXTURE_FORMAT: + if (type != EGL_PBUFFER_BIT) { + err = EGL_BAD_ATTRIBUTE; + break; + } + switch (val) { + case EGL_TEXTURE_RGB: + case EGL_TEXTURE_RGBA: + case EGL_NO_TEXTURE: + break; + default: + err = EGL_BAD_ATTRIBUTE; + break; + } + if (err != EGL_SUCCESS) + break; + surf->TextureFormat = val; + break; + case EGL_TEXTURE_TARGET: + if (type != EGL_PBUFFER_BIT) { + err = EGL_BAD_ATTRIBUTE; + break; + } + switch (val) { + case EGL_TEXTURE_2D: + case EGL_NO_TEXTURE: + break; + default: + err = EGL_BAD_ATTRIBUTE; + break; + } + if (err != EGL_SUCCESS) + break; + surf->TextureTarget = val; + break; + case EGL_MIPMAP_TEXTURE: + if (type != EGL_PBUFFER_BIT) { + err = EGL_BAD_ATTRIBUTE; + break; + } + surf->MipmapTexture = !!val; + break; + /* no pixmap surface specific attributes */ + default: + err = EGL_BAD_ATTRIBUTE; + break; + } + + if (err != EGL_SUCCESS) { + _eglLog(_EGL_WARNING, "bad surface attribute 0x%04x", attr); + break; + } + } + + return err; +} + + +/** * Do error check on parameters and initialize the given _EGLSurface object. * \return EGL_TRUE if no errors, EGL_FALSE otherwise. */ EGLBoolean -_eglInitSurface(_EGLDriver *drv, _EGLSurface *surf, EGLint type, +_eglInitSurface(_EGLSurface *surf, _EGLDisplay *dpy, EGLint type, _EGLConfig *conf, const EGLint *attrib_list) { const char *func; - EGLint width = 0, height = 0, largest = 0; - EGLint texFormat = EGL_NO_TEXTURE, texTarget = EGL_NO_TEXTURE; - EGLint mipmapTex = EGL_FALSE; EGLint renderBuffer = EGL_BACK_BUFFER; -#ifdef EGL_VERSION_1_2 - EGLint colorspace = EGL_COLORSPACE_sRGB; - EGLint alphaFormat = EGL_ALPHA_FORMAT_NONPRE; -#endif - EGLint i; + EGLint err; switch (type) { case EGL_WINDOW_BIT: @@ -70,158 +214,41 @@ _eglInitSurface(_EGLDriver *drv, _EGLSurface *surf, EGLint type, return EGL_FALSE; } - if (!conf) { - _eglError(EGL_BAD_CONFIG, func); - return EGL_FALSE; - } - if ((GET_CONFIG_ATTRIB(conf, EGL_SURFACE_TYPE) & type) == 0) { /* The config can't be used to create a surface of this type */ _eglError(EGL_BAD_CONFIG, func); return EGL_FALSE; } - /* - * Parse attribute list. Different kinds of surfaces support different - * attributes. - */ - for (i = 0; attrib_list && attrib_list[i] != EGL_NONE; i++) { - switch (attrib_list[i]) { - case EGL_WIDTH: - if (type == EGL_PBUFFER_BIT || type == EGL_SCREEN_BIT_MESA) { - width = attrib_list[++i]; - } - else { - _eglError(EGL_BAD_ATTRIBUTE, func); - return EGL_FALSE; - } - break; - case EGL_HEIGHT: - if (type == EGL_PBUFFER_BIT || type == EGL_SCREEN_BIT_MESA) { - height = attrib_list[++i]; - } - else { - _eglError(EGL_BAD_ATTRIBUTE, func); - return EGL_FALSE; - } - break; - case EGL_LARGEST_PBUFFER: - if (type == EGL_PBUFFER_BIT) { - largest = attrib_list[++i]; - } - else { - _eglError(EGL_BAD_ATTRIBUTE, func); - return EGL_FALSE; - } - break; - case EGL_TEXTURE_FORMAT: - if (type == EGL_PBUFFER_BIT) { - texFormat = attrib_list[++i]; - } - else { - _eglError(EGL_BAD_ATTRIBUTE, func); - return EGL_FALSE; - } - break; - case EGL_TEXTURE_TARGET: - if (type == EGL_PBUFFER_BIT) { - texTarget = attrib_list[++i]; - } - else { - _eglError(EGL_BAD_ATTRIBUTE, func); - return EGL_FALSE; - } - break; - case EGL_MIPMAP_TEXTURE: - if (type == EGL_PBUFFER_BIT) { - mipmapTex = attrib_list[++i]; - } - else { - _eglError(EGL_BAD_ATTRIBUTE, func); - return EGL_FALSE; - } - break; -#ifdef EGL_VERSION_1_2 - case EGL_RENDER_BUFFER: - if (type == EGL_WINDOW_BIT) { - renderBuffer = attrib_list[++i]; - if (renderBuffer != EGL_BACK_BUFFER && - renderBuffer != EGL_SINGLE_BUFFER) { - _eglError(EGL_BAD_ATTRIBUTE, func); - return EGL_FALSE; - } - } - else { - _eglError(EGL_BAD_ATTRIBUTE, func); - return EGL_FALSE; - } - break; - case EGL_COLORSPACE: - if (type == EGL_WINDOW_BIT || - type == EGL_PBUFFER_BIT || - type == EGL_PIXMAP_BIT) { - colorspace = attrib_list[++i]; - if (colorspace != EGL_COLORSPACE_sRGB && - colorspace != EGL_COLORSPACE_LINEAR) { - _eglError(EGL_BAD_ATTRIBUTE, func); - return EGL_FALSE; - } - } - else { - _eglError(EGL_BAD_ATTRIBUTE, func); - return EGL_FALSE; - } - break; - case EGL_ALPHA_FORMAT: - if (type == EGL_WINDOW_BIT || - type == EGL_PBUFFER_BIT || - type == EGL_PIXMAP_BIT) { - alphaFormat = attrib_list[++i]; - if (alphaFormat != EGL_ALPHA_FORMAT_NONPRE && - alphaFormat != EGL_ALPHA_FORMAT_PRE) { - _eglError(EGL_BAD_ATTRIBUTE, func); - return EGL_FALSE; - } - } - else { - _eglError(EGL_BAD_ATTRIBUTE, func); - return EGL_FALSE; - } - break; - -#endif /* EGL_VERSION_1_2 */ - default: - _eglError(EGL_BAD_ATTRIBUTE, func); - return EGL_FALSE; - } - } - - if (width < 0 || height < 0) { - _eglError(EGL_BAD_ATTRIBUTE, func); - return EGL_FALSE; - } - memset(surf, 0, sizeof(_EGLSurface)); - surf->Config = conf; + surf->Resource.Display = dpy; surf->Type = type; - surf->Width = width; - surf->Height = height; - surf->TextureFormat = texFormat; - surf->TextureTarget = texTarget; - surf->MipmapTexture = mipmapTex; + surf->Config = conf; + + surf->Width = 0; + surf->Height = 0; + surf->TextureFormat = EGL_NO_TEXTURE; + surf->TextureTarget = EGL_NO_TEXTURE; + surf->MipmapTexture = EGL_FALSE; + surf->LargestPbuffer = EGL_FALSE; + surf->RenderBuffer = renderBuffer; + surf->VGAlphaFormat = EGL_VG_ALPHA_FORMAT_NONPRE; + surf->VGColorspace = EGL_VG_COLORSPACE_sRGB; + surf->MipmapLevel = 0; + surf->MultisampleResolve = EGL_MULTISAMPLE_RESOLVE_DEFAULT; + surf->SwapBehavior = EGL_BUFFER_DESTROYED; + + surf->HorizontalResolution = EGL_UNKNOWN; + surf->VerticalResolution = EGL_UNKNOWN; + surf->AspectRatio = EGL_UNKNOWN; + /* the default swap interval is 1 */ _eglClampSwapInterval(surf, 1); -#ifdef EGL_VERSION_1_2 - surf->SwapBehavior = EGL_BUFFER_DESTROYED; /* XXX ok? */ - surf->HorizontalResolution = EGL_UNKNOWN; /* set by caller */ - surf->VerticalResolution = EGL_UNKNOWN; /* set by caller */ - surf->AspectRatio = EGL_UNKNOWN; /* set by caller */ - surf->RenderBuffer = renderBuffer; - surf->AlphaFormat = alphaFormat; - surf->Colorspace = colorspace; -#endif + err = _eglParseSurfaceAttribList(surf, attrib_list); + if (err != EGL_SUCCESS) + return _eglError(err, func); return EGL_TRUE; } @@ -237,7 +264,7 @@ _eglSwapBuffers(_EGLDriver *drv, _EGLDisplay *dpy, _EGLSurface *surf) EGLBoolean _eglCopyBuffers(_EGLDriver *drv, _EGLDisplay *dpy, _EGLSurface *surf, - NativePixmapType target) + EGLNativePixmapType target) { /* copy surface to native pixmap */ /* All implementation burdon for this is in the device driver */ @@ -252,139 +279,95 @@ _eglQuerySurface(_EGLDriver *drv, _EGLDisplay *dpy, _EGLSurface *surface, switch (attribute) { case EGL_WIDTH: *value = surface->Width; - return EGL_TRUE; + break; case EGL_HEIGHT: *value = surface->Height; - return EGL_TRUE; + break; case EGL_CONFIG_ID: *value = GET_CONFIG_ATTRIB(surface->Config, EGL_CONFIG_ID); - return EGL_TRUE; + break; case EGL_LARGEST_PBUFFER: - *value = dpy->LargestPbuffer; - return EGL_TRUE; - case EGL_SURFACE_TYPE: - *value = surface->Type; - return EGL_TRUE; -#ifdef EGL_VERSION_1_1 + *value = surface->LargestPbuffer; + break; case EGL_TEXTURE_FORMAT: /* texture attributes: only for pbuffers, no error otherwise */ if (surface->Type == EGL_PBUFFER_BIT) *value = surface->TextureFormat; - return EGL_TRUE; + break; case EGL_TEXTURE_TARGET: if (surface->Type == EGL_PBUFFER_BIT) *value = surface->TextureTarget; - return EGL_TRUE; + break; case EGL_MIPMAP_TEXTURE: if (surface->Type == EGL_PBUFFER_BIT) *value = surface->MipmapTexture; - return EGL_TRUE; + break; case EGL_MIPMAP_LEVEL: if (surface->Type == EGL_PBUFFER_BIT) *value = surface->MipmapLevel; - return EGL_TRUE; -#endif /* EGL_VERSION_1_1 */ -#ifdef EGL_VERSION_1_2 + break; case EGL_SWAP_BEHAVIOR: *value = surface->SwapBehavior; - return EGL_TRUE; + break; case EGL_RENDER_BUFFER: *value = surface->RenderBuffer; - return EGL_TRUE; + break; case EGL_PIXEL_ASPECT_RATIO: *value = surface->AspectRatio; - return EGL_TRUE; + break; case EGL_HORIZONTAL_RESOLUTION: *value = surface->HorizontalResolution; - return EGL_TRUE; + break; case EGL_VERTICAL_RESOLUTION: *value = surface->VerticalResolution; - return EGL_TRUE; - case EGL_ALPHA_FORMAT: - *value = surface->AlphaFormat; - return EGL_TRUE; - case EGL_COLORSPACE: - *value = surface->Colorspace; - return EGL_TRUE; -#endif /* EGL_VERSION_1_2 */ + break; + case EGL_MULTISAMPLE_RESOLVE: + *value = surface->MultisampleResolve; + break; + case EGL_VG_ALPHA_FORMAT: + *value = surface->VGAlphaFormat; + break; + case EGL_VG_COLORSPACE: + *value = surface->VGColorspace; + break; default: _eglError(EGL_BAD_ATTRIBUTE, "eglQuerySurface"); return EGL_FALSE; } + + return EGL_TRUE; } /** - * Example function - drivers should do a proper implementation. + * Drivers should do a proper implementation. */ _EGLSurface * _eglCreateWindowSurface(_EGLDriver *drv, _EGLDisplay *dpy, _EGLConfig *conf, - NativeWindowType window, const EGLint *attrib_list) + EGLNativeWindowType window, const EGLint *attrib_list) { -#if 0 /* THIS IS JUST EXAMPLE CODE */ - _EGLSurface *surf; - - surf = (_EGLSurface *) calloc(1, sizeof(_EGLSurface)); - if (!surf) - return NULL; - - if (!_eglInitSurface(drv, surf, EGL_WINDOW_BIT, conf, attrib_list)) { - free(surf); - return NULL; - } - - return surf; -#endif return NULL; } /** - * Example function - drivers should do a proper implementation. + * Drivers should do a proper implementation. */ _EGLSurface * _eglCreatePixmapSurface(_EGLDriver *drv, _EGLDisplay *dpy, _EGLConfig *conf, - NativePixmapType pixmap, const EGLint *attrib_list) + EGLNativePixmapType pixmap, const EGLint *attrib_list) { -#if 0 /* THIS IS JUST EXAMPLE CODE */ - _EGLSurface *surf; - - surf = (_EGLSurface *) calloc(1, sizeof(_EGLSurface)); - if (!surf) - return NULL; - - if (!_eglInitSurface(drv, surf, EGL_PIXMAP_BIT, conf, attrib_list)) { - free(surf); - return NULL; - } - - return surf; -#endif return NULL; } /** - * Example function - drivers should do a proper implementation. + * Drivers should do a proper implementation. */ _EGLSurface * _eglCreatePbufferSurface(_EGLDriver *drv, _EGLDisplay *dpy, _EGLConfig *conf, const EGLint *attrib_list) { -#if 0 /* THIS IS JUST EXAMPLE CODE */ - _EGLSurface *surf; - - surf = (_EGLSurface *) calloc(1, sizeof(_EGLSurface)); - if (!surf) - return NULL; - - if (!_eglInitSurface(drv, surf, EGL_PBUFFER_BIT, conf, attrib_list)) { - free(surf); - return NULL; - } - - return NULL; -#endif return NULL; } @@ -408,14 +391,59 @@ EGLBoolean _eglSurfaceAttrib(_EGLDriver *drv, _EGLDisplay *dpy, _EGLSurface *surface, EGLint attribute, EGLint value) { + EGLint confval; + EGLint err = EGL_SUCCESS; + switch (attribute) { case EGL_MIPMAP_LEVEL: + confval = GET_CONFIG_ATTRIB(surface->Config, EGL_RENDERABLE_TYPE); + if (!(confval & (EGL_OPENGL_ES_BIT | EGL_OPENGL_ES2_BIT))) { + err = EGL_BAD_PARAMETER; + break; + } surface->MipmapLevel = value; break; + case EGL_MULTISAMPLE_RESOLVE: + switch (value) { + case EGL_MULTISAMPLE_RESOLVE_DEFAULT: + break; + case EGL_MULTISAMPLE_RESOLVE_BOX: + confval = GET_CONFIG_ATTRIB(surface->Config, EGL_SURFACE_TYPE); + if (!(confval & EGL_MULTISAMPLE_RESOLVE_BOX_BIT)) + err = EGL_BAD_MATCH; + break; + default: + err = EGL_BAD_ATTRIBUTE; + break; + } + if (err != EGL_SUCCESS) + break; + surface->MultisampleResolve = value; + break; + case EGL_SWAP_BEHAVIOR: + switch (value) { + case EGL_BUFFER_DESTROYED: + break; + case EGL_BUFFER_PRESERVED: + confval = GET_CONFIG_ATTRIB(surface->Config, EGL_SURFACE_TYPE); + if (!(confval & EGL_SWAP_BEHAVIOR_PRESERVED_BIT)) + err = EGL_BAD_MATCH; + break; + default: + err = EGL_BAD_ATTRIBUTE; + break; + } + if (err != EGL_SUCCESS) + break; + surface->SwapBehavior = value; + break; default: - _eglError(EGL_BAD_ATTRIBUTE, "eglSurfaceAttrib"); - return EGL_FALSE; + err = EGL_BAD_ATTRIBUTE; + break; } + + if (err != EGL_SUCCESS) + return _eglError(err, "eglSurfaceAttrib"); return EGL_TRUE; } diff --git a/src/egl/main/eglsurface.h b/src/egl/main/eglsurface.h index dacdf7e63ce..0a00035730f 100644 --- a/src/egl/main/eglsurface.h +++ b/src/egl/main/eglsurface.h @@ -3,6 +3,7 @@ #include "egltypedefs.h" +#include "egldisplay.h" /** @@ -10,38 +11,43 @@ */ struct _egl_surface { - /* Managed by EGLDisplay for linking */ - _EGLDisplay *Display; - _EGLSurface *Next; + /* A surface is a display resource */ + _EGLResource Resource; - /* The bound status of the surface */ - _EGLContext *Binding; - EGLBoolean BoundToTexture; + /* The context that is currently bound to the surface */ + _EGLContext *CurrentContext; _EGLConfig *Config; EGLint Type; /* one of EGL_WINDOW_BIT, EGL_PIXMAP_BIT or EGL_PBUFFER_BIT */ - EGLint Width, Height; - EGLint TextureFormat, TextureTarget; - EGLint MipmapTexture, MipmapLevel; - EGLint SwapInterval; - /* If type == EGL_SCREEN_BIT: */ - EGLint VisibleRefCount; /* number of screens I'm displayed on */ + /* attributes set by attribute list */ + EGLint Width, Height; + EGLenum TextureFormat; + EGLenum TextureTarget; + EGLBoolean MipmapTexture; + EGLBoolean LargestPbuffer; + EGLenum RenderBuffer; + EGLenum VGAlphaFormat; + EGLenum VGColorspace; + + /* attributes set by eglSurfaceAttrib */ + EGLint MipmapLevel; + EGLenum MultisampleResolve; + EGLenum SwapBehavior; -#ifdef EGL_VERSION_1_2 - EGLint SwapBehavior; /* one of EGL_BUFFER_PRESERVED/DESTROYED */ EGLint HorizontalResolution, VerticalResolution; EGLint AspectRatio; - EGLint RenderBuffer; /* EGL_BACK_BUFFER or EGL_SINGLE_BUFFER */ - EGLint AlphaFormat; /* EGL_ALPHA_FORMAT_NONPRE or EGL_ALPHA_FORMAT_PRE */ - EGLint Colorspace; /* EGL_COLORSPACE_sRGB or EGL_COLORSPACE_LINEAR */ -#endif /* EGL_VERSION_1_2 */ + + EGLint SwapInterval; + + /* True if the surface is bound to an OpenGL ES texture */ + EGLBoolean BoundToTexture; }; PUBLIC EGLBoolean -_eglInitSurface(_EGLDriver *drv, _EGLSurface *surf, EGLint type, +_eglInitSurface(_EGLSurface *surf, _EGLDisplay *dpy, EGLint type, _EGLConfig *config, const EGLint *attrib_list); @@ -50,7 +56,7 @@ _eglSwapBuffers(_EGLDriver *drv, _EGLDisplay *dpy, _EGLSurface *surf); extern EGLBoolean -_eglCopyBuffers(_EGLDriver *drv, _EGLDisplay *dpy, _EGLSurface *surf, NativePixmapType target); +_eglCopyBuffers(_EGLDriver *drv, _EGLDisplay *dpy, _EGLSurface *surf, EGLNativePixmapType target); extern EGLBoolean @@ -58,11 +64,11 @@ _eglQuerySurface(_EGLDriver *drv, _EGLDisplay *dpy, _EGLSurface *surf, EGLint at extern _EGLSurface * -_eglCreateWindowSurface(_EGLDriver *drv, _EGLDisplay *dpy, _EGLConfig *conf, NativeWindowType window, const EGLint *attrib_list); +_eglCreateWindowSurface(_EGLDriver *drv, _EGLDisplay *dpy, _EGLConfig *conf, EGLNativeWindowType window, const EGLint *attrib_list); extern _EGLSurface * -_eglCreatePixmapSurface(_EGLDriver *drv, _EGLDisplay *dpy, _EGLConfig *conf, NativePixmapType pixmap, const EGLint *attrib_list); +_eglCreatePixmapSurface(_EGLDriver *drv, _EGLDisplay *dpy, _EGLConfig *conf, EGLNativePixmapType pixmap, const EGLint *attrib_list); extern _EGLSurface * @@ -100,14 +106,78 @@ _eglCreatePbufferFromClientBuffer(_EGLDriver *drv, _EGLDisplay *dpy, /** - * Return true if the surface is bound to a thread. - * A surface bound to a texutre is not considered bound by - * this function. + * Return true if there is a context bound to the surface. + * + * The binding is considered a reference to the surface. Drivers should not + * destroy a surface when it is bound. */ static INLINE EGLBoolean _eglIsSurfaceBound(_EGLSurface *surf) { - return (surf->Binding != NULL); + return (surf->CurrentContext != NULL); +} + + +/** + * Link a surface to a display and return the handle of the link. + * The handle can be passed to client directly. + */ +static INLINE EGLSurface +_eglLinkSurface(_EGLSurface *surf, _EGLDisplay *dpy) +{ + _eglLinkResource(&surf->Resource, _EGL_RESOURCE_SURFACE, dpy); + return (EGLSurface) surf; +} + + +/** + * Unlink a linked surface from its display. + * Accessing an unlinked surface should generate EGL_BAD_SURFACE error. + */ +static INLINE void +_eglUnlinkSurface(_EGLSurface *surf) +{ + _eglUnlinkResource(&surf->Resource, _EGL_RESOURCE_SURFACE); +} + + +/** + * Lookup a handle to find the linked surface. + * Return NULL if the handle has no corresponding linked surface. + */ +static INLINE _EGLSurface * +_eglLookupSurface(EGLSurface surface, _EGLDisplay *dpy) +{ + _EGLSurface *surf = (_EGLSurface *) surface; + if (!dpy || !_eglCheckResource((void *) surf, _EGL_RESOURCE_SURFACE, dpy)) + surf = NULL; + return surf; +} + + +/** + * Return the handle of a linked surface, or EGL_NO_SURFACE. + */ +static INLINE EGLSurface +_eglGetSurfaceHandle(_EGLSurface *surf) +{ + _EGLResource *res = (_EGLResource *) surf; + return (res && _eglIsResourceLinked(res)) ? + (EGLSurface) surf : EGL_NO_SURFACE; +} + + +/** + * Return true if the surface is linked to a display. + * + * The link is considered a reference to the surface (the display is owning the + * surface). Drivers should not destroy a surface when it is linked. + */ +static INLINE EGLBoolean +_eglIsSurfaceLinked(_EGLSurface *surf) +{ + _EGLResource *res = (_EGLResource *) surf; + return (res && _eglIsResourceLinked(res)); } diff --git a/src/egl/main/egltypedefs.h b/src/egl/main/egltypedefs.h index 4461440b9b7..e0c95762c67 100644 --- a/src/egl/main/egltypedefs.h +++ b/src/egl/main/egltypedefs.h @@ -8,6 +8,8 @@ #include "eglcompiler.h" +typedef enum _egl_resource_type _EGLResourceType; + typedef struct _egl_api _EGLAPI; typedef struct _egl_config _EGLConfig; @@ -20,16 +22,16 @@ typedef struct _egl_driver _EGLDriver; typedef struct _egl_extensions _EGLExtensions; +typedef struct _egl_image _EGLImage; + typedef struct _egl_mode _EGLMode; +typedef struct _egl_resource _EGLResource; + typedef struct _egl_screen _EGLScreen; typedef struct _egl_surface _EGLSurface; typedef struct _egl_thread_info _EGLThreadInfo; - -typedef _EGLDriver *(*_EGLMain_t)(const char *args); - - #endif /* EGLTYPEDEFS_INCLUDED */ |