diff options
Diffstat (limited to 'src/egl/drivers/xdri')
-rw-r--r-- | src/egl/drivers/xdri/Makefile | 82 | ||||
-rw-r--r-- | src/egl/drivers/xdri/driinit.c | 34 | ||||
-rw-r--r-- | src/egl/drivers/xdri/egl_xdri.c | 121 | ||||
-rw-r--r-- | src/egl/drivers/xdri/glxinit.c | 100 | ||||
-rw-r--r-- | src/egl/drivers/xdri/glxinit.h | 3 |
5 files changed, 203 insertions, 137 deletions
diff --git a/src/egl/drivers/xdri/Makefile b/src/egl/drivers/xdri/Makefile index 4c1fc9071c..9120620dc5 100644 --- a/src/egl/drivers/xdri/Makefile +++ b/src/egl/drivers/xdri/Makefile @@ -1,78 +1,28 @@ # src/egl/drivers/xdri/Makefile -# Build XEGL DRI driver loader library: egl_xdri.so - - TOP = ../../../.. include $(TOP)/configs/current +EGL_DRIVER = egl_xdri.so -DRIVER_NAME = egl_xdri.so - - -INCLUDE_DIRS = \ - -I. \ - -I/usr/include \ +# steal sources from GLX +GLX_SOURCES = dri_common.c XF86dri.c dri2.c dri2_glx.c dri_glx.c drisw_glx.c +GLX_SOURCES := $(addprefix ../../../glx/x11/,$(GLX_SOURCES)) +GLX_INCLUDES = \ $(shell pkg-config --cflags-only-I libdrm) \ - -I$(TOP)/include \ -I$(TOP)/include/GL/internal \ - -I$(TOP)/src/mesa \ + -I$(TOP)/src/glx/x11 \ -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 + -I$(TOP)/src/mesa +GLX_CFLAGS = -DGLX_DIRECT_RENDERING +EGL_SOURCES = egl_xdri.c glxinit.c driinit.c $(GLX_SOURCES) +EGL_INCLUDES = \ + -I$(TOP)/include \ + -I$(TOP)/src/egl/main \ + $(GLX_INCLUDES) -depend: $(SOURCES) $(HEADERS) - @ echo "running $(MKDEP)" - @ rm -f depend - @ touch depend - $(MKDEP) $(MKDEP_OPTIONS) $(DEFINES) $(INCLUDE_DIRS) \ - $(SOURCES) $(HEADERS) >/dev/null 2>/dev/null +EGL_CFLAGS = $(GLX_CFLAGS) +EGL_LIBS = -lX11 -lGL -include depend -# DO NOT DELETE +include ../Makefile.template diff --git a/src/egl/drivers/xdri/driinit.c b/src/egl/drivers/xdri/driinit.c index 12da1bcd24..3e54f0bd4d 100644 --- a/src/egl/drivers/xdri/driinit.c +++ b/src/egl/drivers/xdri/driinit.c @@ -2,6 +2,7 @@ * DRI initialization. The DRI loaders are defined in src/glx/x11/. */ +#include <stdlib.h> #include <sys/time.h> #include "glxclient.h" @@ -42,18 +43,26 @@ __glXEnableDirectExtension(__GLXscreenConfigs * psc, const char *name) _X_HIDDEN __GLXDRIdisplay * __driCreateDisplay(__GLXdisplayPrivate *dpyPriv, int *version) { - __GLXDRIdisplay *driDisplay; + __GLXDRIdisplay *driDisplay = NULL; int ver = 0; + char *env; + int force_sw; + + env = getenv("EGL_SOFTWARE"); + force_sw = (env && *env != '0'); /* try DRI2 first */ - driDisplay = dri2CreateDisplay(dpyPriv->dpy); - if (driDisplay) { - /* fill in the required field */ - dpyPriv->dri2Display = driDisplay; - ver = 2; + if (!force_sw) { + driDisplay = dri2CreateDisplay(dpyPriv->dpy); + if (driDisplay) { + /* fill in the required field */ + dpyPriv->dri2Display = driDisplay; + ver = 2; + } } - else { - /* try DRI */ + + /* and then DRI */ + if (!force_sw && !driDisplay) { driDisplay = driCreateDisplay(dpyPriv->dpy); if (driDisplay) { dpyPriv->driDisplay = driDisplay; @@ -61,6 +70,15 @@ __driCreateDisplay(__GLXdisplayPrivate *dpyPriv, int *version) } } + /* and then DRISW */ + if (!driDisplay) { + driDisplay = driswCreateDisplay(dpyPriv->dpy); + if (driDisplay) { + dpyPriv->driDisplay = driDisplay; + ver = 0; + } + } + if (version) *version = ver; return driDisplay; diff --git a/src/egl/drivers/xdri/egl_xdri.c b/src/egl/drivers/xdri/egl_xdri.c index 8425b3d11e..2ca9ea8a5b 100644 --- a/src/egl/drivers/xdri/egl_xdri.c +++ b/src/egl/drivers/xdri/egl_xdri.c @@ -62,6 +62,7 @@ struct xdri_egl_driver { _EGLDriver Base; /**< base class */ + void (*FlushCurrentContext)(void); }; @@ -71,6 +72,7 @@ struct xdri_egl_display Display *dpy; __GLXdisplayPrivate *dpyPriv; __GLXDRIdisplay *driDisplay; + int driVersion; __GLXscreenConfigs *psc; EGLint scr; @@ -167,14 +169,10 @@ get_drawable_size(Display *dpy, Drawable d, uint *width, uint *height) static EGLBoolean convert_config(_EGLConfig *conf, EGLint id, const __GLcontextModes *m) { - static const EGLint all_apis = (EGL_OPENGL_ES_BIT | - EGL_OPENGL_ES2_BIT | - EGL_OPENVG_BIT | - EGL_OPENGL_BIT); EGLint val; _eglInitConfig(conf, id); - if (!_eglConfigFromContextModesRec(conf, m, all_apis, all_apis)) + if (!_eglConfigFromContextModesRec(conf, m, EGL_OPENGL_BIT, EGL_OPENGL_BIT)) return EGL_FALSE; if (m->doubleBufferMode) { @@ -215,6 +213,7 @@ convert_config(_EGLConfig *conf, EGLint id, const __GLcontextModes *m) static EGLint create_configs(_EGLDisplay *disp, const __GLcontextModes *m, EGLint first_id) { + struct xdri_egl_display *xdri_dpy = lookup_display(disp); int id = first_id; for (; m; m = m->next) { @@ -224,8 +223,15 @@ create_configs(_EGLDisplay *disp, const __GLcontextModes *m, EGLint first_id) if (!convert_config(&conf, id, m)) continue; - - rb = (m->doubleBufferMode) ? EGL_BACK_BUFFER : EGL_SINGLE_BUFFER; + if (m->doubleBufferMode) { + rb = EGL_BACK_BUFFER; + } + else { + /* ignore single-buffered mode for DRISW */ + if (xdri_dpy->driVersion == 0) + continue; + rb = EGL_SINGLE_BUFFER; + } xdri_conf = CALLOC_STRUCT(xdri_egl_config); if (xdri_conf) { @@ -275,7 +281,7 @@ xdri_eglInitialize(_EGLDriver *drv, _EGLDisplay *dpy, return _eglError(EGL_NOT_INITIALIZED, "eglInitialize"); } - driDisplay = __driCreateDisplay(dpyPriv, NULL); + driDisplay = __driCreateDisplay(dpyPriv, &xdri_dpy->driVersion); if (!driDisplay) { _eglLog(_EGL_WARNING, "failed to create DRI display"); free(xdri_dpy); @@ -297,16 +303,13 @@ xdri_eglInitialize(_EGLDriver *drv, _EGLDisplay *dpy, return _eglError(EGL_NOT_INITIALIZED, "eglInitialize"); } + dpy->DriverData = xdri_dpy; + dpy->ClientAPIsMask = EGL_OPENGL_BIT; + /* 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); - /* we're supporting EGL 1.4 */ *minor = 1; *major = 4; @@ -342,7 +345,6 @@ xdri_eglTerminate(_EGLDriver *drv, _EGLDisplay *dpy) } xdri_dpy->driDisplay->destroyDisplay(xdri_dpy->driDisplay); - __glXRelease(xdri_dpy->dpyPriv); free(xdri_dpy); dpy->DriverData = NULL; @@ -417,19 +419,47 @@ xdri_eglCreateContext(_EGLDriver *drv, _EGLDisplay *dpy, _EGLConfig *conf, } -static EGLBoolean -xdri_eglDestroyContext(_EGLDriver *drv, _EGLDisplay *dpy, _EGLContext *ctx) +/** + * Destroy a context. + */ +static void +destroy_context(_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); - } + /* FIXME a context might live longer than its display */ + if (!dpy->Initialized) + _eglLog(_EGL_FATAL, "destroy a context with an unitialized display"); + xdri_ctx->driContext->destroyContext(xdri_ctx->driContext, + xdri_dpy->psc, xdri_dpy->dpy); + free(xdri_ctx->dummy_gc); + free(xdri_ctx); +} + + +/** + * Destroy a surface. + */ +static void +destroy_surface(_EGLDisplay *dpy, _EGLSurface *surf) +{ + struct xdri_egl_surface *xdri_surf = lookup_surface(surf); + + if (!dpy->Initialized) + _eglLog(_EGL_FATAL, "destroy a surface with an unitialized display"); + + xdri_surf->driDrawable->destroyDrawable(xdri_surf->driDrawable); + free(xdri_surf); +} + + +static EGLBoolean +xdri_eglDestroyContext(_EGLDriver *drv, _EGLDisplay *dpy, _EGLContext *ctx) +{ + if (!_eglIsContextBound(ctx)) + destroy_context(dpy, ctx); return EGL_TRUE; } @@ -441,13 +471,19 @@ 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); - if (!_eglMakeCurrent(drv, dpy, d, r, context)) + /* bind the new context and return the "orphaned" one */ + if (!_eglBindContext(&context, &d, &r)) return EGL_FALSE; + /* flush before context switch */ + if (context && xdri_driver->FlushCurrentContext) + xdri_driver->FlushCurrentContext(); + /* the symbol is defined in libGL.so */ _glapi_check_multithread(); @@ -458,14 +494,18 @@ xdri_eglMakeCurrent(_EGLDriver *drv, _EGLDisplay *dpy, _EGLSurface *d, return EGL_FALSE; } } - else { - _EGLContext *old = _eglGetCurrentContext(); - if (old) { - xdri_ctx = lookup_context(old); - xdri_ctx->driContext->unbindContext(xdri_ctx->driContext); - } + else if (context) { + xdri_ctx = lookup_context(context); + xdri_ctx->driContext->unbindContext(xdri_ctx->driContext); } + if (context && !_eglIsContextLinked(context)) + destroy_context(dpy, context); + if (d && !_eglIsSurfaceLinked(d)) + destroy_surface(dpy, d); + if (r && r != d && !_eglIsSurfaceLinked(r)) + destroy_surface(dpy, r); + return EGL_TRUE; } @@ -475,7 +515,8 @@ xdri_eglMakeCurrent(_EGLDriver *drv, _EGLDisplay *dpy, _EGLSurface *d, */ static _EGLSurface * xdri_eglCreateWindowSurface(_EGLDriver *drv, _EGLDisplay *dpy, _EGLConfig *conf, - NativeWindowType window, const EGLint *attrib_list) + EGLNativeWindowType window, + const EGLint *attrib_list) { struct xdri_egl_display *xdri_dpy = lookup_display(dpy); struct xdri_egl_config *xdri_config = lookup_config(conf); @@ -529,13 +570,8 @@ xdri_eglCreatePbufferSurface(_EGLDriver *drv, _EGLDisplay *dpy, _EGLConfig *conf 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); - } - + if (!_eglIsSurfaceBound(surface)) + destroy_surface(dpy, surface); return EGL_TRUE; } @@ -559,9 +595,14 @@ xdri_eglReleaseTexImage(_EGLDriver *drv, _EGLDisplay *dpy, _EGLSurface *surf, 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->Binding && xdri_driver->FlushCurrentContext) + xdri_driver->FlushCurrentContext(); + xdri_dpy->psc->driScreen->swapBuffers(xdri_surf->driDrawable, 0, 0, 0); return EGL_TRUE; @@ -606,5 +647,9 @@ _eglMain(const char *args) 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(&xdri_drv->Base, "glFlush"); + return &xdri_drv->Base; } diff --git a/src/egl/drivers/xdri/glxinit.c b/src/egl/drivers/xdri/glxinit.c index 7775009394..ba6132788a 100644 --- a/src/egl/drivers/xdri/glxinit.c +++ b/src/egl/drivers/xdri/glxinit.c @@ -1,8 +1,10 @@ /** * 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. + * glcontextmodes.c under src/glx/x11/. The major difference is that DRI + * related code is stripped out. * + * If the maintenance of this file takes too much time, we should consider + * refactoring glxext.c. */ #include <assert.h> @@ -31,8 +33,26 @@ typedef struct GLXGenericGetString static char *__glXExtensionName = GLX_EXTENSION_NAME; static XExtensionInfo *__glXExtensionInfo = NULL; -static /* const */ XExtensionHooks __glXExtensionHooks = { NULL }; -static +static int +__glXCloseDisplay(Display * dpy, XExtCodes * codes) +{ + return XextRemoveDisplay(__glXExtensionInfo, dpy); +} + +static /* const */ XExtensionHooks __glXExtensionHooks = { + NULL, /* create_gc */ + NULL, /* copy_gc */ + NULL, /* flush_gc */ + NULL, /* free_gc */ + NULL, /* create_font */ + NULL, /* free_font */ + __glXCloseDisplay, /* close_display */ + NULL, /* wire_to_event */ + NULL, /* event_to_wire */ + NULL, /* error */ + NULL, /* error_string */ +}; + XEXT_GENERATE_FIND_DISPLAY(__glXFindDisplay, __glXExtensionInfo, __glXExtensionName, &__glXExtensionHooks, __GLX_NUMBER_EVENTS, NULL) @@ -180,6 +200,30 @@ FreeScreenConfigs(__GLXdisplayPrivate * priv) priv->screenConfigs = NULL; } +/* +** Release the private memory referred to in a display private +** structure. The caller will free the extension structure. +*/ +static int +__glXFreeDisplayPrivate(XExtData * extension) +{ + __GLXdisplayPrivate *priv; + + priv = (__GLXdisplayPrivate *) extension->private_data; + FreeScreenConfigs(priv); + if (priv->serverGLXvendor) { + Xfree((char *) priv->serverGLXvendor); + priv->serverGLXvendor = 0x0; /* to protect against double free's */ + } + if (priv->serverGLXversion) { + Xfree((char *) priv->serverGLXversion); + priv->serverGLXversion = 0x0; /* to protect against double free's */ + } + + Xfree((char *) priv); + return 0; +} + /************************************************************************/ /* @@ -570,40 +614,40 @@ AllocAndFetchScreenConfigs(Display * dpy, __GLXdisplayPrivate * priv) 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); + XExtData **privList, *private, *found; __GLXdisplayPrivate *dpyPriv; + XEDataObject dataObj; int major, minor; if (!XextHasExtension(info)) return NULL; + /* See if a display private already exists. If so, return it */ + dataObj.display = dpy; + privList = XEHeadOfExtensionList(dataObj); + found = XFindOnExtensionList(privList, info->codes->extension); + if (found) + return (__GLXdisplayPrivate *) found->private_data; + /* See if the versions are compatible */ if (!QueryVersion(dpy, info->codes->major_opcode, &major, &minor)) return NULL; + /* + ** Allocate memory for all the pieces needed for this buffer. + */ + private = (XExtData *) Xmalloc(sizeof(XExtData)); + if (!private) + return NULL; dpyPriv = (__GLXdisplayPrivate *) Xcalloc(1, sizeof(__GLXdisplayPrivate)); - if (!dpyPriv) + if (!dpyPriv) { + Xfree(private); return NULL; + } /* ** Init the display private and then read in the screen config @@ -619,8 +663,20 @@ __glXInitialize(Display * dpy) if (!AllocAndFetchScreenConfigs(dpy, dpyPriv)) { Xfree(dpyPriv); + Xfree(private); return NULL; } + /* + ** Fill in the private structure. This is the actual structure that + ** hangs off of the Display structure. Our private structure is + ** referred to by this structure. Got that? + */ + private->number = info->codes->extension; + private->next = 0; + private->free_private = __glXFreeDisplayPrivate; + private->private_data = (char *) dpyPriv; + XAddToExtensionList(privList, private); + return dpyPriv; } diff --git a/src/egl/drivers/xdri/glxinit.h b/src/egl/drivers/xdri/glxinit.h index 57206e627b..1cc7c460fe 100644 --- a/src/egl/drivers/xdri/glxinit.h +++ b/src/egl/drivers/xdri/glxinit.h @@ -8,7 +8,4 @@ extern void _gl_context_modes_destroy(__GLcontextModes * modes); -extern void -__glXRelease(__GLXdisplayPrivate *dpyPriv); - #endif /* GLXINIT_INCLUDED */ |