diff options
Diffstat (limited to 'src/egl')
54 files changed, 6284 insertions, 1990 deletions
diff --git a/src/egl/Makefile b/src/egl/Makefile index fb4db8f9b9..5b09e178c6 100644 --- a/src/egl/Makefile +++ b/src/egl/Makefile @@ -1,8 +1,9 @@ # src/egl/Makefile TOP = ../.. +include $(TOP)/configs/current -SUBDIRS = main drivers/demo drivers/dri +SUBDIRS = main drivers default: subdirs @@ -15,6 +16,12 @@ subdirs: fi \ done +install: + @for dir in $(SUBDIRS) ; do \ + if [ -d $$dir ] ; then \ + (cd $$dir && $(MAKE) install) || exit 1 ; \ + fi \ + done clean: -@for dir in $(SUBDIRS) ; do \ diff --git a/src/egl/drivers/Makefile b/src/egl/drivers/Makefile new file mode 100644 index 0000000000..dde4ee2255 --- /dev/null +++ b/src/egl/drivers/Makefile @@ -0,0 +1,31 @@ +# src/egl/drivers/Makefile + +TOP = ../../.. +include $(TOP)/configs/current + +SUBDIRS = $(EGL_DRIVERS_DIRS) + + +default: subdirs + + +subdirs: + @for dir in $(SUBDIRS) ; do \ + if [ -d $$dir ] ; then \ + (cd $$dir ; $(MAKE)) || exit 1 ; \ + fi \ + done + +install: + @ for dir in $(SUBDIRS) ; do \ + if [ -d $$dir ] ; then \ + (cd $$dir ; $(MAKE) install) || exit 1 ; \ + fi \ + done + +clean: + @for dir in $(SUBDIRS) ; do \ + if [ -d $$dir ] ; then \ + (cd $$dir ; $(MAKE) clean) ; \ + fi \ + done diff --git a/src/egl/drivers/demo/Makefile b/src/egl/drivers/demo/Makefile index 6ca25aa5d6..444dfb35bd 100644 --- a/src/egl/drivers/demo/Makefile +++ b/src/egl/drivers/demo/Makefile @@ -4,7 +4,7 @@ TOP = ../../../.. include $(TOP)/configs/current -INCLUDE_DIRS = -I$(TOP)/include -I$(TOP)/src/egl/main +INCLUDE_DIRS = -I$(TOP)/include -I$(TOP)/src/egl/main $(X11_INCLUDES) SOURCES = demo.c @@ -25,7 +25,7 @@ $(TOP)/$(LIB_DIR)/demodriver.so: $(OBJECTS) -ldflags '$(LDFLAGS)' -install $(TOP)/$(LIB_DIR) \ $(OBJECTS) - +install: clean: -rm -f *.o diff --git a/src/egl/drivers/demo/demo.c b/src/egl/drivers/demo/demo.c index 45545755c0..aea4894448 100644 --- a/src/egl/drivers/demo/demo.c +++ b/src/egl/drivers/demo/demo.c @@ -21,7 +21,7 @@ typedef struct demo_driver { _EGLDriver Base; /* base class/object */ - GLuint DemoStuff; + unsigned DemoStuff; } DemoDriver; #define DEMO_DRIVER(D) ((DemoDriver *) (D)) @@ -33,7 +33,7 @@ typedef struct demo_driver typedef struct demo_surface { _EGLSurface Base; /* base class/object */ - GLuint DemoStuff; + unsigned DemoStuff; } DemoSurface; @@ -43,15 +43,14 @@ typedef struct demo_surface typedef struct demo_context { _EGLContext Base; /* base class/object */ - GLuint DemoStuff; + unsigned DemoStuff; } DemoContext; static EGLBoolean -demoInitialize(_EGLDriver *drv, EGLDisplay dpy, EGLint *major, EGLint *minor) +demoInitialize(_EGLDriver *drv, _EGLDisplay *disp, EGLint *major, EGLint *minor) { - _EGLDisplay *disp = _eglLookupDisplay(dpy); _EGLScreen *scrn; EGLint i; @@ -67,25 +66,27 @@ demoInitialize(_EGLDriver *drv, EGLDisplay dpy, EGLint *major, EGLint *minor) /* Create the display's visual configs - silly example */ for (i = 0; i < 4; i++) { - _EGLConfig config; - _eglInitConfig(&config, i + 1); - _eglSetConfigAttrib(&config, EGL_RED_SIZE, 8); - _eglSetConfigAttrib(&config, EGL_GREEN_SIZE, 8); - _eglSetConfigAttrib(&config, EGL_BLUE_SIZE, 8); - _eglSetConfigAttrib(&config, EGL_ALPHA_SIZE, 8); - _eglSetConfigAttrib(&config, EGL_BUFFER_SIZE, 32); + _EGLConfig *config = calloc(1, sizeof(_EGLConfig)); + _eglInitConfig(config, i + 1); + _eglSetConfigAttrib(config, EGL_RED_SIZE, 8); + _eglSetConfigAttrib(config, EGL_GREEN_SIZE, 8); + _eglSetConfigAttrib(config, EGL_BLUE_SIZE, 8); + _eglSetConfigAttrib(config, EGL_ALPHA_SIZE, 8); + _eglSetConfigAttrib(config, EGL_BUFFER_SIZE, 32); if (i & 1) { - _eglSetConfigAttrib(&config, EGL_DEPTH_SIZE, 32); + _eglSetConfigAttrib(config, EGL_DEPTH_SIZE, 32); } if (i & 2) { - _eglSetConfigAttrib(&config, EGL_STENCIL_SIZE, 8); + _eglSetConfigAttrib(config, EGL_STENCIL_SIZE, 8); } - _eglSetConfigAttrib(&config, EGL_SURFACE_TYPE, + _eglSetConfigAttrib(config, EGL_SURFACE_TYPE, (EGL_WINDOW_BIT | EGL_PIXMAP_BIT | EGL_PBUFFER_BIT)); - _eglAddConfig(disp, &config); + _eglAddConfig(disp, config); } - drv->Initialized = EGL_TRUE; + /* enable supported extensions */ + disp->Extensions.MESA_screen_surface = EGL_TRUE; + disp->Extensions.MESA_copy_context = EGL_TRUE; *major = 1; *minor = 0; @@ -95,71 +96,56 @@ demoInitialize(_EGLDriver *drv, EGLDisplay dpy, EGLint *major, EGLint *minor) static EGLBoolean -demoTerminate(_EGLDriver *drv, EGLDisplay dpy) +demoTerminate(_EGLDriver *drv, _EGLDisplay *dpy) { /*DemoDriver *demo = DEMO_DRIVER(dpy);*/ - free(drv); return EGL_TRUE; } static DemoContext * -LookupDemoContext(EGLContext ctx) +LookupDemoContext(_EGLContext *c) { - _EGLContext *c = _eglLookupContext(ctx); return (DemoContext *) c; } static DemoSurface * -LookupDemoSurface(EGLSurface surf) +LookupDemoSurface(_EGLSurface *s) { - _EGLSurface *s = _eglLookupSurface(surf); return (DemoSurface *) s; } - -static EGLContext -demoCreateContext(_EGLDriver *drv, EGLDisplay dpy, EGLConfig config, EGLContext share_list, const EGLint *attrib_list) +static _EGLContext * +demoCreateContext(_EGLDriver *drv, _EGLDisplay *dpy, _EGLConfig *conf, _EGLContext *share_list, const EGLint *attrib_list) { - _EGLConfig *conf; DemoContext *c; int i; - conf = _eglLookupConfig(drv, dpy, config); - if (!conf) { - _eglError(EGL_BAD_CONFIG, "eglCreateContext"); - return EGL_NO_CONTEXT; - } - for (i = 0; attrib_list && attrib_list[i] != EGL_NONE; i++) { switch (attrib_list[i]) { /* no attribs defined for now */ default: _eglError(EGL_BAD_ATTRIBUTE, "eglCreateContext"); - return EGL_NO_CONTEXT; + return NULL; } } c = (DemoContext *) calloc(1, sizeof(DemoContext)); if (!c) - return EGL_NO_CONTEXT; + return NULL; - _eglInitContext(drv, dpy, &c->Base, config, attrib_list); + _eglInitContext(drv, &c->Base, conf, attrib_list); c->DemoStuff = 1; printf("demoCreateContext\n"); - /* generate handle and insert into hash table */ - _eglSaveContext(&c->Base); - assert(c->Base.Handle); - - return c->Base.Handle; + return &c->Base; } -static EGLSurface -demoCreateWindowSurface(_EGLDriver *drv, EGLDisplay dpy, EGLConfig config, NativeWindowType window, const EGLint *attrib_list) +static _EGLSurface * +demoCreateWindowSurface(_EGLDriver *drv, _EGLDisplay *dpy, _EGLConfig *conf, NativeWindowType window, const EGLint *attrib_list) { int i; for (i = 0; attrib_list && attrib_list[i] != EGL_NONE; i++) { @@ -167,107 +153,88 @@ demoCreateWindowSurface(_EGLDriver *drv, EGLDisplay dpy, EGLConfig config, Nativ /* no attribs at this time */ default: _eglError(EGL_BAD_ATTRIBUTE, "eglCreateWindowSurface"); - return EGL_NO_SURFACE; + return NULL; } } printf("eglCreateWindowSurface()\n"); /* XXX unfinished */ - return EGL_NO_SURFACE; + return NULL; } -static EGLSurface -demoCreatePixmapSurface(_EGLDriver *drv, EGLDisplay dpy, EGLConfig config, NativePixmapType pixmap, const EGLint *attrib_list) +static _EGLSurface * +demoCreatePixmapSurface(_EGLDriver *drv, _EGLDisplay *dpy, _EGLConfig *conf, NativePixmapType pixmap, const EGLint *attrib_list) { - _EGLConfig *conf; EGLint i; - conf = _eglLookupConfig(drv, dpy, config); - if (!conf) { - _eglError(EGL_BAD_CONFIG, "eglCreatePixmapSurface"); - return EGL_NO_SURFACE; - } - for (i = 0; attrib_list && attrib_list[i] != EGL_NONE; i++) { switch (attrib_list[i]) { /* no attribs at this time */ default: _eglError(EGL_BAD_ATTRIBUTE, "eglCreatePixmapSurface"); - return EGL_NO_SURFACE; + return NULL; } } if (conf->Attrib[EGL_SURFACE_TYPE - FIRST_ATTRIB] == 0) { _eglError(EGL_BAD_MATCH, "eglCreatePixmapSurface"); - return EGL_NO_SURFACE; + return NULL; } printf("eglCreatePixmapSurface()\n"); - return EGL_NO_SURFACE; + return NULL; } -static EGLSurface -demoCreatePbufferSurface(_EGLDriver *drv, EGLDisplay dpy, EGLConfig config, +static _EGLSurface * +demoCreatePbufferSurface(_EGLDriver *drv, _EGLDisplay *dpy, _EGLConfig *conf, const EGLint *attrib_list) { DemoSurface *surf = (DemoSurface *) calloc(1, sizeof(DemoSurface)); + if (!surf) - return EGL_NO_SURFACE; + return NULL; - if (!_eglInitSurface(drv, dpy, &surf->Base, EGL_PBUFFER_BIT, - config, attrib_list)) { + if (!_eglInitSurface(drv, &surf->Base, EGL_PBUFFER_BIT, + conf, attrib_list)) { free(surf); - return EGL_NO_SURFACE; + return NULL; } /* a real driver would allocate the pbuffer memory here */ - return surf->Base.Handle; + return &surf->Base; } static EGLBoolean -demoDestroySurface(_EGLDriver *drv, EGLDisplay dpy, EGLSurface surface) +demoDestroySurface(_EGLDriver *drv, _EGLDisplay *dpy, _EGLSurface *surface) { DemoSurface *fs = LookupDemoSurface(surface); - _eglRemoveSurface(&fs->Base); - if (fs->Base.IsBound) { - fs->Base.DeletePending = EGL_TRUE; - } - else { + if (!_eglIsSurfaceBound(&fs->Base)) free(fs); - } return EGL_TRUE; } static EGLBoolean -demoDestroyContext(_EGLDriver *drv, EGLDisplay dpy, EGLContext context) +demoDestroyContext(_EGLDriver *drv, _EGLDisplay *dpy, _EGLContext *context) { DemoContext *fc = LookupDemoContext(context); - _eglRemoveContext(&fc->Base); - if (fc->Base.IsBound) { - fc->Base.DeletePending = EGL_TRUE; - } - else { + if (!_eglIsContextBound(&fc->Base)) free(fc); - } return EGL_TRUE; } static EGLBoolean -demoMakeCurrent(_EGLDriver *drv, EGLDisplay dpy, EGLSurface draw, EGLSurface read, EGLContext context) +demoMakeCurrent(_EGLDriver *drv, _EGLDisplay *dpy, _EGLSurface *drawSurf, _EGLSurface *readSurf, _EGLContext *ctx) { /*DemoDriver *demo = DEMO_DRIVER(dpy);*/ - DemoSurface *readSurf = LookupDemoSurface(read); - DemoSurface *drawSurf = LookupDemoSurface(draw); - DemoContext *ctx = LookupDemoContext(context); EGLBoolean b; - b = _eglMakeCurrent(drv, dpy, draw, read, context); + b = _eglMakeCurrent(drv, dpy, drawSurf, readSurf, ctx); if (!b) return EGL_FALSE; @@ -281,12 +248,19 @@ demoMakeCurrent(_EGLDriver *drv, EGLDisplay dpy, EGLSurface draw, EGLSurface rea } +static void +demoUnload(_EGLDriver *drv) +{ + free(drv); +} + + /** * The bootstrap function. Return a new DemoDriver object and * plug in API functions. */ _EGLDriver * -_eglMain(_EGLDisplay *dpy) +_eglMain(const char *args) { DemoDriver *demo; @@ -308,9 +282,8 @@ _eglMain(_EGLDisplay *dpy) demo->Base.API.DestroySurface = demoDestroySurface; demo->Base.API.DestroyContext = demoDestroyContext; - /* enable supported extensions */ - demo->Base.Extensions.MESA_screen_surface = EGL_TRUE; - demo->Base.Extensions.MESA_copy_context = EGL_TRUE; + demo->Base.Name = "egl/demo"; + demo->Base.Unload = demoUnload; return &demo->Base; } diff --git a/src/egl/drivers/dri/Makefile b/src/egl/drivers/dri/Makefile index af0c40fe2b..7339c97c77 100644 --- a/src/egl/drivers/dri/Makefile +++ b/src/egl/drivers/dri/Makefile @@ -8,7 +8,7 @@ include $(TOP)/configs/current INCLUDE_DIRS = \ -I. \ -I/usr/include \ - -I/usr/include/drm \ + $(shell pkg-config --cflags-only-I libdrm) \ -I$(TOP)/include \ -I$(TOP)/include/GL/internal \ -I$(TOP)/src/mesa \ @@ -29,6 +29,8 @@ SOURCES = egldri.c OBJECTS = $(SOURCES:.c=.o) +DRM_LIB = `pkg-config --libs libdrm` + .c.o: $(CC) -c $(INCLUDE_DIRS) $(CFLAGS) $< -o $@ @@ -44,18 +46,23 @@ library: $(TOP)/$(LIB_DIR)/libEGLdri.so $(TOP)/$(LIB_DIR)/libEGLdri.so: $(OBJECTS) $(MKLIB) -o EGLdri -linker '$(CC)' -ldflags '$(LDFLAGS)' \ -major 1 -minor 0 \ - -install $(TOP)/$(LIB_DIR) -ldl $(OBJECTS) + -install $(TOP)/$(LIB_DIR) -ldl $(OBJECTS) $(LIBS) +install: + $(INSTALL) -d $(DESTDIR)$(INSTALL_LIB_DIR) + $(MINSTALL) $(TOP)/$(LIB_DIR)/libEGLdri.so $(DESTDIR)$(INSTALL_LIB_DIR) clean: -rm -f *.o -rm -f *.so + -rm -f depend depend.bak depend: $(SOURCES) $(HEADERS) @ echo "running $(MKDEP)" + @ rm -f depend @ touch depend $(MKDEP) $(MKDEP_OPTIONS) $(DEFINES) $(INCLUDE_DIRS) \ - $(SOURCES) $(HEADERS) > /dev/null + $(SOURCES) $(HEADERS) >/dev/null 2>/dev/null include depend # DO NOT DELETE diff --git a/src/egl/drivers/dri/egldri.c b/src/egl/drivers/dri/egldri.c index cab0be2bd1..9e400be624 100644 --- a/src/egl/drivers/dri/egldri.c +++ b/src/egl/drivers/dri/egldri.c @@ -1,5 +1,6 @@ /** - * Generic EGL driver for DRI. + * Generic EGL driver for DRI. This is basically an "adaptor" driver + * that allows libEGL to load/use regular DRI drivers. * * This file contains all the code needed to interface DRI-based drivers * with libEGL. @@ -23,6 +24,7 @@ #include "egldisplay.h" #include "eglcontext.h" #include "eglconfig.h" +#include "eglconfigutil.h" #include "eglsurface.h" #include "eglscreen.h" #include "eglglobals.h" @@ -32,18 +34,72 @@ #include "egldri.h" const char *sysfs = "/sys/class"; -#define None 0 + static const int empty_attribute_list[1] = { None }; + +/** + * Given a card number, return the name of the DRI driver to use. + * This generally means reading the contents of + * /sys/class/drm/cardX/dri_library_name, where X is the card number + */ +static EGLBoolean +driver_name_from_card_number(int card, char *driverName, int maxDriverName) +{ + char path[2000]; + FILE *f; + int length; + + snprintf(path, sizeof(path), "%s/drm/card%d/dri_library_name", sysfs, card); + + f = fopen(path, "r"); + if (!f) + return EGL_FALSE; + + fgets(driverName, maxDriverName, f); + fclose(f); + + if ((length = strlen(driverName)) > 1) { + /* remove the trailing newline from sysfs */ + driverName[length - 1] = '\0'; + strncat(driverName, "_dri", maxDriverName); + return EGL_TRUE; + } + else { + return EGL_FALSE; + } +} + + + /** * The bootstrap function. * Return a new driDriver object and plug in API functions. * This function, in turn, loads a specific DRI driver (ex: r200_dri.so). */ _EGLDriver * -_eglMain(_EGLDisplay *dpy) +_eglMain(_EGLDisplay *dpy, const char *args) { +#if 1 + const int card = args ? atoi(args) : 0; + _EGLDriver *driver = NULL; + char driverName[1000]; + + if (!driver_name_from_card_number(card, driverName, sizeof(driverName))) { + _eglLog(_EGL_WARNING, + "Unable to determine driver name for card %d\n", card); + return NULL; + } + + _eglLog(_EGL_DEBUG, "Driver name: %s\n", driverName); + + driver = _eglOpenDriver(dpy, driverName, args); + + return driver; + +#else + int length; char path[NAME_MAX]; struct dirent *dirent; @@ -58,14 +114,19 @@ _eglMain(_EGLDisplay *dpy) _eglLog(_EGL_WARNING, "%s DRM devices not found.", path); return EGL_FALSE; } + + /* loop over dir entries looking for cardX where "X" is in the + * dpy->DriverName ":X" string. + */ while ((dirent = readdir(dir))) { if (strncmp(&dirent->d_name[0], "card", 4) != 0) continue; - if (strcmp(&dirent->d_name[4], &dpy->Name[1]) != 0) + if (strcmp(&dirent->d_name[4], &driverName[1]) != 0) continue; - snprintf(path, sizeof(path), "%s/drm/card%s/dri_library_name", sysfs, &dpy->Name[1]); + snprintf(path, sizeof(path), "%s/drm/card%s/dri_library_name", + sysfs, &driverName[1]); _eglLog(_EGL_INFO, "Opening %s", path); #if 1 file = fopen(path, "r"); @@ -89,6 +150,7 @@ _eglMain(_EGLDisplay *dpy) closedir(dir); return driver; +#endif } @@ -109,7 +171,10 @@ _eglDRICreateContext(_EGLDriver *drv, EGLDisplay dpy, EGLConfig config, if (!c) return EGL_NO_CONTEXT; - if (!_eglInitContext(drv, dpy, &c->Base, config, attrib_list)) { + conf = _eglLookupConfig(drv, dpy, config); + assert(conf); + + if (!_eglInitContext(drv, &c->Base, conf, attrib_list)) { free(c); return EGL_NO_CONTEXT; } @@ -127,8 +192,6 @@ _eglDRICreateContext(_EGLDriver *drv, EGLDisplay dpy, EGLConfig config, else sharePriv = NULL; - conf = _eglLookupConfig(drv, dpy, config); - assert(conf); _eglConfigToContextModesRec(conf, &visMode); c->driContext.private = disp->driScreen.createNewContext(disp, &visMode, @@ -138,10 +201,10 @@ _eglDRICreateContext(_EGLDriver *drv, EGLDisplay dpy, EGLConfig config, return EGL_FALSE; } - /* generate handle and insert into hash table */ - _eglSaveContext(&c->Base); + /* link to display */ + _eglLinkContext(&c->Base, &disp->Base); - return c->Base.Handle; + return _eglGetContextHandle(&c->Base); } @@ -152,13 +215,15 @@ _eglDRIMakeCurrent(_EGLDriver *drv, EGLDisplay dpy, EGLSurface draw, driDisplay *disp = Lookup_driDisplay(dpy); driContext *ctx = Lookup_driContext(context); EGLBoolean b; + __DRIid drawBuf = (__DRIid) draw; + __DRIid readBuf = (__DRIid) read; b = _eglMakeCurrent(drv, dpy, draw, read, context); if (!b) return EGL_FALSE; if (ctx) { - ctx->driContext.bindContext(disp, 0, read, draw, &ctx->driContext); + ctx->driContext.bindContext(disp, 0, drawBuf, readBuf, &ctx->driContext); } else { /* what's this??? */ @@ -173,14 +238,18 @@ _eglDRICreatePbufferSurface(_EGLDriver *drv, EGLDisplay dpy, EGLConfig config, const EGLint *attrib_list) { driSurface *surf; + _EGLConfig *conf; + + conf = _eglLookupConfig(drv, dpy, config); + assert(conf); surf = (driSurface *) calloc(1, sizeof(*surf)); if (!surf) { return EGL_NO_SURFACE; } - if (!_eglInitSurface(drv, dpy, &surf->Base, EGL_PBUFFER_BIT, - config, attrib_list)) { + if (!_eglInitSurface(drv, &surf->Base, EGL_PBUFFER_BIT, + conf, attrib_list)) { free(surf); return EGL_NO_SURFACE; } @@ -190,7 +259,7 @@ _eglDRICreatePbufferSurface(_EGLDriver *drv, EGLDisplay dpy, EGLConfig config, #if 0 GLcontext *ctx = NULL; /* this _should_ be OK */ #endif - GLvisual visMode; + __GLcontextModes visMode; _EGLConfig *conf = _eglLookupConfig(drv, dpy, config); assert(conf); /* bad config should be caught earlier */ _eglConfigToContextModesRec(conf, &visMode); @@ -211,7 +280,7 @@ _eglDRICreatePbufferSurface(_EGLDriver *drv, EGLDisplay dpy, EGLConfig config, #endif } - _eglSaveSurface(&surf->Base); + _eglLinkSurface(&surf->Base, _eglLookupDisplay(dpy)); return surf->Base.Handle; } @@ -223,16 +292,12 @@ _eglDRIDestroySurface(_EGLDriver *drv, EGLDisplay dpy, EGLSurface surface) driDisplay *disp = Lookup_driDisplay(dpy); driSurface *fs = Lookup_driSurface(surface); - _eglRemoveSurface(&fs->Base); + _eglUnlinkSurface(&fs->Base); fs->drawable.destroyDrawable(disp, fs->drawable.private); - if (fs->Base.IsBound) { - fs->Base.DeletePending = EGL_TRUE; - } - else { + if (!_eglIsSurfaceBound(&fs->Base)) free(fs); - } return EGL_TRUE; } @@ -243,16 +308,12 @@ _eglDRIDestroyContext(_EGLDriver *drv, EGLDisplay dpy, EGLContext context) driDisplay *disp = Lookup_driDisplay(dpy); driContext *fc = Lookup_driContext(context); - _eglRemoveContext(&fc->Base); + _eglUnlinkContext(&fc->Base); fc->driContext.destroyContext(disp, 0, fc->driContext.private); - if (fc->Base.IsBound) { - fc->Base.DeletePending = EGL_TRUE; - } - else { + if (!_eglIsContextBound(&fc->Base)) free(fc); - } return EGL_TRUE; } @@ -267,7 +328,8 @@ _eglDRICreateScreenSurfaceMESA(_EGLDriver *drv, EGLDisplay dpy, EGLConfig cfg, _EGLConfig *config = _eglLookupConfig(drv, dpy, cfg); driDisplay *disp = Lookup_driDisplay(dpy); driSurface *surface; - GLvisual visMode; + __GLcontextModes visMode; + __DRIid drawBuf; surface = (driSurface *) calloc(1, sizeof(*surface)); if (!surface) { @@ -275,13 +337,13 @@ _eglDRICreateScreenSurfaceMESA(_EGLDriver *drv, EGLDisplay dpy, EGLConfig cfg, } /* init base class, do error checking, etc. */ - if (!_eglInitSurface(drv, dpy, &surface->Base, EGL_SCREEN_BIT_MESA, - cfg, attrib_list)) { + if (!_eglInitSurface(drv, &surface->Base, EGL_SCREEN_BIT_MESA, + config, attrib_list)) { free(surface); return EGL_NO_SURFACE; } - _eglSaveSurface(&surface->Base); + _eglLinkSurface(&surface->Base &disp->Base); /* @@ -292,11 +354,13 @@ _eglDRICreateScreenSurfaceMESA(_EGLDriver *drv, EGLDisplay dpy, EGLConfig cfg, /* convert EGLConfig to GLvisual */ _eglConfigToContextModesRec(config, &visMode); + drawBuf = (__DRIid) _eglGetSurfaceHandle(&surface->Base); + /* Create a new DRI drawable */ - if (!disp->driScreen.createNewDrawable(disp, &visMode, surface->Base.Handle, + if (!disp->driScreen.createNewDrawable(disp, &visMode, drawBuf, &surface->drawable, GLX_WINDOW_BIT, empty_attribute_list)) { - _eglRemoveSurface(&surface->Base); + _eglUnlinkSurface(&surface->Base); free(surface); return EGL_NO_SURFACE; } @@ -715,7 +779,7 @@ __eglGetDrawableInfo(__DRInativeDisplay * ndpy, int screen, __DRIid drawable, { __DRIscreen *pDRIScreen; __DRIscreenPrivate *psp; - driSurface *surf = Lookup_driSurface(drawable); + driSurface *surf = Lookup_driSurface((EGLSurface) drawable); pDRIScreen = __eglFindDRIScreen(ndpy, screen); @@ -1019,8 +1083,10 @@ _eglDRICreateDisplay(driDisplay *dpy, __DRIframebuffer *framebuffer) api_ver, & interface_methods, NULL); - if (!dpy->driScreen.private) + if (!dpy->driScreen.private) { + _eglLog(_EGL_WARNING, "egldri.c: DRI create new screen failed"); return EGL_FALSE; + } DRM_UNLOCK( dpy->drmFD, dpy->pSAREA, dpy->serverContext ); @@ -1080,6 +1146,7 @@ _eglDRIInitialize(_EGLDriver *drv, EGLDisplay dpy, { _EGLDisplay *disp = _eglLookupDisplay(dpy); driDisplay *display; + const char *driverName = (const char *) disp->NativeDisplay; assert(disp); @@ -1088,13 +1155,13 @@ _eglDRIInitialize(_EGLDriver *drv, EGLDisplay dpy, */ display = calloc(1, sizeof(*display)); display->Base = *disp; - _eglHashInsert(_eglGlobal.Displays, disp->Handle, display); + _eglSaveDisplay(&display->Base); free(disp); *major = 1; *minor = 0; - sscanf(&disp->Name[1], "%d", &display->minor); + sscanf(driverName + 1, "%d", &display->minor); drv->Initialized = EGL_TRUE; return EGL_TRUE; diff --git a/src/egl/drivers/dri/egldri.h b/src/egl/drivers/dri/egldri.h index 34b12d64fc..54a9a4ea26 100644 --- a/src/egl/drivers/dri/egldri.h +++ b/src/egl/drivers/dri/egldri.h @@ -1,11 +1,14 @@ #ifndef EGLDRI_INCLUDED #define EGLDRI_INCLUDED +#include <stdlib.h> +#include <string.h> +#include <stdint.h> #include "egldisplay.h" #include "eglscreen.h" #include "eglsurface.h" #include "eglcontext.h" -#include "mtypes.h" + #include "dri_util.h" #include "drm_sarea.h" @@ -14,7 +17,7 @@ */ typedef struct dri_display { - _EGLDisplay Base; /* base class/object */ + _EGLDisplay Base; /**< base class */ void *pFB; int drmFD; /**< \brief DRM device file descriptor */ int minor; @@ -32,7 +35,7 @@ typedef struct dri_display unsigned long FBStart; /**< \brief physical address of the framebuffer */ void *driverClientMsg; int driverClientMsgSize; - int chipset; + unsigned chipset; void *driverPrivate; drm_magic_t magic; diff --git a/src/egl/drivers/glx/Makefile b/src/egl/drivers/glx/Makefile new file mode 100644 index 0000000000..20ef0352ad --- /dev/null +++ b/src/egl/drivers/glx/Makefile @@ -0,0 +1,77 @@ +# src/egl/drivers/glx/Makefile + +# Build XEGL DRI driver loader library: egl_glx.so + + +TOP = ../../../.. +include $(TOP)/configs/current + + +EXTRA_DEFINES = -DDEFAULT_DRIVER_DIR=\"$(DRI_DRIVER_SEARCH_DIR)\" + +DRIVER_NAME = egl_glx.so + + +INCLUDE_DIRS = \ + -I. \ + -I/usr/include \ + $(shell pkg-config --cflags-only-I libdrm) \ + -I$(TOP)/include \ + -I$(TOP)/include/GL/internal \ + -I$(TOP)/src/mesa/glapi \ + -I$(TOP)/src/mesa/drivers/dri/common \ + -I$(TOP)/src/mesa/main \ + -I$(TOP)/src/mesa \ + -I$(TOP)/src/egl/main \ + -I$(TOP)/src/glx/x11 + +SOURCES = egl_glx.c + +OBJECTS = $(SOURCES:.c=.o) + +DRM_LIB = `pkg-config --libs libdrm` + +MISC_LIBS = -ldl -lXext -lGL + + +.c.o: + $(CC) -c $(INCLUDE_DIRS) $(CFLAGS) $(EXTRA_DEFINES) $< -o $@ + + +.PHONY: library + + +default: depend library Makefile + + +library: $(TOP)/$(LIB_DIR)/$(DRIVER_NAME) + + +# Make the egl_glx.so library +$(TOP)/$(LIB_DIR)/$(DRIVER_NAME): $(OBJECTS) + $(TOP)/bin/mklib -o $(DRIVER_NAME) \ + -noprefix \ + -major 1 -minor 0 \ + -L$(TOP)/$(LIB_DIR) \ + -install $(TOP)/$(LIB_DIR) \ + $(OBJECTS) $(DRM_LIB) $(MISC_LIBS) + +install: + $(INSTALL) -d $(DESTDIR)$(INSTALL_LIB_DIR) + $(MINSTALL) $(TOP)/$(LIB_DIR)/$(DRIVER_NAME) $(DESTDIR)$(INSTALL_LIB_DIR) + +clean: + rm -f *.o + rm -f *.so + rm -f depend depend.bak + + +depend: $(SOURCES) $(HEADERS) + @ echo "running $(MKDEP)" + @ rm -f depend + @ touch depend + $(MKDEP) $(MKDEP_OPTIONS) $(DEFINES) $(INCLUDE_DIRS) \ + $(SOURCES) $(HEADERS) >/dev/null 2>/dev/null + +include depend +# DO NOT DELETE diff --git a/src/egl/drivers/glx/egl_glx.c b/src/egl/drivers/glx/egl_glx.c new file mode 100644 index 0000000000..4685f600e2 --- /dev/null +++ b/src/egl/drivers/glx/egl_glx.c @@ -0,0 +1,882 @@ +/************************************************************************** + * + * Copyright 2008 Tungsten Graphics, Inc., Cedar Park, Texas. + * All Rights Reserved. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the + * "Software"), to deal in the Software without restriction, including + * without limitation the rights to use, copy, modify, merge, publish, + * distribute, sub license, and/or sell copies of the Software, and to + * permit persons to whom the Software is furnished to do so, subject to + * the following conditions: + * + * The above copyright notice and this permission notice (including the + * next paragraph) shall be included in all copies or substantial portions + * of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS + * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. + * IN NO EVENT SHALL TUNGSTEN GRAPHICS AND/OR ITS SUPPLIERS BE LIABLE FOR + * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, + * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE + * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + * + **************************************************************************/ + + +/** + * This is an EGL driver that wraps GLX. This gives the benefit of being + * completely agnostic of the direct rendering implementation. + * + * Authors: Alan Hourihane <alanh@tungstengraphics.com> + */ + +/* + * TODO: + * + * test eglBind/ReleaseTexImage + */ + + +#include <assert.h> +#include <stdio.h> +#include <sys/types.h> +#include <sys/stat.h> +#include <fcntl.h> +#include "dlfcn.h" +#include <X11/Xlib.h> +#include <GL/gl.h> +#include "glxclient.h" + +#include "eglconfig.h" +#include "eglcontext.h" +#include "egldisplay.h" +#include "egldriver.h" +#include "eglglobals.h" +#include "egllog.h" +#include "eglsurface.h" + +#include <GL/gl.h> + +#define CALLOC_STRUCT(T) (struct T *) calloc(1, sizeof(struct T)) + +static const EGLint all_apis = (EGL_OPENGL_ES_BIT + | EGL_OPENGL_ES2_BIT + | EGL_OPENVG_BIT + /* | EGL_OPENGL_BIT */); /* can't do */ + +struct visual_attribs +{ + /* X visual attribs */ + int id; + int klass; + int depth; + int redMask, greenMask, blueMask; + int colormapSize; + int bitsPerRGB; + + /* GL visual attribs */ + int supportsGL; + int transparentType; + int transparentRedValue; + int transparentGreenValue; + int transparentBlueValue; + int transparentAlphaValue; + int transparentIndexValue; + int bufferSize; + int level; + int render_type; + int doubleBuffer; + int stereo; + int auxBuffers; + int redSize, greenSize, blueSize, alphaSize; + int depthSize; + int stencilSize; + int accumRedSize, accumGreenSize, accumBlueSize, accumAlphaSize; + int numSamples, numMultisample; + int visualCaveat; +}; + +/** subclass of _EGLDriver */ +struct GLX_egl_driver +{ + _EGLDriver Base; /**< base class */ +}; + + +/** driver data of _EGLDisplay */ +struct GLX_egl_display +{ + Display *dpy; + XVisualInfo *visuals; + GLXFBConfig *fbconfigs; + + int glx_maj, glx_min; +}; + + +/** subclass of _EGLContext */ +struct GLX_egl_context +{ + _EGLContext Base; /**< base class */ + + GLXContext context; +}; + + +/** subclass of _EGLSurface */ +struct GLX_egl_surface +{ + _EGLSurface Base; /**< base class */ + + GLXDrawable drawable; +}; + + +/** subclass of _EGLConfig */ +struct GLX_egl_config +{ + _EGLConfig Base; /**< base class */ + int index; +}; + +/** cast wrapper */ +static struct GLX_egl_driver * +GLX_egl_driver(_EGLDriver *drv) +{ + return (struct GLX_egl_driver *) drv; +} + +static struct GLX_egl_display * +GLX_egl_display(_EGLDisplay *dpy) +{ + return (struct GLX_egl_display *) dpy->DriverData; +} + +static struct GLX_egl_context * +GLX_egl_context(_EGLContext *ctx) +{ + return (struct GLX_egl_context *) ctx; +} + +static struct GLX_egl_surface * +GLX_egl_surface(_EGLSurface *surf) +{ + return (struct GLX_egl_surface *) surf; +} + +static int +GLX_egl_config_index(_EGLConfig *conf) +{ + return ((struct GLX_egl_config *) conf)->index; +} + +static GLboolean +get_visual_attribs(Display *dpy, XVisualInfo *vInfo, + struct visual_attribs *attribs) +{ + const char *ext = glXQueryExtensionsString(dpy, vInfo->screen); + int rgba; + + memset(attribs, 0, sizeof(struct visual_attribs)); + + attribs->id = vInfo->visualid; +#if defined(__cplusplus) || defined(c_plusplus) + attribs->klass = vInfo->c_class; +#else + attribs->klass = vInfo->class; +#endif + attribs->depth = vInfo->depth; + attribs->redMask = vInfo->red_mask; + attribs->greenMask = vInfo->green_mask; + attribs->blueMask = vInfo->blue_mask; + attribs->colormapSize = vInfo->colormap_size; + attribs->bitsPerRGB = vInfo->bits_per_rgb; + + if (glXGetConfig(dpy, vInfo, GLX_USE_GL, &attribs->supportsGL) != 0 || + !attribs->supportsGL) + return GL_FALSE; + glXGetConfig(dpy, vInfo, GLX_BUFFER_SIZE, &attribs->bufferSize); + glXGetConfig(dpy, vInfo, GLX_LEVEL, &attribs->level); + glXGetConfig(dpy, vInfo, GLX_RGBA, &rgba); + if (!rgba) + return GL_FALSE; + attribs->render_type = GLX_RGBA_BIT; + + glXGetConfig(dpy, vInfo, GLX_DOUBLEBUFFER, &attribs->doubleBuffer); + if (!attribs->doubleBuffer) + return GL_FALSE; + + glXGetConfig(dpy, vInfo, GLX_STEREO, &attribs->stereo); + glXGetConfig(dpy, vInfo, GLX_AUX_BUFFERS, &attribs->auxBuffers); + glXGetConfig(dpy, vInfo, GLX_RED_SIZE, &attribs->redSize); + glXGetConfig(dpy, vInfo, GLX_GREEN_SIZE, &attribs->greenSize); + glXGetConfig(dpy, vInfo, GLX_BLUE_SIZE, &attribs->blueSize); + glXGetConfig(dpy, vInfo, GLX_ALPHA_SIZE, &attribs->alphaSize); + glXGetConfig(dpy, vInfo, GLX_DEPTH_SIZE, &attribs->depthSize); + glXGetConfig(dpy, vInfo, GLX_STENCIL_SIZE, &attribs->stencilSize); + glXGetConfig(dpy, vInfo, GLX_ACCUM_RED_SIZE, &attribs->accumRedSize); + glXGetConfig(dpy, vInfo, GLX_ACCUM_GREEN_SIZE, &attribs->accumGreenSize); + glXGetConfig(dpy, vInfo, GLX_ACCUM_BLUE_SIZE, &attribs->accumBlueSize); + glXGetConfig(dpy, vInfo, GLX_ACCUM_ALPHA_SIZE, &attribs->accumAlphaSize); + + /* get transparent pixel stuff */ + glXGetConfig(dpy, vInfo,GLX_TRANSPARENT_TYPE, &attribs->transparentType); + if (attribs->transparentType == GLX_TRANSPARENT_RGB) { + glXGetConfig(dpy, vInfo, GLX_TRANSPARENT_RED_VALUE, &attribs->transparentRedValue); + glXGetConfig(dpy, vInfo, GLX_TRANSPARENT_GREEN_VALUE, &attribs->transparentGreenValue); + glXGetConfig(dpy, vInfo, GLX_TRANSPARENT_BLUE_VALUE, &attribs->transparentBlueValue); + glXGetConfig(dpy, vInfo, GLX_TRANSPARENT_ALPHA_VALUE, &attribs->transparentAlphaValue); + } + else if (attribs->transparentType == GLX_TRANSPARENT_INDEX) { + glXGetConfig(dpy, vInfo, GLX_TRANSPARENT_INDEX_VALUE, &attribs->transparentIndexValue); + } + + /* multisample attribs */ +#ifdef GLX_ARB_multisample + if (ext && strstr(ext, "GLX_ARB_multisample")) { + glXGetConfig(dpy, vInfo, GLX_SAMPLE_BUFFERS_ARB, &attribs->numMultisample); + glXGetConfig(dpy, vInfo, GLX_SAMPLES_ARB, &attribs->numSamples); + } +#endif + else { + attribs->numSamples = 0; + attribs->numMultisample = 0; + } + +#if defined(GLX_EXT_visual_rating) + if (ext && strstr(ext, "GLX_EXT_visual_rating")) { + glXGetConfig(dpy, vInfo, GLX_VISUAL_CAVEAT_EXT, &attribs->visualCaveat); + } + else { + attribs->visualCaveat = GLX_NONE_EXT; + } +#else + attribs->visualCaveat = 0; +#endif + + return GL_TRUE; +} + +#ifdef GLX_VERSION_1_3 + +static int +glx_token_to_visual_class(int visual_type) +{ + switch (visual_type) { + case GLX_TRUE_COLOR: + return TrueColor; + case GLX_DIRECT_COLOR: + return DirectColor; + case GLX_PSEUDO_COLOR: + return PseudoColor; + case GLX_STATIC_COLOR: + return StaticColor; + case GLX_GRAY_SCALE: + return GrayScale; + case GLX_STATIC_GRAY: + return StaticGray; + case GLX_NONE: + default: + return None; + } +} + +static int +get_fbconfig_attribs(Display *dpy, GLXFBConfig fbconfig, + struct visual_attribs *attribs) +{ + int visual_type; + int fbconfig_id; + + memset(attribs, 0, sizeof(struct visual_attribs)); + + glXGetFBConfigAttrib(dpy, fbconfig, GLX_FBCONFIG_ID, &fbconfig_id); + + glXGetFBConfigAttrib(dpy, fbconfig, GLX_VISUAL_ID, &attribs->id); + +#if 0 + attribs->depth = vInfo->depth; + attribs->redMask = vInfo->red_mask; + attribs->greenMask = vInfo->green_mask; + attribs->blueMask = vInfo->blue_mask; + attribs->colormapSize = vInfo->colormap_size; + attribs->bitsPerRGB = vInfo->bits_per_rgb; +#endif + + glXGetFBConfigAttrib(dpy, fbconfig, GLX_X_VISUAL_TYPE, &visual_type); + attribs->klass = glx_token_to_visual_class(visual_type); + + glXGetFBConfigAttrib(dpy, fbconfig, GLX_BUFFER_SIZE, &attribs->bufferSize); + glXGetFBConfigAttrib(dpy, fbconfig, GLX_LEVEL, &attribs->level); + glXGetFBConfigAttrib(dpy, fbconfig, GLX_RENDER_TYPE, &attribs->render_type); + if (!(attribs->render_type & GLX_RGBA_BIT)) + return 0; + + glXGetFBConfigAttrib(dpy, fbconfig, GLX_DOUBLEBUFFER, &attribs->doubleBuffer); + if (!attribs->doubleBuffer) + return 0; + + glXGetFBConfigAttrib(dpy, fbconfig, GLX_STEREO, &attribs->stereo); + glXGetFBConfigAttrib(dpy, fbconfig, GLX_AUX_BUFFERS, &attribs->auxBuffers); + + glXGetFBConfigAttrib(dpy, fbconfig, GLX_RED_SIZE, &attribs->redSize); + glXGetFBConfigAttrib(dpy, fbconfig, GLX_GREEN_SIZE, &attribs->greenSize); + glXGetFBConfigAttrib(dpy, fbconfig, GLX_BLUE_SIZE, &attribs->blueSize); + glXGetFBConfigAttrib(dpy, fbconfig, GLX_ALPHA_SIZE, &attribs->alphaSize); + glXGetFBConfigAttrib(dpy, fbconfig, GLX_DEPTH_SIZE, &attribs->depthSize); + glXGetFBConfigAttrib(dpy, fbconfig, GLX_STENCIL_SIZE, &attribs->stencilSize); + + glXGetFBConfigAttrib(dpy, fbconfig, GLX_ACCUM_RED_SIZE, &attribs->accumRedSize); + glXGetFBConfigAttrib(dpy, fbconfig, GLX_ACCUM_GREEN_SIZE, &attribs->accumGreenSize); + glXGetFBConfigAttrib(dpy, fbconfig, GLX_ACCUM_BLUE_SIZE, &attribs->accumBlueSize); + glXGetFBConfigAttrib(dpy, fbconfig, GLX_ACCUM_ALPHA_SIZE, &attribs->accumAlphaSize); + + /* get transparent pixel stuff */ + glXGetFBConfigAttrib(dpy, fbconfig,GLX_TRANSPARENT_TYPE, &attribs->transparentType); + if (attribs->transparentType == GLX_TRANSPARENT_RGB) { + glXGetFBConfigAttrib(dpy, fbconfig, GLX_TRANSPARENT_RED_VALUE, &attribs->transparentRedValue); + glXGetFBConfigAttrib(dpy, fbconfig, GLX_TRANSPARENT_GREEN_VALUE, &attribs->transparentGreenValue); + glXGetFBConfigAttrib(dpy, fbconfig, GLX_TRANSPARENT_BLUE_VALUE, &attribs->transparentBlueValue); + glXGetFBConfigAttrib(dpy, fbconfig, GLX_TRANSPARENT_ALPHA_VALUE, &attribs->transparentAlphaValue); + } + else if (attribs->transparentType == GLX_TRANSPARENT_INDEX) { + glXGetFBConfigAttrib(dpy, fbconfig, GLX_TRANSPARENT_INDEX_VALUE, &attribs->transparentIndexValue); + } + + glXGetFBConfigAttrib(dpy, fbconfig, GLX_SAMPLE_BUFFERS, &attribs->numMultisample); + glXGetFBConfigAttrib(dpy, fbconfig, GLX_SAMPLES, &attribs->numSamples); + + glXGetFBConfigAttrib(dpy, fbconfig, GLX_CONFIG_CAVEAT, &attribs->visualCaveat); + + if (attribs->id == 0) { + attribs->id = fbconfig_id; + return EGL_PBUFFER_BIT | EGL_PIXMAP_BIT; + } + + return EGL_WINDOW_BIT; +} + +#endif + +static EGLBoolean +create_configs(_EGLDisplay *disp, struct GLX_egl_display *GLX_dpy) +{ + XVisualInfo theTemplate; + int numVisuals; + long mask; + int i; + struct visual_attribs attribs; + + GLX_dpy->fbconfigs = NULL; + +#ifdef GLX_VERSION_1_3 + /* get list of all fbconfigs on this screen */ + GLX_dpy->fbconfigs = glXGetFBConfigs(GLX_dpy->dpy, DefaultScreen(GLX_dpy->dpy), &numVisuals); + + if (numVisuals == 0) { + GLX_dpy->fbconfigs = NULL; + goto xvisual; + } + + for (i = 0; i < numVisuals; i++) { + struct GLX_egl_config *config; + int bit; + + bit = get_fbconfig_attribs(GLX_dpy->dpy, GLX_dpy->fbconfigs[i], &attribs); + if (!bit) + continue; + + config = CALLOC_STRUCT(GLX_egl_config); + + config->index = i; + _eglInitConfig(&config->Base, (i+1)); + SET_CONFIG_ATTRIB(&config->Base, EGL_NATIVE_VISUAL_ID, attribs.id); + SET_CONFIG_ATTRIB(&config->Base, EGL_BUFFER_SIZE, attribs.bufferSize); + SET_CONFIG_ATTRIB(&config->Base, EGL_RED_SIZE, attribs.redSize); + SET_CONFIG_ATTRIB(&config->Base, EGL_GREEN_SIZE, attribs.greenSize); + SET_CONFIG_ATTRIB(&config->Base, EGL_BLUE_SIZE, attribs.blueSize); + SET_CONFIG_ATTRIB(&config->Base, EGL_ALPHA_SIZE, attribs.alphaSize); + SET_CONFIG_ATTRIB(&config->Base, EGL_DEPTH_SIZE, attribs.depthSize); + SET_CONFIG_ATTRIB(&config->Base, EGL_STENCIL_SIZE, attribs.stencilSize); + SET_CONFIG_ATTRIB(&config->Base, EGL_SAMPLES, attribs.numSamples); + SET_CONFIG_ATTRIB(&config->Base, EGL_SAMPLE_BUFFERS, attribs.numMultisample); + SET_CONFIG_ATTRIB(&config->Base, EGL_CONFORMANT, all_apis); + SET_CONFIG_ATTRIB(&config->Base, EGL_RENDERABLE_TYPE, all_apis); + SET_CONFIG_ATTRIB(&config->Base, EGL_SURFACE_TYPE, bit); + + /* XXX possibly other things to init... */ + + _eglAddConfig(disp, &config->Base); + } + + goto end; +#endif + +xvisual: + /* get list of all visuals on this screen */ + theTemplate.screen = DefaultScreen(GLX_dpy->dpy); + mask = VisualScreenMask; + GLX_dpy->visuals = XGetVisualInfo(GLX_dpy->dpy, mask, &theTemplate, &numVisuals); + + for (i = 0; i < numVisuals; i++) { + struct GLX_egl_config *config; + + if (!get_visual_attribs(GLX_dpy->dpy, &GLX_dpy->visuals[i], &attribs)) + continue; + + config = CALLOC_STRUCT(GLX_egl_config); + + config->index = i; + _eglInitConfig(&config->Base, (i+1)); + SET_CONFIG_ATTRIB(&config->Base, EGL_NATIVE_VISUAL_ID, attribs.id); + SET_CONFIG_ATTRIB(&config->Base, EGL_BUFFER_SIZE, attribs.bufferSize); + SET_CONFIG_ATTRIB(&config->Base, EGL_RED_SIZE, attribs.redSize); + SET_CONFIG_ATTRIB(&config->Base, EGL_GREEN_SIZE, attribs.greenSize); + SET_CONFIG_ATTRIB(&config->Base, EGL_BLUE_SIZE, attribs.blueSize); + SET_CONFIG_ATTRIB(&config->Base, EGL_ALPHA_SIZE, attribs.alphaSize); + SET_CONFIG_ATTRIB(&config->Base, EGL_DEPTH_SIZE, attribs.depthSize); + SET_CONFIG_ATTRIB(&config->Base, EGL_STENCIL_SIZE, attribs.stencilSize); + SET_CONFIG_ATTRIB(&config->Base, EGL_SAMPLES, attribs.numSamples); + SET_CONFIG_ATTRIB(&config->Base, EGL_SAMPLE_BUFFERS, attribs.numMultisample); + SET_CONFIG_ATTRIB(&config->Base, EGL_CONFORMANT, all_apis); + SET_CONFIG_ATTRIB(&config->Base, EGL_RENDERABLE_TYPE, all_apis); + SET_CONFIG_ATTRIB(&config->Base, EGL_SURFACE_TYPE, + (EGL_WINDOW_BIT /*| EGL_PBUFFER_BIT | EGL_PIXMAP_BIT*/)); + + /* XXX possibly other things to init... */ + + _eglAddConfig(disp, &config->Base); + } + +end: + return EGL_TRUE; +} + +/** + * Called via eglInitialize(), GLX_drv->API.Initialize(). + */ +static EGLBoolean +GLX_eglInitialize(_EGLDriver *drv, _EGLDisplay *disp, + EGLint *major, EGLint *minor) +{ + struct GLX_egl_display *GLX_dpy; + + GLX_dpy = CALLOC_STRUCT(GLX_egl_display); + if (!GLX_dpy) + return _eglError(EGL_BAD_ALLOC, "eglInitialize"); + + GLX_dpy->dpy = (Display *) disp->NativeDisplay; + if (!GLX_dpy->dpy) { + GLX_dpy->dpy = XOpenDisplay(NULL); + if (!GLX_dpy->dpy) { + _eglLog(_EGL_WARNING, "GLX: XOpenDisplay failed"); + free(GLX_dpy); + return EGL_FALSE; + } + } + + disp->DriverData = (void *) GLX_dpy; + disp->ClientAPIsMask = all_apis; + + glXQueryVersion(GLX_dpy->dpy, &GLX_dpy->glx_maj, &GLX_dpy->glx_min); + + /* we're supporting EGL 1.4 */ + *major = 1; + *minor = 4; + + create_configs(disp, GLX_dpy); + + return EGL_TRUE; +} + +/** + * Called via eglTerminate(), drv->API.Terminate(). + */ +static EGLBoolean +GLX_eglTerminate(_EGLDriver *drv, _EGLDisplay *disp) +{ + struct GLX_egl_display *GLX_dpy = GLX_egl_display(disp); + + _eglReleaseDisplayResources(drv, disp); + _eglCleanupDisplay(disp); + + if (GLX_dpy->visuals) + XFree(GLX_dpy->visuals); + if (GLX_dpy->fbconfigs) + XFree(GLX_dpy->fbconfigs); + + if (!disp->NativeDisplay) + XCloseDisplay(GLX_dpy->dpy); + free(GLX_dpy); + + disp->DriverData = NULL; + + return EGL_TRUE; +} + + +/** + * Called via eglCreateContext(), drv->API.CreateContext(). + */ +static _EGLContext * +GLX_eglCreateContext(_EGLDriver *drv, _EGLDisplay *disp, _EGLConfig *conf, + _EGLContext *share_list, const EGLint *attrib_list) +{ + struct GLX_egl_context *GLX_ctx = CALLOC_STRUCT(GLX_egl_context); + struct GLX_egl_display *GLX_dpy = GLX_egl_display(disp); + struct GLX_egl_context *GLX_ctx_shared = GLX_egl_context(share_list); + + if (!GLX_ctx) { + _eglError(EGL_BAD_ALLOC, "eglCreateContext"); + return NULL; + } + + if (!_eglInitContext(drv, &GLX_ctx->Base, conf, attrib_list)) { + free(GLX_ctx); + return NULL; + } + +#ifdef GLX_VERSION_1_3 + if (GLX_dpy->fbconfigs) + GLX_ctx->context = + glXCreateNewContext(GLX_dpy->dpy, + GLX_dpy->fbconfigs[GLX_egl_config_index(conf)], + GLX_RGBA_TYPE, + GLX_ctx_shared ? GLX_ctx_shared->context : NULL, + GL_TRUE); + else +#endif + GLX_ctx->context = + glXCreateContext(GLX_dpy->dpy, + &GLX_dpy->visuals[GLX_egl_config_index(conf)], + GLX_ctx_shared ? GLX_ctx_shared->context : NULL, + GL_TRUE); + if (!GLX_ctx->context) { + free(GLX_ctx); + return NULL; + } + +#if 1 + /* (maybe?) need to have a direct rendering context */ + if (!glXIsDirect(GLX_dpy->dpy, GLX_ctx->context)) { + glXDestroyContext(GLX_dpy->dpy, GLX_ctx->context); + free(GLX_ctx); + return NULL; + } +#endif + + return &GLX_ctx->Base; +} + + +/** + * Called via eglMakeCurrent(), drv->API.MakeCurrent(). + */ +static EGLBoolean +GLX_eglMakeCurrent(_EGLDriver *drv, _EGLDisplay *disp, _EGLSurface *dsurf, + _EGLSurface *rsurf, _EGLContext *ctx) +{ + struct GLX_egl_display *GLX_dpy = GLX_egl_display(disp); + struct GLX_egl_surface *GLX_dsurf = GLX_egl_surface(dsurf); + struct GLX_egl_surface *GLX_rsurf = GLX_egl_surface(rsurf); + struct GLX_egl_context *GLX_ctx = GLX_egl_context(ctx); + GLXDrawable ddraw, rdraw; + GLXContext cctx; + + if (!_eglMakeCurrent(drv, disp, dsurf, rsurf, ctx)) + return EGL_FALSE; + + ddraw = (GLX_dsurf) ? GLX_dsurf->drawable : None; + rdraw = (GLX_rsurf) ? GLX_rsurf->drawable : None; + cctx = (GLX_ctx) ? GLX_ctx->context : NULL; + +#ifdef GLX_VERSION_1_3 + if (glXMakeContextCurrent(GLX_dpy->dpy, ddraw, rdraw, cctx)) + return EGL_TRUE; +#endif + + if (ddraw == rdraw && glXMakeCurrent(GLX_dpy->dpy, ddraw, cctx)) + return EGL_TRUE; + + return EGL_FALSE; +} + +/** Get size of given window */ +static Status +get_drawable_size(Display *dpy, Drawable d, uint *width, uint *height) +{ + Window root; + Status stat; + int xpos, ypos; + unsigned int w, h, bw, depth; + stat = XGetGeometry(dpy, d, &root, &xpos, &ypos, &w, &h, &bw, &depth); + *width = w; + *height = h; + return stat; +} + +/** + * Called via eglCreateWindowSurface(), drv->API.CreateWindowSurface(). + */ +static _EGLSurface * +GLX_eglCreateWindowSurface(_EGLDriver *drv, _EGLDisplay *disp, _EGLConfig *conf, + NativeWindowType window, const EGLint *attrib_list) +{ + struct GLX_egl_display *GLX_dpy = GLX_egl_display(disp); + struct GLX_egl_surface *GLX_surf; + uint width, height; + + GLX_surf = CALLOC_STRUCT(GLX_egl_surface); + if (!GLX_surf) { + _eglError(EGL_BAD_ALLOC, "eglCreateWindowSurface"); + return NULL; + } + + if (!_eglInitSurface(drv, &GLX_surf->Base, EGL_WINDOW_BIT, + conf, attrib_list)) { + free(GLX_surf); + return NULL; + } + + GLX_surf->drawable = window; + get_drawable_size(GLX_dpy->dpy, window, &width, &height); + GLX_surf->Base.Width = width; + GLX_surf->Base.Height = height; + + return &GLX_surf->Base; +} + +#ifdef GLX_VERSION_1_3 +static _EGLSurface * +GLX_eglCreatePixmapSurface(_EGLDriver *drv, _EGLDisplay *disp, _EGLConfig *conf, + NativePixmapType pixmap, const EGLint *attrib_list) +{ + struct GLX_egl_display *GLX_dpy = GLX_egl_display(disp); + struct GLX_egl_surface *GLX_surf; + int i; + + /* GLX must >= 1.3 */ + if (!(GLX_dpy->glx_maj == 1 && GLX_dpy->glx_min >= 3)) + return NULL; + + GLX_surf = CALLOC_STRUCT(GLX_egl_surface); + if (!GLX_surf) { + _eglError(EGL_BAD_ALLOC, "eglCreatePixmapSurface"); + return NULL; + } + + if (!_eglInitSurface(drv, &GLX_surf->Base, EGL_PIXMAP_BIT, + conf, attrib_list)) { + free(GLX_surf); + return NULL; + } + + for (i = 0; attrib_list && attrib_list[i] != EGL_NONE; i++) { + switch (attrib_list[i]) { + /* no attribs at this time */ + default: + _eglError(EGL_BAD_ATTRIBUTE, "eglCreatePixmapSurface"); + free(GLX_surf); + return NULL; + } + } + + GLX_surf->drawable = + glXCreatePixmap(GLX_dpy->dpy, + GLX_dpy->fbconfigs[GLX_egl_config_index(conf)], + pixmap, NULL); + if (!GLX_surf->drawable) { + free(GLX_surf); + return NULL; + } + + return &GLX_surf->Base; +} + +static _EGLSurface * +GLX_eglCreatePbufferSurface(_EGLDriver *drv, _EGLDisplay *disp, + _EGLConfig *conf, const EGLint *attrib_list) +{ + struct GLX_egl_display *GLX_dpy = GLX_egl_display(disp); + struct GLX_egl_surface *GLX_surf; + int attribs[5]; + int i = 0, j = 0; + + /* GLX must >= 1.3 */ + if (!(GLX_dpy->glx_maj == 1 && GLX_dpy->glx_min >= 3)) + return NULL; + + GLX_surf = CALLOC_STRUCT(GLX_egl_surface); + if (!GLX_surf) { + _eglError(EGL_BAD_ALLOC, "eglCreatePbufferSurface"); + return NULL; + } + + if (!_eglInitSurface(drv, &GLX_surf->Base, EGL_PBUFFER_BIT, + conf, attrib_list)) { + free(GLX_surf); + return NULL; + } + + while(attrib_list[i] != EGL_NONE) { + switch (attrib_list[i]) { + case EGL_WIDTH: + attribs[j++] = GLX_PBUFFER_WIDTH; + attribs[j++] = attrib_list[i+1]; + break; + case EGL_HEIGHT: + attribs[j++] = GLX_PBUFFER_HEIGHT; + attribs[j++] = attrib_list[i+1]; + break; + } + i++; + } + attribs[j++] = 0; + + GLX_surf->drawable = + glXCreatePbuffer(GLX_dpy->dpy, + GLX_dpy->fbconfigs[GLX_egl_config_index(conf)], + attribs); + if (!GLX_surf->drawable) { + free(GLX_surf); + return NULL; + } + + return &GLX_surf->Base; +} +#endif + +static EGLBoolean +GLX_eglDestroySurface(_EGLDriver *drv, _EGLDisplay *disp, _EGLSurface *surf) +{ + struct GLX_egl_display *GLX_dpy = GLX_egl_display(disp); + if (!_eglIsSurfaceBound(surf)) { + struct GLX_egl_surface *GLX_surf = GLX_egl_surface(surf); + switch (surf->Type) { + case EGL_PBUFFER_BIT: + glXDestroyPbuffer(GLX_dpy->dpy, GLX_surf->drawable); + break; + case EGL_PIXMAP_BIT: + glXDestroyPixmap(GLX_dpy->dpy, GLX_surf->drawable); + break; + default: + break; + } + free(surf); + } + + return EGL_TRUE; +} + + +static EGLBoolean +GLX_eglBindTexImage(_EGLDriver *drv, _EGLDisplay *disp, _EGLSurface *surf, + EGLint buffer) +{ + struct GLX_egl_display *GLX_dpy = GLX_egl_display(disp); + struct GLX_egl_surface *GLX_surf = GLX_egl_surface(surf); + + /* buffer ?? */ + glXBindTexImageEXT(GLX_dpy->dpy, GLX_surf->drawable, + GLX_FRONT_LEFT_EXT, NULL); + + return EGL_TRUE; +} + + +static EGLBoolean +GLX_eglReleaseTexImage(_EGLDriver *drv, _EGLDisplay *disp, _EGLSurface *surf, + EGLint buffer) +{ + struct GLX_egl_display *GLX_dpy = GLX_egl_display(disp); + struct GLX_egl_surface *GLX_surf = GLX_egl_surface(surf); + + /* buffer ?? */ + glXReleaseTexImageEXT(GLX_dpy->dpy, GLX_surf->drawable, + GLX_FRONT_LEFT_EXT); + + return EGL_TRUE; +} + + +static EGLBoolean +GLX_eglSwapBuffers(_EGLDriver *drv, _EGLDisplay *disp, _EGLSurface *draw) +{ + struct GLX_egl_display *GLX_dpy = GLX_egl_display(disp); + struct GLX_egl_surface *GLX_surf = GLX_egl_surface(draw); + + _eglLog(_EGL_DEBUG, "GLX: EGL SwapBuffers 0x%x",draw); + + glXSwapBuffers(GLX_dpy->dpy, GLX_surf->drawable); + + return EGL_TRUE; +} + +/* + * Called from eglGetProcAddress() via drv->API.GetProcAddress(). + */ +static _EGLProc +GLX_eglGetProcAddress(const char *procname) +{ + /* This is a bit of a hack to get at the gallium/Mesa state tracker + * function st_get_proc_address(). This will probably change at + * some point. + */ + _EGLProc (*get_proc_addr)(const char *procname); + _EGLProc proc_addr; + get_proc_addr = dlsym(NULL, "st_get_proc_address"); + if (get_proc_addr) + return get_proc_addr(procname); + + proc_addr = glXGetProcAddress((const GLubyte *)procname); + if (proc_addr) + return proc_addr; + + return (_EGLProc)dlsym(NULL, procname); +} + + +static void +GLX_Unload(_EGLDriver *drv) +{ + struct GLX_egl_driver *GLX_drv = GLX_egl_driver(drv); + free(GLX_drv); +} + + +/** + * This is the main entrypoint into the driver, called by libEGL. + * Create a new _EGLDriver object and init its dispatch table. + */ +_EGLDriver * +_eglMain(const char *args) +{ + struct GLX_egl_driver *GLX_drv = CALLOC_STRUCT(GLX_egl_driver); + + if (!GLX_drv) + return NULL; + + _eglInitDriverFallbacks(&GLX_drv->Base); + GLX_drv->Base.API.Initialize = GLX_eglInitialize; + GLX_drv->Base.API.Terminate = GLX_eglTerminate; + GLX_drv->Base.API.CreateContext = GLX_eglCreateContext; + GLX_drv->Base.API.MakeCurrent = GLX_eglMakeCurrent; + GLX_drv->Base.API.CreateWindowSurface = GLX_eglCreateWindowSurface; +#ifdef GLX_VERSION_1_3 + GLX_drv->Base.API.CreatePixmapSurface = GLX_eglCreatePixmapSurface; + GLX_drv->Base.API.CreatePbufferSurface = GLX_eglCreatePbufferSurface; +#endif + GLX_drv->Base.API.DestroySurface = GLX_eglDestroySurface; + GLX_drv->Base.API.BindTexImage = GLX_eglBindTexImage; + GLX_drv->Base.API.ReleaseTexImage = GLX_eglReleaseTexImage; + GLX_drv->Base.API.SwapBuffers = GLX_eglSwapBuffers; + GLX_drv->Base.API.GetProcAddress = GLX_eglGetProcAddress; + + GLX_drv->Base.Name = "GLX"; + GLX_drv->Base.Unload = GLX_Unload; + + return &GLX_drv->Base; +} diff --git a/src/egl/drivers/xdri/Makefile b/src/egl/drivers/xdri/Makefile new file mode 100644 index 0000000000..4c1fc9071c --- /dev/null +++ b/src/egl/drivers/xdri/Makefile @@ -0,0 +1,78 @@ +# src/egl/drivers/xdri/Makefile + +# Build XEGL DRI driver loader library: egl_xdri.so + + +TOP = ../../../.. +include $(TOP)/configs/current + + +DRIVER_NAME = egl_xdri.so + + +INCLUDE_DIRS = \ + -I. \ + -I/usr/include \ + $(shell pkg-config --cflags-only-I libdrm) \ + -I$(TOP)/include \ + -I$(TOP)/include/GL/internal \ + -I$(TOP)/src/mesa \ + -I$(TOP)/src/mesa/glapi \ + -I$(TOP)/src/egl/main \ + -I$(TOP)/src/glx/x11 + +HEADERS = glxinit.h driinit.h +SOURCES = egl_xdri.c glxinit.c driinit.c + +DRI_SOURCES = dri_common.c XF86dri.c dri2.c dri2_glx.c dri_glx.c +DRI_SOURCES := $(addprefix ../../../glx/x11/,$(DRI_SOURCES)) + +SOURCES += $(DRI_SOURCES) + +OBJECTS = $(SOURCES:.c=.o) + +DRM_LIB = `pkg-config --libs libdrm` + +CFLAGS += -DGLX_DIRECT_RENDERING + +.c.o: + $(CC) -c $(INCLUDE_DIRS) $(CFLAGS) $< -o $@ + + +.PHONY: library + + +default: depend library Makefile + + +library: $(TOP)/$(LIB_DIR)/$(DRIVER_NAME) + + +# Make the egl_xdri.so library +$(TOP)/$(LIB_DIR)/$(DRIVER_NAME): $(OBJECTS) + $(TOP)/bin/mklib -o $(DRIVER_NAME) \ + -noprefix \ + -major 1 -minor 0 \ + -L$(TOP)/$(LIB_DIR) \ + -install $(TOP)/$(LIB_DIR) \ + $(OBJECTS) $(DRM_LIB) $(GL_LIB_DEPS) + +install: + $(INSTALL) -d $(DESTDIR)$(INSTALL_LIB_DIR) + $(MINSTALL) $(TOP)/$(LIB_DIR)/$(DRIVER_NAME) $(DESTDIR)$(INSTALL_LIB_DIR) + +clean: + rm -f *.o + rm -f *.so + rm -f depend depend.bak + + +depend: $(SOURCES) $(HEADERS) + @ echo "running $(MKDEP)" + @ rm -f depend + @ touch depend + $(MKDEP) $(MKDEP_OPTIONS) $(DEFINES) $(INCLUDE_DIRS) \ + $(SOURCES) $(HEADERS) >/dev/null 2>/dev/null + +include depend +# DO NOT DELETE diff --git a/src/egl/drivers/xdri/driinit.c b/src/egl/drivers/xdri/driinit.c new file mode 100644 index 0000000000..12da1bcd24 --- /dev/null +++ b/src/egl/drivers/xdri/driinit.c @@ -0,0 +1,67 @@ +/** + * DRI initialization. The DRI loaders are defined in src/glx/x11/. + */ + +#include <sys/time.h> + +#include "glxclient.h" +#include "driinit.h" + +/* for __DRI_SYSTEM_TIME extension */ +_X_HIDDEN int +__glXGetUST(int64_t * ust) +{ + struct timeval tv; + + if (ust == NULL) { + return -EFAULT; + } + + if (gettimeofday(&tv, NULL) == 0) { + ust[0] = (tv.tv_sec * 1000000) + tv.tv_usec; + return 0; + } + else { + return -errno; + } +} + +_X_HIDDEN GLboolean +__driGetMscRateOML(__DRIdrawable * draw, + int32_t * numerator, int32_t * denominator, void *private) +{ + return GL_FALSE; +} + +/* ignore glx extensions */ +_X_HIDDEN void +__glXEnableDirectExtension(__GLXscreenConfigs * psc, const char *name) +{ +} + +_X_HIDDEN __GLXDRIdisplay * +__driCreateDisplay(__GLXdisplayPrivate *dpyPriv, int *version) +{ + __GLXDRIdisplay *driDisplay; + int ver = 0; + + /* try DRI2 first */ + driDisplay = dri2CreateDisplay(dpyPriv->dpy); + if (driDisplay) { + /* fill in the required field */ + dpyPriv->dri2Display = driDisplay; + ver = 2; + } + else { + /* try DRI */ + driDisplay = driCreateDisplay(dpyPriv->dpy); + if (driDisplay) { + dpyPriv->driDisplay = driDisplay; + ver = 1; + } + } + + if (version) + *version = ver; + return driDisplay; +} diff --git a/src/egl/drivers/xdri/driinit.h b/src/egl/drivers/xdri/driinit.h new file mode 100644 index 0000000000..6ea05cebef --- /dev/null +++ b/src/egl/drivers/xdri/driinit.h @@ -0,0 +1,9 @@ +#ifndef DRIINIT_INCLUDED +#define DRIINIT_INCLUDED + +#include "glxclient.h" + +extern __GLXDRIdisplay * +__driCreateDisplay(__GLXdisplayPrivate *dpyPriv, int *version); + +#endif /* DRIINIT_INCLUDED */ diff --git a/src/egl/drivers/xdri/egl_xdri.c b/src/egl/drivers/xdri/egl_xdri.c new file mode 100644 index 0000000000..9793e4f8b4 --- /dev/null +++ b/src/egl/drivers/xdri/egl_xdri.c @@ -0,0 +1,784 @@ +/************************************************************************** + * + * Copyright 2008 Tungsten Graphics, Inc., Cedar Park, Texas. + * All Rights Reserved. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the + * "Software"), to deal in the Software without restriction, including + * without limitation the rights to use, copy, modify, merge, publish, + * distribute, sub license, and/or sell copies of the Software, and to + * permit persons to whom the Software is furnished to do so, subject to + * the following conditions: + * + * The above copyright notice and this permission notice (including the + * next paragraph) shall be included in all copies or substantial portions + * of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS + * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. + * IN NO EVENT SHALL TUNGSTEN GRAPHICS AND/OR ITS SUPPLIERS BE LIABLE FOR + * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, + * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE + * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + * + **************************************************************************/ + + +/** + * Code to interface a DRI driver to libEGL. + * Note that unlike previous DRI/EGL interfaces, this one is meant to + * be used _with_ X. Applications will use eglCreateWindowSurface() + * to render into X-created windows. + * + * This is an EGL driver that, in turn, loads a regular DRI driver. + * There are some dependencies on code in libGL, but those could be + * removed with some effort. + * + * Authors: Brian Paul + */ + +#include <assert.h> +#include <stdlib.h> +#include <X11/Xlib.h> + +#include "glxinit.h" +#include "driinit.h" +#include "glapi/glapi.h" /* for glapi functions */ + +#include "eglconfig.h" +#include "eglcontext.h" +#include "egldisplay.h" +#include "egldriver.h" +#include "eglglobals.h" +#include "egllog.h" +#include "eglsurface.h" +#include "eglimage.h" + +#include "EGL/internal/eglimage_dri.h" + +#define MAX_DEPTH 32 +#define CALLOC_STRUCT(T) (struct T *) calloc(1, sizeof(struct T)) + +/** subclass of _EGLDriver */ +struct xdri_egl_driver +{ + _EGLDriver Base; /**< base class */ + void (*FlushCurrentContext)(void); +}; + + +/** driver data of _EGLDisplay */ +struct xdri_egl_display +{ + Display *dpy; + __GLXdisplayPrivate *dpyPriv; + __GLXDRIdisplay *driDisplay; + + __GLXscreenConfigs *psc; + EGLint scr; + + const __GLcontextModes *imageConfigs[MAX_DEPTH + 1]; +}; + + +/** subclass of _EGLContext */ +struct xdri_egl_context +{ + _EGLContext Base; /**< base class */ + + /* just enough info to create dri contexts */ + GLXContext dummy_gc; + + __GLXDRIcontext *driContext; +}; + + +/** subclass of _EGLSurface */ +struct xdri_egl_surface +{ + _EGLSurface Base; /**< base class */ + + Drawable drawable; + __GLXDRIdrawable *driDrawable; +}; + + +/** subclass of _EGLImage */ +struct xdri_egl_image +{ + _EGLImage Base; /**< base class */ + + Drawable pixmap; + __GLXDRIdrawable *driDrawable; +}; + + +/** subclass of _EGLConfig */ +struct xdri_egl_config +{ + _EGLConfig Base; /**< base class */ + + const __GLcontextModes *mode; /**< corresponding GLX mode */ +}; + + + +/** cast wrapper */ +static INLINE struct xdri_egl_driver * +xdri_egl_driver(_EGLDriver *drv) +{ + return (struct xdri_egl_driver *) drv; +} + + +static INLINE struct xdri_egl_display * +lookup_display(_EGLDisplay *dpy) +{ + return (struct xdri_egl_display *) dpy->DriverData; +} + + +/** Map EGLSurface handle to xdri_egl_surface object */ +static INLINE struct xdri_egl_surface * +lookup_surface(_EGLSurface *surface) +{ + return (struct xdri_egl_surface *) surface; +} + + +/** Map EGLContext handle to xdri_egl_context object */ +static INLINE struct xdri_egl_context * +lookup_context(_EGLContext *context) +{ + return (struct xdri_egl_context *) context; +} + + +/** Map EGLConfig handle to xdri_egl_config object */ +static INLINE struct xdri_egl_config * +lookup_config(_EGLConfig *conf) +{ + return (struct xdri_egl_config *) conf; +} + + +/** Map EGLImage handle to xdri_egl_image object */ +static INLINE struct xdri_egl_image * +lookup_image(_EGLImage *img) +{ + return (struct xdri_egl_image *) img; +} + + +/** Get size of given window */ +static Status +get_drawable_size(Display *dpy, Drawable d, uint *width, uint *height) +{ + Window root; + Status stat; + int xpos, ypos; + unsigned int w, h, bw, depth; + stat = XGetGeometry(dpy, d, &root, &xpos, &ypos, &w, &h, &bw, &depth); + *width = w; + *height = h; + return stat; +} + + +#if EGL_KHR_image_base +/** Get depth of given window */ +static Status +get_drawable_depth(Display *dpy, Drawable d, uint *depth_ret) +{ + Window root; + Status stat; + int xpos, ypos; + unsigned int w, h, bw, depth; + stat = XGetGeometry(dpy, d, &root, &xpos, &ypos, &w, &h, &bw, &depth); + *depth_ret = depth; + return stat; +} + + +/** + * The config of a pixmap must be guessed from its depth. Do the guess once + * for all depths. + */ +static void +find_image_configs(_EGLDisplay *dpy, const __GLcontextModes *modes) +{ + struct xdri_egl_display *xdri_dpy = lookup_display(dpy); + EGLint depth; + + for (depth = 0; depth < MAX_DEPTH + 1; depth++) { + const __GLcontextModes *m; + + for (m = modes; m; m = m->next) { + /* the depth of a pixmap might not include alpha */ + if (m->rgbBits != depth && (m->rgbBits - m->alphaBits) != depth) + continue; + if (!m->visualID) + continue; + + if (depth == 32) { + if (m->bindToTextureRgba) { + xdri_dpy->imageConfigs[depth] = m; + break; + } + } + + if (m->bindToTextureRgb) { + xdri_dpy->imageConfigs[depth] = m; + break; + } + } + + if (m) + _eglLog(_EGL_DEBUG, "Use mode 0x%02x for depth %d", + m->visualID, depth); + } +} +#endif /* EGL_KHR_image_base */ + + +/** + * Produce a set of EGL configs. + */ +static EGLint +create_configs(_EGLDisplay *disp, const __GLcontextModes *m, EGLint first_id) +{ + static const EGLint all_apis = (EGL_OPENGL_ES_BIT | + EGL_OPENGL_ES2_BIT | + EGL_OPENVG_BIT | + EGL_OPENGL_BIT); + int id = first_id; + + for (; m; m = m->next) { + /* add double buffered visual */ + if (m->doubleBufferMode) { + struct xdri_egl_config *config = CALLOC_STRUCT(xdri_egl_config); + + _eglInitConfig(&config->Base, id++); + + SET_CONFIG_ATTRIB(&config->Base, EGL_BUFFER_SIZE, m->rgbBits); + SET_CONFIG_ATTRIB(&config->Base, EGL_RED_SIZE, m->redBits); + SET_CONFIG_ATTRIB(&config->Base, EGL_GREEN_SIZE, m->greenBits); + SET_CONFIG_ATTRIB(&config->Base, EGL_BLUE_SIZE, m->blueBits); + SET_CONFIG_ATTRIB(&config->Base, EGL_ALPHA_SIZE, m->alphaBits); + SET_CONFIG_ATTRIB(&config->Base, EGL_DEPTH_SIZE, m->depthBits); + SET_CONFIG_ATTRIB(&config->Base, EGL_STENCIL_SIZE, m->stencilBits); + SET_CONFIG_ATTRIB(&config->Base, EGL_SAMPLES, m->samples); + SET_CONFIG_ATTRIB(&config->Base, EGL_SAMPLE_BUFFERS, m->sampleBuffers); + SET_CONFIG_ATTRIB(&config->Base, EGL_NATIVE_VISUAL_ID, m->visualID); + SET_CONFIG_ATTRIB(&config->Base, EGL_NATIVE_VISUAL_TYPE, m->visualType); + SET_CONFIG_ATTRIB(&config->Base, EGL_CONFORMANT, all_apis); + SET_CONFIG_ATTRIB(&config->Base, EGL_RENDERABLE_TYPE, all_apis); + SET_CONFIG_ATTRIB(&config->Base, EGL_SURFACE_TYPE, EGL_WINDOW_BIT); + + /* XXX possibly other things to init... */ + + /* Ptr from EGL config to GLcontextMode. Used in CreateContext(). */ + config->mode = m; + + _eglAddConfig(disp, &config->Base); + } + } + + return id; +} + + +/** + * Called via eglInitialize(), xdri_dpy->API.Initialize(). + */ +static EGLBoolean +xdri_eglInitialize(_EGLDriver *drv, _EGLDisplay *dpy, + EGLint *minor, EGLint *major) +{ + struct xdri_egl_display *xdri_dpy; + __GLXdisplayPrivate *dpyPriv; + __GLXDRIdisplay *driDisplay; + __GLXscreenConfigs *psc; + EGLint first_id = 1; + int scr; + + xdri_dpy = CALLOC_STRUCT(xdri_egl_display); + if (!xdri_dpy) + return _eglError(EGL_BAD_ALLOC, "eglInitialize"); + + xdri_dpy->dpy = (Display *) dpy->NativeDisplay; + if (!xdri_dpy->dpy) { + xdri_dpy->dpy = XOpenDisplay(NULL); + if (!xdri_dpy->dpy) { + free(xdri_dpy); + return _eglError(EGL_NOT_INITIALIZED, "eglInitialize"); + } + } + + dpyPriv = __glXInitialize(xdri_dpy->dpy); + if (!dpyPriv) { + _eglLog(_EGL_WARNING, "failed to create GLX display"); + free(xdri_dpy); + return _eglError(EGL_NOT_INITIALIZED, "eglInitialize"); + } + + driDisplay = __driCreateDisplay(dpyPriv, NULL); + if (!driDisplay) { + _eglLog(_EGL_WARNING, "failed to create DRI display"); + free(xdri_dpy); + return _eglError(EGL_NOT_INITIALIZED, "eglInitialize"); + } + + scr = DefaultScreen(xdri_dpy->dpy); + psc = &dpyPriv->screenConfigs[scr]; + + xdri_dpy->dpyPriv = dpyPriv; + xdri_dpy->driDisplay = driDisplay; + xdri_dpy->psc = psc; + xdri_dpy->scr = scr; + + psc->driScreen = driDisplay->createScreen(psc, scr, dpyPriv); + if (!psc->driScreen) { + _eglLog(_EGL_WARNING, "failed to create DRI screen #%d", scr); + free(xdri_dpy); + return _eglError(EGL_NOT_INITIALIZED, "eglInitialize"); + } + + /* add visuals and fbconfigs */ + first_id = create_configs(dpy, psc->visuals, first_id); + create_configs(dpy, psc->configs, first_id); + + dpy->DriverData = xdri_dpy; + dpy->ClientAPIsMask = (EGL_OPENGL_BIT | + EGL_OPENGL_ES_BIT | + EGL_OPENGL_ES2_BIT | + EGL_OPENVG_BIT); + +#if EGL_KHR_image_base + /* must be called after DriverData is set */ + find_image_configs(dpy, psc->configs); + + dpy->Extensions.KHR_image = EGL_TRUE; + dpy->Extensions.KHR_image_base = EGL_TRUE; + dpy->Extensions.KHR_image_pixmap = EGL_TRUE; +#endif + + /* we're supporting EGL 1.4 */ + *minor = 1; + *major = 4; + + return EGL_TRUE; +} + + +/** + * Called via eglTerminate(), drv->API.Terminate(). + */ +static EGLBoolean +xdri_eglTerminate(_EGLDriver *drv, _EGLDisplay *dpy) +{ + struct xdri_egl_display *xdri_dpy = lookup_display(dpy); + __GLXscreenConfigs *psc; + + _eglReleaseDisplayResources(drv, dpy); + _eglCleanupDisplay(dpy); + + psc = xdri_dpy->psc; + if (psc->driver_configs) { + unsigned int i; + for (i = 0; psc->driver_configs[i]; i++) + free((__DRIconfig *) psc->driver_configs[i]); + free(psc->driver_configs); + psc->driver_configs = NULL; + } + if (psc->driScreen) { + psc->driScreen->destroyScreen(psc); + free(psc->driScreen); + psc->driScreen = NULL; + } + + xdri_dpy->driDisplay->destroyDisplay(xdri_dpy->driDisplay); + __glXRelease(xdri_dpy->dpyPriv); + + free(xdri_dpy); + dpy->DriverData = NULL; + + return EGL_TRUE; +} + + +/* + * Called from eglGetProcAddress() via drv->API.GetProcAddress(). + */ +static _EGLProc +xdri_eglGetProcAddress(const char *procname) +{ + /* the symbol is defined in libGL.so */ + return (_EGLProc) _glapi_get_proc_address(procname); +} + + +/** + * Called via eglCreateContext(), drv->API.CreateContext(). + */ +static _EGLContext * +xdri_eglCreateContext(_EGLDriver *drv, _EGLDisplay *dpy, _EGLConfig *conf, + _EGLContext *share_list, const EGLint *attrib_list) +{ + struct xdri_egl_display *xdri_dpy = lookup_display(dpy); + struct xdri_egl_config *xdri_config = lookup_config(conf); + struct xdri_egl_context *shared = lookup_context(share_list); + __GLXscreenConfigs *psc = xdri_dpy->psc; + int renderType = GLX_RGBA_BIT; + struct xdri_egl_context *xdri_ctx; + + xdri_ctx = CALLOC_STRUCT(xdri_egl_context); + if (!xdri_ctx) { + _eglError(EGL_BAD_ALLOC, "eglCreateContext"); + return NULL; + } + + xdri_ctx->dummy_gc = CALLOC_STRUCT(__GLXcontextRec); + if (!xdri_ctx->dummy_gc) { + _eglError(EGL_BAD_ALLOC, "eglCreateContext"); + free(xdri_ctx); + return NULL; + } + + if (!_eglInitContext(drv, &xdri_ctx->Base, &xdri_config->Base, attrib_list)) { + free(xdri_ctx->dummy_gc); + free(xdri_ctx); + return NULL; + } + + xdri_ctx->driContext = + psc->driScreen->createContext(psc, + xdri_config->mode, + xdri_ctx->dummy_gc, + (shared) ? shared->dummy_gc : NULL, + renderType); + if (!xdri_ctx->driContext) { + free(xdri_ctx->dummy_gc); + free(xdri_ctx); + return NULL; + } + + /* fill in the required field */ + xdri_ctx->dummy_gc->driContext = xdri_ctx->driContext; + + return &xdri_ctx->Base; +} + + +static EGLBoolean +xdri_eglDestroyContext(_EGLDriver *drv, _EGLDisplay *dpy, _EGLContext *ctx) +{ + struct xdri_egl_display *xdri_dpy = lookup_display(dpy); + struct xdri_egl_context *xdri_ctx = lookup_context(ctx); + + if (!_eglIsContextBound(ctx)) { + xdri_ctx->driContext->destroyContext(xdri_ctx->driContext, + xdri_dpy->psc, xdri_dpy->dpy); + free(xdri_ctx->dummy_gc); + free(xdri_ctx); + } + + return EGL_TRUE; +} + + +/** + * Called via eglMakeCurrent(), drv->API.MakeCurrent(). + */ +static EGLBoolean +xdri_eglMakeCurrent(_EGLDriver *drv, _EGLDisplay *dpy, _EGLSurface *d, + _EGLSurface *r, _EGLContext *context) +{ + struct xdri_egl_driver *xdri_driver = xdri_egl_driver(drv); + struct xdri_egl_context *xdri_ctx = lookup_context(context); + struct xdri_egl_surface *draw = lookup_surface(d); + struct xdri_egl_surface *read = lookup_surface(r); + _EGLContext *old = _eglGetCurrentContext(); + + /* an unlinked context will be invalid after context switch */ + if (!_eglIsContextLinked(old)) + old = NULL; + + if (!_eglMakeCurrent(drv, dpy, d, r, context)) + return EGL_FALSE; + + /* flush before context switch */ + if (old && old != context && xdri_driver->FlushCurrentContext) + xdri_driver->FlushCurrentContext(); + + /* the symbol is defined in libGL.so */ + _glapi_check_multithread(); + + if (xdri_ctx) { + if (!xdri_ctx->driContext->bindContext(xdri_ctx->driContext, + draw->driDrawable, + read->driDrawable)) { + return EGL_FALSE; + } + } + else if (old) { + xdri_ctx = lookup_context(old); + xdri_ctx->driContext->unbindContext(xdri_ctx->driContext); + } + + return EGL_TRUE; +} + + +/** + * Called via eglCreateWindowSurface(), drv->API.CreateWindowSurface(). + */ +static _EGLSurface * +xdri_eglCreateWindowSurface(_EGLDriver *drv, _EGLDisplay *dpy, _EGLConfig *conf, + NativeWindowType window, const EGLint *attrib_list) +{ + struct xdri_egl_display *xdri_dpy = lookup_display(dpy); + struct xdri_egl_config *xdri_config = lookup_config(conf); + struct xdri_egl_surface *xdri_surf; + uint width, height; + + xdri_surf = CALLOC_STRUCT(xdri_egl_surface); + if (!xdri_surf) { + _eglError(EGL_BAD_ALLOC, "eglCreateWindowSurface"); + return NULL; + } + + if (!_eglInitSurface(drv, &xdri_surf->Base, EGL_WINDOW_BIT, + &xdri_config->Base, attrib_list)) { + free(xdri_surf); + return NULL; + } + + xdri_surf->driDrawable = + xdri_dpy->psc->driScreen->createDrawable(xdri_dpy->psc, + (XID) window, + (GLXDrawable) window, + xdri_config->mode); + if (!xdri_surf->driDrawable) { + free(xdri_surf); + return NULL; + } + + xdri_surf->drawable = (Drawable) window; + + get_drawable_size(xdri_dpy->dpy, window, &width, &height); + xdri_surf->Base.Width = width; + xdri_surf->Base.Height = height; + + return &xdri_surf->Base; +} + + +/** + * Called via eglCreatePbufferSurface(), drv->API.CreatePbufferSurface(). + */ +static _EGLSurface * +xdri_eglCreatePbufferSurface(_EGLDriver *drv, _EGLDisplay *dpy, _EGLConfig *conf, + const EGLint *attrib_list) +{ + return NULL; +} + + + +static EGLBoolean +xdri_eglDestroySurface(_EGLDriver *drv, _EGLDisplay *dpy, _EGLSurface *surface) +{ + struct xdri_egl_surface *xdri_surf = lookup_surface(surface); + + if (!_eglIsSurfaceBound(&xdri_surf->Base)) { + xdri_surf->driDrawable->destroyDrawable(xdri_surf->driDrawable); + free(xdri_surf); + } + + return EGL_TRUE; +} + + +static EGLBoolean +xdri_eglBindTexImage(_EGLDriver *drv, _EGLDisplay *dpy, _EGLSurface *surf, + EGLint buffer) +{ + return EGL_FALSE; +} + + +static EGLBoolean +xdri_eglReleaseTexImage(_EGLDriver *drv, _EGLDisplay *dpy, _EGLSurface *surf, + EGLint buffer) +{ + return EGL_FALSE; +} + + +static EGLBoolean +xdri_eglSwapBuffers(_EGLDriver *drv, _EGLDisplay *dpy, _EGLSurface *draw) +{ + struct xdri_egl_driver *xdri_driver = xdri_egl_driver(drv); + struct xdri_egl_display *xdri_dpy = lookup_display(dpy); + struct xdri_egl_surface *xdri_surf = lookup_surface(draw); + + /* swapBuffers does not flush commands */ + if (draw == _eglGetCurrentSurface(EGL_DRAW) && + xdri_driver->FlushCurrentContext) + xdri_driver->FlushCurrentContext(); + + xdri_dpy->psc->driScreen->swapBuffers(xdri_surf->driDrawable); + + return EGL_TRUE; +} + + +#if EGL_KHR_image_base + + +static _EGLImage * +xdri_eglCreateImageKHR(_EGLDriver *drv, _EGLDisplay *dpy, _EGLContext *ctx, + EGLenum target, EGLClientBuffer buffer, const EGLint *attr_list) +{ + struct xdri_egl_display *xdri_dpy = lookup_display(dpy); + struct xdri_egl_image *xdri_img; + __DRIEGLImage *driImage; + EGLint err = EGL_SUCCESS; + const __GLcontextModes *mode; + uint depth; + + xdri_img = CALLOC_STRUCT(xdri_egl_image); + if (!xdri_img) { + _eglError(EGL_BAD_ALLOC, "eglCreateImageKHR"); + return NULL; + } + + switch (target) { + case EGL_NATIVE_PIXMAP_KHR: + if (ctx) { + err = EGL_BAD_PARAMETER; + break; + } + xdri_img->pixmap = (Pixmap) buffer; + break; + default: + err = EGL_BAD_PARAMETER; + break; + } + + if (err != EGL_SUCCESS) { + _eglError(EGL_BAD_PARAMETER, "eglCreateImageKHR"); + free(xdri_img); + return NULL; + } + + if (!_eglInitImage(drv, &xdri_img->Base, attr_list)) { + free(xdri_img); + return NULL; + } + if (!get_drawable_depth(xdri_dpy->dpy, xdri_img->pixmap, &depth) || + depth > MAX_DEPTH) { + free(xdri_img); + return NULL; + } + mode = xdri_dpy->imageConfigs[depth]; + if (!mode) { + free(xdri_img); + return NULL; + } + + driImage = CALLOC_STRUCT(__DRIEGLImageRec); + if (!driImage) { + _eglError(EGL_BAD_ALLOC, "eglCreateImageKHR"); + free(xdri_img); + return NULL; + } + + xdri_img->driDrawable = + xdri_dpy->psc->driScreen->createDrawable(xdri_dpy->psc, + (XID) xdri_img->pixmap, + (GLXDrawable) xdri_img->pixmap, + mode); + if (!xdri_img->driDrawable) { + free(driImage); + free(xdri_img); + return NULL; + } + + driImage->magic = __DRI_EGL_IMAGE_MAGIC; + driImage->drawable = xdri_img->driDrawable->driDrawable; + driImage->texture_format_rgba = (depth == 32 && mode->bindToTextureRgba); + driImage->level = 0; + + xdri_img->Base.ClientData = (void *) driImage; + + return &xdri_img->Base; +} + + +static EGLBoolean +xdri_eglDestroyImageKHR(_EGLDriver *drv, _EGLDisplay *dpy, _EGLImage *img) +{ + struct xdri_egl_image *xdri_img = lookup_image(img); + + free(xdri_img->Base.ClientData); + xdri_img->driDrawable->destroyDrawable(xdri_img->driDrawable); + free(xdri_img); + return EGL_TRUE; +} + + +#endif /* EGL_KHR_image_base */ + + +static void +xdri_Unload(_EGLDriver *drv) +{ + struct xdri_egl_driver *xdri_drv = xdri_egl_driver(drv); + free(xdri_drv); +} + + +/** + * This is the main entrypoint into the driver, called by libEGL. + * Create a new _EGLDriver object and init its dispatch table. + */ +_EGLDriver * +_eglMain(const char *args) +{ + struct xdri_egl_driver *xdri_drv = CALLOC_STRUCT(xdri_egl_driver); + if (!xdri_drv) + return NULL; + + _eglInitDriverFallbacks(&xdri_drv->Base); + xdri_drv->Base.API.Initialize = xdri_eglInitialize; + xdri_drv->Base.API.Terminate = xdri_eglTerminate; + + xdri_drv->Base.API.GetProcAddress = xdri_eglGetProcAddress; + + xdri_drv->Base.API.CreateContext = xdri_eglCreateContext; + xdri_drv->Base.API.DestroyContext = xdri_eglDestroyContext; + xdri_drv->Base.API.MakeCurrent = xdri_eglMakeCurrent; + xdri_drv->Base.API.CreateWindowSurface = xdri_eglCreateWindowSurface; + xdri_drv->Base.API.CreatePbufferSurface = xdri_eglCreatePbufferSurface; + xdri_drv->Base.API.DestroySurface = xdri_eglDestroySurface; + xdri_drv->Base.API.BindTexImage = xdri_eglBindTexImage; + xdri_drv->Base.API.ReleaseTexImage = xdri_eglReleaseTexImage; + xdri_drv->Base.API.SwapBuffers = xdri_eglSwapBuffers; +#if EGL_KHR_image_base + xdri_drv->Base.API.CreateImageKHR = xdri_eglCreateImageKHR; + xdri_drv->Base.API.DestroyImageKHR = xdri_eglDestroyImageKHR; +#endif /* EGL_KHR_image_base */ + + xdri_drv->Base.Name = "X/DRI"; + xdri_drv->Base.Unload = xdri_Unload; + + /* we need a way to flush commands */ + xdri_drv->FlushCurrentContext = + (void (*)(void)) xdri_eglGetProcAddress("glFlush"); + + return &xdri_drv->Base; +} diff --git a/src/egl/drivers/xdri/glxinit.c b/src/egl/drivers/xdri/glxinit.c new file mode 100644 index 0000000000..7775009394 --- /dev/null +++ b/src/egl/drivers/xdri/glxinit.c @@ -0,0 +1,626 @@ +/** + * GLX initialization. Code based on glxext.c, glx_query.c, and + * glcontextmodes.c under src/glx/x11/. The major difference is that no DRI + * related code here. + * + */ + +#include <assert.h> +#include <X11/Xlib.h> +#include <X11/Xproto.h> +#include <X11/extensions/Xext.h> +#include <X11/extensions/extutil.h> +#include <sys/time.h> + +#include "glxinit.h" + +typedef struct GLXGenericGetString +{ + CARD8 reqType; + CARD8 glxCode; + CARD16 length B16; + CARD32 for_whom B32; + CARD32 name B32; +} xGLXGenericGetStringReq; + +#define sz_xGLXGenericGetStringReq 12 +#define X_GLXGenericGetString 0 + +/* Extension required boiler plate */ + +static char *__glXExtensionName = GLX_EXTENSION_NAME; +static XExtensionInfo *__glXExtensionInfo = NULL; + +static /* const */ XExtensionHooks __glXExtensionHooks = { NULL }; +static +XEXT_GENERATE_FIND_DISPLAY(__glXFindDisplay, __glXExtensionInfo, + __glXExtensionName, &__glXExtensionHooks, + __GLX_NUMBER_EVENTS, NULL) + +static GLint +_gl_convert_from_x_visual_type(int visualType) +{ +#define NUM_VISUAL_TYPES 6 + static const int glx_visual_types[NUM_VISUAL_TYPES] = { + GLX_STATIC_GRAY, GLX_GRAY_SCALE, + GLX_STATIC_COLOR, GLX_PSEUDO_COLOR, + GLX_TRUE_COLOR, GLX_DIRECT_COLOR + }; + + return ((unsigned) visualType < NUM_VISUAL_TYPES) + ? glx_visual_types[visualType] : GLX_NONE; +} + +static __GLcontextModes * +_gl_context_modes_create(unsigned count, size_t minimum_size) +{ + const size_t size = (minimum_size > sizeof(__GLcontextModes)) + ? minimum_size : sizeof(__GLcontextModes); + __GLcontextModes *base = NULL; + __GLcontextModes **next; + unsigned i; + + next = &base; + for (i = 0; i < count; i++) { + *next = (__GLcontextModes *) Xmalloc(size); + if (*next == NULL) { + _gl_context_modes_destroy(base); + base = NULL; + break; + } + + memset(*next, 0, size); + (*next)->visualID = GLX_DONT_CARE; + (*next)->visualType = GLX_DONT_CARE; + (*next)->visualRating = GLX_NONE; + (*next)->transparentPixel = GLX_NONE; + (*next)->transparentRed = GLX_DONT_CARE; + (*next)->transparentGreen = GLX_DONT_CARE; + (*next)->transparentBlue = GLX_DONT_CARE; + (*next)->transparentAlpha = GLX_DONT_CARE; + (*next)->transparentIndex = GLX_DONT_CARE; + (*next)->xRenderable = GLX_DONT_CARE; + (*next)->fbconfigID = GLX_DONT_CARE; + (*next)->swapMethod = GLX_SWAP_UNDEFINED_OML; + (*next)->bindToTextureRgb = GLX_DONT_CARE; + (*next)->bindToTextureRgba = GLX_DONT_CARE; + (*next)->bindToMipmapTexture = GLX_DONT_CARE; + (*next)->bindToTextureTargets = GLX_DONT_CARE; + (*next)->yInverted = GLX_DONT_CARE; + + next = &((*next)->next); + } + + return base; +} + +_X_HIDDEN void +_gl_context_modes_destroy(__GLcontextModes * modes) +{ + while (modes != NULL) { + __GLcontextModes *const next = modes->next; + + Xfree(modes); + modes = next; + } +} + +_X_HIDDEN char * +__glXQueryServerString(Display * dpy, int opcode, CARD32 screen, CARD32 name) +{ + xGLXGenericGetStringReq *req; + xGLXSingleReply reply; + int length; + int numbytes; + char *buf; + CARD32 for_whom = screen; + CARD32 glxCode = X_GLXQueryServerString; + + + LockDisplay(dpy); + + + /* All of the GLX protocol requests for getting a string from the server + * look the same. The exact meaning of the for_whom field is usually + * either the screen number (for glXQueryServerString) or the context tag + * (for GLXSingle). + */ + + GetReq(GLXGenericGetString, req); + req->reqType = opcode; + req->glxCode = glxCode; + req->for_whom = for_whom; + req->name = name; + + _XReply(dpy, (xReply *) & reply, 0, False); + + length = reply.length * 4; + numbytes = reply.size; + + buf = (char *) Xmalloc(numbytes); + if (buf != NULL) { + _XRead(dpy, buf, numbytes); + length -= numbytes; + } + + _XEatData(dpy, length); + + UnlockDisplay(dpy); + SyncHandle(); + + return buf; +} + +/************************************************************************/ +/* +** Free the per screen configs data as well as the array of +** __glXScreenConfigs. +*/ +static void +FreeScreenConfigs(__GLXdisplayPrivate * priv) +{ + __GLXscreenConfigs *psc; + GLint i, screens; + + /* Free screen configuration information */ + psc = priv->screenConfigs; + screens = ScreenCount(priv->dpy); + for (i = 0; i < screens; i++, psc++) { + if (psc->configs) { + _gl_context_modes_destroy(psc->configs); + psc->configs = NULL; /* NOTE: just for paranoia */ + } + if (psc->visuals) { + _gl_context_modes_destroy(psc->visuals); + psc->visuals = NULL; /* NOTE: just for paranoia */ + } + Xfree((char *) psc->serverGLXexts); + } + XFree((char *) priv->screenConfigs); + priv->screenConfigs = NULL; +} + +/************************************************************************/ + +/* +** Query the version of the GLX extension. This procedure works even if +** the client extension is not completely set up. +*/ +static Bool +QueryVersion(Display * dpy, int opcode, int *major, int *minor) +{ + xGLXQueryVersionReq *req; + xGLXQueryVersionReply reply; + + /* Send the glXQueryVersion request */ + LockDisplay(dpy); + GetReq(GLXQueryVersion, req); + req->reqType = opcode; + req->glxCode = X_GLXQueryVersion; + req->majorVersion = GLX_MAJOR_VERSION; + req->minorVersion = GLX_MINOR_VERSION; + _XReply(dpy, (xReply *) & reply, 0, False); + UnlockDisplay(dpy); + SyncHandle(); + + if (reply.majorVersion != GLX_MAJOR_VERSION) { + /* + ** The server does not support the same major release as this + ** client. + */ + return GL_FALSE; + } + *major = reply.majorVersion; + *minor = min(reply.minorVersion, GLX_MINOR_VERSION); + return GL_TRUE; +} + +_X_HIDDEN void +__glXInitializeVisualConfigFromTags(__GLcontextModes * config, int count, + const INT32 * bp, Bool tagged_only, + Bool fbconfig_style_tags) +{ + int i; + + if (!tagged_only) { + /* Copy in the first set of properties */ + config->visualID = *bp++; + + config->visualType = _gl_convert_from_x_visual_type(*bp++); + + config->rgbMode = *bp++; + + config->redBits = *bp++; + config->greenBits = *bp++; + config->blueBits = *bp++; + config->alphaBits = *bp++; + config->accumRedBits = *bp++; + config->accumGreenBits = *bp++; + config->accumBlueBits = *bp++; + config->accumAlphaBits = *bp++; + + config->doubleBufferMode = *bp++; + config->stereoMode = *bp++; + + config->rgbBits = *bp++; + config->depthBits = *bp++; + config->stencilBits = *bp++; + config->numAuxBuffers = *bp++; + config->level = *bp++; + + count -= __GLX_MIN_CONFIG_PROPS; + } + + /* + ** Additional properties may be in a list at the end + ** of the reply. They are in pairs of property type + ** and property value. + */ + +#define FETCH_OR_SET(tag) \ + config-> tag = ( fbconfig_style_tags ) ? *bp++ : 1 + + for (i = 0; i < count; i += 2) { + switch (*bp++) { + case GLX_RGBA: + FETCH_OR_SET(rgbMode); + break; + case GLX_BUFFER_SIZE: + config->rgbBits = *bp++; + break; + case GLX_LEVEL: + config->level = *bp++; + break; + case GLX_DOUBLEBUFFER: + FETCH_OR_SET(doubleBufferMode); + break; + case GLX_STEREO: + FETCH_OR_SET(stereoMode); + break; + case GLX_AUX_BUFFERS: + config->numAuxBuffers = *bp++; + break; + case GLX_RED_SIZE: + config->redBits = *bp++; + break; + case GLX_GREEN_SIZE: + config->greenBits = *bp++; + break; + case GLX_BLUE_SIZE: + config->blueBits = *bp++; + break; + case GLX_ALPHA_SIZE: + config->alphaBits = *bp++; + break; + case GLX_DEPTH_SIZE: + config->depthBits = *bp++; + break; + case GLX_STENCIL_SIZE: + config->stencilBits = *bp++; + break; + case GLX_ACCUM_RED_SIZE: + config->accumRedBits = *bp++; + break; + case GLX_ACCUM_GREEN_SIZE: + config->accumGreenBits = *bp++; + break; + case GLX_ACCUM_BLUE_SIZE: + config->accumBlueBits = *bp++; + break; + case GLX_ACCUM_ALPHA_SIZE: + config->accumAlphaBits = *bp++; + break; + case GLX_VISUAL_CAVEAT_EXT: + config->visualRating = *bp++; + break; + case GLX_X_VISUAL_TYPE: + config->visualType = *bp++; + break; + case GLX_TRANSPARENT_TYPE: + config->transparentPixel = *bp++; + break; + case GLX_TRANSPARENT_INDEX_VALUE: + config->transparentIndex = *bp++; + break; + case GLX_TRANSPARENT_RED_VALUE: + config->transparentRed = *bp++; + break; + case GLX_TRANSPARENT_GREEN_VALUE: + config->transparentGreen = *bp++; + break; + case GLX_TRANSPARENT_BLUE_VALUE: + config->transparentBlue = *bp++; + break; + case GLX_TRANSPARENT_ALPHA_VALUE: + config->transparentAlpha = *bp++; + break; + case GLX_VISUAL_ID: + config->visualID = *bp++; + break; + case GLX_DRAWABLE_TYPE: + config->drawableType = *bp++; + break; + case GLX_RENDER_TYPE: + config->renderType = *bp++; + break; + case GLX_X_RENDERABLE: + config->xRenderable = *bp++; + break; + case GLX_FBCONFIG_ID: + config->fbconfigID = *bp++; + break; + case GLX_MAX_PBUFFER_WIDTH: + config->maxPbufferWidth = *bp++; + break; + case GLX_MAX_PBUFFER_HEIGHT: + config->maxPbufferHeight = *bp++; + break; + case GLX_MAX_PBUFFER_PIXELS: + config->maxPbufferPixels = *bp++; + break; + case GLX_OPTIMAL_PBUFFER_WIDTH_SGIX: + config->optimalPbufferWidth = *bp++; + break; + case GLX_OPTIMAL_PBUFFER_HEIGHT_SGIX: + config->optimalPbufferHeight = *bp++; + break; + case GLX_VISUAL_SELECT_GROUP_SGIX: + config->visualSelectGroup = *bp++; + break; + case GLX_SWAP_METHOD_OML: + config->swapMethod = *bp++; + break; + case GLX_SAMPLE_BUFFERS_SGIS: + config->sampleBuffers = *bp++; + break; + case GLX_SAMPLES_SGIS: + config->samples = *bp++; + break; + case GLX_BIND_TO_TEXTURE_RGB_EXT: + config->bindToTextureRgb = *bp++; + break; + case GLX_BIND_TO_TEXTURE_RGBA_EXT: + config->bindToTextureRgba = *bp++; + break; + case GLX_BIND_TO_MIPMAP_TEXTURE_EXT: + config->bindToMipmapTexture = *bp++; + break; + case GLX_BIND_TO_TEXTURE_TARGETS_EXT: + config->bindToTextureTargets = *bp++; + break; + case GLX_Y_INVERTED_EXT: + config->yInverted = *bp++; + break; + case None: + i = count; + break; + default: + break; + } + } + + config->renderType = + (config->rgbMode) ? GLX_RGBA_BIT : GLX_COLOR_INDEX_BIT; + + config->haveAccumBuffer = ((config->accumRedBits + + config->accumGreenBits + + config->accumBlueBits + + config->accumAlphaBits) > 0); + config->haveDepthBuffer = (config->depthBits > 0); + config->haveStencilBuffer = (config->stencilBits > 0); +} + +static __GLcontextModes * +createConfigsFromProperties(Display * dpy, int nvisuals, int nprops, + int screen, GLboolean tagged_only) +{ + INT32 buf[__GLX_TOTAL_CONFIG], *props; + unsigned prop_size; + __GLcontextModes *modes, *m; + int i; + + if (nprops == 0) + return NULL; + + /* FIXME: Is the __GLX_MIN_CONFIG_PROPS test correct for FBconfigs? */ + + /* Check number of properties */ + if (nprops < __GLX_MIN_CONFIG_PROPS || nprops > __GLX_MAX_CONFIG_PROPS) + return NULL; + + /* Allocate memory for our config structure */ + modes = _gl_context_modes_create(nvisuals, sizeof(__GLcontextModes)); + if (!modes) + return NULL; + + prop_size = nprops * __GLX_SIZE_INT32; + if (prop_size <= sizeof(buf)) + props = buf; + else + props = Xmalloc(prop_size); + + /* Read each config structure and convert it into our format */ + m = modes; + for (i = 0; i < nvisuals; i++) { + _XRead(dpy, (char *) props, prop_size); + /* Older X servers don't send this so we default it here. */ + m->drawableType = GLX_WINDOW_BIT; + __glXInitializeVisualConfigFromTags(m, nprops, props, + tagged_only, GL_TRUE); + m->screen = screen; + m = m->next; + } + + if (props != buf) + Xfree(props); + + return modes; +} + +static GLboolean +getVisualConfigs(Display * dpy, __GLXdisplayPrivate * priv, int screen) +{ + xGLXGetVisualConfigsReq *req; + __GLXscreenConfigs *psc; + xGLXGetVisualConfigsReply reply; + + LockDisplay(dpy); + + psc = priv->screenConfigs + screen; + psc->visuals = NULL; + GetReq(GLXGetVisualConfigs, req); + req->reqType = priv->majorOpcode; + req->glxCode = X_GLXGetVisualConfigs; + req->screen = screen; + + if (!_XReply(dpy, (xReply *) & reply, 0, False)) + goto out; + + psc->visuals = createConfigsFromProperties(dpy, + reply.numVisuals, + reply.numProps, + screen, GL_FALSE); + + out: + UnlockDisplay(dpy); + return psc->visuals != NULL; +} + +static GLboolean +getFBConfigs(Display * dpy, __GLXdisplayPrivate * priv, int screen) +{ + xGLXGetFBConfigsReq *fb_req; + xGLXGetFBConfigsSGIXReq *sgi_req; + xGLXVendorPrivateWithReplyReq *vpreq; + xGLXGetFBConfigsReply reply; + __GLXscreenConfigs *psc; + + psc = priv->screenConfigs + screen; + psc->serverGLXexts = + __glXQueryServerString(dpy, priv->majorOpcode, screen, GLX_EXTENSIONS); + + LockDisplay(dpy); + + psc->configs = NULL; + if (atof(priv->serverGLXversion) >= 1.3) { + GetReq(GLXGetFBConfigs, fb_req); + fb_req->reqType = priv->majorOpcode; + fb_req->glxCode = X_GLXGetFBConfigs; + fb_req->screen = screen; + } + else if (strstr(psc->serverGLXexts, "GLX_SGIX_fbconfig") != NULL) { + GetReqExtra(GLXVendorPrivateWithReply, + sz_xGLXGetFBConfigsSGIXReq + + sz_xGLXVendorPrivateWithReplyReq, vpreq); + sgi_req = (xGLXGetFBConfigsSGIXReq *) vpreq; + sgi_req->reqType = priv->majorOpcode; + sgi_req->glxCode = X_GLXVendorPrivateWithReply; + sgi_req->vendorCode = X_GLXvop_GetFBConfigsSGIX; + sgi_req->screen = screen; + } + else + goto out; + + if (!_XReply(dpy, (xReply *) & reply, 0, False)) + goto out; + + psc->configs = createConfigsFromProperties(dpy, + reply.numFBConfigs, + reply.numAttribs * 2, + screen, GL_TRUE); + + out: + UnlockDisplay(dpy); + return psc->configs != NULL; +} + +static GLboolean +AllocAndFetchScreenConfigs(Display * dpy, __GLXdisplayPrivate * priv) +{ + __GLXscreenConfigs *psc; + GLint i, screens; + + /* + ** First allocate memory for the array of per screen configs. + */ + screens = ScreenCount(dpy); + psc = (__GLXscreenConfigs *) Xmalloc(screens * sizeof(__GLXscreenConfigs)); + if (!psc) { + return GL_FALSE; + } + memset(psc, 0, screens * sizeof(__GLXscreenConfigs)); + priv->screenConfigs = psc; + + priv->serverGLXversion = + __glXQueryServerString(dpy, priv->majorOpcode, 0, GLX_VERSION); + if (priv->serverGLXversion == NULL) { + FreeScreenConfigs(priv); + return GL_FALSE; + } + + for (i = 0; i < screens; i++, psc++) { + getFBConfigs(dpy, priv, i); + getVisualConfigs(dpy, priv, i); + psc->scr = i; + psc->dpy = dpy; + } + + SyncHandle(); + + return GL_TRUE; +} + +_X_HIDDEN void +__glXRelease(__GLXdisplayPrivate *dpyPriv) +{ + FreeScreenConfigs(dpyPriv); + + if (dpyPriv->serverGLXvendor) { + Xfree((char *) dpyPriv->serverGLXvendor); + dpyPriv->serverGLXvendor = NULL; + } + if (dpyPriv->serverGLXversion) { + Xfree((char *) dpyPriv->serverGLXversion); + dpyPriv->serverGLXversion = NULL; + } + + Xfree(dpyPriv); +} + +_X_HIDDEN __GLXdisplayPrivate * +__glXInitialize(Display * dpy) +{ + XExtDisplayInfo *info = __glXFindDisplay(dpy); + __GLXdisplayPrivate *dpyPriv; + int major, minor; + + if (!XextHasExtension(info)) + return NULL; + + /* See if the versions are compatible */ + if (!QueryVersion(dpy, info->codes->major_opcode, &major, &minor)) + return NULL; + + dpyPriv = (__GLXdisplayPrivate *) Xcalloc(1, sizeof(__GLXdisplayPrivate)); + if (!dpyPriv) + return NULL; + + /* + ** Init the display private and then read in the screen config + ** structures from the server. + */ + dpyPriv->majorOpcode = info->codes->major_opcode; + dpyPriv->majorVersion = major; + dpyPriv->minorVersion = minor; + dpyPriv->dpy = dpy; + + dpyPriv->serverGLXvendor = NULL; + dpyPriv->serverGLXversion = NULL; + + if (!AllocAndFetchScreenConfigs(dpy, dpyPriv)) { + Xfree(dpyPriv); + return NULL; + } + + return dpyPriv; +} diff --git a/src/egl/drivers/xdri/glxinit.h b/src/egl/drivers/xdri/glxinit.h new file mode 100644 index 0000000000..57206e627b --- /dev/null +++ b/src/egl/drivers/xdri/glxinit.h @@ -0,0 +1,14 @@ +#ifndef GLXINIT_INCLUDED +#define GLXINIT_INCLUDED + +#include <X11/Xlib.h> +#include "glxclient.h" + +/* this is used by DRI loaders */ +extern void +_gl_context_modes_destroy(__GLcontextModes * modes); + +extern void +__glXRelease(__GLXdisplayPrivate *dpyPriv); + +#endif /* GLXINIT_INCLUDED */ diff --git a/src/egl/main/Makefile b/src/egl/main/Makefile index 7ab78197c7..1fc51e930e 100644 --- a/src/egl/main/Makefile +++ b/src/egl/main/Makefile @@ -4,38 +4,55 @@ TOP = ../../.. include $(TOP)/configs/current -INCLUDE_DIRS = -I$(TOP)/include -I$(TOP)/src/mesa/glapi +INCLUDE_DIRS = -I$(TOP)/include -I$(TOP)/src/mesa/glapi $(X11_INCLUDES) HEADERS = \ + eglclient.h \ + eglcompiler.h \ eglconfig.h \ + eglconfigutil.h \ eglcontext.h \ + eglcurrent.h \ + egldefines.h \ egldisplay.h \ egldriver.h \ eglglobals.h \ + eglimage.h \ egllog.h \ - eglhash.h \ + eglmisc.h \ eglmode.h \ + eglmutex.h \ eglscreen.h \ + eglstring.h \ eglsurface.h SOURCES = \ eglapi.c \ + eglclient.c \ eglconfig.c \ + eglconfigutil.c \ eglcontext.c \ + eglcurrent.c \ egldisplay.c \ egldriver.c \ eglglobals.c \ + eglimage.c \ egllog.c \ - eglhash.c \ + eglmisc.c \ eglmode.c \ eglscreen.c \ + eglstring.c \ eglsurface.c OBJECTS = $(SOURCES:.c=.o) +# Undefined for now +LOCAL_CFLAGS = -D_EGL_PLATFORM_X=1 + + .c.o: - $(CC) -c $(INCLUDE_DIRS) $(CFLAGS) $< -o $@ + $(CC) -c $(INCLUDE_DIRS) $(CFLAGS) $(LOCAL_CFLAGS) $< -o $@ @@ -48,20 +65,26 @@ library: $(TOP)/$(LIB_DIR)/libEGL.so $(TOP)/$(LIB_DIR)/libEGL.so: $(OBJECTS) $(MKLIB) -o EGL -linker '$(CC)' -ldflags '$(LDFLAGS)' \ -major 1 -minor 0 \ - -install $(TOP)/$(LIB_DIR) -ldl $(OBJECTS) - + -install $(TOP)/$(LIB_DIR) \ + $(EGL_LIB_DEPS) $(OBJECTS) +install: default + $(INSTALL) -d $(DESTDIR)$(INSTALL_LIB_DIR) + $(MINSTALL) $(TOP)/$(LIB_DIR)/libEGL.so* $(DESTDIR)$(INSTALL_LIB_DIR) clean: -rm -f *.o *.so* -rm -f core.* + -rm -f depend depend.bak depend: $(SOURCES) $(HEADERS) @ echo "running $(MKDEP)" + @ rm -f depend @ touch depend $(MKDEP) $(MKDEP_OPTIONS) $(DEFINES) $(INCLUDE_DIRS) \ - $(SOURCES) $(HEADERS) > /dev/null + $(SOURCES) $(HEADERS) > /dev/null 2>/dev/null + include depend # DO NOT DELETE diff --git a/src/egl/main/README.txt b/src/egl/main/README.txt new file mode 100644 index 0000000000..b3d253dd13 --- /dev/null +++ b/src/egl/main/README.txt @@ -0,0 +1,71 @@ + + +Notes about the EGL library: + + +The EGL code here basically consists of two things: + +1. An EGL API dispatcher. This directly routes all the eglFooBar() API + calls into driver-specific functions. + +2. Fallbacks for EGL API functions. A driver _could_ implement all the + EGL API calls from scratch. But in many cases, the fallbacks provided + in libEGL (such as eglChooseConfig()) will do the job. + + + +Bootstrapping: + +When the apps calls eglOpenDisplay() a device driver is selected and loaded +(look for dlsym() or LoadLibrary() in egldriver.c). + +The driver's _eglMain() function is then called. This driver function +allocates, initializes and returns a new _EGLDriver object (usually a +subclass of that type). + +As part of initialization, the dispatch table in _EGLDriver->API must be +populated with all the EGL entrypoints. Typically, _eglInitDriverFallbacks() +can be used to plug in default/fallback functions. Some functions like +driver->API.Initialize and driver->API.Terminate _must_ be implemented +with driver-specific code (no default/fallback function is possible). + + +A bit later, the app will call eglInitialize(). This will get routed +to the driver->API.Initialize() function. Any additional driver +initialization that wasn't done in _eglMain() should be done at this +point. Typically, this will involve setting up visual configs, etc. + + + +Special Functions: + +Certain EGL functions _must_ be implemented by the driver. This includes: + +eglCreateContext +eglCreateWindowSurface +eglCreatePixmapSurface +eglCreatePBufferSurface +eglMakeCurrent +eglSwapBuffers + +Most of the EGLConfig-related functions can be implemented with the +defaults/fallbacks. Same thing for the eglGet/Query functions. + + + + +Teardown: + +When eglTerminate() is called, the driver->API.Terminate() function is +called. The driver should clean up after itself. eglTerminate() will +then close/unload the driver (shared library). + + + + +Subclassing: + +The internal libEGL data structures such as _EGLDisplay, _EGLContext, +_EGLSurface, etc should be considered base classes from which drivers +will derive subclasses. + diff --git a/src/egl/main/eglapi.c b/src/egl/main/eglapi.c index bfa580e6c3..d39266fda3 100644 --- a/src/egl/main/eglapi.c +++ b/src/egl/main/eglapi.c @@ -29,7 +29,6 @@ */ - #include <stdio.h> #include <stdlib.h> #include <string.h> @@ -39,276 +38,554 @@ #include "eglglobals.h" #include "egldriver.h" #include "eglsurface.h" - +#include "eglconfig.h" +#include "eglscreen.h" +#include "eglmode.h" +#include "eglimage.h" /** - * NOTE: displayName is treated as a string in _eglChooseDriver()!!! - * This will probably change! - * See _eglChooseDriver() for details! + * This is typically the first EGL function that an application calls. + * We initialize our global vars and create a private _EGLDisplay object. */ -EGLDisplay APIENTRY -eglGetDisplay(NativeDisplayType displayName) +EGLDisplay EGLAPIENTRY +eglGetDisplay(NativeDisplayType nativeDisplay) { _EGLDisplay *dpy; - _eglInitGlobals(); - dpy = _eglNewDisplay(displayName); - if (dpy) - return dpy->Handle; - else - return EGL_NO_DISPLAY; + dpy = _eglFindDisplay(nativeDisplay); + if (!dpy) { + dpy = _eglNewDisplay(nativeDisplay); + if (dpy) + _eglLinkDisplay(dpy); + } + return _eglGetDisplayHandle(dpy); } -EGLBoolean APIENTRY +/** + * This is typically the second EGL function that an application calls. + * Here we load/initialize the actual hardware driver. + */ +EGLBoolean EGLAPIENTRY eglInitialize(EGLDisplay dpy, EGLint *major, EGLint *minor) { - if (dpy) { - _EGLDriver *drv = _eglChooseDriver(dpy); - if (drv) - return drv->API.Initialize(drv, dpy, major, 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__); + + /* Initialize the particular display now */ + if (!drv->API.Initialize(drv, disp, &major_int, &minor_int)) { + _eglCloseDriver(drv, disp); + return _eglError(EGL_NOT_INITIALIZED, __FUNCTION__); + } + + disp->APImajor = major_int; + disp->APIminor = minor_int; + snprintf(disp->Version, sizeof(disp->Version), + "%d.%d (%s)", major_int, minor_int, drv->Name); + + /* update the global notion of supported APIs */ + _eglGlobal.ClientAPIsMask |= disp->ClientAPIsMask; + + disp->Driver = drv; + } else { + major_int = disp->APImajor; + minor_int = disp->APIminor; } - return EGL_FALSE; + + /* Update applications version of major and minor if not NULL */ + if ((major != NULL) && (minor != NULL)) { + *major = major_int; + *minor = minor_int; + } + + return EGL_TRUE; } -EGLBoolean APIENTRY +EGLBoolean EGLAPIENTRY eglTerminate(EGLDisplay dpy) { - _EGLDriver *drv = _eglLookupDriver(dpy); - if (drv) - return _eglCloseDriver(drv, dpy); - else - return EGL_FALSE; + _EGLDisplay *disp = _eglLookupDisplay(dpy); + _EGLDriver *drv; + + if (!disp) + return _eglError(EGL_BAD_DISPLAY, __FUNCTION__); + + drv = disp->Driver; + if (drv) { + drv->API.Terminate(drv, disp); + _eglCloseDriver(drv, disp); + disp->Driver = NULL; + } + + return EGL_TRUE; } -const char * APIENTRY -eglQueryString(EGLDisplay dpy, EGLint name) +/** + * A bunch of check functions and declare macros to simply error checking. + */ +static INLINE _EGLDriver * +_eglCheckDisplay(_EGLDisplay *disp, const char *msg) { - _EGLDriver *drv = _eglLookupDriver(dpy); - if (drv) - return drv->API.QueryString(drv, dpy, name); - else + if (!disp) { + _eglError(EGL_BAD_DISPLAY, msg); + return NULL; + } + if (!disp->Driver) { + _eglError(EGL_NOT_INITIALIZED, msg); return NULL; + } + return disp->Driver; } -EGLBoolean APIENTRY -eglGetConfigs(EGLDisplay dpy, EGLConfig *configs, EGLint config_size, EGLint *num_config) +static INLINE _EGLDriver * +_eglCheckSurface(_EGLDisplay *disp, _EGLSurface *surf, const char *msg) { - _EGLDriver *drv = _eglLookupDriver(dpy); - /* XXX check drv for null in remaining functions */ - return drv->API.GetConfigs(drv, dpy, configs, config_size, num_config); + _EGLDriver *drv = _eglCheckDisplay(disp, msg); + if (!drv) + return NULL; + if (!surf) { + _eglError(EGL_BAD_SURFACE, msg); + return NULL; + } + return drv; } -EGLBoolean APIENTRY -eglChooseConfig(EGLDisplay dpy, const EGLint *attrib_list, EGLConfig *configs, EGLint config_size, EGLint *num_config) +static INLINE _EGLDriver * +_eglCheckContext(_EGLDisplay *disp, _EGLContext *context, const char *msg) { - _EGLDriver *drv = _eglLookupDriver(dpy); - return drv->API.ChooseConfig(drv, dpy, attrib_list, configs, config_size, num_config); + _EGLDriver *drv = _eglCheckDisplay(disp, msg); + if (!drv) + return NULL; + if (!context) { + _eglError(EGL_BAD_CONTEXT, msg); + return NULL; + } + return drv; } -EGLBoolean APIENTRY -eglGetConfigAttrib(EGLDisplay dpy, EGLConfig config, EGLint attribute, EGLint *value) +static INLINE _EGLDriver * +_eglCheckConfig(_EGLDisplay *disp, _EGLConfig *conf, const char *msg) { - _EGLDriver *drv = _eglLookupDriver(dpy); - return drv->API.GetConfigAttrib(drv, dpy, config, attribute, value); + _EGLDriver *drv = _eglCheckDisplay(disp, msg); + if (!drv) + return NULL; + if (!conf) { + _eglError(EGL_BAD_CONFIG, msg); + return NULL; + } + return drv; } -EGLContext APIENTRY -eglCreateContext(EGLDisplay dpy, EGLConfig config, EGLContext share_list, const EGLint *attrib_list) +#define _EGL_DECLARE_DD(dpy) \ + _EGLDisplay *disp = _eglLookupDisplay(dpy); \ + _EGLDriver *drv; \ + do { \ + drv = _eglCheckDisplay(disp, __FUNCTION__); \ + if (!drv) \ + return EGL_FALSE; \ + } while (0) + + +#define _EGL_DECLARE_DD_AND_SURFACE(dpy, surface) \ + _EGLDisplay *disp = _eglLookupDisplay(dpy); \ + _EGLSurface *surf = _eglLookupSurface((surface), disp); \ + _EGLDriver *drv; \ + do { \ + drv = _eglCheckSurface(disp, surf, __FUNCTION__); \ + if (!drv) \ + return EGL_FALSE; \ + } while (0) + + +#define _EGL_DECLARE_DD_AND_CONTEXT(dpy, ctx) \ + _EGLDisplay *disp = _eglLookupDisplay(dpy); \ + _EGLContext *context = _eglLookupContext((ctx), disp); \ + _EGLDriver *drv; \ + do { \ + drv = _eglCheckContext(disp, context, __FUNCTION__); \ + if (!drv) \ + return EGL_FALSE; \ + } while (0) + + +#ifdef EGL_MESA_screen_surface + + +static INLINE _EGLDriver * +_eglCheckScreen(_EGLDisplay *disp, _EGLScreen *scrn, const char *msg) { - _EGLDriver *drv = _eglLookupDriver(dpy); - return drv->API.CreateContext(drv, dpy, config, share_list, attrib_list); + _EGLDriver *drv = _eglCheckDisplay(disp, msg); + if (!drv) + return NULL; + if (!scrn) { + _eglError(EGL_BAD_SCREEN_MESA, msg); + return NULL; + } + return drv; } -EGLBoolean APIENTRY -eglDestroyContext(EGLDisplay dpy, EGLContext ctx) +static INLINE _EGLDriver * +_eglCheckMode(_EGLDisplay *disp, _EGLMode *m, const char *msg) +{ + _EGLDriver *drv = _eglCheckDisplay(disp, msg); + if (!drv) + return NULL; + if (!m) { + _eglError(EGL_BAD_MODE_MESA, msg); + return NULL; + } + return drv; +} + + +#define _EGL_DECLARE_DD_AND_SCREEN(dpy, screen) \ + _EGLDisplay *disp = _eglLookupDisplay(dpy); \ + _EGLScreen *scrn = _eglLookupScreen((screen), disp); \ + _EGLDriver *drv; \ + do { \ + drv = _eglCheckScreen(disp, scrn, __FUNCTION__); \ + if (!drv) \ + return EGL_FALSE; \ + } while (0) + + +#define _EGL_DECLARE_DD_AND_MODE(dpy, mode) \ + _EGLDisplay *disp = _eglLookupDisplay(dpy); \ + _EGLMode *m = _eglLookupMode((mode), disp); \ + _EGLDriver *drv; \ + do { \ + drv = _eglCheckMode(disp, m, __FUNCTION__); \ + if (!drv) \ + return EGL_FALSE; \ + } while (0) + + +#endif /* EGL_MESA_screen_surface */ + + +const char * EGLAPIENTRY +eglQueryString(EGLDisplay dpy, EGLint name) { - _EGLDriver *drv = _eglLookupDriver(dpy); - return drv->API.DestroyContext(drv, dpy, ctx); + _EGL_DECLARE_DD(dpy); + return drv->API.QueryString(drv, disp, name); } -EGLBoolean APIENTRY -eglMakeCurrent(EGLDisplay dpy, EGLSurface draw, EGLSurface read, EGLContext ctx) +EGLBoolean EGLAPIENTRY +eglGetConfigs(EGLDisplay dpy, EGLConfig *configs, + EGLint config_size, EGLint *num_config) { - _EGLDriver *drv = _eglLookupDriver(dpy); - return drv->API.MakeCurrent(drv, dpy, draw, read, ctx); + _EGL_DECLARE_DD(dpy); + return drv->API.GetConfigs(drv, disp, configs, config_size, num_config); } -EGLBoolean APIENTRY -eglQueryContext(EGLDisplay dpy, EGLContext ctx, EGLint attribute, EGLint *value) +EGLBoolean EGLAPIENTRY +eglChooseConfig(EGLDisplay dpy, const EGLint *attrib_list, EGLConfig *configs, + EGLint config_size, EGLint *num_config) { - _EGLDriver *drv = _eglLookupDriver(dpy); - return drv->API.QueryContext(drv, dpy, ctx, attribute, value); + _EGL_DECLARE_DD(dpy); + return drv->API.ChooseConfig(drv, disp, attrib_list, configs, + config_size, num_config); } -EGLSurface APIENTRY -eglCreateWindowSurface(EGLDisplay dpy, EGLConfig config, NativeWindowType window, const EGLint *attrib_list) +EGLBoolean EGLAPIENTRY +eglGetConfigAttrib(EGLDisplay dpy, EGLConfig config, + EGLint attribute, EGLint *value) { - _EGLDriver *drv = _eglLookupDriver(dpy); - return drv->API.CreateWindowSurface(drv, dpy, config, window, attrib_list); + _EGLDisplay *disp = _eglLookupDisplay(dpy); + _EGLConfig *conf = _eglLookupConfig(config, disp); + _EGLDriver *drv; + + drv = _eglCheckConfig(disp, conf, __FUNCTION__); + if (!drv) + return EGL_FALSE; + + return drv->API.GetConfigAttrib(drv, disp, conf, attribute, value); } -EGLSurface APIENTRY -eglCreatePixmapSurface(EGLDisplay dpy, EGLConfig config, NativePixmapType pixmap, const EGLint *attrib_list) +EGLContext EGLAPIENTRY +eglCreateContext(EGLDisplay dpy, EGLConfig config, EGLContext share_list, + const EGLint *attrib_list) { - _EGLDriver *drv = _eglLookupDriver(dpy); - return drv->API.CreatePixmapSurface(drv, dpy, config, pixmap, attrib_list); + _EGLDisplay *disp = _eglLookupDisplay(dpy); + _EGLConfig *conf = _eglLookupConfig(config, disp); + _EGLContext *share = _eglLookupContext(share_list, disp); + _EGLDriver *drv; + _EGLContext *context; + + drv = _eglCheckConfig(disp, conf, __FUNCTION__); + if (!drv) + return EGL_NO_CONTEXT; + if (!share && share_list != EGL_NO_CONTEXT) { + _eglError(EGL_BAD_CONTEXT, __FUNCTION__); + return EGL_NO_CONTEXT; + } + + context = drv->API.CreateContext(drv, disp, conf, share, attrib_list); + if (context) + return _eglLinkContext(context, disp); + else + return EGL_NO_CONTEXT; } -EGLSurface APIENTRY -eglCreatePbufferSurface(EGLDisplay dpy, EGLConfig config, const EGLint *attrib_list) +EGLBoolean EGLAPIENTRY +eglDestroyContext(EGLDisplay dpy, EGLContext ctx) { - _EGLDriver *drv = _eglLookupDriver(dpy); - return drv->API.CreatePbufferSurface(drv, dpy, config, attrib_list); + _EGL_DECLARE_DD_AND_CONTEXT(dpy, ctx); + _eglUnlinkContext(context); + return drv->API.DestroyContext(drv, disp, context); } -EGLBoolean APIENTRY -eglDestroySurface(EGLDisplay dpy, EGLSurface surface) +EGLBoolean EGLAPIENTRY +eglMakeCurrent(EGLDisplay dpy, EGLSurface draw, EGLSurface read, + EGLContext ctx) { - _EGLDriver *drv = _eglLookupDriver(dpy); - return drv->API.DestroySurface(drv, dpy, surface); + _EGLDisplay *disp = _eglLookupDisplay(dpy); + _EGLContext *context = _eglLookupContext(ctx, disp); + _EGLSurface *draw_surf = _eglLookupSurface(draw, disp); + _EGLSurface *read_surf = _eglLookupSurface(read, disp); + _EGLDriver *drv; + + drv = _eglCheckDisplay(disp, __FUNCTION__); + if (!drv) + return EGL_FALSE; + if (!context && ctx != EGL_NO_CONTEXT) + return _eglError(EGL_BAD_CONTEXT, __FUNCTION__); + if ((!draw_surf && draw != EGL_NO_SURFACE) || + (!read_surf && read != EGL_NO_SURFACE)) + return _eglError(EGL_BAD_SURFACE, __FUNCTION__); + + return drv->API.MakeCurrent(drv, disp, draw_surf, read_surf, context); } -EGLBoolean APIENTRY -eglQuerySurface(EGLDisplay dpy, EGLSurface surface, EGLint attribute, EGLint *value) +EGLBoolean EGLAPIENTRY +eglQueryContext(EGLDisplay dpy, EGLContext ctx, + EGLint attribute, EGLint *value) { - _EGLDriver *drv = _eglLookupDriver(dpy); - return drv->API.QuerySurface(drv, dpy, surface, attribute, value); + _EGL_DECLARE_DD_AND_CONTEXT(dpy, ctx); + return drv->API.QueryContext(drv, disp, context, attribute, value); } -EGLBoolean APIENTRY -eglSurfaceAttrib(EGLDisplay dpy, EGLSurface surface, EGLint attribute, EGLint value) +EGLSurface EGLAPIENTRY +eglCreateWindowSurface(EGLDisplay dpy, EGLConfig config, + NativeWindowType window, const EGLint *attrib_list) { - _EGLDriver *drv = _eglLookupDriver(dpy); - return drv->API.SurfaceAttrib(drv, dpy, surface, attribute, value); + _EGLDisplay *disp = _eglLookupDisplay(dpy); + _EGLConfig *conf = _eglLookupConfig(config, disp); + _EGLDriver *drv; + _EGLSurface *surf; + + drv = _eglCheckConfig(disp, conf, __FUNCTION__); + if (!drv) + return EGL_NO_SURFACE; + + surf = drv->API.CreateWindowSurface(drv, disp, conf, window, attrib_list); + if (surf) + return _eglLinkSurface(surf, disp); + else + return EGL_NO_SURFACE; } -EGLBoolean APIENTRY +EGLSurface EGLAPIENTRY +eglCreatePixmapSurface(EGLDisplay dpy, EGLConfig config, + NativePixmapType pixmap, const EGLint *attrib_list) +{ + _EGLDisplay *disp = _eglLookupDisplay(dpy); + _EGLConfig *conf = _eglLookupConfig(config, disp); + _EGLDriver *drv; + _EGLSurface *surf; + + drv = _eglCheckConfig(disp, conf, __FUNCTION__); + if (!drv) + return EGL_NO_SURFACE; + + surf = drv->API.CreatePixmapSurface(drv, disp, conf, pixmap, attrib_list); + if (surf) + return _eglLinkSurface(surf, disp); + else + return EGL_NO_SURFACE; +} + + +EGLSurface EGLAPIENTRY +eglCreatePbufferSurface(EGLDisplay dpy, EGLConfig config, + const EGLint *attrib_list) +{ + _EGLDisplay *disp = _eglLookupDisplay(dpy); + _EGLConfig *conf = _eglLookupConfig(config, disp); + _EGLDriver *drv; + _EGLSurface *surf; + + drv = _eglCheckConfig(disp, conf, __FUNCTION__); + if (!drv) + return EGL_NO_SURFACE; + + surf = drv->API.CreatePbufferSurface(drv, disp, conf, attrib_list); + if (surf) + return _eglLinkSurface(surf, disp); + else + return EGL_NO_SURFACE; +} + + +EGLBoolean EGLAPIENTRY +eglDestroySurface(EGLDisplay dpy, EGLSurface surface) +{ + _EGL_DECLARE_DD_AND_SURFACE(dpy, surface); + _eglUnlinkSurface(surf); + return drv->API.DestroySurface(drv, disp, surf); +} + +EGLBoolean EGLAPIENTRY +eglQuerySurface(EGLDisplay dpy, EGLSurface surface, + EGLint attribute, EGLint *value) +{ + _EGL_DECLARE_DD_AND_SURFACE(dpy, surface); + return drv->API.QuerySurface(drv, disp, surf, attribute, value); +} + +EGLBoolean EGLAPIENTRY +eglSurfaceAttrib(EGLDisplay dpy, EGLSurface surface, + EGLint attribute, EGLint value) +{ + _EGL_DECLARE_DD_AND_SURFACE(dpy, surface); + return drv->API.SurfaceAttrib(drv, disp, surf, attribute, value); +} + + +EGLBoolean EGLAPIENTRY eglBindTexImage(EGLDisplay dpy, EGLSurface surface, EGLint buffer) { - _EGLDriver *drv = _eglLookupDriver(dpy); - return drv->API.BindTexImage(drv, dpy, surface, buffer); + _EGL_DECLARE_DD_AND_SURFACE(dpy, surface); + return drv->API.BindTexImage(drv, disp, surf, buffer); } -EGLBoolean APIENTRY +EGLBoolean EGLAPIENTRY eglReleaseTexImage(EGLDisplay dpy, EGLSurface surface, EGLint buffer) { - _EGLDriver *drv = _eglLookupDriver(dpy); - return drv->API.ReleaseTexImage(drv, dpy, surface, buffer); + _EGL_DECLARE_DD_AND_SURFACE(dpy, surface); + return drv->API.ReleaseTexImage(drv, disp, surf, buffer); } -EGLBoolean APIENTRY +EGLBoolean EGLAPIENTRY eglSwapInterval(EGLDisplay dpy, EGLint interval) { - _EGLDriver *drv = _eglLookupDriver(dpy); - return drv->API.SwapInterval(drv, dpy, interval); + _EGL_DECLARE_DD(dpy); + return drv->API.SwapInterval(drv, disp, interval); } -EGLBoolean APIENTRY -eglSwapBuffers(EGLDisplay dpy, EGLSurface draw) +EGLBoolean EGLAPIENTRY +eglSwapBuffers(EGLDisplay dpy, EGLSurface surface) { - _EGLDriver *drv = _eglLookupDriver(dpy); - return drv->API.SwapBuffers(drv, dpy, draw); + _EGL_DECLARE_DD_AND_SURFACE(dpy, surface); + return drv->API.SwapBuffers(drv, disp, surf); } -EGLBoolean APIENTRY +EGLBoolean EGLAPIENTRY eglCopyBuffers(EGLDisplay dpy, EGLSurface surface, NativePixmapType target) { - _EGLDriver *drv = _eglLookupDriver(dpy); - return drv->API.CopyBuffers(drv, dpy, surface, target); + _EGL_DECLARE_DD_AND_SURFACE(dpy, surface); + return drv->API.CopyBuffers(drv, disp, surf, target); } -EGLBoolean APIENTRY +EGLBoolean EGLAPIENTRY eglWaitGL(void) { - EGLDisplay dpy = eglGetCurrentDisplay(); - if (dpy != EGL_NO_DISPLAY) { - _EGLDriver *drv = _eglLookupDriver(dpy); - return drv->API.WaitGL(drv, dpy); - } - else - return EGL_FALSE; + _EGLDisplay *disp = _eglGetCurrentDisplay(); + _EGLDriver *drv; + + if (!disp) + return EGL_TRUE; + + /* a current display is always initialized */ + drv = disp->Driver; + + return drv->API.WaitGL(drv, disp); } -EGLBoolean APIENTRY +EGLBoolean EGLAPIENTRY eglWaitNative(EGLint engine) { - EGLDisplay dpy = eglGetCurrentDisplay(); - if (dpy != EGL_NO_DISPLAY) { - _EGLDriver *drv = _eglLookupDriver(dpy); - return drv->API.WaitNative(drv, dpy, engine); - } - else - return EGL_FALSE; + _EGLDisplay *disp = _eglGetCurrentDisplay(); + _EGLDriver *drv; + + if (!disp) + return EGL_TRUE; + + /* a current display is always initialized */ + drv = disp->Driver; + + return drv->API.WaitNative(drv, disp, engine); } -EGLDisplay APIENTRY +EGLDisplay EGLAPIENTRY eglGetCurrentDisplay(void) { _EGLDisplay *dpy = _eglGetCurrentDisplay(); - if (dpy) - return dpy->Handle; - else - return EGL_NO_DISPLAY; + return _eglGetDisplayHandle(dpy); } -EGLContext APIENTRY +EGLContext EGLAPIENTRY eglGetCurrentContext(void) { _EGLContext *ctx = _eglGetCurrentContext(); - if (ctx) - return ctx->Handle; - else - return EGL_NO_CONTEXT; + return _eglGetContextHandle(ctx); } -EGLSurface APIENTRY +EGLSurface EGLAPIENTRY eglGetCurrentSurface(EGLint readdraw) { _EGLSurface *s = _eglGetCurrentSurface(readdraw); - if (s) - return s->Handle; - else - return EGL_NO_SURFACE; + return _eglGetSurfaceHandle(s); } -EGLint APIENTRY +EGLint EGLAPIENTRY eglGetError(void) { _EGLThreadInfo *t = _eglGetCurrentThread(); EGLint e = t->LastError; - t->LastError = EGL_SUCCESS; + if (!_eglIsCurrentThreadDummy()) + t->LastError = EGL_SUCCESS; return e; } -void (* APIENTRY eglGetProcAddress(const char *procname))() +void (* EGLAPIENTRY eglGetProcAddress(const char *procname))() { typedef void (*genericFunc)(); struct name_function { @@ -368,6 +645,10 @@ void (* APIENTRY eglGetProcAddress(const char *procname))() { "eglReleaseThread", (_EGLProc) eglReleaseThread }, { "eglWaitClient", (_EGLProc) eglWaitClient }, #endif /* EGL_VERSION_1_2 */ +#ifdef EGL_KHR_image_base + { "eglCreateImageKHR", (_EGLProc) eglCreateImageKHR }, + { "eglDestroyImageKHR", (_EGLProc) eglDestroyImageKHR }, +#endif /* EGL_KHR_image_base */ { NULL, NULL } }; EGLint i; @@ -376,12 +657,15 @@ void (* APIENTRY eglGetProcAddress(const char *procname))() return (genericFunc) egl_functions[i].function; } } -#if 0 - /* XXX enable this code someday */ - return (genericFunc) _glapi_get_proc_address(procname); -#else + + /* now loop over drivers to query their procs */ + for (i = 0; i < _eglGlobal.NumDrivers; i++) { + _EGLProc p = _eglGlobal.Drivers[i]->API.GetProcAddress(procname); + if (p) + return p; + } + return NULL; -#endif } @@ -389,116 +673,173 @@ void (* APIENTRY eglGetProcAddress(const char *procname))() * EGL_MESA_screen extension */ -EGLBoolean APIENTRY +EGLBoolean EGLAPIENTRY eglChooseModeMESA(EGLDisplay dpy, EGLScreenMESA screen, const EGLint *attrib_list, EGLModeMESA *modes, EGLint modes_size, EGLint *num_modes) { - _EGLDriver *drv = _eglLookupDriver(dpy); - if (drv) - return drv->API.ChooseModeMESA(drv, dpy, screen, attrib_list, modes, modes_size, num_modes); - else - return EGL_FALSE; + _EGL_DECLARE_DD_AND_SCREEN(dpy, screen); + return drv->API.ChooseModeMESA(drv, disp, scrn, attrib_list, + modes, modes_size, num_modes); } -EGLBoolean APIENTRY -eglGetModesMESA(EGLDisplay dpy, EGLScreenMESA screen, EGLModeMESA *modes, EGLint mode_size, EGLint *num_mode) +EGLBoolean EGLAPIENTRY +eglGetModesMESA(EGLDisplay dpy, EGLScreenMESA screen, EGLModeMESA *modes, + EGLint mode_size, EGLint *num_mode) { - _EGLDriver *drv = _eglLookupDriver(dpy); - if (drv) - return drv->API.GetModesMESA(drv, dpy, screen, modes, mode_size, num_mode); - else - return EGL_FALSE; + _EGL_DECLARE_DD_AND_SCREEN(dpy, screen); + return drv->API.GetModesMESA(drv, disp, scrn, modes, mode_size, num_mode); } -EGLBoolean APIENTRY -eglGetModeAttribMESA(EGLDisplay dpy, EGLModeMESA mode, EGLint attribute, EGLint *value) +EGLBoolean EGLAPIENTRY +eglGetModeAttribMESA(EGLDisplay dpy, EGLModeMESA mode, + EGLint attribute, EGLint *value) { - _EGLDriver *drv = _eglLookupDriver(dpy); - if (drv) - return drv->API.GetModeAttribMESA(drv, dpy, mode, attribute, value); - else - return EGL_FALSE; + _EGL_DECLARE_DD_AND_MODE(dpy, mode); + return drv->API.GetModeAttribMESA(drv, disp, m, attribute, value); } -EGLBoolean APIENTRY -eglCopyContextMESA(EGLDisplay dpy, EGLContext source, EGLContext dest, EGLint mask) +EGLBoolean EGLAPIENTRY +eglCopyContextMESA(EGLDisplay dpy, EGLContext source, EGLContext dest, + EGLint mask) { - _EGLDriver *drv = _eglLookupDriver(dpy); - if (drv) - return drv->API.CopyContextMESA(drv, dpy, source, dest, mask); - else + _EGLDisplay *disp = _eglLookupDisplay(dpy); + _EGLContext *source_context = _eglLookupContext(source, disp); + _EGLContext *dest_context = _eglLookupContext(dest, disp); + _EGLDriver *drv; + + drv = _eglCheckContext(disp, source_context, __FUNCTION__); + if (!drv || !dest_context) { + if (drv) + _eglError(EGL_BAD_CONTEXT, __FUNCTION__); return EGL_FALSE; + } + + return drv->API.CopyContextMESA(drv, disp, source_context, dest_context, + mask); } EGLBoolean -eglGetScreensMESA(EGLDisplay dpy, EGLScreenMESA *screens, EGLint max_screens, EGLint *num_screens) +eglGetScreensMESA(EGLDisplay dpy, EGLScreenMESA *screens, + EGLint max_screens, EGLint *num_screens) { - _EGLDriver *drv = _eglLookupDriver(dpy); - if (drv) - return drv->API.GetScreensMESA(drv, dpy, screens, max_screens, num_screens); - else - return EGL_FALSE; + _EGL_DECLARE_DD(dpy); + return drv->API.GetScreensMESA(drv, disp, screens, + max_screens, num_screens); } EGLSurface -eglCreateScreenSurfaceMESA(EGLDisplay dpy, EGLConfig config, const EGLint *attrib_list) +eglCreateScreenSurfaceMESA(EGLDisplay dpy, EGLConfig config, + const EGLint *attrib_list) { - _EGLDriver *drv = _eglLookupDriver(dpy); - return drv->API.CreateScreenSurfaceMESA(drv, dpy, config, attrib_list); + _EGLDisplay *disp = _eglLookupDisplay(dpy); + _EGLConfig *conf = _eglLookupConfig(config, disp); + _EGLDriver *drv; + _EGLSurface *surf; + + drv = _eglCheckConfig(disp, conf, __FUNCTION__); + if (!drv) + return EGL_NO_SURFACE; + + surf = drv->API.CreateScreenSurfaceMESA(drv, disp, conf, attrib_list); + if (surf) + return _eglLinkSurface(surf, disp); + else + return EGL_NO_SURFACE; } EGLBoolean -eglShowScreenSurfaceMESA(EGLDisplay dpy, EGLint screen, EGLSurface surface, EGLModeMESA mode) +eglShowScreenSurfaceMESA(EGLDisplay dpy, EGLint screen, + EGLSurface surface, EGLModeMESA mode) { - _EGLDriver *drv = _eglLookupDriver(dpy); - return drv->API.ShowScreenSurfaceMESA(drv, dpy, screen, surface, mode); + _EGLDisplay *disp = _eglLookupDisplay(dpy); + _EGLScreen *scrn = _eglLookupScreen((EGLScreenMESA) screen, disp); + _EGLSurface *surf = _eglLookupSurface(surface, disp); + _EGLMode *m = _eglLookupMode(mode, disp); + _EGLDriver *drv; + + drv = _eglCheckScreen(disp, scrn, __FUNCTION__); + if (!drv) + return EGL_FALSE; + if (!surf && surface != EGL_NO_SURFACE) + return _eglError(EGL_BAD_SURFACE, __FUNCTION__); + if (!m && mode != EGL_NO_MODE_MESA) + return _eglError(EGL_BAD_MODE_MESA, __FUNCTION__); + + return drv->API.ShowScreenSurfaceMESA(drv, disp, scrn, surf, m); } EGLBoolean eglScreenPositionMESA(EGLDisplay dpy, EGLScreenMESA screen, EGLint x, EGLint y) { - _EGLDriver *drv = _eglLookupDriver(dpy); - return drv->API.ScreenPositionMESA(drv, dpy, screen, x, y); + _EGL_DECLARE_DD_AND_SCREEN(dpy, screen); + return drv->API.ScreenPositionMESA(drv, disp, scrn, x, y); } EGLBoolean -eglQueryScreenMESA( EGLDisplay dpy, EGLScreenMESA screen, EGLint attribute, EGLint *value) +eglQueryScreenMESA(EGLDisplay dpy, EGLScreenMESA screen, + EGLint attribute, EGLint *value) { - _EGLDriver *drv = _eglLookupDriver(dpy); - return drv->API.QueryScreenMESA(drv, dpy, screen, attribute, value); + _EGL_DECLARE_DD_AND_SCREEN(dpy, screen); + return drv->API.QueryScreenMESA(drv, disp, scrn, attribute, value); } EGLBoolean -eglQueryScreenSurfaceMESA(EGLDisplay dpy, EGLScreenMESA screen, EGLSurface *surface) +eglQueryScreenSurfaceMESA(EGLDisplay dpy, EGLScreenMESA screen, + EGLSurface *surface) { - _EGLDriver *drv = _eglLookupDriver(dpy); - return drv->API.QueryScreenSurfaceMESA(drv, dpy, screen, surface); + _EGLDisplay *disp = _eglLookupDisplay(dpy); + _EGLScreen *scrn = _eglLookupScreen((EGLScreenMESA) screen, disp); + _EGLDriver *drv; + _EGLSurface *surf; + + drv = _eglCheckScreen(disp, scrn, __FUNCTION__); + if (!drv) + return EGL_FALSE; + + if (drv->API.QueryScreenSurfaceMESA(drv, disp, scrn, &surf) != EGL_TRUE) + surf = NULL; + if (surface) + *surface = _eglGetSurfaceHandle(surf); + return (surf != NULL); } EGLBoolean eglQueryScreenModeMESA(EGLDisplay dpy, EGLScreenMESA screen, EGLModeMESA *mode) { - _EGLDriver *drv = _eglLookupDriver(dpy); - return drv->API.QueryScreenModeMESA(drv, dpy, screen, mode); + _EGLDisplay *disp = _eglLookupDisplay(dpy); + _EGLScreen *scrn = _eglLookupScreen((EGLScreenMESA) screen, disp); + _EGLDriver *drv; + _EGLMode *m; + + drv = _eglCheckScreen(disp, scrn, __FUNCTION__); + if (!drv) + return EGL_FALSE; + + if (drv->API.QueryScreenModeMESA(drv, disp, scrn, &m) != EGL_TRUE) + m = NULL; + if (mode) + *mode = m->Handle; + + return (m != NULL); } const char * eglQueryModeStringMESA(EGLDisplay dpy, EGLModeMESA mode) { - _EGLDriver *drv = _eglLookupDriver(dpy); - return drv->API.QueryModeStringMESA(drv, dpy, mode); + _EGL_DECLARE_DD_AND_MODE(dpy, mode); + return drv->API.QueryModeStringMESA(drv, disp, m); } @@ -508,22 +849,49 @@ eglQueryModeStringMESA(EGLDisplay dpy, EGLModeMESA mode) #ifdef EGL_VERSION_1_2 + +/** + * Specify the client API to use for subsequent calls including: + * eglCreateContext() + * eglGetCurrentContext() + * eglGetCurrentDisplay() + * eglGetCurrentSurface() + * eglMakeCurrent(when the ctx parameter is EGL NO CONTEXT) + * eglWaitClient() + * eglWaitNative() + * See section 3.7 "Rendering Context" in the EGL specification for details. + */ EGLBoolean eglBindAPI(EGLenum api) { _EGLThreadInfo *t = _eglGetCurrentThread(); + if (_eglIsCurrentThreadDummy()) + return _eglError(EGL_BAD_ALLOC, "eglBindAPI"); + + if (!_eglIsApiValid(api)) + return _eglError(EGL_BAD_PARAMETER, "eglBindAPI"); + switch (api) { +#ifdef EGL_VERSION_1_4 + case EGL_OPENGL_API: + if (_eglGlobal.ClientAPIsMask & EGL_OPENGL_BIT) { + t->CurrentAPIIndex = _eglConvertApiToIndex(api); + return EGL_TRUE; + } + _eglError(EGL_BAD_PARAMETER, "eglBindAPI"); + return EGL_FALSE; +#endif case EGL_OPENGL_ES_API: - if (_eglGlobal.OpenGLESAPISupported) { - t->CurrentAPI = api; + if (_eglGlobal.ClientAPIsMask & (EGL_OPENGL_ES_BIT | EGL_OPENGL_ES2_BIT)) { + t->CurrentAPIIndex = _eglConvertApiToIndex(api); return EGL_TRUE; } _eglError(EGL_BAD_PARAMETER, "eglBindAPI"); return EGL_FALSE; case EGL_OPENVG_API: - if (_eglGlobal.OpenVGAPISupported) { - t->CurrentAPI = api; + if (_eglGlobal.ClientAPIsMask & EGL_OPENVG_BIT) { + t->CurrentAPIIndex = _eglConvertApiToIndex(api); return EGL_TRUE; } _eglError(EGL_BAD_PARAMETER, "eglBindAPI"); @@ -535,38 +903,55 @@ eglBindAPI(EGLenum api) } +/** + * Return the last value set with eglBindAPI(). + */ +EGLenum +eglQueryAPI(void) +{ + /* returns one of EGL_OPENGL_API, EGL_OPENGL_ES_API or EGL_OPENVG_API */ + _EGLThreadInfo *t = _eglGetCurrentThread(); + return _eglConvertApiFromIndex(t->CurrentAPIIndex); +} + + EGLSurface eglCreatePbufferFromClientBuffer(EGLDisplay dpy, EGLenum buftype, EGLClientBuffer buffer, EGLConfig config, const EGLint *attrib_list) { - _EGLDriver *drv = _eglLookupDriver(dpy); - return drv->API.CreatePbufferFromClientBuffer(drv, dpy, buftype, buffer, - config, attrib_list); -} + _EGLDisplay *disp = _eglLookupDisplay(dpy); + _EGLConfig *conf = _eglLookupConfig(config, disp); + _EGLDriver *drv; + _EGLSurface *surf; + drv = _eglCheckConfig(disp, conf, __FUNCTION__); + if (!drv) + return EGL_NO_SURFACE; -EGLenum -eglQueryAPI(void) -{ - /* returns one of EGL_OPENGL_ES_API or EGL_OPENVG_API */ - _EGLThreadInfo *t = _eglGetCurrentThread(); - return t->CurrentAPI; + surf = drv->API.CreatePbufferFromClientBuffer(drv, disp, buftype, buffer, + conf, attrib_list); + if (surf) + return _eglLinkSurface(surf, disp); + else + return EGL_NO_SURFACE; } EGLBoolean eglReleaseThread(void) { - _EGLThreadInfo *t = _eglGetCurrentThread(); - EGLDisplay dpy = eglGetCurrentDisplay(); - if (dpy) { - _EGLDriver *drv = _eglLookupDriver(dpy); - /* unbind context */ - (void) drv->API.MakeCurrent(drv, dpy, EGL_NO_SURFACE, - EGL_NO_SURFACE, EGL_NO_CONTEXT); + /* unbind current context */ + if (!_eglIsCurrentThreadDummy()) { + _EGLDisplay *disp = _eglGetCurrentDisplay(); + _EGLDriver *drv; + if (disp) { + drv = disp->Driver; + (void) drv->API.MakeCurrent(drv, disp, NULL, NULL, NULL); + } } - _eglDeleteThreadData(t); + + _eglDestroyCurrentThread(); return EGL_TRUE; } @@ -574,13 +959,63 @@ eglReleaseThread(void) EGLBoolean eglWaitClient(void) { - EGLDisplay dpy = eglGetCurrentDisplay(); - if (dpy != EGL_NO_DISPLAY) { - _EGLDriver *drv = _eglLookupDriver(dpy); - return drv->API.WaitClient(drv, dpy); + _EGLDisplay *disp = _eglGetCurrentDisplay(); + _EGLDriver *drv; + + if (!disp) + return EGL_TRUE; + + /* a current display is always initialized */ + drv = disp->Driver; + + return drv->API.WaitClient(drv, disp); +} + + +#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__); + + return drv->API.DestroyImageKHR(drv, disp, img); } -#endif /* EGL_VERSION_1_2 */ + +#endif /* EGL_KHR_image_base */ diff --git a/src/egl/main/eglapi.h b/src/egl/main/eglapi.h index 555aa5dd9e..c2c4339294 100644 --- a/src/egl/main/eglapi.h +++ b/src/egl/main/eglapi.h @@ -2,66 +2,79 @@ #define EGLAPI_INCLUDED /** - * Typedefs for all EGL API entrypoint functions. + * A generic function ptr type */ +typedef void (*_EGLProc)(); + +/** + * Typedefs for all EGL API entrypoint functions. + */ /* driver funcs */ -typedef EGLBoolean (*Initialize_t)(_EGLDriver *, EGLDisplay dpy, EGLint *major, EGLint *minor); -typedef EGLBoolean (*Terminate_t)(_EGLDriver *, EGLDisplay dpy); +typedef EGLBoolean (*Initialize_t)(_EGLDriver *, _EGLDisplay *dpy, EGLint *major, EGLint *minor); +typedef EGLBoolean (*Terminate_t)(_EGLDriver *, _EGLDisplay *dpy); /* config funcs */ -typedef EGLBoolean (*GetConfigs_t)(_EGLDriver *drv, EGLDisplay dpy, EGLConfig *configs, EGLint config_size, EGLint *num_config); -typedef EGLBoolean (*ChooseConfig_t)(_EGLDriver *drv, EGLDisplay dpy, const EGLint *attrib_list, EGLConfig *configs, EGLint config_size, EGLint *num_config); -typedef EGLBoolean (*GetConfigAttrib_t)(_EGLDriver *drv, EGLDisplay dpy, EGLConfig config, EGLint attribute, EGLint *value); +typedef EGLBoolean (*GetConfigs_t)(_EGLDriver *drv, _EGLDisplay *dpy, EGLConfig *configs, EGLint config_size, EGLint *num_config); +typedef EGLBoolean (*ChooseConfig_t)(_EGLDriver *drv, _EGLDisplay *dpy, const EGLint *attrib_list, EGLConfig *configs, EGLint config_size, EGLint *num_config); +typedef EGLBoolean (*GetConfigAttrib_t)(_EGLDriver *drv, _EGLDisplay *dpy, _EGLConfig *config, EGLint attribute, EGLint *value); /* 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); -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); +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); +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 (*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); -typedef EGLBoolean (*SurfaceAttrib_t)(_EGLDriver *drv, EGLDisplay dpy, EGLSurface surface, EGLint attribute, EGLint value); -typedef EGLBoolean (*BindTexImage_t)(_EGLDriver *drv, EGLDisplay dpy, EGLSurface surface, EGLint buffer); -typedef EGLBoolean (*ReleaseTexImage_t)(_EGLDriver *drv, EGLDisplay dpy, EGLSurface surface, EGLint buffer); -typedef EGLBoolean (*SwapInterval_t)(_EGLDriver *drv, EGLDisplay dpy, 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 _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 *(*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); +typedef EGLBoolean (*SurfaceAttrib_t)(_EGLDriver *drv, _EGLDisplay *dpy, _EGLSurface *surface, EGLint attribute, EGLint value); +typedef EGLBoolean (*BindTexImage_t)(_EGLDriver *drv, _EGLDisplay *dpy, _EGLSurface *surface, EGLint buffer); +typedef EGLBoolean (*ReleaseTexImage_t)(_EGLDriver *drv, _EGLDisplay *dpy, _EGLSurface *surface, EGLint buffer); +typedef EGLBoolean (*SwapInterval_t)(_EGLDriver *drv, _EGLDisplay *dpy, EGLint interval); +typedef EGLBoolean (*SwapBuffers_t)(_EGLDriver *drv, _EGLDisplay *dpy, _EGLSurface *draw); +typedef EGLBoolean (*CopyBuffers_t)(_EGLDriver *drv, _EGLDisplay *dpy, _EGLSurface *surface, NativePixmapType target); /* misc funcs */ -typedef const char *(*QueryString_t)(_EGLDriver *drv, EGLDisplay dpy, EGLint name); -typedef EGLBoolean (*WaitGL_t)(_EGLDriver *drv, EGLDisplay dpy); -typedef EGLBoolean (*WaitNative_t)(_EGLDriver *drv, EGLDisplay dpy, EGLint engine); +typedef const char *(*QueryString_t)(_EGLDriver *drv, _EGLDisplay *dpy, EGLint name); +typedef EGLBoolean (*WaitGL_t)(_EGLDriver *drv, _EGLDisplay *dpy); +typedef EGLBoolean (*WaitNative_t)(_EGLDriver *drv, _EGLDisplay *dpy, EGLint engine); + +typedef _EGLProc (*GetProcAddress_t)(const char *procname); + #ifdef EGL_MESA_screen_surface -typedef EGLBoolean (*ChooseModeMESA_t)(_EGLDriver *drv, EGLDisplay dpy, EGLScreenMESA screen, const EGLint *attrib_list, EGLModeMESA *modes, EGLint modes_size, EGLint *num_modes); -typedef EGLBoolean (*GetModesMESA_t)(_EGLDriver *drv, EGLDisplay dpy, EGLScreenMESA screen, EGLModeMESA *modes, EGLint mode_size, EGLint *num_mode); -typedef EGLBoolean (*GetModeAttribMESA_t)(_EGLDriver *drv, EGLDisplay dpy, EGLModeMESA mode, EGLint attribute, EGLint *value); -typedef EGLBoolean (*CopyContextMESA_t)(_EGLDriver *drv, EGLDisplay dpy, EGLContext source, EGLContext dest, EGLint mask); -typedef EGLBoolean (*GetScreensMESA_t)(_EGLDriver *drv, EGLDisplay dpy, EGLScreenMESA *screens, EGLint max_screens, EGLint *num_screens); -typedef EGLSurface (*CreateScreenSurfaceMESA_t)(_EGLDriver *drv, EGLDisplay dpy, EGLConfig config, const EGLint *attrib_list); -typedef EGLBoolean (*ShowScreenSurfaceMESA_t)(_EGLDriver *drv, EGLDisplay dpy, EGLScreenMESA screen, EGLSurface surface, EGLModeMESA mode); -typedef EGLBoolean (*ScreenPositionMESA_t)(_EGLDriver *drv, EGLDisplay dpy, EGLScreenMESA screen, EGLint x, EGLint y); -typedef EGLBoolean (*QueryScreenMESA_t)(_EGLDriver *drv, EGLDisplay dpy, EGLScreenMESA screen, EGLint attribute, EGLint *value); -typedef EGLBoolean (*QueryScreenSurfaceMESA_t)(_EGLDriver *drv, EGLDisplay dpy, EGLScreenMESA screen, EGLSurface *surface); -typedef EGLBoolean (*QueryScreenModeMESA_t)(_EGLDriver *drv, EGLDisplay dpy, EGLScreenMESA screen, EGLModeMESA *mode); -typedef const char * (*QueryModeStringMESA_t)(_EGLDriver *drv, EGLDisplay dpy, EGLModeMESA mode); +typedef EGLBoolean (*ChooseModeMESA_t)(_EGLDriver *drv, _EGLDisplay *dpy, _EGLScreen *screen, const EGLint *attrib_list, EGLModeMESA *modes, EGLint modes_size, EGLint *num_modes); +typedef EGLBoolean (*GetModesMESA_t)(_EGLDriver *drv, _EGLDisplay *dpy, _EGLScreen *screen, EGLModeMESA *modes, EGLint mode_size, EGLint *num_mode); +typedef EGLBoolean (*GetModeAttribMESA_t)(_EGLDriver *drv, _EGLDisplay *dpy, _EGLMode *mode, EGLint attribute, EGLint *value); +typedef EGLBoolean (*CopyContextMESA_t)(_EGLDriver *drv, _EGLDisplay *dpy, _EGLContext *source, _EGLContext *dest, EGLint mask); +typedef EGLBoolean (*GetScreensMESA_t)(_EGLDriver *drv, _EGLDisplay *dpy, EGLScreenMESA *screens, EGLint max_screens, EGLint *num_screens); +typedef _EGLSurface *(*CreateScreenSurfaceMESA_t)(_EGLDriver *drv, _EGLDisplay *dpy, _EGLConfig *config, const EGLint *attrib_list); +typedef EGLBoolean (*ShowScreenSurfaceMESA_t)(_EGLDriver *drv, _EGLDisplay *dpy, _EGLScreen *screen, _EGLSurface *surface, _EGLMode *mode); +typedef EGLBoolean (*ScreenPositionMESA_t)(_EGLDriver *drv, _EGLDisplay *dpy, _EGLScreen *screen, EGLint x, EGLint y); +typedef EGLBoolean (*QueryScreenMESA_t)(_EGLDriver *drv, _EGLDisplay *dpy, _EGLScreen *screen, EGLint attribute, EGLint *value); +typedef EGLBoolean (*QueryScreenSurfaceMESA_t)(_EGLDriver *drv, _EGLDisplay *dpy, _EGLScreen *screen, _EGLSurface **surface); +typedef EGLBoolean (*QueryScreenModeMESA_t)(_EGLDriver *drv, _EGLDisplay *dpy, _EGLScreen *screen, _EGLMode **mode); +typedef const char * (*QueryModeStringMESA_t)(_EGLDriver *drv, _EGLDisplay *dpy, _EGLMode *mode); #endif /* EGL_MESA_screen_surface */ #ifdef EGL_VERSION_1_2 -typedef EGLBoolean (*WaitClient_t)(_EGLDriver *drv, EGLDisplay dpy); -typedef EGLSurface (*CreatePbufferFromClientBuffer_t)(_EGLDriver *drv, EGLDisplay dpy, EGLenum buftype, EGLClientBuffer buffer, EGLConfig config, const EGLint *attrib_list); +typedef EGLBoolean (*WaitClient_t)(_EGLDriver *drv, _EGLDisplay *dpy); +typedef _EGLSurface *(*CreatePbufferFromClientBuffer_t)(_EGLDriver *drv, _EGLDisplay *dpy, EGLenum buftype, EGLClientBuffer buffer, _EGLConfig *config, const EGLint *attrib_list); #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 @@ -95,8 +108,9 @@ struct _egl_api QueryString_t QueryString; WaitGL_t WaitGL; WaitNative_t WaitNative; + GetProcAddress_t GetProcAddress; - /* EGL_MESA_screen extension */ +#ifdef EGL_MESA_screen_surface ChooseModeMESA_t ChooseModeMESA; GetModesMESA_t GetModesMESA; GetModeAttribMESA_t GetModeAttribMESA; @@ -109,11 +123,17 @@ struct _egl_api QueryScreenSurfaceMESA_t QueryScreenSurfaceMESA; QueryScreenModeMESA_t QueryScreenModeMESA; QueryModeStringMESA_t QueryModeStringMESA; +#endif /* EGL_MESA_screen_surface */ #ifdef EGL_VERSION_1_2 WaitClient_t WaitClient; 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/eglclient.c b/src/egl/main/eglclient.c new file mode 100644 index 0000000000..8426301948 --- /dev/null +++ b/src/egl/main/eglclient.c @@ -0,0 +1,21 @@ +/** + * Functions that client APIs can call. + */ + + +#include "eglcurrent.h" +#include "egldisplay.h" +#include "eglimage.h" +#include "eglclient.h" + + +/** + * Return the opaque client data of an image. + */ +void * +_eglClientGetImageData(EGLImageKHR image) +{ + _EGLDisplay *dpy = _eglGetCurrentDisplay(); + _EGLImage *img = _eglLookupImage(image, dpy); + return (img) ? img->ClientData : NULL; +} diff --git a/src/egl/main/eglclient.h b/src/egl/main/eglclient.h new file mode 100644 index 0000000000..0158664936 --- /dev/null +++ b/src/egl/main/eglclient.h @@ -0,0 +1,12 @@ +#ifndef EGLCLIENT_INCLUDED +#define EGLCLIENT_INCLUDED + + +#include "egltypedefs.h" + + +extern void * +_eglClientGetImageData(EGLImageKHR image); + + +#endif /* EGLCLIENT_INCLUDED */ diff --git a/src/egl/main/eglcompiler.h b/src/egl/main/eglcompiler.h new file mode 100644 index 0000000000..6b639b75c6 --- /dev/null +++ b/src/egl/main/eglcompiler.h @@ -0,0 +1,64 @@ +#ifndef EGLCOMPILER_INCLUDED +#define EGLCOMPILER_INCLUDED + + +/** + * Get standard integer types + */ +#if (defined(__STDC_VERSION__) && __STDC_VERSION__ >= 199901L) +# include <stdint.h> +#elif defined(_MSC_VER) + typedef __int8 int8_t; + typedef unsigned __int8 uint8_t; + typedef __int16 int16_t; + typedef unsigned __int16 uint16_t; +# ifndef __eglplatform_h_ + typedef __int32 int32_t; +# endif + typedef unsigned __int32 uint32_t; + typedef __int64 int64_t; + typedef unsigned __int64 uint64_t; + +# if defined(_WIN64) + typedef __int64 intptr_t; + typedef unsigned __int64 uintptr_t; +# else + typedef __int32 intptr_t; + typedef unsigned __int32 uintptr_t; +# endif + +# define INT64_C(__val) __val##i64 +# define UINT64_C(__val) __val##ui64 +#else +/* hope the best instead of adding a bunch of ifdef's */ +# include <stdint.h> +#endif + + +/** + * Function inlining + */ +#if defined(__GNUC__) +# define INLINE __inline__ +#elif defined(__MSC__) +# define INLINE __inline +#elif defined(_MSC_VER) +# define INLINE __inline +#elif defined(__ICL) +# define INLINE __inline +#elif defined(__INTEL_COMPILER) +# define INLINE inline +#elif defined(__WATCOMC__) && (__WATCOMC__ >= 1100) +# define INLINE __inline +#elif defined(__SUNPRO_C) && defined(__C99FEATURES__) +# define INLINE inline +# define __inline inline +# define __inline__ inline +#elif (__STDC_VERSION__ >= 199901L) /* C99 */ +# define INLINE inline +#else +# define INLINE +#endif + + +#endif /* EGLCOMPILER_INCLUDED */ diff --git a/src/egl/main/eglconfig.c b/src/egl/main/eglconfig.c index 2a62f95b54..d47b99eed4 100644 --- a/src/egl/main/eglconfig.c +++ b/src/egl/main/eglconfig.c @@ -17,48 +17,6 @@ #define MIN2(A, B) (((A) < (B)) ? (A) : (B)) -/** - * Convert an _EGLConfig to a __GLcontextModes object. - * NOTE: This routine may be incomplete - we're only making sure that - * the fields needed by Mesa (for _mesa_create_context/framebuffer) are - * set correctly. - */ -void -_eglConfigToContextModesRec(const _EGLConfig *config, __GLcontextModes *mode) -{ - memset(mode, 0, sizeof(*mode)); - - mode->rgbMode = GL_TRUE; /* no color index */ - mode->colorIndexMode = GL_FALSE; - mode->doubleBufferMode = GL_TRUE; /* always DB for now */ - mode->stereoMode = GL_FALSE; - - mode->redBits = GET_CONFIG_ATTRIB(config, EGL_RED_SIZE); - mode->greenBits = GET_CONFIG_ATTRIB(config, EGL_GREEN_SIZE); - mode->blueBits = GET_CONFIG_ATTRIB(config, EGL_BLUE_SIZE); - mode->alphaBits = GET_CONFIG_ATTRIB(config, EGL_ALPHA_SIZE); - mode->rgbBits = GET_CONFIG_ATTRIB(config, EGL_BUFFER_SIZE); - - /* no rgba masks - fix? */ - - mode->depthBits = GET_CONFIG_ATTRIB(config, EGL_DEPTH_SIZE); - mode->haveDepthBuffer = mode->depthBits > 0; - - mode->stencilBits = GET_CONFIG_ATTRIB(config, EGL_STENCIL_SIZE); - mode->haveStencilBuffer = mode->stencilBits > 0; - - /* no accum */ - - mode->level = GET_CONFIG_ATTRIB(config, EGL_LEVEL); - mode->samples = GET_CONFIG_ATTRIB(config, EGL_SAMPLES); - mode->sampleBuffers = GET_CONFIG_ATTRIB(config, EGL_SAMPLE_BUFFERS); - - /* surface type - not really needed */ - mode->visualType = GLX_TRUE_COLOR; - mode->renderType = GLX_RGBA_BIT; -} - - void _eglSetConfigAttrib(_EGLConfig *config, EGLint attr, EGLint val) { @@ -76,7 +34,7 @@ void _eglInitConfig(_EGLConfig *config, EGLint id) { memset(config, 0, sizeof(*config)); - config->Handle = id; + config->Handle = (EGLConfig) _eglUIntToPointer((unsigned int) id); _eglSetConfigAttrib(config, EGL_CONFIG_ID, id); _eglSetConfigAttrib(config, EGL_BIND_TO_TEXTURE_RGB, EGL_DONT_CARE); _eglSetConfigAttrib(config, EGL_BIND_TO_TEXTURE_RGBA, EGL_DONT_CARE); @@ -85,9 +43,7 @@ _eglInitConfig(_EGLConfig *config, EGLint id) _eglSetConfigAttrib(config, EGL_NATIVE_VISUAL_TYPE, EGL_DONT_CARE); _eglSetConfigAttrib(config, EGL_MIN_SWAP_INTERVAL, EGL_DONT_CARE); _eglSetConfigAttrib(config, EGL_MAX_SWAP_INTERVAL, EGL_DONT_CARE); - _eglSetConfigAttrib(config, EGL_SURFACE_TYPE, - EGL_SCREEN_BIT_MESA | EGL_PBUFFER_BIT | - EGL_PIXMAP_BIT | EGL_WINDOW_BIT); + _eglSetConfigAttrib(config, EGL_SURFACE_TYPE, EGL_WINDOW_BIT); _eglSetConfigAttrib(config, EGL_TRANSPARENT_TYPE, EGL_NONE); _eglSetConfigAttrib(config, EGL_TRANSPARENT_RED_VALUE, EGL_DONT_CARE); _eglSetConfigAttrib(config, EGL_TRANSPARENT_GREEN_VALUE, EGL_DONT_CARE); @@ -100,16 +56,27 @@ _eglInitConfig(_EGLConfig *config, EGLint id) /** + * Return the public handle for an internal _EGLConfig. + * This is the inverse of _eglLookupConfig(). + */ +EGLConfig +_eglGetConfigHandle(_EGLConfig *config) +{ + return config ? config->Handle : 0; +} + + +/** * Given an EGLConfig handle, return the corresponding _EGLConfig object. + * This is the inverse of _eglGetConfigHandle(). */ _EGLConfig * -_eglLookupConfig(_EGLDriver *drv, EGLDisplay dpy, EGLConfig config) +_eglLookupConfig(EGLConfig config, _EGLDisplay *disp) { EGLint i; - _EGLDisplay *disp = _eglLookupDisplay(dpy); for (i = 0; i < disp->NumConfigs; i++) { - if (disp->Configs[i].Handle == config) { - return disp->Configs + i; + if (disp->Configs[i]->Handle == config) { + return disp->Configs[i]; } } return NULL; @@ -118,23 +85,32 @@ _eglLookupConfig(_EGLDriver *drv, EGLDisplay dpy, EGLConfig config) /** * Add the given _EGLConfig to the given display. + * Note that we just save the ptr to the config (we don't copy the config). */ _EGLConfig * -_eglAddConfig(_EGLDisplay *display, const _EGLConfig *config) +_eglAddConfig(_EGLDisplay *display, _EGLConfig *config) { - _EGLConfig *newConfigs; + _EGLConfig **newConfigs; EGLint n; + /* do some sanity checks on the config's attribs */ + assert(GET_CONFIG_ATTRIB(config, EGL_CONFIG_ID) > 0); + assert(GET_CONFIG_ATTRIB(config, EGL_RENDERABLE_TYPE) != 0x0); + assert(GET_CONFIG_ATTRIB(config, EGL_SURFACE_TYPE) != 0x0); + assert(GET_CONFIG_ATTRIB(config, EGL_RED_SIZE) > 0); + assert(GET_CONFIG_ATTRIB(config, EGL_GREEN_SIZE) > 0); + assert(GET_CONFIG_ATTRIB(config, EGL_BLUE_SIZE) > 0); + n = display->NumConfigs; - newConfigs = (_EGLConfig *) realloc(display->Configs, - (n + 1) * sizeof(_EGLConfig)); + /* realloc array of ptrs */ + newConfigs = (_EGLConfig **) realloc(display->Configs, + (n + 1) * sizeof(_EGLConfig *)); if (newConfigs) { display->Configs = newConfigs; - display->Configs[n] = *config; /* copy struct */ - display->Configs[n].Handle = n; + display->Configs[n] = config; display->NumConfigs++; - return display->Configs + n; + return config; } else { return NULL; @@ -156,6 +132,9 @@ _eglParseConfigAttribs(_EGLConfig *config, const EGLint *attrib_list) config->Attrib[i] = EGL_DONT_CARE; } + /* by default choose windows unless otherwise specified */ + config->Attrib[EGL_SURFACE_TYPE - FIRST_ATTRIB] = EGL_WINDOW_BIT; + for (i = 0; attrib_list && attrib_list[i] != EGL_NONE; i++) { const EGLint attr = attrib_list[i]; if (attr >= EGL_BUFFER_SIZE && @@ -176,7 +155,7 @@ _eglParseConfigAttribs(_EGLConfig *config, const EGLint *attrib_list) } else if (attr == EGL_RENDERABLE_TYPE) { EGLint renType = attrib_list[++i]; - if (renType & ~(EGL_OPENGL_ES_BIT | EGL_OPENVG_BIT)) { + if (renType & ~(EGL_OPENGL_ES_BIT | EGL_OPENGL_ES2_BIT | EGL_OPENVG_BIT)) { _eglError(EGL_BAD_ATTRIBUTE, "eglChooseConfig"); return EGL_FALSE; } @@ -339,10 +318,9 @@ _eglCompareConfigs(const void *a, const void *b) * Typical fallback routine for eglChooseConfig */ EGLBoolean -_eglChooseConfig(_EGLDriver *drv, EGLDisplay dpy, const EGLint *attrib_list, +_eglChooseConfig(_EGLDriver *drv, _EGLDisplay *disp, const EGLint *attrib_list, EGLConfig *configs, EGLint config_size, EGLint *num_configs) { - _EGLDisplay *disp = _eglLookupDisplay(dpy); _EGLConfig **configList, criteria; EGLint i, count; @@ -360,8 +338,8 @@ _eglChooseConfig(_EGLDriver *drv, EGLDisplay dpy, const EGLint *attrib_list, /* make array of pointers to qualifying configs */ for (i = count = 0; i < disp->NumConfigs && count < config_size; i++) { - if (_eglConfigQualifies(disp->Configs + i, &criteria)) { - configList[count++] = disp->Configs + i; + if (_eglConfigQualifies(disp->Configs[i], &criteria)) { + configList[count++] = disp->Configs[i]; } } @@ -369,8 +347,10 @@ _eglChooseConfig(_EGLDriver *drv, EGLDisplay dpy, const EGLint *attrib_list, qsort(configList, count, sizeof(_EGLConfig *), _eglCompareConfigs); /* copy config handles to output array */ - for (i = 0; i < count; i++) { - configs[i] = configList[i]->Handle; + if (configs) { + for (i = 0; i < count; i++) { + configs[i] = configList[i]->Handle; + } } free(configList); @@ -385,10 +365,9 @@ _eglChooseConfig(_EGLDriver *drv, EGLDisplay dpy, const EGLint *attrib_list, * Fallback for eglGetConfigAttrib. */ EGLBoolean -_eglGetConfigAttrib(_EGLDriver *drv, EGLDisplay dpy, EGLConfig config, +_eglGetConfigAttrib(_EGLDriver *drv, _EGLDisplay *dpy, _EGLConfig *conf, EGLint attribute, EGLint *value) { - const _EGLConfig *conf = _eglLookupConfig(drv, dpy, config); const EGLint k = attribute - FIRST_ATTRIB; if (k >= 0 && k < MAX_ATTRIBS) { *value = conf->Attrib[k]; @@ -405,21 +384,14 @@ _eglGetConfigAttrib(_EGLDriver *drv, EGLDisplay dpy, EGLConfig config, * Fallback for eglGetConfigs. */ EGLBoolean -_eglGetConfigs(_EGLDriver *drv, EGLDisplay dpy, EGLConfig *configs, +_eglGetConfigs(_EGLDriver *drv, _EGLDisplay *disp, EGLConfig *configs, EGLint config_size, EGLint *num_config) { - _EGLDisplay *disp = _eglLookupDisplay(dpy); - - if (!drv->Initialized) { - _eglError(EGL_NOT_INITIALIZED, "eglGetConfigs"); - return EGL_FALSE; - } - if (configs) { EGLint i; *num_config = MIN2(disp->NumConfigs, config_size); for (i = 0; i < *num_config; i++) { - configs[i] = disp->Configs[i].Handle; + configs[i] = disp->Configs[i]->Handle; } } else { @@ -429,210 +401,3 @@ _eglGetConfigs(_EGLDriver *drv, EGLDisplay dpy, EGLConfig *configs, return EGL_TRUE; } - - -/** - * Creates a set of \c __GLcontextModes 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 ptr_to_modes Pointer to a pointer to a linked list of - * \c __GLcontextModes. Upon completion, a pointer to - * the next element to be process will be stored here. - * If the function fails and returns \c GL_FALSE, this - * value will be unmodified, but some elements in the - * linked list may be modified. - * \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. - */ -GLboolean -_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 */ - }; - - 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 */ - }; - - 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, - "[%s:%u] Framebuffer type 0x%04x has 0 bytes per pixel.", - __FUNCTION__, __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; - - 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; - - default: - _eglLog(_EGL_WARNING, - "[%s:%u] Framebuffer format 0x%04x is not GL_RGB, GL_RGBA, GL_BGR, or GL_BGRA.", - __FUNCTION__, __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/eglconfig.h b/src/egl/main/eglconfig.h index 441b3f4d20..36ed96ae95 100644 --- a/src/egl/main/eglconfig.h +++ b/src/egl/main/eglconfig.h @@ -3,10 +3,10 @@ #include "egltypedefs.h" -#include "GL/internal/glcore.h" +#include <GLES/gl.h> -#define MAX_ATTRIBS 100 +#define MAX_ATTRIBS 128 #define FIRST_ATTRIB EGL_BUFFER_SIZE @@ -17,7 +17,11 @@ struct _egl_config }; -#define SET_CONFIG_ATTRIB(CONF, ATTR, VAL) ((CONF)->Attrib[(ATTR) - FIRST_ATTRIB] = VAL) +#define SET_CONFIG_ATTRIB(CONF, ATTR, VAL) \ + assert((ATTR) - FIRST_ATTRIB < MAX_ATTRIBS); \ + ((CONF)->Attrib[(ATTR) - FIRST_ATTRIB] = VAL) + + #define GET_CONFIG_ATTRIB(CONF, ATTR) ((CONF)->Attrib[(ATTR) - FIRST_ATTRIB]) @@ -25,12 +29,16 @@ extern void _eglInitConfig(_EGLConfig *config, EGLint id); +extern EGLConfig +_eglGetConfigHandle(_EGLConfig *config); + + extern _EGLConfig * -_eglLookupConfig(_EGLDriver *drv, EGLDisplay dpy, EGLConfig config); +_eglLookupConfig(EGLConfig config, _EGLDisplay *dpy); extern _EGLConfig * -_eglAddConfig(_EGLDisplay *display, const _EGLConfig *config); +_eglAddConfig(_EGLDisplay *display, _EGLConfig *config); extern EGLBoolean @@ -38,30 +46,19 @@ _eglParseConfigAttribs(_EGLConfig *config, const EGLint *attrib_list); extern EGLBoolean -_eglChooseConfig(_EGLDriver *drv, EGLDisplay dpy, const EGLint *attrib_list, EGLConfig *configs, EGLint config_size, EGLint *num_config); +_eglChooseConfig(_EGLDriver *drv, _EGLDisplay *dpy, const EGLint *attrib_list, EGLConfig *configs, EGLint config_size, EGLint *num_config); extern EGLBoolean -_eglGetConfigAttrib(_EGLDriver *drv, EGLDisplay dpy, EGLConfig config, EGLint attribute, EGLint *value); +_eglGetConfigAttrib(_EGLDriver *drv, _EGLDisplay *dpy, _EGLConfig *conf, EGLint attribute, EGLint *value); extern EGLBoolean -_eglGetConfigs(_EGLDriver *drv, EGLDisplay dpy, EGLConfig *configs, EGLint config_size, EGLint *num_config); +_eglGetConfigs(_EGLDriver *drv, _EGLDisplay *dpy, EGLConfig *configs, EGLint config_size, EGLint *num_config); extern void _eglSetConfigAttrib(_EGLConfig *config, EGLint attr, EGLint val); -extern GLboolean -_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 ); - -extern void -_eglConfigToContextModesRec(const _EGLConfig *config, __GLcontextModes *mode); - #endif /* EGLCONFIG_INCLUDED */ diff --git a/src/egl/main/eglconfigutil.c b/src/egl/main/eglconfigutil.c new file mode 100644 index 0000000000..c9d00e7982 --- /dev/null +++ b/src/egl/main/eglconfigutil.c @@ -0,0 +1,260 @@ +/** + * Extra utility functions related to EGL configs. + */ + + +#include <stdlib.h> +#include <stdio.h> +#include <string.h> +#include "eglconfigutil.h" +#include "egllog.h" + + +/** + * Convert an _EGLConfig to a __GLcontextModes object. + * NOTE: This routine may be incomplete - we're only making sure that + * the fields needed by Mesa (for _mesa_create_context/framebuffer) are + * set correctly. + */ +void +_eglConfigToContextModesRec(const _EGLConfig *config, __GLcontextModes *mode) +{ + memset(mode, 0, sizeof(*mode)); + + mode->rgbMode = GL_TRUE; /* no color index */ + mode->colorIndexMode = GL_FALSE; + mode->doubleBufferMode = GL_TRUE; /* always DB for now */ + mode->stereoMode = GL_FALSE; + + mode->redBits = GET_CONFIG_ATTRIB(config, EGL_RED_SIZE); + mode->greenBits = GET_CONFIG_ATTRIB(config, EGL_GREEN_SIZE); + mode->blueBits = GET_CONFIG_ATTRIB(config, EGL_BLUE_SIZE); + mode->alphaBits = GET_CONFIG_ATTRIB(config, EGL_ALPHA_SIZE); + mode->rgbBits = GET_CONFIG_ATTRIB(config, EGL_BUFFER_SIZE); + + /* no rgba masks - fix? */ + + mode->depthBits = GET_CONFIG_ATTRIB(config, EGL_DEPTH_SIZE); + mode->haveDepthBuffer = mode->depthBits > 0; + + mode->stencilBits = GET_CONFIG_ATTRIB(config, EGL_STENCIL_SIZE); + mode->haveStencilBuffer = mode->stencilBits > 0; + + /* no accum */ + + mode->level = GET_CONFIG_ATTRIB(config, EGL_LEVEL); + mode->samples = GET_CONFIG_ATTRIB(config, EGL_SAMPLES); + mode->sampleBuffers = GET_CONFIG_ATTRIB(config, EGL_SAMPLE_BUFFERS); + + /* surface type - not really needed */ + mode->visualType = GLX_TRUE_COLOR; + mode->renderType = GLX_RGBA_BIT; +} + + + +/** + * 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 new file mode 100644 index 0000000000..c477b94737 --- /dev/null +++ b/src/egl/main/eglconfigutil.h @@ -0,0 +1,26 @@ + +#ifndef EGLCONFIGUTIL_INCLUDED +#define EGLCONFIGUTIL_INCLUDED + +#include "eglconfig.h" +#include "GL/internal/glcore.h" +#if (!defined(WIN32) && !defined(_WIN32_WCE)) +#include "stdint.h" +#endif + + +extern void +_eglConfigToContextModesRec(const _EGLConfig *config, __GLcontextModes *mode); + + +extern 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 374c006dae..b094f49bfc 100644 --- a/src/egl/main/eglcontext.c +++ b/src/egl/main/eglcontext.c @@ -6,115 +6,72 @@ #include "egldisplay.h" #include "egldriver.h" #include "eglglobals.h" -#include "eglhash.h" #include "eglsurface.h" /** - * Initialize the given _EGLContext object to defaults. + * Initialize the given _EGLContext object to defaults and/or the values + * in the attrib_list. */ EGLBoolean -_eglInitContext(_EGLDriver *drv, EGLDisplay dpy, _EGLContext *ctx, - EGLConfig config, const EGLint *attrib_list) +_eglInitContext(_EGLDriver *drv, _EGLContext *ctx, + _EGLConfig *conf, const EGLint *attrib_list) { - _EGLConfig *conf; - _EGLDisplay *display = _eglLookupDisplay(dpy); EGLint i; + const EGLenum api = eglQueryAPI(); - conf = _eglLookupConfig(drv, dpy, config); - if (!conf) { - _eglError(EGL_BAD_CONFIG, "eglCreateContext"); + if (api == EGL_NONE) { + _eglError(EGL_BAD_MATCH, "eglCreateContext(no client API)"); return EGL_FALSE; } + memset(ctx, 0, sizeof(_EGLContext)); + + ctx->ClientVersion = 1; /* the default, per EGL spec */ + for (i = 0; attrib_list && attrib_list[i] != EGL_NONE; i++) { switch (attrib_list[i]) { - /* no attribs defined for now */ + case EGL_CONTEXT_CLIENT_VERSION: + i++; + ctx->ClientVersion = attrib_list[i]; + break; default: - _eglError(EGL_BAD_ATTRIBUTE, "eglCreateContext"); - return EGL_NO_CONTEXT; + _eglError(EGL_BAD_ATTRIBUTE, "_eglInitContext"); + return EGL_FALSE; } } - memset(ctx, 0, sizeof(_EGLContext)); - ctx->Display = display; ctx->Config = conf; ctx->DrawSurface = EGL_NO_SURFACE; ctx->ReadSurface = EGL_NO_SURFACE; + ctx->ClientAPI = api; return EGL_TRUE; } -/* - * Assign an EGLContext handle to the _EGLContext object then put it into - * the hash table. - */ -void -_eglSaveContext(_EGLContext *ctx) -{ - assert(ctx); - ctx->Handle = _eglHashGenKey(_eglGlobal.Contexts); - _eglHashInsert(_eglGlobal.Contexts, ctx->Handle, ctx); -} - - -/** - * Remove the given _EGLContext object from the hash table. - */ -void -_eglRemoveContext(_EGLContext *ctx) -{ - _eglHashRemove(_eglGlobal.Contexts, ctx->Handle); -} - - -/** - * Return the _EGLContext object that corresponds to the given - * EGLContext handle. - */ -_EGLContext * -_eglLookupContext(EGLContext ctx) -{ - _EGLContext *c = (_EGLContext *) _eglHashLookup(_eglGlobal.Contexts, ctx); - return c; -} - - -/** - * Return the currently bound _EGLContext object, or NULL. - */ -_EGLContext * -_eglGetCurrentContext(void) -{ - _EGLThreadInfo *t = _eglGetCurrentThread(); - return t->CurrentContext; -} - - /** * Just a placeholder/demo function. Real driver will never use this! */ -EGLContext -_eglCreateContext(_EGLDriver *drv, EGLDisplay dpy, EGLConfig config, - EGLContext share_list, const EGLint *attrib_list) +_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 EGL_NO_CONTEXT; + return NULL; - if (!_eglInitContext(drv, dpy, context, config, attrib_list)) { + if (!_eglInitContext(drv, context, conf, attrib_list)) { free(context); - return EGL_NO_CONTEXT; + return NULL; } - _eglSaveContext(context); - return context->Handle; + return context; #endif - return EGL_NO_CONTEXT; + return NULL; } @@ -122,40 +79,21 @@ _eglCreateContext(_EGLDriver *drv, EGLDisplay dpy, EGLConfig config, * Default fallback routine - drivers should usually override this. */ EGLBoolean -_eglDestroyContext(_EGLDriver *drv, EGLDisplay dpy, EGLContext ctx) +_eglDestroyContext(_EGLDriver *drv, _EGLDisplay *dpy, _EGLContext *ctx) { - _EGLContext *context = _eglLookupContext(ctx); - if (context) { - _eglHashRemove(_eglGlobal.Contexts, ctx); - if (context->IsBound) { - context->DeletePending = EGL_TRUE; - } - else { - free(context); - } - return EGL_TRUE; - } - else { - _eglError(EGL_BAD_CONTEXT, "eglDestroyContext"); - return EGL_TRUE; - } + if (!_eglIsContextBound(ctx)) + free(ctx); + return EGL_TRUE; } EGLBoolean -_eglQueryContext(_EGLDriver *drv, EGLDisplay dpy, EGLContext ctx, +_eglQueryContext(_EGLDriver *drv, _EGLDisplay *dpy, _EGLContext *c, EGLint attribute, EGLint *value) { - _EGLContext *c = _eglLookupContext(ctx); - (void) drv; (void) dpy; - if (!c) { - _eglError(EGL_BAD_CONTEXT, "eglQueryContext"); - return EGL_FALSE; - } - switch (attribute) { case EGL_CONFIG_ID: *value = GET_CONFIG_ATTRIB(c->Config, EGL_CONFIG_ID); @@ -163,8 +101,11 @@ _eglQueryContext(_EGLDriver *drv, EGLDisplay dpy, EGLContext ctx, #ifdef EGL_VERSION_1_2 case EGL_CONTEXT_CLIENT_TYPE: *value = c->ClientAPI; - return EGL_FALSE; + return EGL_TRUE; #endif /* EGL_VERSION_1_2 */ + case EGL_CONTEXT_CLIENT_VERSION: + *value = c->ClientVersion; + return EGL_TRUE; default: _eglError(EGL_BAD_ATTRIBUTE, "eglQueryContext"); return EGL_FALSE; @@ -174,90 +115,100 @@ _eglQueryContext(_EGLDriver *drv, EGLDisplay dpy, EGLContext ctx, /** * Drivers will typically call this to do the error checking and - * update the various IsBound and DeletePending flags. + * update the various flags. * Then, the driver will do its device-dependent Make-Current stuff. */ EGLBoolean -_eglMakeCurrent(_EGLDriver *drv, EGLDisplay dpy, EGLSurface d, - EGLSurface r, EGLContext context) +_eglMakeCurrent(_EGLDriver *drv, _EGLDisplay *dpy, _EGLSurface *draw, + _EGLSurface *read, _EGLContext *ctx) { _EGLThreadInfo *t = _eglGetCurrentThread(); - _EGLContext *ctx = _eglLookupContext(context); - _EGLSurface *draw = _eglLookupSurface(d); - _EGLSurface *read = _eglLookupSurface(r); + _EGLContext *oldContext = NULL; + _EGLSurface *oldDrawSurface = NULL; + _EGLSurface *oldReadSurface = NULL; + EGLint apiIndex; - _EGLContext *oldContext = _eglGetCurrentContext(); - _EGLSurface *oldDrawSurface = _eglGetCurrentSurface(EGL_DRAW); - _EGLSurface *oldReadSurface = _eglGetCurrentSurface(EGL_READ); + if (_eglIsCurrentThreadDummy()) + return _eglError(EGL_BAD_ALLOC, "eglMakeCurrent"); - /* error checking */ if (ctx) { - if (draw == NULL || read == NULL) { - _eglError(EGL_BAD_MATCH, "eglMakeCurrent"); - return EGL_FALSE; - } - if (draw->Config != ctx->Config) { - _eglError(EGL_BAD_MATCH, "eglMakeCurrent"); - return EGL_FALSE; - } - if (read->Config != ctx->Config) { - _eglError(EGL_BAD_MATCH, "eglMakeCurrent"); - return EGL_FALSE; + /* error checking */ + if (ctx->Binding && ctx->Binding != t) + return _eglError(EGL_BAD_ACCESS, "eglMakeCurrent"); + if (draw == NULL || read == NULL) + 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"); + +#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; } +#endif + apiIndex = _eglConvertApiToIndex(ctx->ClientAPI); + } + else { + if (draw != NULL || read != NULL) + return _eglError(EGL_BAD_MATCH, "eglMakeCurrent"); + apiIndex = t->CurrentAPIIndex; } - /* - * check if the old context or surfaces need to be deleted - */ - if (oldDrawSurface != NULL) { - oldDrawSurface->IsBound = EGL_FALSE; - if (oldDrawSurface->DeletePending) { - /* make sure we don't try to rebind a deleted surface */ - if (draw == oldDrawSurface || draw == oldReadSurface) { - draw = NULL; - } - /* really delete surface now */ - drv->API.DestroySurface(drv, dpy, oldDrawSurface->Handle); + 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; + + /* + * check if the old context or surfaces need to be deleted + */ + if (!_eglIsSurfaceLinked(oldDrawSurface)) { + assert(draw != oldDrawSurface && read != oldDrawSurface); + drv->API.DestroySurface(drv, dpy, oldDrawSurface); } - } - if (oldReadSurface != NULL && oldReadSurface != oldDrawSurface) { - oldReadSurface->IsBound = EGL_FALSE; - if (oldReadSurface->DeletePending) { - /* make sure we don't try to rebind a deleted surface */ - if (read == oldDrawSurface || read == oldReadSurface) { - read = NULL; - } - /* really delete surface now */ - drv->API.DestroySurface(drv, dpy, oldReadSurface->Handle); + if (oldReadSurface != oldDrawSurface && + !_eglIsSurfaceLinked(oldReadSurface)) { + assert(draw != oldReadSurface && read != oldReadSurface); + drv->API.DestroySurface(drv, dpy, oldReadSurface); } - } - if (oldContext != NULL) { - oldContext->IsBound = EGL_FALSE; - if (oldContext->DeletePending) { - /* make sure we don't try to rebind a deleted context */ - if (ctx == oldContext) { - ctx = NULL; - } - /* really delete context now */ - drv->API.DestroyContext(drv, dpy, oldContext->Handle); + if (!_eglIsContextLinked(oldContext)) { + assert(ctx != oldContext); + drv->API.DestroyContext(drv, dpy, oldContext); } } + /* build new bindings */ if (ctx) { - /* check read/draw again, in case we deleted them above */ - if (draw == NULL || read == NULL) { - _eglError(EGL_BAD_MATCH, "eglMakeCurrent"); - return EGL_FALSE; - } + t->CurrentContexts[apiIndex] = ctx; + ctx->Binding = t; ctx->DrawSurface = draw; ctx->ReadSurface = read; - ctx->IsBound = EGL_TRUE; - draw->IsBound = EGL_TRUE; - read->IsBound = EGL_TRUE; + draw->Binding = ctx; + read->Binding = ctx; } - t->CurrentContext = ctx; - return EGL_TRUE; } diff --git a/src/egl/main/eglcontext.h b/src/egl/main/eglcontext.h index 82bfde151f..647f24488f 100644 --- a/src/egl/main/eglcontext.h +++ b/src/egl/main/eglcontext.h @@ -11,61 +11,55 @@ */ struct _egl_context { - EGLContext Handle; /* The public/opaque handle which names this object */ - - _EGLDisplay *Display; /* who do I belong to? */ - - _EGLConfig *Config; + /* Managed by EGLDisplay for linking */ + _EGLDisplay *Display; + _EGLContext *Next; + /* The bound status of the context */ + _EGLThreadInfo *Binding; _EGLSurface *DrawSurface; _EGLSurface *ReadSurface; - EGLBoolean IsBound; - EGLBoolean DeletePending; -#ifdef EGL_VERSION_1_2 - EGLint ClientAPI; /* Either EGL_OPENGL_ES_API or EGL_OPENVG_API */ -#endif /* EGL_VERSION_1_2 */ + _EGLConfig *Config; + + EGLint ClientAPI; /**< EGL_OPENGL_ES_API, EGL_OPENGL_API, EGL_OPENVG_API */ + EGLint ClientVersion; /**< 1 = OpenGLES 1.x, 2 = OpenGLES 2.x */ }; extern EGLBoolean -_eglInitContext(_EGLDriver *drv, EGLDisplay dpy, _EGLContext *ctx, - EGLConfig config, const EGLint *attrib_list); - - -extern void -_eglSaveContext(_EGLContext *ctx); - - -extern void -_eglRemoveContext(_EGLContext *ctx); +_eglInitContext(_EGLDriver *drv, _EGLContext *ctx, + _EGLConfig *config, const EGLint *attrib_list); extern _EGLContext * -_eglLookupContext(EGLContext ctx); - - -extern _EGLContext * -_eglGetCurrentContext(void); - - -extern EGLContext -_eglCreateContext(_EGLDriver *drv, EGLDisplay dpy, EGLConfig config, EGLContext share_list, const EGLint *attrib_list); +_eglCreateContext(_EGLDriver *drv, _EGLDisplay *dpy, _EGLConfig *conf, _EGLContext *share_list, const EGLint *attrib_list); extern EGLBoolean -_eglDestroyContext(_EGLDriver *drv, EGLDisplay dpy, EGLContext ctx); +_eglDestroyContext(_EGLDriver *drv, _EGLDisplay *dpy, _EGLContext *ctx); extern EGLBoolean -_eglQueryContext(_EGLDriver *drv, EGLDisplay dpy, EGLContext ctx, EGLint attribute, EGLint *value); +_eglQueryContext(_EGLDriver *drv, _EGLDisplay *dpy, _EGLContext *ctx, EGLint attribute, EGLint *value); extern EGLBoolean -_eglMakeCurrent(_EGLDriver *drv, EGLDisplay dpy, EGLSurface draw, EGLSurface read, EGLContext ctx); +_eglMakeCurrent(_EGLDriver *drv, _EGLDisplay *dpy, _EGLSurface *draw, _EGLSurface *read, _EGLContext *ctx); extern EGLBoolean _eglCopyContextMESA(_EGLDriver *drv, EGLDisplay dpy, EGLContext source, EGLContext dest, EGLint mask); + +/** + * Return true if the context is bound to a thread. + */ +static INLINE EGLBoolean +_eglIsContextBound(_EGLContext *ctx) +{ + return (ctx->Binding != NULL); +} + + #endif /* EGLCONTEXT_INCLUDED */ diff --git a/src/egl/main/eglcurrent.c b/src/egl/main/eglcurrent.c new file mode 100644 index 0000000000..4431f964f6 --- /dev/null +++ b/src/egl/main/eglcurrent.c @@ -0,0 +1,342 @@ +#include <stdlib.h> +#include <string.h> +#include "eglcurrent.h" +#include "eglcontext.h" +#include "egllog.h" +#include "eglmutex.h" +#include "eglglobals.h" + + +/* This should be kept in sync with _eglInitThreadInfo() */ +#define _EGL_THREAD_INFO_INITIALIZER \ + { EGL_SUCCESS, { NULL }, 1 } + +/* a fallback thread info to guarantee that every thread always has one */ +static _EGLThreadInfo dummy_thread = _EGL_THREAD_INFO_INITIALIZER; + + +#ifdef GLX_USE_TLS +static __thread const _EGLThreadInfo *_egl_TSD; + __attribute__ ((tls_model("initial-exec"))); + +static INLINE void _eglSetTSD(const _EGLThreadInfo *t) +{ + _egl_TSD = t; +} + +static INLINE _EGLThreadInfo *_eglGetTSD(void) +{ + return (_EGLThreadInfo *) _egl_TSD; +} + +static INLINE void _eglFiniTSD(void) +{ +} + +static INLINE EGLBoolean _eglInitTSD(void (*dtor)(_EGLThreadInfo *)) +{ + /* TODO destroy TSD */ + (void) dtor; + (void) _eglFiniTSD; + return EGL_TRUE; +} + +#elif PTHREADS +#include <pthread.h> + +static _EGL_DECLARE_MUTEX(_egl_TSDMutex); +static EGLBoolean _egl_TSDInitialized; +static pthread_key_t _egl_TSD; +static void (*_egl_FreeTSD)(_EGLThreadInfo *); + +static INLINE void _eglSetTSD(const _EGLThreadInfo *t) +{ + pthread_setspecific(_egl_TSD, (const void *) t); +} + +static INLINE _EGLThreadInfo *_eglGetTSD(void) +{ + return (_EGLThreadInfo *) pthread_getspecific(_egl_TSD); +} + +static INLINE void _eglFiniTSD(void) +{ + _eglLockMutex(&_egl_TSDMutex); + if (_egl_TSDInitialized) { + _EGLThreadInfo *t = _eglGetTSD(); + + _egl_TSDInitialized = EGL_FALSE; + if (t && _egl_FreeTSD) + _egl_FreeTSD((void *) t); + pthread_key_delete(_egl_TSD); + } + _eglUnlockMutex(&_egl_TSDMutex); +} + +static INLINE EGLBoolean _eglInitTSD(void (*dtor)(_EGLThreadInfo *)) +{ + if (!_egl_TSDInitialized) { + _eglLockMutex(&_egl_TSDMutex); + + /* check again after acquiring lock */ + if (!_egl_TSDInitialized) { + if (pthread_key_create(&_egl_TSD, (void (*)(void *)) dtor) != 0) { + _eglUnlockMutex(&_egl_TSDMutex); + return EGL_FALSE; + } + _egl_FreeTSD = dtor; + _eglAddAtExitCall(_eglFiniTSD); + _egl_TSDInitialized = EGL_TRUE; + } + + _eglUnlockMutex(&_egl_TSDMutex); + } + + return EGL_TRUE; +} + +#else /* PTHREADS */ +static const _EGLThreadInfo *_egl_TSD; +static void (*_egl_FreeTSD)(_EGLThreadInfo *); + +static INLINE void _eglSetTSD(const _EGLThreadInfo *t) +{ + _egl_TSD = t; +} + +static INLINE _EGLThreadInfo *_eglGetTSD(void) +{ + return (_EGLThreadInfo *) _egl_TSD; +} + +static INLINE void _eglFiniTSD(void) +{ + if (_egl_FreeTSD && _egl_TSD) + _egl_FreeTSD((_EGLThreadInfo *) _egl_TSD); +} + +static INLINE EGLBoolean _eglInitTSD(void (*dtor)(_EGLThreadInfo *)) +{ + if (!_egl_FreeTSD && dtor) { + _egl_FreeTSD = dtor; + _eglAddAtExitCall(_eglFiniTSD); + } + return EGL_TRUE; +} + +#endif /* !PTHREADS */ + + +static void +_eglInitThreadInfo(_EGLThreadInfo *t) +{ + memset(t, 0, sizeof(*t)); + t->LastError = EGL_SUCCESS; + /* default, per EGL spec */ + t->CurrentAPIIndex = _eglConvertApiToIndex(EGL_OPENGL_ES_API); +} + + +/** + * Allocate and init a new _EGLThreadInfo object. + */ +static _EGLThreadInfo * +_eglCreateThreadInfo(void) +{ + _EGLThreadInfo *t = (_EGLThreadInfo *) calloc(1, sizeof(_EGLThreadInfo)); + if (t) + _eglInitThreadInfo(t); + else + t = &dummy_thread; + return t; +} + + +/** + * Delete/free a _EGLThreadInfo object. + */ +static void +_eglDestroyThreadInfo(_EGLThreadInfo *t) +{ + if (t != &dummy_thread) + free(t); +} + + +/** + * Make sure TSD is initialized and return current value. + */ +static INLINE _EGLThreadInfo * +_eglCheckedGetTSD(void) +{ + if (_eglInitTSD(&_eglDestroyThreadInfo) != EGL_TRUE) { + _eglLog(_EGL_FATAL, "failed to initialize \"current\" system"); + return NULL; + } + + return _eglGetTSD(); +} + + +/** + * Return the calling thread's thread info. + * If the calling thread nevers calls this function before, or if its thread + * info was destroyed, a new one is created. This function never returns NULL. + * In the case allocation fails, a dummy one is returned. See also + * _eglIsCurrentThreadDummy. + */ +_EGLThreadInfo * +_eglGetCurrentThread(void) +{ + _EGLThreadInfo *t = _eglCheckedGetTSD(); + if (!t) { + t = _eglCreateThreadInfo(); + _eglSetTSD(t); + } + + return t; +} + + +/** + * Destroy the calling thread's thread info. + */ +void +_eglDestroyCurrentThread(void) +{ + _EGLThreadInfo *t = _eglCheckedGetTSD(); + if (t) { + _eglDestroyThreadInfo(t); + _eglSetTSD(NULL); + } +} + + +/** + * Return true if the calling thread's thread info is dummy. + * A dummy thread info is shared by all threads and should not be modified. + * Functions like eglBindAPI or eglMakeCurrent should check for dummy-ness + * before updating the thread info. + */ +EGLBoolean +_eglIsCurrentThreadDummy(void) +{ + _EGLThreadInfo *t = _eglCheckedGetTSD(); + return (!t || t == &dummy_thread); +} + + +/** + * 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. + */ +_EGLDisplay * +_eglGetCurrentDisplay(void) +{ + _EGLThreadInfo *t = _eglGetCurrentThread(); + _EGLContext *ctx = t->CurrentContexts[t->CurrentAPIIndex]; + if (ctx) + return ctx->Display; + else + return NULL; +} + + +/** + * Return the read or write surface of the currently bound context, or NULL. + */ +_EGLSurface * +_eglGetCurrentSurface(EGLint readdraw) +{ + _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; +} + + +/** + * Record EGL error code. + */ +EGLBoolean +_eglError(EGLint errCode, const char *msg) +{ + _EGLThreadInfo *t = _eglGetCurrentThread(); + const char *s; + + if (t == &dummy_thread) + return EGL_FALSE; + + if (t->LastError == EGL_SUCCESS) { + t->LastError = errCode; + + switch (errCode) { + case EGL_BAD_ACCESS: + s = "EGL_BAD_ACCESS"; + break; + case EGL_BAD_ALLOC: + s = "EGL_BAD_ALLOC"; + break; + case EGL_BAD_ATTRIBUTE: + s = "EGL_BAD_ATTRIBUTE"; + break; + case EGL_BAD_CONFIG: + s = "EGL_BAD_CONFIG"; + break; + case EGL_BAD_CONTEXT: + s = "EGL_BAD_CONTEXT"; + break; + case EGL_BAD_CURRENT_SURFACE: + s = "EGL_BAD_CURRENT_SURFACE"; + break; + case EGL_BAD_DISPLAY: + s = "EGL_BAD_DISPLAY"; + break; + case EGL_BAD_MATCH: + s = "EGL_BAD_MATCH"; + break; + case EGL_BAD_NATIVE_PIXMAP: + s = "EGL_BAD_NATIVE_PIXMAP"; + break; + case EGL_BAD_NATIVE_WINDOW: + s = "EGL_BAD_NATIVE_WINDOW"; + break; + case EGL_BAD_PARAMETER: + s = "EGL_BAD_PARAMETER"; + break; + case EGL_BAD_SURFACE: + s = "EGL_BAD_SURFACE"; + break; + case EGL_BAD_SCREEN_MESA: + s = "EGL_BAD_SCREEN_MESA"; + break; + case EGL_BAD_MODE_MESA: + s = "EGL_BAD_MODE_MESA"; + break; + default: + s = "other"; + } + _eglLog(_EGL_DEBUG, "EGL user error 0x%x (%s) in %s\n", errCode, s, msg); + } + + return EGL_FALSE; +} diff --git a/src/egl/main/eglcurrent.h b/src/egl/main/eglcurrent.h new file mode 100644 index 0000000000..8eb241029e --- /dev/null +++ b/src/egl/main/eglcurrent.h @@ -0,0 +1,84 @@ +#ifndef EGLCURRENT_INCLUDED +#define EGLCURRENT_INCLUDED + +#include "egltypedefs.h" + + +#define _EGL_API_NUM_INDICES \ + (EGL_OPENGL_API - EGL_OPENGL_ES_API + 2) /* idx 0 is for EGL_NONE */ + + +/** + * Per-thread info + */ +struct _egl_thread_info +{ + EGLint LastError; + _EGLContext *CurrentContexts[_EGL_API_NUM_INDICES]; + /* use index for fast access to current context */ + EGLint CurrentAPIIndex; +}; + + +/** + * Return true if a client API enum can be converted to an index. + */ +static INLINE EGLBoolean +_eglIsApiValid(EGLenum api) +{ + return ((api >= EGL_OPENGL_ES_API && api <= EGL_OPENGL_API) || + api == EGL_NONE); +} + + +/** + * Convert a client API enum to an index, for use by thread info. + * The client API enum is assumed to be valid. + */ +static INLINE EGLint +_eglConvertApiToIndex(EGLenum api) +{ + return (api != EGL_NONE) ? api - EGL_OPENGL_ES_API + 1 : 0; +} + + +/** + * Convert an index, used by thread info, to a client API enum. + * The index is assumed to be valid. + */ +static INLINE EGLenum +_eglConvertApiFromIndex(EGLint idx) +{ + return (idx) ? EGL_OPENGL_ES_API + idx - 1 : EGL_NONE; +} + + +extern _EGLThreadInfo * +_eglGetCurrentThread(void); + + +extern void +_eglDestroyCurrentThread(void); + + +extern EGLBoolean +_eglIsCurrentThreadDummy(void); + + +extern _EGLContext * +_eglGetCurrentContext(void); + + +extern _EGLDisplay * +_eglGetCurrentDisplay(void); + + +extern _EGLSurface * +_eglGetCurrentSurface(EGLint readdraw); + + +extern EGLBoolean +_eglError(EGLint errCode, const char *msg); + + +#endif /* EGLCURRENT_INCLUDED */ diff --git a/src/egl/main/egldefines.h b/src/egl/main/egldefines.h new file mode 100644 index 0000000000..8fc2301b79 --- /dev/null +++ b/src/egl/main/egldefines.h @@ -0,0 +1,45 @@ +/************************************************************************** + * + * Copyright 2008 Tungsten Graphics, Inc., Cedar Park, Texas. + * All Rights Reserved. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the + * "Software"), to deal in the Software without restriction, including + * without limitation the rights to use, copy, modify, merge, publish, + * distribute, sub license, and/or sell copies of the Software, and to + * permit persons to whom the Software is furnished to do so, subject to + * the following conditions: + * + * The above copyright notice and this permission notice (including the + * next paragraph) shall be included in all copies or substantial portions + * of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS + * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. + * IN NO EVENT SHALL TUNGSTEN GRAPHICS AND/OR ITS SUPPLIERS BE LIABLE FOR + * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, + * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE + * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + * + **************************************************************************/ + + + +/** + * Internal EGL defines + */ + + +#ifndef EGLDEFINES_INCLUDED +#define EGLDEFINES_INCLUDED + + +#define _EGL_MAX_EXTENSIONS_LEN 1000 + +#define _EGL_VENDOR_STRING "Mesa Project" + + + +#endif /* EGLDEFINES_INCLUDED */ diff --git a/src/egl/main/egldisplay.c b/src/egl/main/egldisplay.c index 074a85bf26..896d60dbe1 100644 --- a/src/egl/main/egldisplay.c +++ b/src/egl/main/egldisplay.c @@ -1,71 +1,371 @@ +/** + * Functions related to EGLDisplay. + */ + +#include <assert.h> #include <stdlib.h> #include <string.h> #include "eglcontext.h" +#include "eglsurface.h" #include "egldisplay.h" +#include "egldriver.h" #include "eglglobals.h" -#include "eglhash.h" +#include "eglstring.h" +#include "eglmutex.h" +#include "egllog.h" + + +/** + * Finish display management. + */ +void +_eglFiniDisplay(void) +{ + _EGLDisplay *dpyList, *dpy; + + /* atexit function is called with global mutex locked */ + dpyList = _eglGlobal.DisplayList; + while (dpyList) { + /* pop list head */ + dpy = dpyList; + dpyList = dpyList->Next; + + if (dpy->ContextList || dpy->SurfaceList) + _eglLog(_EGL_DEBUG, "Display %p is destroyed with resources", dpy); + + free(dpy); + } + _eglGlobal.DisplayList = NULL; +} -static char * -my_strdup(const char *s) +/** + * 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) { - int l = strlen(s); - char *s2 = malloc(l + 1); - strcpy(s2, s); - return s2; + 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; } /** - * We're assuming that the NativeDisplayType parameter is actually - * a string. - * Return a new _EGLDisplay object for the given displayName + * 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 displayName) +_eglNewDisplay(NativeDisplayType nativeDisplay) { _EGLDisplay *dpy = (_EGLDisplay *) calloc(1, sizeof(_EGLDisplay)); if (dpy) { - dpy->Handle = _eglHashGenKey(_eglGlobal.Displays); - _eglHashInsert(_eglGlobal.Displays, dpy->Handle, dpy); - if (displayName) - dpy->Name = my_strdup(displayName); - else - dpy->Name = NULL; - dpy->Driver = NULL; /* this gets set later */ + dpy->NativeDisplay = nativeDisplay; + + dpy->DriverName = _eglPreloadDriver(dpy); + if (!dpy->DriverName) { + free(dpy); + return NULL; + } } return dpy; } /** - * Return the _EGLDisplay object that corresponds to the given public/ - * opaque display handle. + * Link a display to itself and return the handle of the link. + * The handle can be passed to client directly. */ -_EGLDisplay * -_eglLookupDisplay(EGLDisplay dpy) +EGLDisplay +_eglLinkDisplay(_EGLDisplay *dpy) +{ + _eglLockMutex(_eglGlobal.Mutex); + + dpy->Next = _eglGlobal.DisplayList; + _eglGlobal.DisplayList = dpy; + + _eglUnlockMutex(_eglGlobal.Mutex); + + return (EGLDisplay) dpy; +} + + +/** + * Unlink a linked display from itself. + * Accessing an unlinked display should generate EGL_BAD_DISPLAY error. + */ +void +_eglUnlinkDisplay(_EGLDisplay *dpy) { - _EGLDisplay *d = (_EGLDisplay *) _eglHashLookup(_eglGlobal.Displays, dpy); - return d; + _EGLDisplay *prev; + + _eglLockMutex(_eglGlobal.Mutex); + + prev = _eglGlobal.DisplayList; + if (prev != dpy) { + while (prev) { + if (prev->Next == dpy) + break; + prev = prev->Next; + } + assert(prev); + prev->Next = dpy->Next; + } + else { + _eglGlobal.DisplayList = dpy->Next; + } + + _eglUnlockMutex(_eglGlobal.Mutex); } +/** + * Find the display corresponding to the specified native display id in all + * linked displays. + */ _EGLDisplay * -_eglGetCurrentDisplay(void) +_eglFindDisplay(NativeDisplayType nativeDisplay) { - _EGLContext *ctx = _eglGetCurrentContext(); - if (ctx) - return ctx->Display; - else - return NULL; + _EGLDisplay *dpy; + + _eglLockMutex(_eglGlobal.Mutex); + + dpy = _eglGlobal.DisplayList; + while (dpy) { + if (dpy->NativeDisplay == nativeDisplay) { + _eglUnlockMutex(_eglGlobal.Mutex); + return dpy; + } + dpy = dpy->Next; + } + + _eglUnlockMutex(_eglGlobal.Mutex); + + return NULL; +} + + +/** + * Destroy the contexts and surfaces that are linked to the display. + */ +void +_eglReleaseDisplayResources(_EGLDriver *drv, _EGLDisplay *display) +{ + _EGLContext *contexts; + _EGLSurface *surfaces; + + contexts = display->ContextList; + surfaces = display->SurfaceList; + + while (contexts) { + _EGLContext *ctx = contexts; + contexts = contexts->Next; + + _eglUnlinkContext(ctx); + drv->API.DestroyContext(drv, display, ctx); + } + assert(!display->ContextList); + + while (surfaces) { + _EGLSurface *surf = surfaces; + surfaces = surfaces->Next; + + _eglUnlinkSurface(surf); + drv->API.DestroySurface(drv, display, surf); + } + assert(!display->SurfaceList); } +/** + * Free all the data hanging of an _EGLDisplay object, but not + * the object itself. + */ void _eglCleanupDisplay(_EGLDisplay *disp) { + EGLint i; + + if (disp->Configs) { + for (i = 0; i < disp->NumConfigs; i++) + free(disp->Configs[i]); + free(disp->Configs); + disp->Configs = NULL; + disp->NumConfigs = 0; + } + /* XXX incomplete */ - free(disp->Configs); - free(disp->Name); - /* driver deletes _EGLDisplay */ } + + +/** + * 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 + + +/** + * Return EGL_TRUE if the given handle is a valid handle to a display. + */ +EGLBoolean +_eglCheckDisplayHandle(EGLDisplay dpy) +{ + _EGLDisplay *cur; + + _eglLockMutex(_eglGlobal.Mutex); + cur = _eglGlobal.DisplayList; + while (cur) { + if (cur == (_EGLDisplay *) dpy) + break; + cur = cur->Next; + } + _eglUnlockMutex(_eglGlobal.Mutex); + return (cur != NULL); +} + + +/** + * Return EGL_TRUE if the given handle is a valid handle to a context. + */ +EGLBoolean +_eglCheckContextHandle(EGLContext ctx, _EGLDisplay *dpy) +{ + _EGLContext *cur = NULL; + + if (dpy) + cur = dpy->ContextList; + while (cur) { + if (cur == (_EGLContext *) ctx) { + assert(cur->Display == dpy); + break; + } + cur = cur->Next; + } + return (cur != NULL); +} + + +/** + * Return EGL_TRUE if the given handle is a valid handle to a surface. + */ +EGLBoolean +_eglCheckSurfaceHandle(EGLSurface surf, _EGLDisplay *dpy) +{ + _EGLSurface *cur = NULL; + + if (dpy) + cur = dpy->SurfaceList; + while (cur) { + if (cur == (_EGLSurface *) surf) { + assert(cur->Display == dpy); + break; + } + cur = cur->Next; + } + return (cur != NULL); +} + + +#endif /* !_EGL_SKIP_HANDLE_CHECK */ diff --git a/src/egl/main/egldisplay.h b/src/egl/main/egldisplay.h index 1a03fdd4ad..cf103b35c6 100644 --- a/src/egl/main/egldisplay.h +++ b/src/egl/main/egldisplay.h @@ -1,44 +1,277 @@ #ifndef EGLDISPLAY_INCLUDED #define EGLDISPLAY_INCLUDED - #include "egltypedefs.h" +#include "egldefines.h" +#include "eglcontext.h" +#include "eglsurface.h" + + +/** + * Optional EGL extensions info. + */ +struct _egl_extensions +{ + EGLBoolean MESA_screen_surface; + EGLBoolean MESA_copy_context; + EGLBoolean KHR_image; + EGLBoolean KHR_image_base; + EGLBoolean KHR_image_pixmap; + + char String[_EGL_MAX_EXTENSIONS_LEN]; +}; struct _egl_display { - EGLDisplay Handle; + /* used to link displays */ + _EGLDisplay *Next; - char *Name; + EGLNativeDisplayType NativeDisplay; + + const char *DriverName; _EGLDriver *Driver; + void *DriverData; /* private to driver */ + + int APImajor, APIminor; /**< as returned by eglInitialize() */ + char Version[1000]; /**< initialized from APImajor/minor, DriverName */ + + /** Bitmask of supported APIs (EGL_xx_BIT) set by the driver during init */ + EGLint ClientAPIsMask; + char ClientAPIs[1000]; /**< updated by eglQueryString */ + + _EGLExtensions Extensions; + + int LargestPbuffer; EGLint NumScreens; _EGLScreen **Screens; /* array [NumScreens] */ EGLint NumConfigs; - _EGLConfig *Configs; /* array [NumConfigs] */ + _EGLConfig **Configs; /* array [NumConfigs] of ptr to _EGLConfig */ + + /* lists of linked contexts and surface */ + _EGLContext *ContextList; + _EGLSurface *SurfaceList; + + _EGLImage *ImageList; }; +extern void +_eglFiniDisplay(void); + + +extern char * +_eglSplitDisplayString(const char *dpyString, const char **args); + + extern _EGLDisplay * _eglNewDisplay(NativeDisplayType displayName); -extern _EGLDisplay * -_eglLookupDisplay(EGLDisplay dpy); +extern EGLDisplay +_eglLinkDisplay(_EGLDisplay *dpy); + + +extern void +_eglUnlinkDisplay(_EGLDisplay *dpy); extern _EGLDisplay * -_eglGetCurrentDisplay(void); +_eglFindDisplay(NativeDisplayType nativeDisplay); + + +extern void +_eglReleaseDisplayResources(_EGLDriver *drv, _EGLDisplay *dpy); extern void _eglCleanupDisplay(_EGLDisplay *disp); -extern EGLBoolean -_eglQueryDisplayMESA(_EGLDriver *drv, EGLDisplay dpy, EGLint attrib, EGLint *value); +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 + + +extern EGLBoolean +_eglCheckDisplayHandle(EGLDisplay dpy); + + +extern EGLBoolean +_eglCheckContextHandle(EGLContext ctx, _EGLDisplay *dpy); + + +extern EGLBoolean +_eglCheckSurfaceHandle(EGLSurface surf, _EGLDisplay *dpy); + + +#else /* !_EGL_SKIP_HANDLE_CHECK */ +/* Only do a quick check. This is NOT standard compliant. */ + +static INLINE EGLBoolean +_eglCheckDisplayHandle(EGLDisplay dpy) +{ + return ((_EGLDisplay *) dpy != NULL); +} + + +static INLINE EGLBoolean +_eglCheckContextHandle(EGLContext ctx, _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); +} + + +#endif /* _EGL_SKIP_HANDLE_CHECK */ + + +/** + * Lookup a handle to find the linked display. + * Return NULL if the handle has no corresponding linked display. + */ +static INLINE _EGLDisplay * +_eglLookupDisplay(EGLDisplay display) +{ + _EGLDisplay *dpy = (_EGLDisplay *) display; + if (!_eglCheckDisplayHandle(display)) + dpy = NULL; + return dpy; +} + + +/** + * Return the handle of a linked display, or EGL_NO_DISPLAY. + */ +static INLINE EGLDisplay +_eglGetDisplayHandle(_EGLDisplay *dpy) +{ + return (EGLDisplay) ((dpy) ? dpy : EGL_NO_DISPLAY); +} + + +/** + * Return true if the display is linked. + */ +static INLINE EGLBoolean +_eglIsDisplayLinked(_EGLDisplay *dpy) +{ + return (EGLBoolean) (_eglGetDisplayHandle(dpy) != EGL_NO_DISPLAY); +} + + +/** + * 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; +} + + +/** + * 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); +} + + +/** + * Return true if the surface is linked to a display. + */ +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) +{ + return (unsigned int) ((uintptr_t) p); +} #endif /* EGLDISPLAY_INCLUDED */ diff --git a/src/egl/main/egldriver.c b/src/egl/main/egldriver.c index bda06dd827..89e04a7130 100644 --- a/src/egl/main/egldriver.c +++ b/src/egl/main/egldriver.c @@ -1,131 +1,338 @@ +/** + * Functions for choosing and opening/loading device drivers. + */ + + #include <assert.h> -#include <dlfcn.h> -#include <stdio.h> #include <string.h> +#include <stdio.h> +#include <stdlib.h> #include "eglconfig.h" #include "eglcontext.h" +#include "egldefines.h" #include "egldisplay.h" #include "egldriver.h" #include "eglglobals.h" #include "egllog.h" +#include "eglmisc.h" #include "eglmode.h" #include "eglscreen.h" +#include "eglstring.h" #include "eglsurface.h" +#include "eglimage.h" - -const char *DefaultDriverName = "demodriver"; - +#if defined(_EGL_PLATFORM_X) +#include <dlfcn.h> +#elif defined(_EGL_PLATFORM_WINDOWS) +/* Use static linking on Windows for now */ +#define WINDOWS_STATIC_LINK +#endif /** - * Choose and open/init the hardware driver for the given EGLDisplay. - * Previously, the EGLDisplay was created with _eglNewDisplay() where - * we recorded the user's NativeDisplayType parameter. - * - * Now we'll use the NativeDisplayType value. - * - * Currently, the native display value is treated as a string. - * If the first character is ':' we interpret it as a screen or card index - * number (i.e. ":0" or ":1", etc) - * Else if the first character is '!' we interpret it as specific driver name - * (i.e. "!r200" or "!i830". + * Wrappers for dlopen/dlclose() */ -_EGLDriver * -_eglChooseDriver(EGLDisplay display) -{ - _EGLDisplay *dpy = _eglLookupDisplay(display); - _EGLDriver *drv; - const char *driverName = DefaultDriverName; - const char *name; +#if defined(_EGL_PLATFORM_WINDOWS) +#ifdef WINDOWS_STATIC_LINK + static const char *DefaultDriverName = "Windows EGL Static Library"; +#else + /* XXX Need to decide how to do dynamic name lookup on Windows */ + static const char *DefaultDriverName = "TBD"; +#endif + typedef HMODULE lib_handle; + + static HMODULE + open_library(const char *filename) + { +#ifdef WINDOWS_STATIC_LINK + return 0; +#else + return LoadLibrary(filename); +#endif + } + + static void + close_library(HMODULE lib) + { +#ifdef WINDOWS_STATIC_LINK +#else + FreeLibrary(lib); +#endif + } - assert(dpy); +#elif defined(_EGL_PLATFORM_X) + static const char *DefaultDriverName = "egl_softpipe"; - name = dpy->Name; - if (!name) { - /* use default */ + typedef void * lib_handle; + + static void * + open_library(const char *filename) + { + return dlopen(filename, RTLD_LAZY); } - else if (name[0] == ':' && (name[1] >= '0' && name[1] <= '9') && !name[2]) { - /* XXX probe hardware here to determine which driver to open */ - driverName = "libEGLdri"; + + static void + close_library(void *lib) + { + dlclose(lib); } - else if (name[0] == '!') { - /* use specified driver name */ - driverName = name + 1; + +#endif + + +/** + * 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->NativeDisplay) { + /* assume (wrongly!) that the native display is a display string */ + path = _eglSplitDisplayString((const char *) dpy->NativeDisplay, &args); } - else { - /* Maybe display was returned by XOpenDisplay? */ - _eglLog(_EGL_FATAL, "eglChooseDriver() bad name"); + suffix = "so"; +#elif defined(_EGL_PLATFORM_WINDOWS) + suffix = "dll"; +#endif /* _EGL_PLATFORM_X */ + + 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; + } } - _eglLog(_EGL_INFO, "eglChooseDriver() choosing %s", driverName); - - drv = _eglOpenDriver(dpy, driverName); - dpy->Driver = drv; + if (argsRet) + *argsRet = (args) ? _eglstrdup(args) : NULL; - return drv; + return path; } /** - * Open/load the named driver and call its bootstrap function: _eglMain(). - * \return new _EGLDriver object. + * Open the named driver and find its bootstrap function: _eglMain(). */ -_EGLDriver * -_eglOpenDriver(_EGLDisplay *dpy, const char *driverName) +static _EGLMain_t +_eglOpenLibrary(const char *driverPath, lib_handle *handle) { - _EGLDriver *drv; _EGLMain_t mainFunc; - void *lib; - char driverFilename[1000]; - - /* XXX also prepend a directory path??? */ - sprintf(driverFilename, "%s.so", driverName); - - _eglLog(_EGL_DEBUG, "dlopen(%s)", driverFilename); - lib = dlopen(driverFilename, RTLD_NOW); + lib_handle lib; + + assert(driverPath); + +#if defined(_EGL_PLATFORM_WINDOWS) +/* Use static linking on Windows for now */ +#ifdef WINDOWS_STATIC_LINK + lib = 0; + mainFunc = (_EGLMain_t)_eglMain; +#else + /* XXX untested */ + _eglLog(_EGL_DEBUG, "dlopen(%s)", driverPath); + lib = open_library(driverPath); + if (!lib) { + _eglLog(_EGL_WARNING, "Could not open %s", + driverPath); + return NULL; + } + mainFunc = (_EGLMain_t) GetProcAddress(lib, "_eglMain"); +#endif +#elif defined(_EGL_PLATFORM_X) + _eglLog(_EGL_DEBUG, "dlopen(%s)", driverPath); + lib = open_library(driverPath); if (!lib) { _eglLog(_EGL_WARNING, "Could not open %s (%s)", - driverFilename, dlerror()); + driverPath, dlerror()); + if (!getenv("EGL_DRIVER")) + _eglLog(_EGL_WARNING, + "The driver can be overridden by setting EGL_DRIVER"); return NULL; } - mainFunc = (_EGLMain_t) dlsym(lib, "_eglMain"); +#endif + if (!mainFunc) { - _eglLog(_EGL_WARNING, "_eglMain not found in %s", driverFilename); - dlclose(lib); + _eglLog(_EGL_WARNING, "_eglMain not found in %s", driverPath); + if (lib) + close_library(lib); return NULL; } - drv = mainFunc(dpy); + *handle = lib; + return mainFunc; +} + + +/** + * Load the named driver. The path and args passed will be + * owned by the driver and freed. + */ +static _EGLDriver * +_eglLoadDriver(char *path, char *args) +{ + _EGLMain_t mainFunc; + lib_handle lib; + _EGLDriver *drv = NULL; + + mainFunc = _eglOpenLibrary(path, &lib); + if (!mainFunc) + return NULL; + + drv = mainFunc(args); if (!drv) { - dlclose(lib); + if (lib) + close_library(lib); return NULL; } - /* with a recurvise open you want the inner most handle */ - if (!drv->LibHandle) - drv->LibHandle = lib; - else - dlclose(lib); - drv->Display = dpy; + if (!drv->Name) { + _eglLog(_EGL_WARNING, "Driver loaded from %s has no name", path); + drv->Name = "UNNAMED"; + } + + drv->Path = path; + drv->Args = args; + drv->LibHandle = lib; + + return drv; +} + + +/** + * Match a display to a preloaded driver. + */ +static _EGLDriver * +_eglMatchDriver(_EGLDisplay *dpy) +{ + _EGLDriver *defaultDriver = NULL; + EGLint i; + + for (i = 0; i < _eglGlobal.NumDrivers; i++) { + _EGLDriver *drv = _eglGlobal.Drivers[i]; + + /* display specifies a driver */ + if (dpy->DriverName) { + if (strcmp(dpy->DriverName, drv->Name) == 0) + return drv; + } + else if (drv->Probe) { + if (drv->Probe(drv, dpy)) + return drv; + } + else { + if (!defaultDriver) + defaultDriver = drv; + } + } + + return defaultDriver; +} + + +/** + * Load a driver and save it. + */ +const char * +_eglPreloadDriver(_EGLDisplay *dpy) +{ + char *path, *args; + _EGLDriver *drv; + EGLint i; + + path = _eglChooseDriver(dpy, &args); + if (!path) + return NULL; + + 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; + } + } + + drv = _eglLoadDriver(path, args); + if (!drv) + return NULL; + + _eglGlobal.Drivers[_eglGlobal.NumDrivers++] = drv; + + return drv->Name; +} + + +/** + * Open a preloaded driver. + */ +_EGLDriver * +_eglOpenDriver(_EGLDisplay *dpy) +{ + _EGLDriver *drv = _eglMatchDriver(dpy); return drv; } +/** + * Close a preloaded driver. + */ EGLBoolean -_eglCloseDriver(_EGLDriver *drv, EGLDisplay dpy) +_eglCloseDriver(_EGLDriver *drv, _EGLDisplay *dpy) { - void *handle = drv->LibHandle; - EGLBoolean b; + return EGL_TRUE; +} - _eglLog(_EGL_INFO, "Closing driver"); - /* - * XXX check for currently bound context/surfaces and delete them? - */ +/** + * Unload preloaded drivers. + */ +void +_eglUnloadDrivers(void) +{ + EGLint i; + for (i = 0; i < _eglGlobal.NumDrivers; i++) { + _EGLDriver *drv = _eglGlobal.Drivers[i]; + lib_handle handle = drv->LibHandle; + + if (drv->Path) + free((char *) drv->Path); + if (drv->Args) + free((char *) drv->Args); + + /* destroy driver */ + if (drv->Unload) + drv->Unload(drv); + + if (handle) + close_library(handle); + _eglGlobal.Drivers[i] = NULL; + } - b = drv->API.Terminate(drv, dpy); - dlclose(handle); - return b; + _eglGlobal.NumDrivers = 0; } @@ -198,75 +405,56 @@ _eglInitDriverFallbacks(_EGLDriver *drv) #ifdef EGL_VERSION_1_2 drv->API.CreatePbufferFromClientBuffer = _eglCreatePbufferFromClientBuffer; #endif /* EGL_VERSION_1_2 */ -} - - -/** - * Examine the individual extension enable/disable flags and recompute - * the driver's Extensions string. - */ -static void -_eglUpdateExtensionsString(_EGLDriver *drv) -{ - drv->Extensions.String[0] = 0; - if (drv->Extensions.MESA_screen_surface) - strcat(drv->Extensions.String, "EGL_MESA_screen_surface "); - if (drv->Extensions.MESA_copy_context) - strcat(drv->Extensions.String, "EGL_MESA_copy_context "); - assert(strlen(drv->Extensions.String) < MAX_EXTENSIONS_LEN); +#ifdef EGL_KHR_image_base + drv->API.CreateImageKHR = _eglCreateImageKHR; + drv->API.DestroyImageKHR = _eglDestroyImageKHR; +#endif /* EGL_KHR_image_base */ } -const char * -_eglQueryString(_EGLDriver *drv, EGLDisplay dpy, EGLint name) +/** + * Try to determine which EGL APIs (OpenGL, OpenGL ES, OpenVG, etc) + * are supported on the system by looking for standard library names. + */ +EGLint +_eglFindAPIs(void) { - (void) drv; - (void) dpy; - switch (name) { - case EGL_VENDOR: - return "Mesa Project"; - case EGL_VERSION: - return "1.0"; - case EGL_EXTENSIONS: - _eglUpdateExtensionsString(drv); - return drv->Extensions.String; -#ifdef EGL_VERSION_1_2 - case EGL_CLIENT_APIS: - /* XXX need to initialize somewhere */ - return drv->ClientAPIs; + 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"; #endif - default: - _eglError(EGL_BAD_PARAMETER, "eglQueryString"); - return NULL; - } -} + if ((lib = open_library(es1_libname))) { + close_library(lib); + mask |= EGL_OPENGL_ES_BIT; + } -EGLBoolean -_eglWaitGL(_EGLDriver *drv, EGLDisplay dpy) -{ - /* just a placeholder */ - (void) drv; - (void) dpy; - return EGL_TRUE; -} + if ((lib = open_library(es2_libname))) { + close_library(lib); + mask |= EGL_OPENGL_ES2_BIT; + } + if ((lib = open_library(gl_libname))) { + close_library(lib); + mask |= EGL_OPENGL_BIT; + } -EGLBoolean -_eglWaitNative(_EGLDriver *drv, EGLDisplay dpy, EGLint engine) -{ - /* just a placeholder */ - (void) drv; - (void) dpy; - switch (engine) { - case EGL_CORE_NATIVE_ENGINE: - break; - default: - _eglError(EGL_BAD_PARAMETER, "eglWaitNative(engine)"); - return EGL_FALSE; + if ((lib = open_library(vg_libname))) { + close_library(lib); + mask |= EGL_OPENVG_BIT; } - return EGL_TRUE; + return mask; } diff --git a/src/egl/main/egldriver.h b/src/egl/main/egldriver.h index 88526e973d..6c848eb35e 100644 --- a/src/egl/main/egldriver.h +++ b/src/egl/main/egldriver.h @@ -5,56 +5,43 @@ #include "egltypedefs.h" #include "eglapi.h" -/* should probably use a dynamic-length string, but this will do */ -#define MAX_EXTENSIONS_LEN 1000 - - -/** - * Optional EGL extensions info. - */ -struct _egl_extensions -{ - EGLBoolean MESA_screen_surface; - EGLBoolean MESA_copy_context; - - char String[MAX_EXTENSIONS_LEN]; -}; - /** * Base class for device drivers. */ struct _egl_driver { - EGLBoolean Initialized; /* set by driver after initialized */ - - void *LibHandle; /* dlopen handle */ + void *LibHandle; /**< dlopen handle */ + const char *Path; /**< path to this driver */ + const char *Args; /**< args to load this driver */ - _EGLDisplay *Display; + 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 */ + void (*Unload)(_EGLDriver *drv); - int ABIversion; - int APImajor, APIminor; /* returned through eglInitialize */ - const char *ClientAPIs; - - _EGLAPI API; - - _EGLExtensions Extensions; + _EGLAPI API; /**< EGL API dispatch table */ }; -extern _EGLDriver *_eglMain(_EGLDisplay *dpy); +extern _EGLDriver *_eglMain(const char *args); -extern _EGLDriver * -_eglChooseDriver(EGLDisplay dpy); +extern const char * +_eglPreloadDriver(_EGLDisplay *dpy); extern _EGLDriver * -_eglOpenDriver(_EGLDisplay *dpy, const char *driverName); +_eglOpenDriver(_EGLDisplay *dpy); extern EGLBoolean -_eglCloseDriver(_EGLDriver *drv, EGLDisplay dpy); +_eglCloseDriver(_EGLDriver *drv, _EGLDisplay *dpy); + + +void +_eglUnloadDrivers(void); extern _EGLDriver * @@ -65,17 +52,8 @@ extern void _eglInitDriverFallbacks(_EGLDriver *drv); -extern const char * -_eglQueryString(_EGLDriver *drv, EGLDisplay dpy, EGLint name); - - -extern EGLBoolean -_eglWaitGL(_EGLDriver *drv, EGLDisplay dpy); - - -extern EGLBoolean -_eglWaitNative(_EGLDriver *drv, EGLDisplay dpy, EGLint engine); - +extern EGLint +_eglFindAPIs(void); #endif /* EGLDRIVER_INCLUDED */ diff --git a/src/egl/main/eglglobals.c b/src/egl/main/eglglobals.c index 608311d749..3ae4c1ad3a 100644 --- a/src/egl/main/eglglobals.c +++ b/src/egl/main/eglglobals.c @@ -1,148 +1,56 @@ -#include <stdio.h> #include <stdlib.h> +#include <assert.h> #include "eglglobals.h" +#include "egldriver.h" +#include "egllog.h" +#include "eglmutex.h" -struct _egl_global _eglGlobal = { .Initialized = EGL_FALSE }; +#define ARRAY_SIZE(a) (sizeof(a) / sizeof((a)[0])) -/** - * Init the fields in the _eglGlobal struct - * May be safely called more than once. - */ -void -_eglInitGlobals(void) -{ - if (!_eglGlobal.Initialized) { - _eglGlobal.Displays = _eglNewHashTable(); - _eglGlobal.Contexts = _eglNewHashTable(); - _eglGlobal.Surfaces = _eglNewHashTable(); - _eglGlobal.FreeScreenHandle = 1; - _eglGlobal.Initialized = EGL_TRUE; - - _eglGlobal.OpenGLESAPISupported = EGL_TRUE; - _eglGlobal.OpenVGAPISupported = EGL_FALSE; - - /* XXX temporary */ - _eglGlobal.ThreadInfo = _eglNewThreadInfo(); - } -} - - -/** - * Should call this via an atexit handler. - */ -void -_eglDestroyGlobals(void) +static _EGL_DECLARE_MUTEX(_eglGlobalMutex); +struct _egl_global _eglGlobal = { - /* XXX TODO walk over table entries, deleting each */ - _eglDeleteHashTable(_eglGlobal.Displays); - _eglDeleteHashTable(_eglGlobal.Contexts); - _eglDeleteHashTable(_eglGlobal.Surfaces); -} - - -/** - * Allocate and init a new _EGLThreadInfo object. - */ -_EGLThreadInfo * -_eglNewThreadInfo(void) + &_eglGlobalMutex, /* Mutex */ + NULL, /* DisplayList */ + 1, /* FreeScreenHandle */ + 0x0, /* ClientAPIsMask */ + 0, /* NumDrivers */ + { NULL }, /* Drivers */ + 2, /* NumAtExitCalls */ + { /* AtExitCalls */ + _eglFiniDisplay, + _eglUnloadDrivers + }, +}; + + +static void +_eglAtExit(void) { - _EGLThreadInfo *t = (_EGLThreadInfo *) calloc(1, sizeof(_EGLThreadInfo)); - if (t) { - t->CurrentContext = EGL_NO_CONTEXT; - t->LastError = EGL_SUCCESS; - t->CurrentAPI = EGL_NONE; - } - return t; + EGLint i; + for (i = _eglGlobal.NumAtExitCalls - 1; i >= 0; i--) + _eglGlobal.AtExitCalls[i](); } -/** - * Delete/free a _EGLThreadInfo object. - */ void -_eglDeleteThreadData(_EGLThreadInfo *t) -{ - free(t); -} - - - -/** - * Return pointer to calling thread's _EGLThreadInfo object. - * Create a new one if needed. - * Should never return NULL. - */ -_EGLThreadInfo * -_eglGetCurrentThread(void) +_eglAddAtExitCall(void (*func)(void)) { - _eglInitGlobals(); - - /* XXX temporary */ - return _eglGlobal.ThreadInfo; -} + if (func) { + static EGLBoolean registered = EGL_FALSE; + _eglLockMutex(_eglGlobal.Mutex); -/** - * Record EGL error code. - */ -void -_eglError(EGLint errCode, const char *msg) -{ - _EGLThreadInfo *t = _eglGetCurrentThread(); - const char *s; + if (!registered) { + atexit(_eglAtExit); + registered = EGL_TRUE; + } - if (t->LastError == EGL_SUCCESS) { - t->LastError = errCode; + assert(_eglGlobal.NumAtExitCalls < ARRAY_SIZE(_eglGlobal.AtExitCalls)); + _eglGlobal.AtExitCalls[_eglGlobal.NumAtExitCalls++] = func; - switch (errCode) { - case EGL_BAD_ACCESS: - s = "EGL_BAD_ACCESS"; - break; - case EGL_BAD_ALLOC: - s = "EGL_BAD_ALLOC"; - break; - case EGL_BAD_ATTRIBUTE: - s = "EGL_BAD_ATTRIBUTE"; - break; - case EGL_BAD_CONFIG: - s = "EGL_BAD_CONFIG"; - break; - case EGL_BAD_CONTEXT: - s = "EGL_BAD_CONTEXT"; - break; - case EGL_BAD_CURRENT_SURFACE: - s = "EGL_BAD_CURRENT_SURFACE"; - break; - case EGL_BAD_DISPLAY: - s = "EGL_BAD_DISPLAY"; - break; - case EGL_BAD_MATCH: - s = "EGL_BAD_MATCH"; - break; - case EGL_BAD_NATIVE_PIXMAP: - s = "EGL_BAD_NATIVE_PIXMAP"; - break; - case EGL_BAD_NATIVE_WINDOW: - s = "EGL_BAD_NATIVE_WINDOW"; - break; - case EGL_BAD_PARAMETER: - s = "EGL_BAD_PARAMETER"; - break; - case EGL_BAD_SURFACE: - s = "EGL_BAD_SURFACE"; - break; - case EGL_BAD_SCREEN_MESA: - s = "EGL_BAD_SCREEN_MESA"; - break; - case EGL_BAD_MODE_MESA: - s = "EGL_BAD_MODE_MESA"; - break; - default: - s = "other"; - } - /* XXX temporary */ - fprintf(stderr, "EGL user error 0x%x (%s) in %s\n", errCode, s, msg); + _eglUnlockMutex(_eglGlobal.Mutex); } } diff --git a/src/egl/main/eglglobals.h b/src/egl/main/eglglobals.h index c16baa2d6b..58511076d4 100644 --- a/src/egl/main/eglglobals.h +++ b/src/egl/main/eglglobals.h @@ -2,18 +2,9 @@ #define EGLGLOBALS_INCLUDED #include "egltypedefs.h" -#include "eglhash.h" - - -/** - * Per-thread info - */ -struct _egl_thread_info -{ - EGLint LastError; - _EGLContext *CurrentContext; - EGLenum CurrentAPI; -}; +#include "egldisplay.h" +#include "eglcurrent.h" +#include "eglmutex.h" /** @@ -21,20 +12,21 @@ struct _egl_thread_info */ struct _egl_global { - EGLBoolean Initialized; + _EGLMutex *Mutex; - _EGLHashtable *Displays; - _EGLHashtable *Contexts; - _EGLHashtable *Surfaces; + /* the list of all displays */ + _EGLDisplay *DisplayList; EGLScreenMESA FreeScreenHandle; - /* XXX these may be temporary */ - EGLBoolean OpenGLESAPISupported; - EGLBoolean OpenVGAPISupported; + /* bitmaks of supported APIs (supported by _some_ driver) */ + EGLint ClientAPIsMask; + + EGLint NumDrivers; + _EGLDriver *Drivers[10]; - /* XXX temporary - should be thread-specific data (TSD) */ - _EGLThreadInfo *ThreadInfo; + EGLint NumAtExitCalls; + void (*AtExitCalls[10])(void); }; @@ -42,27 +34,7 @@ extern struct _egl_global _eglGlobal; extern void -_eglInitGlobals(void); - - -extern void -_eglDestroyGlobals(void); - - -extern _EGLThreadInfo * -_eglNewThreadInfo(void); - - -extern void -_eglDeleteThreadData(_EGLThreadInfo *t); - - -extern _EGLThreadInfo * -_eglGetCurrentThread(void); - - -extern void -_eglError(EGLint errCode, const char *msg); +_eglAddAtExitCall(void (*func)(void)); #endif /* EGLGLOBALS_INCLUDED */ diff --git a/src/egl/main/eglhash.c b/src/egl/main/eglhash.c deleted file mode 100644 index 8e3da2e906..0000000000 --- a/src/egl/main/eglhash.c +++ /dev/null @@ -1,347 +0,0 @@ -/** - * \file hash.c - * Generic hash table. - * - * This code taken from Mesa and adapted. - */ - -#include <assert.h> -#include <stdlib.h> -#include <stdio.h> -#include "eglhash.h" - - -#define TABLE_SIZE 1023 /**< Size of lookup table/array */ - -#define HASH_FUNC(K) ((K) % TABLE_SIZE) - - -/* - * Unfinished mutex stuff - */ - -typedef int _EGLMutex; - -static void -_eglInitMutex(_EGLMutex m) -{ -} - -static void -_eglDestroyMutex(_EGLMutex m) -{ -} - -static void -_eglLockMutex(_EGLMutex m) -{ -} - -static void -_eglUnlockMutex(_EGLMutex m) -{ -} - - - -typedef struct _egl_hashentry _EGLHashentry; - -struct _egl_hashentry -{ - EGLuint Key; /**< the entry's key */ - void *Data; /**< the entry's data */ - _EGLHashentry *Next; /**< pointer to next entry */ -}; - - -struct _egl_hashtable -{ - _EGLHashentry *Table[TABLE_SIZE]; /**< the lookup table */ - EGLuint MaxKey; /**< highest key inserted so far */ - _EGLMutex Mutex; /**< mutual exclusion lock */ -}; - - -/** - * Create a new hash table. - * - * \return pointer to a new, empty hash table. - */ -_EGLHashtable * -_eglNewHashTable(void) -{ - _EGLHashtable *table = (_EGLHashtable *) calloc(1, sizeof(_EGLHashtable)); - if (table) { - _eglInitMutex(table->Mutex); - table->MaxKey = 1; - } - return table; -} - - - -/** - * Delete a hash table. - * Frees each entry on the hash table and then the hash table structure itself. - * Note that the caller should have already traversed the table and deleted - * the objects in the table (i.e. We don't free the entries' data pointer). - * - * \param table the hash table to delete. - */ -void -_eglDeleteHashTable(_EGLHashtable *table) -{ - EGLuint i; - assert(table); - for (i = 0; i < TABLE_SIZE; i++) { - _EGLHashentry *entry = table->Table[i]; - while (entry) { - _EGLHashentry *next = entry->Next; - free(entry); - entry = next; - } - } - _eglDestroyMutex(table->Mutex); - free(table); -} - - - -/** - * Lookup an entry in the hash table. - * - * \param table the hash table. - * \param key the key. - * - * \return pointer to user's data or NULL if key not in table - */ -void * -_eglHashLookup(const _EGLHashtable *table, EGLuint key) -{ - EGLuint pos; - const _EGLHashentry *entry; - - assert(table); - - if (!key) - return NULL; - - pos = HASH_FUNC(key); - entry = table->Table[pos]; - while (entry) { - if (entry->Key == key) { - return entry->Data; - } - entry = entry->Next; - } - return NULL; -} - - - -/** - * Insert a key/pointer pair into the hash table. - * If an entry with this key already exists we'll replace the existing entry. - * - * \param table the hash table. - * \param key the key (not zero). - * \param data pointer to user data. - */ -void -_eglHashInsert(_EGLHashtable *table, EGLuint key, void *data) -{ - /* search for existing entry with this key */ - EGLuint pos; - _EGLHashentry *entry; - - assert(table); - assert(key); - - _eglLockMutex(table->Mutex); - - if (key > table->MaxKey) - table->MaxKey = key; - - pos = HASH_FUNC(key); - entry = table->Table[pos]; - while (entry) { - if (entry->Key == key) { - /* replace entry's data */ - entry->Data = data; - _eglUnlockMutex(table->Mutex); - return; - } - entry = entry->Next; - } - - /* alloc and insert new table entry */ - entry = (_EGLHashentry *) malloc(sizeof(_EGLHashentry)); - entry->Key = key; - entry->Data = data; - entry->Next = table->Table[pos]; - table->Table[pos] = entry; - - _eglUnlockMutex(table->Mutex); -} - - - -/** - * Remove an entry from the hash table. - * - * \param table the hash table. - * \param key key of entry to remove. - * - * While holding the hash table's lock, searches the entry with the matching - * key and unlinks it. - */ -void -_eglHashRemove(_EGLHashtable *table, EGLuint key) -{ - EGLuint pos; - _EGLHashentry *entry, *prev; - - assert(table); - assert(key); - - _eglLockMutex(table->Mutex); - - pos = HASH_FUNC(key); - prev = NULL; - entry = table->Table[pos]; - while (entry) { - if (entry->Key == key) { - /* found it! */ - if (prev) { - prev->Next = entry->Next; - } - else { - table->Table[pos] = entry->Next; - } - free(entry); - _eglUnlockMutex(table->Mutex); - return; - } - prev = entry; - entry = entry->Next; - } - - _eglUnlockMutex(table->Mutex); -} - - - -/** - * Get the key of the "first" entry in the hash table. - * - * This is used in the course of deleting all display lists when - * a context is destroyed. - * - * \param table the hash table - * - * \return key for the "first" entry in the hash table. - * - * While holding the lock, walks through all table positions until finding - * the first entry of the first non-empty one. - */ -EGLuint -_eglHashFirstEntry(_EGLHashtable *table) -{ - EGLuint pos; - assert(table); - _eglLockMutex(table->Mutex); - for (pos = 0; pos < TABLE_SIZE; pos++) { - if (table->Table[pos]) { - _eglUnlockMutex(table->Mutex); - return table->Table[pos]->Key; - } - } - _eglUnlockMutex(table->Mutex); - return 0; -} - - -/** - * Given a hash table key, return the next key. This is used to walk - * over all entries in the table. Note that the keys returned during - * walking won't be in any particular order. - * \return next hash key or 0 if end of table. - */ -EGLuint -_eglHashNextEntry(const _EGLHashtable *table, EGLuint key) -{ - const _EGLHashentry *entry; - EGLuint pos; - - assert(table); - assert(key); - - /* Find the entry with given key */ - pos = HASH_FUNC(key); - entry = table->Table[pos]; - while (entry) { - if (entry->Key == key) { - break; - } - entry = entry->Next; - } - - if (!entry) { - /* the key was not found, we can't find next entry */ - return 0; - } - - if (entry->Next) { - /* return next in linked list */ - return entry->Next->Key; - } - else { - /* look for next non-empty table slot */ - pos++; - while (pos < TABLE_SIZE) { - if (table->Table[pos]) { - return table->Table[pos]->Key; - } - pos++; - } - return 0; - } -} - - -/** - * Dump contents of hash table for debugging. - * - * \param table the hash table. - */ -void -_eglHashPrint(const _EGLHashtable *table) -{ - EGLuint i; - assert(table); - for (i = 0; i < TABLE_SIZE; i++) { - const _EGLHashentry *entry = table->Table[i]; - while (entry) { - printf("%u %p\n", entry->Key, entry->Data); - entry = entry->Next; - } - } -} - - - -/** - * Return a new, unused hash key. - */ -EGLuint -_eglHashGenKey(_EGLHashtable *table) -{ - EGLuint k; - - _eglLockMutex(table->Mutex); - k = table->MaxKey; - table->MaxKey++; - _eglUnlockMutex(table->Mutex); - return k; -} - diff --git a/src/egl/main/eglhash.h b/src/egl/main/eglhash.h deleted file mode 100644 index 1d6db9598c..0000000000 --- a/src/egl/main/eglhash.h +++ /dev/null @@ -1,39 +0,0 @@ -/** - * \file eglhash.h - * Generic hash table. - */ - - -#ifndef EGLHASH_INCLUDED -#define EGLHASH_INCLUDED - - -/* XXX move this? */ -typedef unsigned int EGLuint; - - -typedef struct _egl_hashtable _EGLHashtable; - - -extern _EGLHashtable *_eglNewHashTable(void); - -extern void _eglDeleteHashTable(_EGLHashtable *table); - -extern void *_eglHashLookup(const _EGLHashtable *table, EGLuint key); - -extern void _eglHashInsert(_EGLHashtable *table, EGLuint key, void *data); - -extern void _eglHashRemove(_EGLHashtable *table, EGLuint key); - -extern EGLuint _eglHashFirstEntry(_EGLHashtable *table); - -extern EGLuint _eglHashNextEntry(const _EGLHashtable *table, EGLuint key); - -extern void _eglHashPrint(const _EGLHashtable *table); - -extern EGLuint _eglHashGenKey(_EGLHashtable *table); - -extern void _egltest_hash_functions(void); - - -#endif /* EGLHASH_INCLUDED */ diff --git a/src/egl/main/eglimage.c b/src/egl/main/eglimage.c new file mode 100644 index 0000000000..dc1c728320 --- /dev/null +++ b/src/egl/main/eglimage.c @@ -0,0 +1,104 @@ +#include <assert.h> + +#include "eglimage.h" +#include "egldisplay.h" + +EGLBoolean +_eglInitImage(_EGLDriver *drv, _EGLImage *img, const EGLint *attrib_list) +{ + EGLint i; + + img->Preserved = EGL_FALSE; + + for (i = 0; attrib_list && attrib_list[i] != EGL_NONE; i++) { + switch (attrib_list[i]) { + case EGL_IMAGE_PRESERVED_KHR: + i++; + img->Preserved = attrib_list[i]; + break; + default: + /* not an error */ + break; + } + } + + 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; +} + + +EGLImageKHR +_eglLinkImage(_EGLImage *img, _EGLDisplay *dpy) +{ + img->Display = dpy; + img->Next = dpy->ImageList; + dpy->ImageList = img; + return (EGLImageKHR) img; +} + + +void +_eglUnlinkImage(_EGLImage *img) +{ + _EGLImage *prev; + + prev = img->Display->ImageList; + if (prev != img) { + while (prev) { + if (prev->Next == img) + break; + prev = prev->Next; + } + assert(prev); + prev->Next = img->Next; + } + else { + img->Display->ImageList = img->Next; + } + + img->Next = NULL; + img->Display = NULL; +} + + +#ifndef _EGL_SKIP_HANDLE_CHECK + + +/** + * Return EGL_TRUE if the given handle is a valid handle to an image. + */ +EGLBoolean +_eglCheckImageHandle(EGLImageKHR img, _EGLDisplay *dpy) +{ + _EGLImage *cur = NULL; + + if (dpy) + cur = dpy->ImageList; + while (cur) { + if (cur == (_EGLImage *) img) { + assert(cur->Display == dpy); + break; + } + cur = cur->Next; + } + return (cur != NULL); +} + + +#endif /* _EGL_SKIP_HANDLE_CHECK */ diff --git a/src/egl/main/eglimage.h b/src/egl/main/eglimage.h new file mode 100644 index 0000000000..3a96028e3d --- /dev/null +++ b/src/egl/main/eglimage.h @@ -0,0 +1,93 @@ +#ifndef EGLIMAGE_INCLUDED +#define EGLIMAGE_INCLUDED + + +#include "egltypedefs.h" + + +/** + * "Base" class for device driver images. + */ +struct _egl_image +{ + /* Client data that client APIs and the driver agree on */ + void *ClientData; + + /* Managed by EGLDisplay for linking */ + _EGLDisplay *Display; + _EGLImage *Next; + + EGLBoolean Preserved; +}; + + +extern EGLBoolean +_eglInitImage(_EGLDriver *drv, _EGLImage *img, 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); + + +extern EGLImageKHR +_eglLinkImage(_EGLImage *img, _EGLDisplay *dpy); + + +extern void +_eglUnlinkImage(_EGLImage *img); + + +#ifndef _EGL_SKIP_HANDLE_CHECK + + +extern EGLBoolean +_eglCheckImageHandle(EGLImageKHR img, _EGLDisplay *dpy); + + +#else + + +/** + * Perform a quick check on the handle. + */ +static INLINE EGLBoolean +_eglCheckImageHandle(EGLImageKHR img, _EGLDisplay *dpy) +{ + _EGLImage *i = (_EGLImage *) img; + return (dpy && i && i->Display == dpy); +} + + +#endif + + +/** + * 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 (!_eglCheckImageHandle(img, dpy)) + img = NULL; + return img; +} + + +/** + * Return the handle of a linked image. + */ +static INLINE EGLImageKHR +_eglGetImageHandle(_EGLImage *img) +{ + return (EGLImageKHR) ((img && img->Display) ? img : EGL_NO_IMAGE_KHR); +} + + +#endif /* EGLIMAGE_INCLUDED */ diff --git a/src/egl/main/egllog.c b/src/egl/main/egllog.c index dc1daaa996..1d7a0a388c 100644 --- a/src/egl/main/egllog.c +++ b/src/egl/main/egllog.c @@ -1,5 +1,7 @@ /** * Logging facility for debug/info messages. + * _EGL_FATAL messages are printed to stderr + * The EGL_LOG_LEVEL var controls the output of other warning/info/debug msgs. */ @@ -10,37 +12,41 @@ #include "egllog.h" #define MAXSTRING 1000 -#define FALLBACK_LOG_LEVEL _EGL_DEBUG -#define FALLBACK_LOG_LEVEL_STR "debug" +#define FALLBACK_LOG_LEVEL _EGL_WARNING +#define FALLBACK_LOG_LEVEL_STR "warning" static EGLint ReportingLevel = -1; static void -log_level_initialize (void) +log_level_initialize(void) { - char *log_env = getenv ("EGL_LOG_LEVEL"); +#if defined(_EGL_PLATFORM_X) + char *log_env = getenv("EGL_LOG_LEVEL"); +#else + char *log_env = NULL; +#endif if (log_env == NULL) { ReportingLevel = FALLBACK_LOG_LEVEL; } - else if (strcasecmp (log_env, "fatal") == 0) { + else if (strcasecmp(log_env, "fatal") == 0) { ReportingLevel = _EGL_FATAL; } - else if (strcasecmp (log_env, "warning") == 0) { + else if (strcasecmp(log_env, "warning") == 0) { ReportingLevel = _EGL_WARNING; } - else if (strcasecmp (log_env, "info") == 0) { + else if (strcasecmp(log_env, "info") == 0) { ReportingLevel = _EGL_INFO; } - else if (strcasecmp (log_env, "debug") == 0) { + else if (strcasecmp(log_env, "debug") == 0) { ReportingLevel = _EGL_DEBUG; } else { - fprintf (stderr, "Unrecognized EGL_LOG_LEVEL environment variable value. " - "Expected one of \"fatal\", \"warning\", \"info\", \"debug\". " - "Got \"%s\". Falling back to \"%s\".\n", - log_env, FALLBACK_LOG_LEVEL_STR); + fprintf(stderr, "Unrecognized EGL_LOG_LEVEL environment variable value. " + "Expected one of \"fatal\", \"warning\", \"info\", \"debug\". " + "Got \"%s\". Falling back to \"%s\".\n", + log_env, FALLBACK_LOG_LEVEL_STR); ReportingLevel = FALLBACK_LOG_LEVEL; } } @@ -59,7 +65,7 @@ _eglLog(EGLint level, const char *fmtStr, ...) static int log_level_initialized = 0; if (!log_level_initialized) { - log_level_initialize (); + log_level_initialize(); log_level_initialized = 1; } @@ -85,7 +91,7 @@ _eglLog(EGLint level, const char *fmtStr, ...) vsnprintf(msg, MAXSTRING, fmtStr, args); va_end(args); - fprintf(stderr, "EGL %s: %s\n", levelStr, msg); + fprintf(stderr, "libEGL %s: %s\n", levelStr, msg); if (level == _EGL_FATAL) { exit(1); /* or abort()? */ diff --git a/src/egl/main/eglmisc.c b/src/egl/main/eglmisc.c new file mode 100644 index 0000000000..f40321b1df --- /dev/null +++ b/src/egl/main/eglmisc.c @@ -0,0 +1,141 @@ +/************************************************************************** + * + * Copyright 2008 Tungsten Graphics, Inc., Cedar Park, Texas. + * All Rights Reserved. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the + * "Software"), to deal in the Software without restriction, including + * without limitation the rights to use, copy, modify, merge, publish, + * distribute, sub license, and/or sell copies of the Software, and to + * permit persons to whom the Software is furnished to do so, subject to + * the following conditions: + * + * The above copyright notice and this permission notice (including the + * next paragraph) shall be included in all copies or substantial portions + * of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS + * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. + * IN NO EVENT SHALL TUNGSTEN GRAPHICS AND/OR ITS SUPPLIERS BE LIABLE FOR + * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, + * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE + * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + * + **************************************************************************/ + + +/** + * Small/misc EGL functions + */ + + +#include <assert.h> +#include <string.h> +#include "eglglobals.h" +#include "eglmisc.h" +#include "egldisplay.h" + + +/** + * Examine the individual extension enable/disable flags and recompute + * the driver's Extensions string. + */ +static void +_eglUpdateExtensionsString(_EGLDisplay *dpy) +{ + 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 "); + if (dpy->Extensions.KHR_image) + strcat(exts, "EGL_KHR_image "); + if (dpy->Extensions.KHR_image_base) + strcat(exts, "EGL_KHR_image_base "); + if (dpy->Extensions.KHR_image_pixmap) + strcat(exts, "EGL_KHR_image_pixmap "); + assert(strlen(exts) < _EGL_MAX_EXTENSIONS_LEN); +} + + +static void +_eglUpdateAPIsString(_EGLDisplay *dpy) +{ + char *apis = dpy->ClientAPIs; + + if (apis[0] || !dpy->ClientAPIsMask) + return; + + if (dpy->ClientAPIsMask & EGL_OPENGL_BIT) + strcat(apis, "OpenGL "); + + if (dpy->ClientAPIsMask & EGL_OPENGL_ES_BIT) + strcat(apis, "OpenGL_ES "); + + if (dpy->ClientAPIsMask & EGL_OPENGL_ES2_BIT) + strcat(apis, "OpenGL_ES2 "); + + if (dpy->ClientAPIsMask & EGL_OPENVG_BIT) + strcat(apis, "OpenVG "); + + assert(strlen(apis) < sizeof(dpy->ClientAPIs)); +} + + +const char * +_eglQueryString(_EGLDriver *drv, _EGLDisplay *dpy, EGLint name) +{ + (void) drv; + (void) dpy; + switch (name) { + case EGL_VENDOR: + return _EGL_VENDOR_STRING; + case EGL_VERSION: + return dpy->Version; + case EGL_EXTENSIONS: + _eglUpdateExtensionsString(dpy); + return dpy->Extensions.String; +#ifdef EGL_VERSION_1_2 + case EGL_CLIENT_APIS: + _eglUpdateAPIsString(dpy); + return dpy->ClientAPIs; +#endif + default: + _eglError(EGL_BAD_PARAMETER, "eglQueryString"); + return NULL; + } +} + + +EGLBoolean +_eglWaitGL(_EGLDriver *drv, _EGLDisplay *dpy) +{ + /* just a placeholder */ + (void) drv; + (void) dpy; + return EGL_TRUE; +} + + +EGLBoolean +_eglWaitNative(_EGLDriver *drv, _EGLDisplay *dpy, EGLint engine) +{ + /* just a placeholder */ + (void) drv; + (void) dpy; + switch (engine) { + case EGL_CORE_NATIVE_ENGINE: + break; + default: + _eglError(EGL_BAD_PARAMETER, "eglWaitNative(engine)"); + return EGL_FALSE; + } + + return EGL_TRUE; +} diff --git a/src/egl/main/eglmisc.h b/src/egl/main/eglmisc.h new file mode 100644 index 0000000000..a15c839be2 --- /dev/null +++ b/src/egl/main/eglmisc.h @@ -0,0 +1,47 @@ +/************************************************************************** + * + * Copyright 2008 Tungsten Graphics, Inc., Cedar Park, Texas. + * All Rights Reserved. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the + * "Software"), to deal in the Software without restriction, including + * without limitation the rights to use, copy, modify, merge, publish, + * distribute, sub license, and/or sell copies of the Software, and to + * permit persons to whom the Software is furnished to do so, subject to + * the following conditions: + * + * The above copyright notice and this permission notice (including the + * next paragraph) shall be included in all copies or substantial portions + * of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS + * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. + * IN NO EVENT SHALL TUNGSTEN GRAPHICS AND/OR ITS SUPPLIERS BE LIABLE FOR + * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, + * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE + * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + * + **************************************************************************/ + + +#ifndef EGLMISC_INCLUDED +#define EGLMISC_INCLUDED + +#include "egldriver.h" + + +extern const char * +_eglQueryString(_EGLDriver *drv, _EGLDisplay *dpy, EGLint name); + + +extern EGLBoolean +_eglWaitGL(_EGLDriver *drv, _EGLDisplay *dpy); + + +extern EGLBoolean +_eglWaitNative(_EGLDriver *drv, _EGLDisplay *dpy, EGLint engine); + + +#endif /* EGLMISC_INCLUDED */ diff --git a/src/egl/main/eglmode.c b/src/egl/main/eglmode.c index 786432234b..0f3ba6e5c0 100644 --- a/src/egl/main/eglmode.c +++ b/src/egl/main/eglmode.c @@ -34,9 +34,8 @@ my_strdup(const char *s) * or null if non-existant. */ _EGLMode * -_eglLookupMode(EGLDisplay dpy, EGLModeMESA mode) +_eglLookupMode(EGLModeMESA mode, _EGLDisplay *disp) { - const _EGLDisplay *disp = _eglLookupDisplay(dpy); EGLint scrnum; /* loop over all screens on the display */ @@ -272,19 +271,13 @@ _eglCompareModes(const void *a, const void *b) * Called via eglChooseModeMESA API function. */ EGLBoolean -_eglChooseModeMESA(_EGLDriver *drv, EGLDisplay dpy, EGLScreenMESA screen, +_eglChooseModeMESA(_EGLDriver *drv, _EGLDisplay *dpy, _EGLScreen *scrn, const EGLint *attrib_list, EGLModeMESA *modes, EGLint modes_size, EGLint *num_modes) { - const _EGLScreen *scrn = _eglLookupScreen(dpy, screen); _EGLMode **modeList, min; EGLint i, count; - if (!scrn) { - _eglError(EGL_BAD_SCREEN_MESA, "eglChooseModeMESA"); - return EGL_FALSE; - } - if (!_eglParseModeAttribs(&min, attrib_list)) { /* error code will have been recorded */ return EGL_FALSE; @@ -326,16 +319,9 @@ _eglChooseModeMESA(_EGLDriver *drv, EGLDisplay dpy, EGLScreenMESA screen, * Called via eglGetModesMESA() API function. */ EGLBoolean -_eglGetModesMESA(_EGLDriver *drv, EGLDisplay dpy, EGLScreenMESA screen, +_eglGetModesMESA(_EGLDriver *drv, _EGLDisplay *dpy, _EGLScreen *scrn, EGLModeMESA *modes, EGLint modes_size, EGLint *num_modes) { - _EGLScreen *scrn = _eglLookupScreen(dpy, screen); - - if (!scrn) { - _eglError(EGL_BAD_SCREEN_MESA, "eglGetModesMESA"); - return EGL_FALSE; - } - if (modes) { EGLint i; *num_modes = MIN2(scrn->NumModes, modes_size); @@ -356,17 +342,11 @@ _eglGetModesMESA(_EGLDriver *drv, EGLDisplay dpy, EGLScreenMESA screen, * Query an attribute of a mode. */ EGLBoolean -_eglGetModeAttribMESA(_EGLDriver *drv, EGLDisplay dpy, - EGLModeMESA mode, EGLint attribute, EGLint *value) +_eglGetModeAttribMESA(_EGLDriver *drv, _EGLDisplay *dpy, + _EGLMode *m, EGLint attribute, EGLint *value) { - _EGLMode *m = _eglLookupMode(dpy, mode); EGLint v; - if (!m) { - _eglError(EGL_BAD_MODE_MESA, "eglGetModeAttribMESA"); - return EGL_FALSE; - } - v = getModeAttrib(m, attribute); if (v < 0) { _eglError(EGL_BAD_ATTRIBUTE, "eglGetModeAttribMESA"); @@ -382,13 +362,8 @@ _eglGetModeAttribMESA(_EGLDriver *drv, EGLDisplay dpy, * This is the default function called by eglQueryModeStringMESA(). */ const char * -_eglQueryModeStringMESA(_EGLDriver *drv, EGLDisplay dpy, EGLModeMESA mode) +_eglQueryModeStringMESA(_EGLDriver *drv, _EGLDisplay *dpy, _EGLMode *m) { - _EGLMode *m = _eglLookupMode(dpy, mode); - if (!m) { - _eglError(EGL_BAD_MODE_MESA, "eglQueryModeStringMESA"); - return NULL; - } return m->Name; } diff --git a/src/egl/main/eglmode.h b/src/egl/main/eglmode.h index e70da85759..af7c2c56d3 100644 --- a/src/egl/main/eglmode.h +++ b/src/egl/main/eglmode.h @@ -4,6 +4,9 @@ #include "egltypedefs.h" +#define EGL_NO_MODE_MESA 0 + + /** * Data structure which corresponds to an EGLModeMESA. */ @@ -23,7 +26,7 @@ struct _egl_mode extern _EGLMode * -_eglLookupMode(EGLDisplay dpy, EGLModeMESA mode); +_eglLookupMode(EGLModeMESA mode, _EGLDisplay *dpy); extern _EGLMode * @@ -32,23 +35,23 @@ _eglAddNewMode(_EGLScreen *screen, EGLint width, EGLint height, extern EGLBoolean -_eglChooseModeMESA(_EGLDriver *drv, EGLDisplay dpy, EGLScreenMESA screen, +_eglChooseModeMESA(_EGLDriver *drv, _EGLDisplay *dpy, _EGLScreen *scrn, const EGLint *attrib_list, EGLModeMESA *modes, EGLint modes_size, EGLint *num_modes); extern EGLBoolean -_eglGetModesMESA(_EGLDriver *drv, EGLDisplay dpy, EGLScreenMESA screen, +_eglGetModesMESA(_EGLDriver *drv, _EGLDisplay *dpy, _EGLScreen *scrn, EGLModeMESA *modes, EGLint modes_size, EGLint *num_modes); extern EGLBoolean -_eglGetModeAttribMESA(_EGLDriver *drv, EGLDisplay dpy, EGLModeMESA mode, +_eglGetModeAttribMESA(_EGLDriver *drv, _EGLDisplay *dpy, _EGLMode *m, EGLint attribute, EGLint *value); extern const char * -_eglQueryModeStringMESA(_EGLDriver *drv, EGLDisplay dpy, EGLModeMESA mode); +_eglQueryModeStringMESA(_EGLDriver *drv, _EGLDisplay *dpy, _EGLMode *m); #endif /* EGLMODE_INCLUDED */ diff --git a/src/egl/main/eglmutex.h b/src/egl/main/eglmutex.h new file mode 100644 index 0000000000..29faba0f24 --- /dev/null +++ b/src/egl/main/eglmutex.h @@ -0,0 +1,52 @@ +#ifndef EGLMUTEX_INCLUDED +#define EGLMUTEX_INCLUDED + +#include "eglcompiler.h" + +#ifdef PTHREADS +#include <pthread.h> + +typedef pthread_mutex_t _EGLMutex; + +static INLINE void _eglInitMutex(_EGLMutex *m) +{ + pthread_mutex_init(m, NULL); +} + +static INLINE void +_eglDestroyMutex(_EGLMutex *m) +{ + pthread_mutex_destroy(m); +} + +static INLINE void +_eglLockMutex(_EGLMutex *m) +{ + pthread_mutex_lock(m); +} + +static INLINE void +_eglUnlockMutex(_EGLMutex *m) +{ + pthread_mutex_unlock(m); +} + +#define _EGL_MUTEX_INITIALIZER PTHREAD_MUTEX_INITIALIZER +#define _EGL_DECLARE_MUTEX(m) \ + _EGLMutex m = _EGL_MUTEX_INITIALIZER + +#else + +typedef int _EGLMutex; +static INLINE void _eglInitMutex(_EGLMutex *m) { (void) m; } +static INLINE void _eglDestroyMutex(_EGLMutex *m) { (void) m; } +static INLINE void _eglLockMutex(_EGLMutex *m) { (void) m; } +static INLINE void _eglUnlockMutex(_EGLMutex *m) { (void) m; } + +#define _EGL_MUTEX_INITIALIZER 0 +#define _EGL_DECLARE_MUTEX(m) \ + _EGLMutex m = _EGL_MUTEX_INITIALIZER + +#endif + +#endif /* EGLMUTEX_INCLUDED */ diff --git a/src/egl/main/eglscreen.c b/src/egl/main/eglscreen.c index 9c9a8377bf..14a1e9f8fe 100644 --- a/src/egl/main/eglscreen.c +++ b/src/egl/main/eglscreen.c @@ -52,13 +52,9 @@ _eglInitScreen(_EGLScreen *screen) * Given a public screen handle, return the internal _EGLScreen object. */ _EGLScreen * -_eglLookupScreen(EGLDisplay dpy, EGLScreenMESA screen) +_eglLookupScreen(EGLScreenMESA screen, _EGLDisplay *display) { EGLint i; - _EGLDisplay *display = _eglLookupDisplay(dpy); - - if (!display) - return NULL; for (i = 0; i < display->NumScreens; i++) { if (display->Screens[i]->Handle == screen) @@ -89,17 +85,11 @@ _eglAddScreen(_EGLDisplay *display, _EGLScreen *screen) EGLBoolean -_eglGetScreensMESA(_EGLDriver *drv, EGLDisplay dpy, EGLScreenMESA *screens, +_eglGetScreensMESA(_EGLDriver *drv, _EGLDisplay *display, EGLScreenMESA *screens, EGLint max_screens, EGLint *num_screens) { - _EGLDisplay *display = _eglLookupDisplay(dpy); EGLint n; - if (!display) { - _eglError(EGL_BAD_DISPLAY, "eglGetScreensMESA"); - return EGL_FALSE; - } - if (display->NumScreens > max_screens) { n = max_screens; } @@ -122,8 +112,8 @@ _eglGetScreensMESA(_EGLDriver *drv, EGLDisplay dpy, EGLScreenMESA *screens, /** * Example function - drivers should do a proper implementation. */ -EGLSurface -_eglCreateScreenSurfaceMESA(_EGLDriver *drv, EGLDisplay dpy, EGLConfig config, +_EGLSurface * +_eglCreateScreenSurfaceMESA(_EGLDriver *drv, _EGLDisplay *dpy, _EGLConfig *conf, const EGLint *attrib_list) { #if 0 /* THIS IS JUST EXAMPLE CODE */ @@ -131,19 +121,17 @@ _eglCreateScreenSurfaceMESA(_EGLDriver *drv, EGLDisplay dpy, EGLConfig config, surf = (_EGLSurface *) calloc(1, sizeof(_EGLSurface)); if (!surf) - return EGL_NO_SURFACE; + return NULL; - if (!_eglInitSurface(drv, dpy, surf, EGL_SCREEN_BIT_MESA, - config, attrib_list)) { + if (!_eglInitSurface(drv, surf, EGL_SCREEN_BIT_MESA, + conf, attrib_list)) { free(surf); - return EGL_NO_SURFACE; + return NULL; } - _eglSaveSurface(surf); - - return surf->Handle; + return surf; #endif - return EGL_NO_SURFACE; + return NULL; } @@ -155,28 +143,15 @@ _eglCreateScreenSurfaceMESA(_EGLDriver *drv, EGLDisplay dpy, EGLConfig config, * this with code that _really_ shows the surface. */ EGLBoolean -_eglShowScreenSurfaceMESA(_EGLDriver *drv, EGLDisplay dpy, - EGLScreenMESA screen, EGLSurface surface, - EGLModeMESA m) +_eglShowScreenSurfaceMESA(_EGLDriver *drv, _EGLDisplay *dpy, + _EGLScreen *scrn, _EGLSurface *surf, + _EGLMode *mode) { - _EGLScreen *scrn = _eglLookupScreen(dpy, screen); - _EGLMode *mode = _eglLookupMode(dpy, m); - - if (!scrn) { - _eglError(EGL_BAD_SCREEN_MESA, "eglShowSurfaceMESA"); - return EGL_FALSE; - } - if (!mode && (m != EGL_NO_MODE_MESA )) { - _eglError(EGL_BAD_MODE_MESA, "eglShowSurfaceMESA"); - return EGL_FALSE; - } - - if (surface == EGL_NO_SURFACE) { + if (!surf) { scrn->CurrentSurface = NULL; } else { - _EGLSurface *surf = _eglLookupSurface(surface); - if (!surf || surf->Type != EGL_SCREEN_BIT_MESA) { + if (surf->Type != EGL_SCREEN_BIT_MESA) { _eglError(EGL_BAD_SURFACE, "eglShowSurfaceMESA"); return EGL_FALSE; } @@ -201,18 +176,10 @@ _eglShowScreenSurfaceMESA(_EGLDriver *drv, EGLDisplay dpy, * this with code that _really_ sets the mode. */ EGLBoolean -_eglScreenModeMESA(_EGLDriver *drv, EGLDisplay dpy, EGLScreenMESA screen, - EGLModeMESA mode) +_eglScreenModeMESA(_EGLDriver *drv, _EGLDisplay *dpy, _EGLScreen *scrn, + _EGLMode *m) { - _EGLScreen *scrn = _eglLookupScreen(dpy, screen); - - if (!scrn) { - _eglError(EGL_BAD_SCREEN_MESA, "eglScreenModeMESA"); - return EGL_FALSE; - } - - scrn->CurrentMode = _eglLookupMode(dpy, mode); - + scrn->CurrentMode = m; return EGL_TRUE; } @@ -221,15 +188,9 @@ _eglScreenModeMESA(_EGLDriver *drv, EGLDisplay dpy, EGLScreenMESA screen, * Set a screen's surface origin. */ EGLBoolean -_eglScreenPositionMESA(_EGLDriver *drv, EGLDisplay dpy, - EGLScreenMESA screen, EGLint x, EGLint y) +_eglScreenPositionMESA(_EGLDriver *drv, _EGLDisplay *dpy, + _EGLScreen *scrn, EGLint x, EGLint y) { - _EGLScreen *scrn = _eglLookupScreen(dpy, screen); - if (!scrn) { - _eglError(EGL_BAD_SCREEN_MESA, "eglScreenPositionMESA"); - return EGL_FALSE; - } - scrn->OriginX = x; scrn->OriginY = y; @@ -241,14 +202,10 @@ _eglScreenPositionMESA(_EGLDriver *drv, EGLDisplay dpy, * Query a screen's current surface. */ EGLBoolean -_eglQueryScreenSurfaceMESA(_EGLDriver *drv, EGLDisplay dpy, - EGLScreenMESA screen, EGLSurface *surface) +_eglQueryScreenSurfaceMESA(_EGLDriver *drv, _EGLDisplay *dpy, + _EGLScreen *scrn, _EGLSurface **surf) { - const _EGLScreen *scrn = _eglLookupScreen(dpy, screen); - if (scrn->CurrentSurface) - *surface = scrn->CurrentSurface->Handle; - else - *surface = EGL_NO_SURFACE; + *surf = scrn->CurrentSurface; return EGL_TRUE; } @@ -257,29 +214,18 @@ _eglQueryScreenSurfaceMESA(_EGLDriver *drv, EGLDisplay dpy, * Query a screen's current mode. */ EGLBoolean -_eglQueryScreenModeMESA(_EGLDriver *drv, EGLDisplay dpy, EGLScreenMESA screen, - EGLModeMESA *mode) +_eglQueryScreenModeMESA(_EGLDriver *drv, _EGLDisplay *dpy, _EGLScreen *scrn, + _EGLMode **m) { - const _EGLScreen *scrn = _eglLookupScreen(dpy, screen); - if (scrn->CurrentMode) - *mode = scrn->CurrentMode->Handle; - else - *mode = EGL_NO_MODE_MESA; + *m = scrn->CurrentMode; return EGL_TRUE; } EGLBoolean -_eglQueryScreenMESA(_EGLDriver *drv, EGLDisplay dpy, EGLScreenMESA screen, +_eglQueryScreenMESA(_EGLDriver *drv, _EGLDisplay *dpy, _EGLScreen *scrn, EGLint attribute, EGLint *value) { - const _EGLScreen *scrn = _eglLookupScreen(dpy, screen); - - if (!scrn) { - _eglError(EGL_BAD_SCREEN_MESA, "eglQueryScreenMESA"); - return EGL_FALSE; - } - switch (attribute) { case EGL_SCREEN_POSITION_MESA: value[0] = scrn->OriginX; diff --git a/src/egl/main/eglscreen.h b/src/egl/main/eglscreen.h index 833439b410..8860a2aa7f 100644 --- a/src/egl/main/eglscreen.h +++ b/src/egl/main/eglscreen.h @@ -35,7 +35,7 @@ _eglInitScreen(_EGLScreen *screen); extern _EGLScreen * -_eglLookupScreen(EGLDisplay dpy, EGLScreenMESA screen); +_eglLookupScreen(EGLScreenMESA screen, _EGLDisplay *dpy); extern void @@ -43,40 +43,40 @@ _eglAddScreen(_EGLDisplay *display, _EGLScreen *screen); extern EGLBoolean -_eglGetScreensMESA(_EGLDriver *drv, EGLDisplay dpy, EGLScreenMESA *screens, EGLint max_screens, EGLint *num_screens); +_eglGetScreensMESA(_EGLDriver *drv, _EGLDisplay *dpy, EGLScreenMESA *screens, EGLint max_screens, EGLint *num_screens); -extern EGLSurface -_eglCreateScreenSurfaceMESA(_EGLDriver *drv, EGLDisplay dpy, EGLConfig config, const EGLint *attrib_list); +extern _EGLSurface * +_eglCreateScreenSurfaceMESA(_EGLDriver *drv, _EGLDisplay *dpy, _EGLConfig *conf, const EGLint *attrib_list); extern EGLBoolean -_eglShowScreenSurfaceMESA(_EGLDriver *drv, EGLDisplay dpy, EGLScreenMESA screen, EGLSurface surface, EGLModeMESA mode); +_eglShowScreenSurfaceMESA(_EGLDriver *drv, _EGLDisplay *dpy, _EGLScreen *scrn, _EGLSurface *surf, _EGLMode *m); extern EGLBoolean -_eglScreenModeMESA(_EGLDriver *drv, EGLDisplay dpy, EGLScreenMESA screen, EGLModeMESA mode); +_eglScreenModeMESA(_EGLDriver *drv, _EGLDisplay *dpy, _EGLScreen *scrn, _EGLMode *m); extern EGLBoolean -_eglScreenPositionMESA(_EGLDriver *drv, EGLDisplay dpy, EGLScreenMESA screen, EGLint x, EGLint y); +_eglScreenPositionMESA(_EGLDriver *drv, _EGLDisplay *dpy, _EGLScreen *scrn, EGLint x, EGLint y); extern EGLBoolean -_eglQueryDisplayMESA(_EGLDriver *drv, EGLDisplay dpy, EGLint attribute, EGLint *value); +_eglQueryDisplayMESA(_EGLDriver *drv, _EGLDisplay *dpy, EGLint attribute, EGLint *value); extern EGLBoolean -_eglQueryScreenSurfaceMESA(_EGLDriver *drv, EGLDisplay dpy, - EGLScreenMESA screen, EGLSurface *surface); +_eglQueryScreenSurfaceMESA(_EGLDriver *drv, _EGLDisplay *dpy, + _EGLScreen *scrn, _EGLSurface **surface); extern EGLBoolean -_eglQueryScreenModeMESA(_EGLDriver *drv, EGLDisplay dpy, EGLScreenMESA screen, EGLModeMESA *mode); +_eglQueryScreenModeMESA(_EGLDriver *drv, _EGLDisplay *dpy, _EGLScreen *scrn, _EGLMode **m); extern EGLBoolean -_eglQueryScreenMESA(_EGLDriver *drv, EGLDisplay dpy, EGLScreenMESA screen, EGLint attribute, EGLint *value); +_eglQueryScreenMESA(_EGLDriver *drv, _EGLDisplay *dpy, _EGLScreen *scrn, EGLint attribute, EGLint *value); extern void diff --git a/src/egl/main/eglstring.c b/src/egl/main/eglstring.c new file mode 100644 index 0000000000..ba7406158c --- /dev/null +++ b/src/egl/main/eglstring.c @@ -0,0 +1,24 @@ +/** + * String utils. + */ + +#include <stdlib.h> +#include <string.h> +#include "eglstring.h" + + +char * +_eglstrdup(const char *s) +{ + if (s) { + int l = strlen(s); + char *s2 = malloc(l + 1); + if (s2) + strcpy(s2, s); + return s2; + } + return NULL; +} + + + diff --git a/src/egl/main/eglstring.h b/src/egl/main/eglstring.h new file mode 100644 index 0000000000..10468636e8 --- /dev/null +++ b/src/egl/main/eglstring.h @@ -0,0 +1,9 @@ +#ifndef EGLSTRING_INCLUDED +#define EGLSTRING_INCLUDED + + +extern char * +_eglstrdup(const char *s); + + +#endif /* EGLSTRING_INCLUDED */ diff --git a/src/egl/main/eglsurface.c b/src/egl/main/eglsurface.c index 874f318e96..e7a1a8329e 100644 --- a/src/egl/main/eglsurface.c +++ b/src/egl/main/eglsurface.c @@ -6,10 +6,11 @@ #include <assert.h> #include <stdlib.h> #include <string.h> +#include "egldisplay.h" #include "eglcontext.h" #include "eglconfig.h" +#include "egldriver.h" #include "eglglobals.h" -#include "eglhash.h" #include "egllog.h" #include "eglsurface.h" @@ -19,14 +20,13 @@ * \return EGL_TRUE if no errors, EGL_FALSE otherwise. */ EGLBoolean -_eglInitSurface(_EGLDriver *drv, EGLDisplay dpy, - _EGLSurface *surf, EGLint type, EGLConfig config, - const EGLint *attrib_list) +_eglInitSurface(_EGLDriver *drv, _EGLSurface *surf, EGLint type, + _EGLConfig *conf, const EGLint *attrib_list) { const char *func; - _EGLConfig *conf; EGLint width = 0, height = 0, largest = 0; - EGLint texFormat = 0, texTarget = 0, mipmapTex = 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; @@ -54,12 +54,17 @@ _eglInitSurface(_EGLDriver *drv, EGLDisplay dpy, return EGL_FALSE; } - conf = _eglLookupConfig(drv, dpy, config); 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. @@ -175,7 +180,7 @@ _eglInitSurface(_EGLDriver *drv, EGLDisplay dpy, } } - if (width <= 0 || height <= 0) { + if (width < 0 || height < 0) { _eglError(EGL_BAD_ATTRIBUTE, func); return EGL_FALSE; } @@ -204,72 +209,16 @@ _eglInitSurface(_EGLDriver *drv, EGLDisplay dpy, } -void -_eglSaveSurface(_EGLSurface *surf) -{ - assert(surf); - assert(!surf->Handle); - surf->Handle = _eglHashGenKey(_eglGlobal.Contexts); - assert(surf->Handle); - _eglHashInsert(_eglGlobal.Surfaces, surf->Handle, surf); -} - - -void -_eglRemoveSurface(_EGLSurface *surf) -{ - _eglHashRemove(_eglGlobal.Surfaces, surf->Handle); -} - - -_EGLSurface * -_eglLookupSurface(EGLSurface surf) -{ - _EGLSurface *c = (_EGLSurface *) _eglHashLookup(_eglGlobal.Surfaces, surf); - return c; -} - - -_EGLSurface * -_eglGetCurrentSurface(EGLint readdraw) -{ - _EGLContext *ctx = _eglGetCurrentContext(); - if (ctx) { - switch (readdraw) { - case EGL_DRAW: - return ctx->DrawSurface; - case EGL_READ: - return ctx->ReadSurface; - default: - return NULL; - } - } - return NULL; -} - - EGLBoolean -_eglSwapBuffers(_EGLDriver *drv, EGLDisplay dpy, EGLSurface draw) +_eglSwapBuffers(_EGLDriver *drv, _EGLDisplay *dpy, _EGLSurface *surf) { - /* Basically just do error checking here. Drivers have to do the - * actual buffer swap. - */ - _EGLContext *context = _eglGetCurrentContext(); - _EGLSurface *surface = _eglLookupSurface(draw); - if (context && context->DrawSurface != surface) { - _eglError(EGL_BAD_SURFACE, "eglSwapBuffers"); - return EGL_FALSE; - } - if (surface == NULL) { - _eglError(EGL_BAD_SURFACE, "eglSwapBuffers"); - return EGL_FALSE; - } + /* Drivers have to do the actual buffer swap. */ return EGL_TRUE; } EGLBoolean -_eglCopyBuffers(_EGLDriver *drv, EGLDisplay dpy, EGLSurface surface, +_eglCopyBuffers(_EGLDriver *drv, _EGLDisplay *dpy, _EGLSurface *surf, NativePixmapType target) { /* copy surface to native pixmap */ @@ -279,14 +228,9 @@ _eglCopyBuffers(_EGLDriver *drv, EGLDisplay dpy, EGLSurface surface, EGLBoolean -_eglQuerySurface(_EGLDriver *drv, EGLDisplay dpy, EGLSurface surf, +_eglQuerySurface(_EGLDriver *drv, _EGLDisplay *dpy, _EGLSurface *surface, EGLint attribute, EGLint *value) { - _EGLSurface *surface = _eglLookupSurface(surf); - if (surface == NULL) { - _eglError(EGL_BAD_SURFACE, "eglQuerySurface"); - return EGL_FALSE; - } switch (attribute) { case EGL_WIDTH: *value = surface->Width; @@ -297,7 +241,9 @@ _eglQuerySurface(_EGLDriver *drv, EGLDisplay dpy, EGLSurface surf, case EGL_CONFIG_ID: *value = GET_CONFIG_ATTRIB(surface->Config, EGL_CONFIG_ID); return EGL_TRUE; - /*XXX case EGL_LARGEST_PBUFFER:*/ + case EGL_LARGEST_PBUFFER: + *value = dpy->LargestPbuffer; + return EGL_TRUE; case EGL_SURFACE_TYPE: *value = surface->Type; return EGL_TRUE; @@ -353,8 +299,8 @@ _eglQuerySurface(_EGLDriver *drv, EGLDisplay dpy, EGLSurface surf, /** * Example function - drivers should do a proper implementation. */ -EGLSurface -_eglCreateWindowSurface(_EGLDriver *drv, EGLDisplay dpy, EGLConfig config, +_EGLSurface * +_eglCreateWindowSurface(_EGLDriver *drv, _EGLDisplay *dpy, _EGLConfig *conf, NativeWindowType window, const EGLint *attrib_list) { #if 0 /* THIS IS JUST EXAMPLE CODE */ @@ -362,26 +308,24 @@ _eglCreateWindowSurface(_EGLDriver *drv, EGLDisplay dpy, EGLConfig config, surf = (_EGLSurface *) calloc(1, sizeof(_EGLSurface)); if (!surf) - return EGL_NO_SURFACE; + return NULL; - if (!_eglInitSurface(drv, dpy, surf, EGL_WINDOW_BIT, config, attrib_list)) { + if (!_eglInitSurface(drv, surf, EGL_WINDOW_BIT, conf, attrib_list)) { free(surf); - return EGL_NO_SURFACE; + return NULL; } - _eglSaveSurface(surf); - - return surf->Handle; + return surf; #endif - return EGL_NO_SURFACE; + return NULL; } /** * Example function - drivers should do a proper implementation. */ -EGLSurface -_eglCreatePixmapSurface(_EGLDriver *drv, EGLDisplay dpy, EGLConfig config, +_EGLSurface * +_eglCreatePixmapSurface(_EGLDriver *drv, _EGLDisplay *dpy, _EGLConfig *conf, NativePixmapType pixmap, const EGLint *attrib_list) { #if 0 /* THIS IS JUST EXAMPLE CODE */ @@ -389,26 +333,24 @@ _eglCreatePixmapSurface(_EGLDriver *drv, EGLDisplay dpy, EGLConfig config, surf = (_EGLSurface *) calloc(1, sizeof(_EGLSurface)); if (!surf) - return EGL_NO_SURFACE; + return NULL; - if (!_eglInitSurface(drv, dpy, surf, EGL_PIXMAP_BIT, config, attrib_list)) { + if (!_eglInitSurface(drv, surf, EGL_PIXMAP_BIT, conf, attrib_list)) { free(surf); - return EGL_NO_SURFACE; + return NULL; } - _eglSaveSurface(surf); - - return surf->Handle; + return surf; #endif - return EGL_NO_SURFACE; + return NULL; } /** * Example function - drivers should do a proper implementation. */ -EGLSurface -_eglCreatePbufferSurface(_EGLDriver *drv, EGLDisplay dpy, EGLConfig config, +_EGLSurface * +_eglCreatePbufferSurface(_EGLDriver *drv, _EGLDisplay *dpy, _EGLConfig *conf, const EGLint *attrib_list) { #if 0 /* THIS IS JUST EXAMPLE CODE */ @@ -416,18 +358,16 @@ _eglCreatePbufferSurface(_EGLDriver *drv, EGLDisplay dpy, EGLConfig config, surf = (_EGLSurface *) calloc(1, sizeof(_EGLSurface)); if (!surf) - return EGL_NO_SURFACE; + return NULL; - if (!_eglInitSurface(drv, dpy, surf, EGL_PBUFFER_BIT, config, attrib_list)) { + if (!_eglInitSurface(drv, surf, EGL_PBUFFER_BIT, conf, attrib_list)) { free(surf); - return EGL_NO_SURFACE; + return NULL; } - _eglSaveSurface(surf); - - return surf->Handle; + return NULL; #endif - return EGL_NO_SURFACE; + return NULL; } @@ -435,23 +375,11 @@ _eglCreatePbufferSurface(_EGLDriver *drv, EGLDisplay dpy, EGLConfig config, * Default fallback routine - drivers should usually override this. */ EGLBoolean -_eglDestroySurface(_EGLDriver *drv, EGLDisplay dpy, EGLSurface surface) +_eglDestroySurface(_EGLDriver *drv, _EGLDisplay *dpy, _EGLSurface *surf) { - _EGLSurface *surf = _eglLookupSurface(surface); - if (surf) { - _eglHashRemove(_eglGlobal.Surfaces, surface); - if (surf->IsBound) { - surf->DeletePending = EGL_TRUE; - } - else { - free(surf); - } - return EGL_TRUE; - } - else { - _eglError(EGL_BAD_SURFACE, "eglDestroySurface"); - return EGL_FALSE; - } + if (!_eglIsSurfaceBound(surf)) + free(surf); + return EGL_TRUE; } @@ -459,15 +387,9 @@ _eglDestroySurface(_EGLDriver *drv, EGLDisplay dpy, EGLSurface surface) * Default fallback routine - drivers might override this. */ EGLBoolean -_eglSurfaceAttrib(_EGLDriver *drv, EGLDisplay dpy, EGLSurface surf, EGLint attribute, EGLint value) +_eglSurfaceAttrib(_EGLDriver *drv, _EGLDisplay *dpy, _EGLSurface *surface, + EGLint attribute, EGLint value) { - _EGLSurface *surface = _eglLookupSurface(surf); - - if (surface == NULL) { - _eglError(EGL_BAD_SURFACE, "eglSurfaceAttrib"); - return EGL_FALSE; - } - switch (attribute) { case EGL_MIPMAP_LEVEL: surface->MipmapLevel = value; @@ -481,30 +403,74 @@ _eglSurfaceAttrib(_EGLDriver *drv, EGLDisplay dpy, EGLSurface surf, EGLint attri EGLBoolean -_eglBindTexImage(_EGLDriver *drv, EGLDisplay dpy, EGLSurface surface, EGLint buffer) +_eglBindTexImage(_EGLDriver *drv, _EGLDisplay *dpy, _EGLSurface *surface, + EGLint buffer) { - /* XXX unfinished */ - return EGL_FALSE; + /* Just do basic error checking and return success/fail. + * Drivers must implement the real stuff. + */ + + if (surface->Type != EGL_PBUFFER_BIT) { + _eglError(EGL_BAD_SURFACE, "eglBindTexImage"); + return EGL_FALSE; + } + + if (surface->TextureFormat == EGL_NO_TEXTURE) { + _eglError(EGL_BAD_MATCH, "eglBindTexImage"); + return EGL_FALSE; + } + + if (buffer != EGL_BACK_BUFFER) { + _eglError(EGL_BAD_PARAMETER, "eglBindTexImage"); + return EGL_FALSE; + } + + surface->BoundToTexture = EGL_TRUE; + + return EGL_TRUE; } EGLBoolean -_eglReleaseTexImage(_EGLDriver *drv, EGLDisplay dpy, EGLSurface surface, EGLint buffer) +_eglReleaseTexImage(_EGLDriver *drv, _EGLDisplay *dpy, _EGLSurface *surface, + EGLint buffer) { - /* XXX unfinished */ - return EGL_FALSE; + /* Just do basic error checking and return success/fail. + * Drivers must implement the real stuff. + */ + + if (surface->Type != EGL_PBUFFER_BIT) { + _eglError(EGL_BAD_SURFACE, "eglBindTexImage"); + return EGL_FALSE; + } + + if (surface->TextureFormat == EGL_NO_TEXTURE) { + _eglError(EGL_BAD_MATCH, "eglBindTexImage"); + return EGL_FALSE; + } + + if (buffer != EGL_BACK_BUFFER) { + _eglError(EGL_BAD_PARAMETER, "eglReleaseTexImage"); + return EGL_FALSE; + } + + if (!surface->BoundToTexture) { + _eglError(EGL_BAD_SURFACE, "eglReleaseTexImage"); + return EGL_FALSE; + } + + surface->BoundToTexture = EGL_FALSE; + + return EGL_TRUE; } EGLBoolean -_eglSwapInterval(_EGLDriver *drv, EGLDisplay dpy, EGLint interval) +_eglSwapInterval(_EGLDriver *drv, _EGLDisplay *dpy, EGLint interval) { _EGLSurface *surf = _eglGetCurrentSurface(EGL_DRAW); - if (surf == NULL) { - _eglError(EGL_BAD_SURFACE, "eglSwapInterval"); - return EGL_FALSE; - } - surf->SwapInterval = interval; + if (surf) + surf->SwapInterval = interval; return EGL_TRUE; } @@ -514,17 +480,17 @@ _eglSwapInterval(_EGLDriver *drv, EGLDisplay dpy, EGLint interval) /** * Example function - drivers should do a proper implementation. */ -EGLSurface -_eglCreatePbufferFromClientBuffer(_EGLDriver *drv, EGLDisplay dpy, +_EGLSurface * +_eglCreatePbufferFromClientBuffer(_EGLDriver *drv, _EGLDisplay *dpy, EGLenum buftype, EGLClientBuffer buffer, - EGLConfig config, const EGLint *attrib_list) + _EGLConfig *conf, const EGLint *attrib_list) { if (buftype != EGL_OPENVG_IMAGE) { _eglError(EGL_BAD_PARAMETER, "eglCreatePbufferFromClientBuffer"); - return EGL_NO_SURFACE; + return NULL; } - return EGL_NO_SURFACE; + return NULL; } #endif /* EGL_VERSION_1_2 */ diff --git a/src/egl/main/eglsurface.h b/src/egl/main/eglsurface.h index 79abeca0b2..f6d44b5922 100644 --- a/src/egl/main/eglsurface.h +++ b/src/egl/main/eglsurface.h @@ -10,12 +10,15 @@ */ struct _egl_surface { - EGLSurface Handle; /* The public/opaque handle which names this object */ - _EGLConfig *Config; + /* Managed by EGLDisplay for linking */ + _EGLDisplay *Display; + _EGLSurface *Next; + + /* The bound status of the surface */ + _EGLContext *Binding; + EGLBoolean BoundToTexture; - /* May need reference counting here */ - EGLBoolean IsBound; - EGLBoolean DeletePending; + _EGLConfig *Config; EGLint Type; /* one of EGL_WINDOW_BIT, EGL_PIXMAP_BIT or EGL_PBUFFER_BIT */ EGLint Width, Height; @@ -38,80 +41,74 @@ struct _egl_surface extern EGLBoolean -_eglInitSurface(_EGLDriver *drv, EGLDisplay dpy, - _EGLSurface *surf, EGLint type, EGLConfig config, - const EGLint *attrib_list); - - -extern void -_eglSaveSurface(_EGLSurface *surf); - - -extern void -_eglRemoveSurface(_EGLSurface *surf); - - -extern _EGLSurface * -_eglLookupSurface(EGLSurface surf); - - -extern _EGLSurface * -_eglGetCurrentSurface(EGLint readdraw); +_eglInitSurface(_EGLDriver *drv, _EGLSurface *surf, EGLint type, + _EGLConfig *config, const EGLint *attrib_list); extern EGLBoolean -_eglSwapBuffers(_EGLDriver *drv, EGLDisplay dpy, EGLSurface draw); +_eglSwapBuffers(_EGLDriver *drv, _EGLDisplay *dpy, _EGLSurface *surf); extern EGLBoolean -_eglCopyBuffers(_EGLDriver *drv, EGLDisplay dpy, EGLSurface surface, NativePixmapType target); +_eglCopyBuffers(_EGLDriver *drv, _EGLDisplay *dpy, _EGLSurface *surf, NativePixmapType target); extern EGLBoolean -_eglQuerySurface(_EGLDriver *drv, EGLDisplay dpy, EGLSurface surface, EGLint attribute, EGLint *value); +_eglQuerySurface(_EGLDriver *drv, _EGLDisplay *dpy, _EGLSurface *surf, EGLint attribute, EGLint *value); -extern EGLSurface -_eglCreateWindowSurface(_EGLDriver *drv, EGLDisplay dpy, EGLConfig config, NativeWindowType window, const EGLint *attrib_list); +extern _EGLSurface * +_eglCreateWindowSurface(_EGLDriver *drv, _EGLDisplay *dpy, _EGLConfig *conf, NativeWindowType window, const EGLint *attrib_list); -extern EGLSurface -_eglCreatePixmapSurface(_EGLDriver *drv, EGLDisplay dpy, EGLConfig config, NativePixmapType pixmap, const EGLint *attrib_list); +extern _EGLSurface * +_eglCreatePixmapSurface(_EGLDriver *drv, _EGLDisplay *dpy, _EGLConfig *conf, NativePixmapType pixmap, const EGLint *attrib_list); -extern EGLSurface -_eglCreatePbufferSurface(_EGLDriver *drv, EGLDisplay dpy, EGLConfig config, const EGLint *attrib_list); +extern _EGLSurface * +_eglCreatePbufferSurface(_EGLDriver *drv, _EGLDisplay *dpy, _EGLConfig *conf, const EGLint *attrib_list); extern EGLBoolean -_eglDestroySurface(_EGLDriver *drv, EGLDisplay dpy, EGLSurface surface); +_eglDestroySurface(_EGLDriver *drv, _EGLDisplay *dpy, _EGLSurface *surf); extern EGLBoolean -_eglSurfaceAttrib(_EGLDriver *drv, EGLDisplay dpy, EGLSurface surface, EGLint attribute, EGLint value); +_eglSurfaceAttrib(_EGLDriver *drv, _EGLDisplay *dpy, _EGLSurface *surf, EGLint attribute, EGLint value); extern EGLBoolean -_eglBindTexImage(_EGLDriver *drv, EGLDisplay dpy, EGLSurface surface, EGLint buffer); +_eglBindTexImage(_EGLDriver *drv, _EGLDisplay *dpy, _EGLSurface *surf, EGLint buffer); extern EGLBoolean -_eglReleaseTexImage(_EGLDriver *drv, EGLDisplay dpy, EGLSurface surface, EGLint buffer); +_eglReleaseTexImage(_EGLDriver *drv, _EGLDisplay *dpy, _EGLSurface *surf, EGLint buffer); extern EGLBoolean -_eglSwapInterval(_EGLDriver *drv, EGLDisplay dpy, EGLint interval); +_eglSwapInterval(_EGLDriver *drv, _EGLDisplay *dpy, EGLint interval); #ifdef EGL_VERSION_1_2 -extern EGLSurface -_eglCreatePbufferFromClientBuffer(_EGLDriver *drv, EGLDisplay dpy, +extern _EGLSurface * +_eglCreatePbufferFromClientBuffer(_EGLDriver *drv, _EGLDisplay *dpy, EGLenum buftype, EGLClientBuffer buffer, - EGLConfig config, const EGLint *attrib_list); + _EGLConfig *conf, const EGLint *attrib_list); #endif /* EGL_VERSION_1_2 */ +/** + * Return true if the surface is bound to a thread. + * A surface bound to a texutre is not considered bound by + * this function. + */ +static INLINE EGLBoolean +_eglIsSurfaceBound(_EGLSurface *surf) +{ + return (surf->Binding != NULL); +} + #endif /* EGLSURFACE_INCLUDED */ diff --git a/src/egl/main/egltypedefs.h b/src/egl/main/egltypedefs.h index fa8cb496f8..b6321716d3 100644 --- a/src/egl/main/egltypedefs.h +++ b/src/egl/main/egltypedefs.h @@ -1,9 +1,12 @@ #ifndef EGLTYPEDEFS_INCLUDED #define EGLTYPEDEFS_INCLUDED +#define EGL_EGLEXT_PROTOTYPES -#include <GLES/egl.h> +#include <EGL/egl.h> +#include <EGL/eglext.h> +#include "eglcompiler.h" typedef struct _egl_api _EGLAPI; @@ -25,10 +28,10 @@ typedef struct _egl_surface _EGLSurface; typedef struct _egl_thread_info _EGLThreadInfo; +typedef struct _egl_image _EGLImage; -typedef void (*_EGLProc)(); -typedef _EGLDriver *(*_EGLMain_t)(_EGLDisplay *dpy); +typedef _EGLDriver *(*_EGLMain_t)(const char *args); #endif /* EGLTYPEDEFS_INCLUDED */ |