From 58ac57c2b7b40b64df2a867d4b9d4e5c5bc13c47 Mon Sep 17 00:00:00 2001 From: Chia-I Wu Date: Sun, 16 Aug 2009 08:51:58 +0800 Subject: egl_xdri: Revive the driver. egl_xdri does not compile for some time. This commit revives the driver. It no longer depends on libGL.so for GLX related functions. Instead, it uses code from src/glx/ directly. Both DRI and DRI2 are supported. Signed-off-by: Chia-I Wu --- src/egl/drivers/xdri/Makefile | 15 +- src/egl/drivers/xdri/driinit.c | 67 +++ src/egl/drivers/xdri/driinit.h | 9 + src/egl/drivers/xdri/egl_xdri.c | 1054 +++++++++------------------------------ src/egl/drivers/xdri/glxinit.c | 626 +++++++++++++++++++++++ src/egl/drivers/xdri/glxinit.h | 14 + 6 files changed, 953 insertions(+), 832 deletions(-) create mode 100644 src/egl/drivers/xdri/driinit.c create mode 100644 src/egl/drivers/xdri/driinit.h create mode 100644 src/egl/drivers/xdri/glxinit.c create mode 100644 src/egl/drivers/xdri/glxinit.h diff --git a/src/egl/drivers/xdri/Makefile b/src/egl/drivers/xdri/Makefile index 8a14027fc7..4c1fc9071c 100644 --- a/src/egl/drivers/xdri/Makefile +++ b/src/egl/drivers/xdri/Makefile @@ -16,19 +16,24 @@ INCLUDE_DIRS = \ $(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/mesa/drivers/dri/common \ -I$(TOP)/src/egl/main \ -I$(TOP)/src/glx/x11 -SOURCES = egl_xdri.c +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` -MISC_LIBS = -ldl -lXext -lGL - +CFLAGS += -DGLX_DIRECT_RENDERING .c.o: $(CC) -c $(INCLUDE_DIRS) $(CFLAGS) $< -o $@ @@ -50,7 +55,7 @@ $(TOP)/$(LIB_DIR)/$(DRIVER_NAME): $(OBJECTS) -major 1 -minor 0 \ -L$(TOP)/$(LIB_DIR) \ -install $(TOP)/$(LIB_DIR) \ - $(OBJECTS) $(DRM_LIB) $(MISC_LIBS) + $(OBJECTS) $(DRM_LIB) $(GL_LIB_DEPS) install: $(INSTALL) -d $(DESTDIR)$(INSTALL_LIB_DIR) 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 + +#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 index d8d29fcef4..518091a2d1 100644 --- a/src/egl/drivers/xdri/egl_xdri.c +++ b/src/egl/drivers/xdri/egl_xdri.c @@ -39,63 +39,40 @@ * Authors: Brian Paul */ - #include -#include -#include -#include -#include -#include "dlfcn.h" +#include #include -#include -#include "xf86dri.h" -#include "glxclient.h" -#include "dri_util.h" -#include "drm_sarea.h" -#define _EGL_PLATFORM_X +#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 "eglhash.h" #include "egllog.h" #include "eglsurface.h" -#include - -typedef void (*glGetIntegerv_t)(GLenum, GLint *); -typedef void (*glBindTexture_t)(GLenum, GLuint); -typedef void (*glCopyTexImage2D_t)(GLenum, GLint, GLenum, GLint, GLint, - GLint, GLint, GLint); - - #define CALLOC_STRUCT(T) (struct T *) calloc(1, sizeof(struct T)) - /** subclass of _EGLDriver */ struct xdri_egl_driver { _EGLDriver Base; /**< base class */ - - const char *dri_driver_name; /**< name of DRI driver to load */ - void *dri_driver_handle; /**< returned by dlopen(dri_driver_name) */ - - __GLXdisplayPrivate *glx_priv; +}; - /* XXX we're not actually using these at this time: */ - int chipset; - int minor; - int drmFD; +/** driver data of _EGLDisplay */ +struct xdri_egl_display +{ + Display *dpy; + __GLXdisplayPrivate *dpyPriv; + __GLXDRIdisplay *driDisplay; - __DRIframebuffer framebuffer; - drm_handle_t hSAREA; - drmAddress pSAREA; - char *busID; - drm_magic_t magic; + __GLXscreenConfigs *psc; + EGLint scr; }; @@ -104,9 +81,10 @@ struct xdri_egl_context { _EGLContext Base; /**< base class */ - __DRIcontext driContext; + /* just enough info to create dri contexts */ + GLXContext dummy_gc; - GLint bound_tex_object; + __GLXDRIcontext *driContext; }; @@ -115,8 +93,8 @@ struct xdri_egl_surface { _EGLSurface Base; /**< base class */ - __DRIid driDrawable; /**< DRI surface */ - drm_drawable_t hDrawable; + Drawable drawable; + __GLXDRIdrawable *driDrawable; }; @@ -131,46 +109,44 @@ struct xdri_egl_config /** cast wrapper */ -static struct xdri_egl_driver * +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 struct xdri_egl_surface * -lookup_surface(EGLSurface surf) +static INLINE struct xdri_egl_surface * +lookup_surface(_EGLSurface *surface) { - _EGLSurface *surface = _eglLookupSurface(surf); return (struct xdri_egl_surface *) surface; } /** Map EGLContext handle to xdri_egl_context object */ -static struct xdri_egl_context * -lookup_context(EGLContext c) +static INLINE struct xdri_egl_context * +lookup_context(_EGLContext *context) { - _EGLContext *context = _eglLookupContext(c); return (struct xdri_egl_context *) context; } -static struct xdri_egl_context * -current_context(void) -{ - return (struct xdri_egl_context *) _eglGetCurrentContext(); -} /** Map EGLConfig handle to xdri_egl_config object */ -static struct xdri_egl_config * -lookup_config(_EGLDriver *drv, EGLDisplay dpy, EGLConfig config) +static INLINE struct xdri_egl_config * +lookup_config(_EGLConfig *conf) { - _EGLConfig *conf = _eglLookupConfig(drv, dpy, config); return (struct xdri_egl_config *) conf; } - /** Get size of given window */ static Status get_drawable_size(Display *dpy, Drawable d, uint *width, uint *height) @@ -188,22 +164,18 @@ get_drawable_size(Display *dpy, Drawable d, uint *width, uint *height) /** * Produce a set of EGL configs. - * Note that we get the list of GLcontextModes from the GLX library. - * This dependency on GLX lib will be removed someday. */ -static void -create_configs(_EGLDisplay *disp, __GLXdisplayPrivate *glx_priv) +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); - __GLXscreenConfigs *scrn = glx_priv->screenConfigs; - const __GLcontextModes *m; - int id = 1; + int id = first_id; - for (m = scrn->configs; m; m = m->next) { - /* EGL requires double-buffered configs */ + for (; m; m = m->next) { + /* add double buffered visual */ if (m->doubleBufferMode) { struct xdri_egl_config *config = CALLOC_STRUCT(xdri_egl_config); @@ -222,9 +194,7 @@ create_configs(_EGLDisplay *disp, __GLXdisplayPrivate *glx_priv) 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); - /* XXX only window rendering allowed ATM */ - SET_CONFIG_ATTRIB(&config->Base, EGL_SURFACE_TYPE, - (EGL_WINDOW_BIT | EGL_PBUFFER_BIT)); + SET_CONFIG_ATTRIB(&config->Base, EGL_SURFACE_TYPE, EGL_WINDOW_BIT); /* XXX possibly other things to init... */ @@ -234,431 +204,76 @@ create_configs(_EGLDisplay *disp, __GLXdisplayPrivate *glx_priv) _eglAddConfig(disp, &config->Base); } } -} - -/** - * Called via __DRIinterfaceMethods object - */ -static __DRIfuncPtr -dri_get_proc_address(const char * proc_name) -{ - return NULL; -} - - -static void -dri_context_modes_destroy(__GLcontextModes *modes) -{ - _eglLog(_EGL_DEBUG, "%s", __FUNCTION__); - - while (modes) { - __GLcontextModes * const next = modes->next; - free(modes); - modes = next; - } + return id; } /** - * Create a linked list of 'count' GLcontextModes. - * These are used during the client/server visual negotiation phase, - * then discarded. + * Called via eglInitialize(), xdri_dpy->API.Initialize(). */ -static __GLcontextModes * -dri_context_modes_create(unsigned count, size_t minimum_size) -{ - /* This code copied from libGLX, and modified */ - const size_t size = (minimum_size > sizeof(__GLcontextModes)) - ? minimum_size : sizeof(__GLcontextModes); - __GLcontextModes * head = NULL; - __GLcontextModes ** next; - unsigned i; - - next = & head; - for (i = 0 ; i < count ; i++) { - *next = (__GLcontextModes *) calloc(1, size); - if (*next == NULL) { - dri_context_modes_destroy(head); - head = NULL; - break; - } - - (*next)->doubleBufferMode = 1; - (*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 = 0; - (*next)->yInverted = GLX_DONT_CARE; - - next = & ((*next)->next); - } - - return head; -} - - -static __DRIscreen * -dri_find_dri_screen(__DRInativeDisplay *ndpy, int scrn) -{ - __GLXdisplayPrivate *priv = __glXInitialize(ndpy); - __GLXscreenConfigs *scrnConf = priv->screenConfigs; - return &scrnConf->driScreen; -} - - -static GLboolean -dri_window_exists(__DRInativeDisplay *ndpy, __DRIid draw) -{ - return EGL_TRUE; -} - - -static GLboolean -dri_create_context(__DRInativeDisplay *ndpy, int screenNum, int configID, - void * contextID, drm_context_t * hw_context) -{ - assert(configID >= 0); - return XF86DRICreateContextWithConfig(ndpy, screenNum, - configID, contextID, hw_context); -} - - -static GLboolean -dri_destroy_context(__DRInativeDisplay * ndpy, int screen, __DRIid context) -{ - return XF86DRIDestroyContext(ndpy, screen, context); -} - - -static GLboolean -dri_create_drawable(__DRInativeDisplay * ndpy, int screen, - __DRIid drawable, drm_drawable_t * hHWDrawable) -{ - _eglLog(_EGL_DEBUG, "XDRI: %s", __FUNCTION__); - - /* Create DRI drawable for given window ID (drawable) */ - if (!XF86DRICreateDrawable(ndpy, screen, drawable, hHWDrawable)) - return EGL_FALSE; - - return EGL_TRUE; -} - - -static GLboolean -dri_destroy_drawable(__DRInativeDisplay * ndpy, int screen, __DRIid drawable) -{ - _eglLog(_EGL_DEBUG, "XDRI: %s", __FUNCTION__); - return XF86DRIDestroyDrawable(ndpy, screen, drawable); -} - - -static GLboolean -dri_get_drawable_info(__DRInativeDisplay *ndpy, int scrn, - __DRIid draw, unsigned int * index, unsigned int * stamp, - int * x, int * y, int * width, int * height, - int * numClipRects, drm_clip_rect_t ** pClipRects, - int * backX, int * backY, - int * numBackClipRects, - drm_clip_rect_t ** pBackClipRects) -{ - _eglLog(_EGL_DEBUG, "XDRI: %s", __FUNCTION__); - - if (!XF86DRIGetDrawableInfo(ndpy, scrn, draw, index, stamp, - x, y, width, height, - numClipRects, pClipRects, - backX, backY, - numBackClipRects, pBackClipRects)) { - return EGL_FALSE; - } - - return EGL_TRUE; -} - - -/** - * Table of functions exported by the loader to the driver. - */ -static const __DRIinterfaceMethods interface_methods = { - dri_get_proc_address, - - dri_context_modes_create, - dri_context_modes_destroy, - - dri_find_dri_screen, - dri_window_exists, - - dri_create_context, - dri_destroy_context, - - dri_create_drawable, - dri_destroy_drawable, - dri_get_drawable_info, - - NULL,/*__eglGetUST,*/ - NULL,/*__eglGetMSCRate,*/ -}; - - - static EGLBoolean -init_drm(struct xdri_egl_driver *xdri_drv, _EGLDisplay *disp) +xdri_eglInitialize(_EGLDriver *drv, _EGLDisplay *dpy, + EGLint *minor, EGLint *major) { - __DRIversion ddx_version; - __DRIversion dri_version; - __DRIversion drm_version; - drmVersionPtr version; - drm_handle_t hFB; - int newlyopened; - int status; - int scrn = DefaultScreen(disp->Xdpy); - -#if 0 - createNewScreen = (PFNCREATENEWSCREENFUNC) - dlsym(xdri_drv->dri_driver_handle, createNewScreenName); - if (!createNewScreen) { - _eglLog(_EGL_WARNING, "XDRI: Couldn't find %s function in the driver.", - createNewScreenName); - return EGL_FALSE; - } - else { - _eglLog(_EGL_DEBUG, "XDRI: Found %s", createNewScreenName); - } -#endif - - /* - * Get the DRI X extension version. - */ - dri_version.major = 4; - dri_version.minor = 0; - dri_version.patch = 0; - - if (!XF86DRIOpenConnection(disp->Xdpy, scrn, - &xdri_drv->hSAREA, &xdri_drv->busID)) { - _eglLog(_EGL_WARNING, "XF86DRIOpenConnection failed"); - } - - xdri_drv->drmFD = drmOpenOnce(NULL, xdri_drv->busID, &newlyopened); - if (xdri_drv->drmFD < 0) { - perror("drmOpenOnce failed: "); - return EGL_FALSE; - } - else { - _eglLog(_EGL_DEBUG, "XDRI: drmOpenOnce returned %d", xdri_drv->drmFD); - } - - - if (drmGetMagic(xdri_drv->drmFD, &xdri_drv->magic)) { - perror("drmGetMagic failed: "); - return EGL_FALSE; - } - - version = drmGetVersion(xdri_drv->drmFD); - if (version) { - drm_version.major = version->version_major; - drm_version.minor = version->version_minor; - drm_version.patch = version->version_patchlevel; - drmFreeVersion(version); - _eglLog(_EGL_DEBUG, "XDRI: Got DRM version %d.%d.%d", - drm_version.major, - drm_version.minor, - drm_version.patch); - } - else { - drm_version.major = -1; - drm_version.minor = -1; - drm_version.patch = -1; - _eglLog(_EGL_WARNING, "XDRI: drmGetVersion() failed"); - return EGL_FALSE; - } - - /* Authenticate w/ server. - */ - if (!XF86DRIAuthConnection(disp->Xdpy, scrn, xdri_drv->magic)) { - _eglLog(_EGL_WARNING, "XDRI: XF86DRIAuthConnection() failed"); - return EGL_FALSE; - } - else { - _eglLog(_EGL_DEBUG, "XDRI: XF86DRIAuthConnection() success"); - } - - /* Get ddx version. - */ - { - char *driverName; - - /* - * Get device name (like "tdfx") and the ddx version - * numbers. We'll check the version in each DRI driver's - * "createNewScreen" function. - */ - if (!XF86DRIGetClientDriverName(disp->Xdpy, scrn, - &ddx_version.major, - &ddx_version.minor, - &ddx_version.patch, - &driverName)) { - _eglLog(_EGL_WARNING, "XDRI: XF86DRIGetClientDriverName failed"); - return EGL_FALSE; - } - else { - _eglLog(_EGL_DEBUG, "XDRI: XF86DRIGetClientDriverName returned %s", driverName); - } - } - - /* Get framebuffer info. - */ - { - int junk; - if (!XF86DRIGetDeviceInfo(disp->Xdpy, scrn, - &hFB, - &junk, - &xdri_drv->framebuffer.size, - &xdri_drv->framebuffer.stride, - &xdri_drv->framebuffer.dev_priv_size, - &xdri_drv->framebuffer.dev_priv)) { - _eglLog(_EGL_WARNING, "XDRI: XF86DRIGetDeviceInfo() failed"); - return EGL_FALSE; + 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"); } - else { - _eglLog(_EGL_DEBUG, "XDRI: XF86DRIGetDeviceInfo() success"); - } - xdri_drv->framebuffer.width = DisplayWidth(disp->Xdpy, scrn); - xdri_drv->framebuffer.height = DisplayHeight(disp->Xdpy, scrn); - } - - /* Map the framebuffer region. (this may not be needed) - */ - status = drmMap(xdri_drv->drmFD, hFB, xdri_drv->framebuffer.size, - (drmAddressPtr) &xdri_drv->framebuffer.base); - if (status != 0) { - _eglLog(_EGL_WARNING, "XDRI: drmMap(framebuffer) failed"); - return EGL_FALSE; - } - else { - _eglLog(_EGL_DEBUG, "XDRI: drmMap(framebuffer) success"); } - /* Map the SAREA region. - */ - status = drmMap(xdri_drv->drmFD, xdri_drv->hSAREA, SAREA_MAX, &xdri_drv->pSAREA); - if (status != 0) { - _eglLog(_EGL_WARNING, "XDRI: drmMap(sarea) failed"); - return EGL_FALSE; - } - else { - _eglLog(_EGL_DEBUG, "XDRI: drmMap(sarea) success"); - } - - return EGL_TRUE; -} - - -/** - * Load the DRI driver named by "xdri_drv->dri_driver_name". - * Basically, dlopen() the library to set "xdri_drv->dri_driver_handle". - * - * Later, we'll call dlsym(createNewScreenName) to get a pointer to - * the driver's createNewScreen() function which is the bootstrap function. - * - * \return EGL_TRUE for success, EGL_FALSE for failure - */ -static EGLBoolean -load_dri_driver(struct xdri_egl_driver *xdri_drv) -{ - char filename[100]; - int flags = RTLD_NOW; - - /* try "egl_xxx_dri.so" first */ - snprintf(filename, sizeof(filename), "egl_%s.so", xdri_drv->dri_driver_name); - _eglLog(_EGL_DEBUG, "XDRI: dlopen(%s)", filename); - xdri_drv->dri_driver_handle = dlopen(filename, flags); - if (xdri_drv->dri_driver_handle) { - _eglLog(_EGL_DEBUG, "XDRI: dlopen(%s) OK", filename); - return EGL_TRUE; - } - else { - _eglLog(_EGL_DEBUG, "XDRI: dlopen(%s) fail (%s)", filename, dlerror()); + dpyPriv = __glXInitialize(xdri_dpy->dpy); + if (!dpyPriv) { + _eglLog(_EGL_WARNING, "failed to create GLX display"); + free(xdri_dpy); + return _eglError(EGL_NOT_INITIALIZED, "eglInitialize"); } - /* try regular "xxx_dri.so" next */ - snprintf(filename, sizeof(filename), "%s.so", xdri_drv->dri_driver_name); - _eglLog(_EGL_DEBUG, "XDRI: dlopen(%s)", filename); - xdri_drv->dri_driver_handle = dlopen(filename, flags); - if (xdri_drv->dri_driver_handle) { - _eglLog(_EGL_DEBUG, "XDRI: dlopen(%s) OK", filename); - return EGL_TRUE; + driDisplay = __driCreateDisplay(dpyPriv, NULL); + if (!driDisplay) { + _eglLog(_EGL_WARNING, "failed to create DRI display"); + free(xdri_dpy); + return _eglError(EGL_NOT_INITIALIZED, "eglInitialize"); } - _eglLog(_EGL_WARNING, "XDRI Could not open %s (%s)", filename, dlerror()); - return EGL_FALSE; -} - - -/** - * Called via eglInitialize(), xdri_drv->API.Initialize(). - */ -static EGLBoolean -xdri_eglInitialize(_EGLDriver *drv, EGLDisplay dpy, - EGLint *minor, EGLint *major) -{ - struct xdri_egl_driver *xdri_drv = xdri_egl_driver(drv); - _EGLDisplay *disp = _eglLookupDisplay(dpy); - static char name[100]; + scr = DefaultScreen(xdri_dpy->dpy); + psc = &dpyPriv->screenConfigs[scr]; - _eglLog(_EGL_DEBUG, "XDRI: eglInitialize"); + xdri_dpy->dpyPriv = dpyPriv; + xdri_dpy->driDisplay = driDisplay; + xdri_dpy->psc = psc; + xdri_dpy->scr = scr; - if (!disp->Xdpy) { - disp->Xdpy = XOpenDisplay(NULL); - if (!disp->Xdpy) { - _eglLog(_EGL_WARNING, "XDRI: XOpenDisplay failed"); - return EGL_FALSE; - } + 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"); } -#if 0 - /* choose the DRI driver to load */ - xdri_drv->dri_driver_name = _eglChooseDRMDriver(0); - if (!load_dri_driver(xdri_drv)) - return EGL_FALSE; -#else - (void) load_dri_driver; -#endif - -#if 0 - if (!init_drm(xdri_drv, disp)) - return EGL_FALSE; -#else - (void) init_drm; -#endif - - /* - * NOTE: this call to __glXInitialize() bootstraps the whole GLX/DRI - * interface, loads the DRI driver, etc. - * This replaces the load_dri_driver() and init_drm() code above. - */ - xdri_drv->glx_priv = __glXInitialize(disp->Xdpy); - - create_configs(disp, xdri_drv->glx_priv); - - xdri_drv->Base.Initialized = EGL_TRUE; + /* add visuals and fbconfigs */ + first_id = create_configs(dpy, psc->visuals, first_id); + create_configs(dpy, psc->configs, first_id); - if (xdri_drv->dri_driver_name) - snprintf(name, sizeof(name), "X/DRI:%s", xdri_drv->dri_driver_name); - else - snprintf(name, sizeof(name), "X/DRI"); - xdri_drv->Base.Name = name; + 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; @@ -668,57 +283,37 @@ xdri_eglInitialize(_EGLDriver *drv, EGLDisplay dpy, } -/* - * Do some clean-up that normally occurs in XCloseDisplay(). - * We do this here because we're about to unload a dynamic library - * that has added some per-display extension data and callbacks. - * If we don't do this here we'll crash in XCloseDisplay() because it'll - * try to call functions that went away when the driver library was unloaded. - */ -static void -FreeDisplayExt(Display *dpy) -{ - _XExtension *ext, *next; - - for (ext = dpy->ext_procs; ext; ext = next) { - next = ext->next; - if (ext->close_display) { - ext->close_display(dpy, &ext->codes); - ext->close_display = NULL; - } - if (ext->name) - Xfree(ext->name); - Xfree(ext); - } - dpy->ext_procs = NULL; - - _XFreeExtData (dpy->ext_data); - dpy->ext_data = NULL; -} - - /** * Called via eglTerminate(), drv->API.Terminate(). */ static EGLBoolean -xdri_eglTerminate(_EGLDriver *drv, EGLDisplay dpy) +xdri_eglTerminate(_EGLDriver *drv, _EGLDisplay *dpy) { - struct xdri_egl_driver *xdri_drv = xdri_egl_driver(drv); - _EGLDisplay *disp = _eglLookupDisplay(dpy); + struct xdri_egl_display *xdri_dpy = lookup_display(dpy); + __GLXscreenConfigs *psc; - _eglLog(_EGL_DEBUG, "XDRI: eglTerminate"); + _eglReleaseDisplayResources(drv, dpy); + _eglCleanupDisplay(dpy); - _eglLog(_EGL_DEBUG, "XDRI: Closing %s", xdri_drv->dri_driver_name); - - FreeDisplayExt(disp->Xdpy); + 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; + } -#if 0 - /* this causes a segfault for some reason */ - dlclose(xdri_drv->dri_driver_handle); -#endif - xdri_drv->dri_driver_handle = NULL; + xdri_dpy->driDisplay->destroyDisplay(xdri_dpy->driDisplay); + __glXRelease(xdri_dpy->dpyPriv); - free((void*) xdri_drv->dri_driver_name); + free(xdri_dpy); + dpy->DriverData = NULL; return EGL_TRUE; } @@ -730,71 +325,77 @@ xdri_eglTerminate(_EGLDriver *drv, EGLDisplay dpy) static _EGLProc xdri_eglGetProcAddress(const char *procname) { -#if 0 - _EGLDriver *drv = NULL; - - struct xdri_egl_driver *xdri_drv = xdri_egl_driver(drv); - /*_EGLDisplay *disp = _eglLookupDisplay(dpy);*/ - _EGLProc *proc = xdri_drv->driScreen.getProcAddress(procname); - return proc; -#elif 1 - /* 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 (*st_get_proc_addr)(const char *procname); - st_get_proc_addr = dlsym(NULL, "st_get_proc_address"); - if (st_get_proc_addr) { - return st_get_proc_addr(procname); - } - return NULL; -#else - return NULL; -#endif + /* 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 config, - EGLContext share_list, const EGLint *attrib_list) -{ - _EGLDisplay *disp = _eglLookupDisplay(dpy); - struct xdri_egl_config *xdri_config = lookup_config(drv, dpy, config); - void *shared = NULL; +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; - struct xdri_egl_context *xdri_ctx = CALLOC_STRUCT(xdri_egl_context); - if (!xdri_ctx) - return EGL_NO_CONTEXT; + xdri_ctx = CALLOC_STRUCT(xdri_egl_context); + if (!xdri_ctx) { + _eglError(EGL_BAD_ALLOC, "eglCreateContext"); + return NULL; + } - if (!_eglInitContext(drv, &xdri_ctx->Base, &xdri_config->Base, attrib_list)) { + xdri_ctx->dummy_gc = CALLOC_STRUCT(__GLXcontextRec); + if (!xdri_ctx->dummy_gc) { + _eglError(EGL_BAD_ALLOC, "eglCreateContext"); free(xdri_ctx); - return EGL_NO_CONTEXT; + return NULL; } - assert(xdri_config); - - { - struct xdri_egl_driver *xdri_drv = xdri_egl_driver(drv); - __GLXscreenConfigs *scrnConf = xdri_drv->glx_priv->screenConfigs; - xdri_ctx->driContext.private = - scrnConf->driScreen.createNewContext(disp->Xdpy, - xdri_config->mode, renderType, - shared, &xdri_ctx->driContext); + if (!_eglInitContext(drv, &xdri_ctx->Base, &xdri_config->Base, attrib_list)) { + free(xdri_ctx->dummy_gc); + free(xdri_ctx); + return NULL; } - if (!xdri_ctx->driContext.private) { - _eglLog(_EGL_DEBUG, "driScreen.createNewContext failed"); + 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 EGL_NO_CONTEXT; + return NULL; } - xdri_ctx->driContext.mode = xdri_config->mode; + /* fill in the required field */ + xdri_ctx->dummy_gc->driContext = xdri_ctx->driContext; - return _eglLinkContext(&xdri_ctx->Base, &disp); + 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; } @@ -802,25 +403,32 @@ xdri_eglCreateContext(_EGLDriver *drv, EGLDisplay dpy, EGLConfig config, * Called via eglMakeCurrent(), drv->API.MakeCurrent(). */ static EGLBoolean -xdri_eglMakeCurrent(_EGLDriver *drv, EGLDisplay dpy, EGLSurface d, - EGLSurface r, EGLContext context) +xdri_eglMakeCurrent(_EGLDriver *drv, _EGLDisplay *dpy, _EGLSurface *d, + _EGLSurface *r, _EGLContext *context) { - _EGLDisplay *disp = _eglLookupDisplay(dpy); struct xdri_egl_context *xdri_ctx = lookup_context(context); - struct xdri_egl_surface *xdri_draw = lookup_surface(d); - struct xdri_egl_surface *xdri_read = lookup_surface(r); - __DRIid draw = xdri_draw ? xdri_draw->driDrawable : 0; - __DRIid read = xdri_read ? xdri_read->driDrawable : 0; - int scrn = DefaultScreen(disp->Xdpy); + struct xdri_egl_surface *draw = lookup_surface(d); + struct xdri_egl_surface *read = lookup_surface(r); if (!_eglMakeCurrent(drv, dpy, d, r, context)) return EGL_FALSE; + /* the symbol is defined in libGL.so */ + _glapi_check_multithread(); - if (xdri_ctx && - !xdri_ctx->driContext.bindContext(disp->Xdpy, scrn, draw, read, - &xdri_ctx->driContext)) { - return EGL_FALSE; + if (xdri_ctx) { + if (!xdri_ctx->driContext->bindContext(xdri_ctx->driContext, + draw->driDrawable, + read->driDrawable)) { + return EGL_FALSE; + } + } + else { + _EGLContext *old = _eglGetCurrentContext(); + if (old) { + xdri_ctx = lookup_context(old); + xdri_ctx->driContext->unbindContext(xdri_ctx->driContext); + } } return EGL_TRUE; @@ -830,307 +438,106 @@ xdri_eglMakeCurrent(_EGLDriver *drv, EGLDisplay dpy, EGLSurface d, /** * Called via eglCreateWindowSurface(), drv->API.CreateWindowSurface(). */ -static EGLSurface -xdri_eglCreateWindowSurface(_EGLDriver *drv, EGLDisplay dpy, EGLConfig config, +static _EGLSurface * +xdri_eglCreateWindowSurface(_EGLDriver *drv, _EGLDisplay *dpy, _EGLConfig *conf, NativeWindowType window, const EGLint *attrib_list) { - _EGLDisplay *disp = _eglLookupDisplay(dpy); - struct xdri_egl_config *xdri_config = lookup_config(drv, dpy, config); + struct xdri_egl_display *xdri_dpy = lookup_display(dpy); + struct xdri_egl_config *xdri_config = lookup_config(conf); struct xdri_egl_surface *xdri_surf; - int scrn = DefaultScreen(disp->Xdpy); uint width, height; xdri_surf = CALLOC_STRUCT(xdri_egl_surface); - if (!xdri_surf) - return EGL_NO_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 EGL_FALSE; + return NULL; } - if (!XF86DRICreateDrawable(disp->Xdpy, scrn, window, &xdri_surf->hDrawable)) { + 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 EGL_FALSE; + return NULL; } - xdri_surf->driDrawable = window; + xdri_surf->drawable = (Drawable) window; - _eglLinkSurface(&xdri_surf->Base, disp); - - get_drawable_size(disp->Xdpy, window, &width, &height); + get_drawable_size(xdri_dpy->dpy, window, &width, &height); xdri_surf->Base.Width = width; xdri_surf->Base.Height = height; - _eglLog(_EGL_DEBUG, - "XDRI: CreateWindowSurface win 0x%x handle %d hDrawable %d", - (int) window, _eglGetSurfaceHandle(&xdri_surf->Base), - (int) xdri_surf->hDrawable); - - return _eglGetSurfaceHandle(&xdri_surf->Base); + return &xdri_surf->Base; } /** * Called via eglCreatePbufferSurface(), drv->API.CreatePbufferSurface(). */ -static EGLSurface -xdri_eglCreatePbufferSurface(_EGLDriver *drv, EGLDisplay dpy, EGLConfig config, +static _EGLSurface * +xdri_eglCreatePbufferSurface(_EGLDriver *drv, _EGLDisplay *dpy, _EGLConfig *conf, const EGLint *attrib_list) { - _EGLDisplay *disp = _eglLookupDisplay(dpy); - struct xdri_egl_surface *xdri_surf; - struct xdri_egl_config *xdri_config = lookup_config(drv, dpy, config); - int scrn = DefaultScreen(disp->Xdpy); - Window window; - - xdri_surf = CALLOC_STRUCT(xdri_egl_surface); - if (!xdri_surf) - return EGL_NO_SURFACE; - - if (!_eglInitSurface(drv, &xdri_surf->Base, EGL_PBUFFER_BIT, - &xdri_config->Base, attrib_list)) { - free(xdri_surf); - return EGL_FALSE; - } - - /* Create a dummy X window */ - { - Window root = RootWindow(disp->Xdpy, scrn); - XSetWindowAttributes attr; - XVisualInfo *visInfo, visTemplate; - unsigned mask; - int nvis; - - visTemplate.visualid = xdri_config->mode->visualID; - visInfo = XGetVisualInfo(disp->Xdpy, VisualIDMask, &visTemplate, &nvis); - if (!visInfo) { - return EGL_NO_SURFACE; - } - - attr.background_pixel = 0; - attr.border_pixel = 0; - attr.colormap = XCreateColormap(disp->Xdpy, root, - visInfo->visual, AllocNone); - attr.event_mask = StructureNotifyMask | ExposureMask | KeyPressMask; - mask = CWBackPixel | CWBorderPixel | CWColormap | CWEventMask; - - window = XCreateWindow(disp->Xdpy, root, 0, 0, - xdri_surf->Base.Width, xdri_surf->Base.Height, - 0, visInfo->depth, InputOutput, - visInfo->visual, mask, &attr); - - /*XMapWindow(disp->Xdpy, window);*/ - XFree(visInfo); - - /* set hints and properties */ - /* - sizehints.width = xdri_surf->Base.Width; - sizehints.height = xdri_surf->Base.Height; - sizehints.flags = USPosition; - XSetNormalHints(disp->Xdpy, window, &sizehints); - */ - } - - if (!XF86DRICreateDrawable(disp->Xdpy, scrn, window, &xdri_surf->hDrawable)) { - free(xdri_surf); - return EGL_FALSE; - } - - xdri_surf->driDrawable = window; - - _eglLinkSurface(&xdri_surf->Base, disp); - - _eglLog(_EGL_DEBUG, - "XDRI: CreatePbufferSurface handle %d hDrawable %d", - _eglGetSurfaceHandle(&xdri_surf->Base), - (int) xdri_surf->hDrawable); - - return _eglGetSurfaceHandle(&xdri_surf->Base); + return NULL; } static EGLBoolean -xdri_eglDestroySurface(_EGLDriver *drv, EGLDisplay dpy, EGLSurface surface) +xdri_eglDestroySurface(_EGLDriver *drv, _EGLDisplay *dpy, _EGLSurface *surface) { struct xdri_egl_surface *xdri_surf = lookup_surface(surface); - if (xdri_surf) { - _eglUnlinkSurface(&xdri_surf->Base); - if (!_eglIsSurfaceBound(&xdri_surf->Base)) { - /* - st_unreference_framebuffer(surf->Framebuffer); - */ - free(xdri_surf); - } - return EGL_TRUE; - } - else { - _eglError(EGL_BAD_SURFACE, "eglDestroySurface"); - return EGL_FALSE; + + 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 surface, +xdri_eglBindTexImage(_EGLDriver *drv, _EGLDisplay *dpy, _EGLSurface *surf, EGLint buffer) { - typedef int (*bind_teximage)(__DRInativeDisplay *dpy, - __DRIid surface, __DRIscreen *psc, - int buffer, int target, int format, - int level, int mipmap); - - bind_teximage egl_dri_bind_teximage; - - _EGLDisplay *disp = _eglLookupDisplay(dpy); - - struct xdri_egl_context *xdri_ctx = current_context(); - struct xdri_egl_driver *xdri_drv = xdri_egl_driver(drv); - struct xdri_egl_surface *xdri_surf = lookup_surface(surface); - - __DRIid dri_surf = xdri_surf ? xdri_surf->driDrawable : 0; - - __GLXscreenConfigs *scrnConf = xdri_drv->glx_priv->screenConfigs; - __DRIscreen *psc = &scrnConf->driScreen; - - /* this call just does error checking */ - if (!_eglBindTexImage(drv, dpy, surface, buffer)) { - return EGL_FALSE; - } - - egl_dri_bind_teximage = - (bind_teximage) dlsym(NULL, "egl_dri_bind_teximage"); - if (egl_dri_bind_teximage) { - return egl_dri_bind_teximage(disp->Xdpy, dri_surf, psc, - buffer, - xdri_surf->Base.TextureTarget, - xdri_surf->Base.TextureFormat, - xdri_surf->Base.MipmapLevel, - xdri_surf->Base.MipmapTexture); - } - else { - /* fallback path based on glCopyTexImage() */ - /* Get/save currently bound 2D texobj name */ - glGetIntegerv_t glGetIntegerv_func = - (glGetIntegerv_t) dlsym(NULL, "glGetIntegerv"); - GLint curTexObj = 0; - if (glGetIntegerv_func) { - (*glGetIntegerv_func)(GL_TEXTURE_BINDING_2D, &curTexObj); - } - xdri_ctx->bound_tex_object = curTexObj; - } - return EGL_FALSE; } static EGLBoolean -xdri_eglReleaseTexImage(_EGLDriver *drv, EGLDisplay dpy, EGLSurface surface, +xdri_eglReleaseTexImage(_EGLDriver *drv, _EGLDisplay *dpy, _EGLSurface *surf, EGLint buffer) { - typedef int (*release_teximage)(__DRInativeDisplay *dpy, - __DRIid surface, __DRIscreen *psc, - int buffer, int target, int format, - int level, int mipmap); - release_teximage egl_dri_release_teximage; - - _EGLDisplay *disp = _eglLookupDisplay(dpy); - - struct xdri_egl_context *xdri_ctx = current_context(); - struct xdri_egl_driver *xdri_drv = xdri_egl_driver(drv); - struct xdri_egl_surface *xdri_surf = lookup_surface(surface); - - __DRIid dri_surf = xdri_surf ? xdri_surf->driDrawable : 0; - - __GLXscreenConfigs *scrnConf = xdri_drv->glx_priv->screenConfigs; - __DRIscreen *psc = &scrnConf->driScreen; - - /* this call just does error checking */ - if (!_eglReleaseTexImage(drv, dpy, surface, buffer)) { - return EGL_FALSE; - } - - egl_dri_release_teximage = - (release_teximage) dlsym(NULL, "egl_dri_release_teximage"); - if (egl_dri_release_teximage) { - return egl_dri_release_teximage(disp->Xdpy, dri_surf, psc, - buffer, - xdri_surf->Base.TextureTarget, - xdri_surf->Base.TextureFormat, - xdri_surf->Base.MipmapLevel, - xdri_surf->Base.MipmapTexture); - } - else { - /* fallback path based on glCopyTexImage() */ - glGetIntegerv_t glGetIntegerv_func = - (glGetIntegerv_t) dlsym(NULL, "glGetIntegerv"); - glBindTexture_t glBindTexture_func = - (glBindTexture_t) dlsym(NULL, "glBindTexture"); - glCopyTexImage2D_t glCopyTexImage2D_func = - (glCopyTexImage2D_t) dlsym(NULL, "glCopyTexImage2D"); - GLint curTexObj; - GLenum intFormat; - GLint level, width, height; - - if (xdri_surf->Base.TextureFormat == EGL_TEXTURE_RGBA) - intFormat = GL_RGBA; - else - intFormat = GL_RGB; - level = xdri_surf->Base.MipmapLevel; - width = xdri_surf->Base.Width >> level; - height = xdri_surf->Base.Height >> level; - - if (width > 0 && height > 0 && - glGetIntegerv_func && glBindTexture_func && glCopyTexImage2D_func) { - glGetIntegerv_func(GL_TEXTURE_BINDING_2D, &curTexObj); - /* restore texobj from time of eglBindTexImage() call */ - if (curTexObj != xdri_ctx->bound_tex_object) - glBindTexture_func(GL_TEXTURE_2D, xdri_ctx->bound_tex_object); - /* copy pbuffer image to texture */ - glCopyTexImage2D_func(GL_TEXTURE_2D, - level, - intFormat, - 0, 0, width, height, 0); - /* restore current texture */ - if (curTexObj != xdri_ctx->bound_tex_object) - glBindTexture_func(GL_TEXTURE_2D, curTexObj); - } - xdri_ctx->bound_tex_object = -1; - } - return EGL_FALSE; } static EGLBoolean -xdri_eglSwapBuffers(_EGLDriver *drv, EGLDisplay dpy, EGLSurface draw) +xdri_eglSwapBuffers(_EGLDriver *drv, _EGLDisplay *dpy, _EGLSurface *draw) { - _EGLDisplay *disp = _eglLookupDisplay(dpy); + struct xdri_egl_display *xdri_dpy = lookup_display(dpy); + struct xdri_egl_surface *xdri_surf = lookup_surface(draw); - _eglLog(_EGL_DEBUG, "XDRI: EGL SwapBuffers"); + xdri_dpy->psc->driScreen->swapBuffers(xdri_surf->driDrawable); - /* error checking step: */ - if (!_eglSwapBuffers(drv, dpy, draw)) - return EGL_FALSE; + return EGL_TRUE; +} - { - struct xdri_egl_surface *xdri_surf = lookup_surface(draw); - struct xdri_egl_driver *xdri_drv = xdri_egl_driver(drv); - __GLXscreenConfigs *scrnConf = xdri_drv->glx_priv->screenConfigs; - __DRIscreen *psc = &scrnConf->driScreen; - __DRIdrawable * const pdraw = psc->getDrawable(disp->Xdpy, - xdri_surf->driDrawable, - psc->private); - - if (pdraw) - pdraw->swapBuffers(disp->Xdpy, pdraw->private); - else - _eglLog(_EGL_WARNING, "pdraw is null in SwapBuffers"); - } - return EGL_TRUE; +static void +xdri_Unload(_EGLDriver *drv) +{ + struct xdri_egl_driver *xdri_drv = xdri_egl_driver(drv); + free(xdri_drv); } @@ -1139,15 +546,12 @@ xdri_eglSwapBuffers(_EGLDriver *drv, EGLDisplay dpy, EGLSurface draw) * Create a new _EGLDriver object and init its dispatch table. */ _EGLDriver * -_eglMain(_EGLDisplay *disp, const char *args) +_eglMain(const char *args) { struct xdri_egl_driver *xdri_drv = CALLOC_STRUCT(xdri_egl_driver); if (!xdri_drv) return NULL; - /* Tell libGL to prefer the EGL drivers over regular DRI drivers */ - __glXPreferEGL(1); - _eglInitDriverFallbacks(&xdri_drv->Base); xdri_drv->Base.API.Initialize = xdri_eglInitialize; xdri_drv->Base.API.Terminate = xdri_eglTerminate; @@ -1155,6 +559,7 @@ _eglMain(_EGLDisplay *disp, const char *args) 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; @@ -1163,13 +568,8 @@ _eglMain(_EGLDisplay *disp, const char *args) xdri_drv->Base.API.ReleaseTexImage = xdri_eglReleaseTexImage; xdri_drv->Base.API.SwapBuffers = xdri_eglSwapBuffers; - xdri_drv->Base.ClientAPIsMask = (EGL_OPENGL_BIT | - EGL_OPENGL_ES_BIT | - EGL_OPENGL_ES2_BIT | - EGL_OPENVG_BIT); xdri_drv->Base.Name = "X/DRI"; - - _eglLog(_EGL_DEBUG, "XDRI: main(%s)", args); + xdri_drv->Base.Unload = xdri_Unload; 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 +#include +#include +#include +#include +#include + +#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 +#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 */ -- cgit v1.2.3