diff options
author | Brian Paul <brian.paul@tungstengraphics.com> | 2008-06-06 15:52:33 -0600 |
---|---|---|
committer | Brian Paul <brian.paul@tungstengraphics.com> | 2008-06-06 15:52:47 -0600 |
commit | 8dafe470fc29cada5f3beab114e2be19fd01dabe (patch) | |
tree | 40b6f41045f8cdd4b1a1994216c74fa8fee18522 /src/egl/drivers | |
parent | ab102d5a9f1db0f76eabbf22cd05b08ff7bb8448 (diff) |
egl: EGL->DRI adaptor/driver
Allows regular DRI drivers to work with libEGL.
Diffstat (limited to 'src/egl/drivers')
-rw-r--r-- | src/egl/drivers/xdri/Makefile | 67 | ||||
-rw-r--r-- | src/egl/drivers/xdri/egl_xdri.c | 833 |
2 files changed, 900 insertions, 0 deletions
diff --git a/src/egl/drivers/xdri/Makefile b/src/egl/drivers/xdri/Makefile new file mode 100644 index 0000000000..477a75184a --- /dev/null +++ b/src/egl/drivers/xdri/Makefile @@ -0,0 +1,67 @@ +# 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 \ + -I/usr/include/drm \ + -I$(TOP)/include \ + -I$(TOP)/include/GL/internal \ + -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 + +OBJECTS = $(SOURCES:.c=.o) + +DRM_LIB = `pkg-config --libs libdrm` + + +.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 \ + -install $(TOP)/$(LIB_DIR) \ + -ldl $(OBJECTS) $(DRM_LIB) + + +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/egl_xdri.c b/src/egl/drivers/xdri/egl_xdri.c new file mode 100644 index 0000000000..4c8511fbbf --- /dev/null +++ b/src/egl/drivers/xdri/egl_xdri.c @@ -0,0 +1,833 @@ +/************************************************************************** + * + * 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 coudl be + * removed with some effort. + * + * Authors: Brian Paul + */ + + +#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 "xf86dri.h" +#include "glxclient.h" +#include "dri_util.h" +#include "drm_sarea.h" + +#define _EGL_PLATFORM_X + +#include "eglconfig.h" +#include "eglcontext.h" +#include "egldisplay.h" +#include "egldriver.h" +#include "eglglobals.h" +#include "eglhash.h" +#include "egllog.h" +#include "eglsurface.h" + + + +#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) */ + + int chipset; + int minor; + int drmFD; + + __DRIscreen driScreen; + __DRIframebuffer framebuffer; + drm_handle_t hSAREA; + drmAddress pSAREA; + char *busID; + drm_magic_t magic; +}; + + +/** subclass of _EGLContext */ +struct xdri_egl_context +{ + _EGLContext Base; /**< base class */ + + __DRIcontext driContext; +}; + + +/** subclass of _EGLSurface */ +struct xdri_egl_surface +{ + _EGLSurface Base; /**< base class */ + + __DRIid driDrawable; /**< DRI surface */ + drm_drawable_t hDrawable; +}; + + +/** subclass of _EGLConfig */ +struct xdri_egl_config +{ + _EGLConfig Base; /**< base class */ + + const __GLcontextModes *mode; /**< corresponding GLX mode */ +}; + + +/** cast wrapper */ +static struct xdri_egl_driver * +xdri_egl_driver(_EGLDriver *drv) +{ + return (struct xdri_egl_driver *) drv; +} + + +/** Map EGLSurface handle to xdri_egl_surface object */ +static struct xdri_egl_surface * +lookup_surface(EGLSurface surf) +{ + _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) +{ + _EGLContext *context = _eglLookupContext(c); + return (struct xdri_egl_context *) context; +} + + +/** Map EGLConfig handle to xdri_egl_config object */ +static struct xdri_egl_config * +lookup_config(_EGLDriver *drv, EGLDisplay dpy, EGLConfig config) +{ + _EGLConfig *conf = _eglLookupConfig(drv, dpy, config); + return (struct xdri_egl_config *) conf; +} + + + +/** + * 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) +{ + const __GLcontextModes *m; + __GLXdisplayPrivate *priv = __glXInitialize(disp->Xdpy); + __GLXscreenConfigs *scrn = priv->screenConfigs; + int id = 1; + + for (m = scrn->configs; m; m = m->next) { + /* EGL requires double-buffered configs */ + 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_NATIVE_VISUAL_ID, m->visualID); + SET_CONFIG_ATTRIB(&config->Base, EGL_NATIVE_VISUAL_TYPE, m->visualType); + /* XXX possibly other things to init... */ + + /* Ptr from EGL config to GLcontextMode. Used in CreateContext(). */ + config->mode = m; + + _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; + } +} + + +/** + * Create a linked list of 'count' GLcontextModes. + * These are used during the client/server visual negotiation phase, + * then discarded. + */ +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) +{ + /* unused? */ + return NULL; +} + + +static GLboolean +dri_window_exists(__DRInativeDisplay *dpy, __DRIid draw) +{ + return EGL_TRUE; +} + + +static GLboolean +dri_create_context(__DRInativeDisplay *dpy, int screenNum, int configID, + void * contextID, drm_context_t * hw_context) +{ + assert(configID >= 0); + return XF86DRICreateContextWithConfig(dpy, 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 *dpy, 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(dpy, 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) +{ + static const char createNewScreenName[] = "__driCreateNewScreen_20050727"; + PFNCREATENEWSCREENFUNC createNewScreen; + int api_ver = 0;/*__glXGetInternalVersion();*/ + __DRIversion ddx_version; + __DRIversion dri_version; + __DRIversion drm_version; + drmVersionPtr version; + drm_handle_t hFB; + int newlyopened; + int status; + __GLcontextModes *modes; + int scrn = DefaultScreen(disp->Xdpy); + + 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); + } + + /* + * 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; + } + 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"); + } + + /* Create the DRI screen. + */ + xdri_drv->driScreen.private = createNewScreen(disp->Xdpy, + scrn, /* screen number */ + &xdri_drv->driScreen, + NULL, /* visuals */ + &ddx_version, + &dri_version, + &drm_version, + &xdri_drv->framebuffer, + xdri_drv->pSAREA, + xdri_drv->drmFD, + api_ver, + &interface_methods, + &modes); + if (!xdri_drv->driScreen.private) { + _eglLog(_EGL_WARNING, "XDRI: create new screen failed"); + return EGL_FALSE; + } + else { + _eglLog(_EGL_DEBUG, "XDRI: create new screen success"); + } + + create_configs(disp); + + /* print modes / debug */ + if (0) { + __GLcontextModes *m; + + for (m = modes; m; m = m->next) { + _eglLog(_EGL_DEBUG, + "mode ID 0x%x rgba %d %d %d %d z %d s %d db %d\n", m->visualID, + m->redBits, m->greenBits, m->blueBits, m->alphaBits, + m->depthBits, m->stencilBits, m->doubleBufferMode); + } + } + + return EGL_TRUE; +} + + +static EGLBoolean +load_dri_driver(struct xdri_egl_driver *xdri_drv) +{ + char filename[100]; + int flags = RTLD_NOW; + + 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_WARNING, "XDRI Could not open %s (%s)", + filename, dlerror()); + + return EGL_FALSE; + } + return EGL_TRUE; +} + + +/** + * 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]; + + _eglLog(_EGL_DEBUG, "XDRI: eglInitialize"); + + if (!disp->Xdpy) { + disp->Xdpy = XOpenDisplay(NULL); + if (!disp->Xdpy) { + _eglLog(_EGL_WARNING, "XDRI: XOpenDisplay failed"); + return EGL_FALSE; + } + } + + /* choose the DRI driver to load */ + xdri_drv->dri_driver_name = _eglChooseDRMDriver(0); + if (!load_dri_driver(xdri_drv)) + return EGL_FALSE; + + if (!init_drm(xdri_drv, disp)) + return EGL_FALSE; + + xdri_drv->Base.Initialized = EGL_TRUE; + + snprintf(name, sizeof(name), "X/DRI:%s", xdri_drv->dri_driver_name); + xdri_drv->Base.Name = name; + + /* 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_driver *xdri_drv = xdri_egl_driver(drv); + + _eglLog(_EGL_DEBUG, "XDRI: eglTerminate"); + + _eglLog(_EGL_DEBUG, "XDRI: Closing %s", xdri_drv->dri_driver_name); + dlclose(xdri_drv->dri_driver_handle); + xdri_drv->dri_driver_handle = NULL; + + free((void*) xdri_drv->dri_driver_name); + + return EGL_TRUE; +} + + +/** + * Called via eglCreateContext(), drv->API.CreateContext(). + */ +static EGLContext +xdri_eglCreateContext(_EGLDriver *drv, EGLDisplay dpy, EGLConfig config, + EGLContext share_list, const EGLint *attrib_list) +{ + struct xdri_egl_driver *xdri_drv = xdri_egl_driver(drv); + _EGLDisplay *disp = _eglLookupDisplay(dpy); + struct xdri_egl_config *xdri_config = lookup_config(drv, dpy, config); + void *shared = NULL; + int renderType = GLX_RGBA_BIT; + + struct xdri_egl_context *xdri_ctx = CALLOC_STRUCT(xdri_egl_context); + if (!xdri_ctx) + return EGL_NO_CONTEXT; + + if (!_eglInitContext(drv, dpy, &xdri_ctx->Base, config, attrib_list)) { + free(xdri_ctx); + return EGL_NO_CONTEXT; + } + + assert(xdri_config); + + xdri_ctx->driContext.private = + xdri_drv->driScreen.createNewContext(disp->Xdpy, + xdri_config->mode, renderType, + shared, &xdri_ctx->driContext); + if (!xdri_ctx->driContext.private) { + free(xdri_ctx); + return EGL_NO_CONTEXT; + } + + xdri_ctx->driContext.mode = xdri_config->mode; + + return _eglGetContextHandle(&xdri_ctx->Base); +} + + +/** + * Called via eglMakeCurrent(), drv->API.MakeCurrent(). + */ +static EGLBoolean +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->driDrawable; + __DRIid read = xdri_read->driDrawable; + int scrn = DefaultScreen(disp->Xdpy); + + if (!_eglMakeCurrent(drv, dpy, d, r, context)) + return EGL_FALSE; + + + if (!xdri_ctx->driContext.bindContext(disp->Xdpy, scrn, draw, read, + &xdri_ctx->driContext)) { + return EGL_FALSE; + } + + return EGL_TRUE; +} + + +/** + * Called via eglCreateWindowSurface(), drv->API.CreateWindowSurface(). + */ +static EGLSurface +xdri_eglCreateWindowSurface(_EGLDriver *drv, EGLDisplay dpy, EGLConfig config, + NativeWindowType window, const EGLint *attrib_list) +{ + _EGLDisplay *disp = _eglLookupDisplay(dpy); + struct xdri_egl_surface *xdri_surf; + int scrn = DefaultScreen(disp->Xdpy); + + xdri_surf = CALLOC_STRUCT(xdri_egl_surface); + if (!xdri_surf) + return EGL_NO_SURFACE; + + if (!_eglInitSurface(drv, dpy, &xdri_surf->Base, EGL_WINDOW_BIT, + config, attrib_list)) { + free(xdri_surf); + return EGL_FALSE; + } + + if (!XF86DRICreateDrawable(disp->Xdpy, scrn, window, &xdri_surf->hDrawable)) { + free(xdri_surf); + return EGL_FALSE; + } + + xdri_surf->driDrawable = window; + + _eglSaveSurface(&xdri_surf->Base); + + _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); +} + + +static EGLBoolean +xdri_eglDestroySurface(_EGLDriver *drv, EGLDisplay dpy, EGLSurface surface) +{ + struct xdri_egl_surface *xdri_surf = lookup_surface(surface); + if (xdri_surf) { + _eglHashRemove(_eglGlobal.Surfaces, (EGLuint) surface); + if (xdri_surf->Base.IsBound) { + xdri_surf->Base.DeletePending = EGL_TRUE; + } + else { + /* + st_unreference_framebuffer(&surf->Framebuffer); + */ + free(xdri_surf); + } + return EGL_TRUE; + } + else { + _eglError(EGL_BAD_SURFACE, "eglDestroySurface"); + return EGL_FALSE; + } +} + + +static EGLBoolean +xdri_eglSwapBuffers(_EGLDriver *drv, EGLDisplay dpy, EGLSurface draw) +{ + _EGLDisplay *disp = _eglLookupDisplay(dpy); + + _eglLog(_EGL_DEBUG, "XDRI: EGL SwapBuffers"); + + /* error checking step: */ + if (!_eglSwapBuffers(drv, dpy, draw)) + return EGL_FALSE; + + { + struct xdri_egl_surface *xdri_surf = lookup_surface(draw); + __GLXdisplayPrivate *priv = __glXInitialize(disp->Xdpy); + __GLXscreenConfigs *scrn = priv->screenConfigs; + __DRIscreen *psc = &scrn->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; +} + + +/** + * This is the main entrypoint into the driver, called by libEGL. + * Create a new _EGLDriver object and init its dispatch table. + */ +_EGLDriver * +_eglMain(_EGLDisplay *disp, 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.CreateContext = xdri_eglCreateContext; + xdri_drv->Base.API.MakeCurrent = xdri_eglMakeCurrent; + xdri_drv->Base.API.CreateWindowSurface = xdri_eglCreateWindowSurface; + xdri_drv->Base.API.DestroySurface = xdri_eglDestroySurface; + xdri_drv->Base.API.SwapBuffers = xdri_eglSwapBuffers; + + xdri_drv->Base.ClientAPIsMask = EGL_OPENGL_BIT /*| EGL_OPENGL_ES_BIT*/; + xdri_drv->Base.Name = "X/DRI"; + + _eglLog(_EGL_DEBUG, "XDRI: main(%s)", args); + + return &xdri_drv->Base; +} |