diff options
author | Chia-I Wu <olvaffe@gmail.com> | 2009-09-15 14:16:22 +0800 |
---|---|---|
committer | Chia-I Wu <olvaffe@gmail.com> | 2009-09-15 14:16:22 +0800 |
commit | e2ba90a9cc762cf00a168f0a59d31e7dc52fc42e (patch) | |
tree | fe3206d7602ad935296884742980f3c4d30bd867 /src/egl/drivers | |
parent | 11a4292d4eb515813b82b8d688a318adef66b3e6 (diff) | |
parent | b4b8800315637d9218a81c76f09df7d601710d29 (diff) |
Merge commit 'eee/mesa-es' into android
Diffstat (limited to 'src/egl/drivers')
-rw-r--r-- | src/egl/drivers/Makefile | 31 | ||||
-rw-r--r-- | src/egl/drivers/demo/Makefile | 4 | ||||
-rw-r--r-- | src/egl/drivers/demo/demo.c | 147 | ||||
-rw-r--r-- | src/egl/drivers/dri/Makefile | 13 | ||||
-rw-r--r-- | src/egl/drivers/dri/egldri.c | 143 | ||||
-rw-r--r-- | src/egl/drivers/dri/egldri.h | 9 | ||||
-rw-r--r-- | src/egl/drivers/glx/Makefile | 77 | ||||
-rw-r--r-- | src/egl/drivers/glx/egl_glx.c | 882 | ||||
-rw-r--r-- | src/egl/drivers/xdri/Makefile | 78 | ||||
-rw-r--r-- | src/egl/drivers/xdri/driinit.c | 67 | ||||
-rw-r--r-- | src/egl/drivers/xdri/driinit.h | 9 | ||||
-rw-r--r-- | src/egl/drivers/xdri/egl_xdri.c | 784 | ||||
-rw-r--r-- | src/egl/drivers/xdri/glxinit.c | 626 | ||||
-rw-r--r-- | src/egl/drivers/xdri/glxinit.h | 14 |
14 files changed, 2751 insertions, 133 deletions
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 */ |