diff options
author | Keith Whitwell <[email protected]> | 2008-09-11 16:05:15 +0100 |
---|---|---|
committer | Keith Whitwell <[email protected]> | 2008-09-11 16:05:15 +0100 |
commit | 0397b2bb41b0f337af2949a15bcd7d0e7e8a7dc1 (patch) | |
tree | 732c93d74ed806942a13bf15575a61aa4f001253 /src/egl/drivers/xdri/egl_xdri.c | |
parent | 80af50b35b5a4e8890e15b28940576f8a1ac1476 (diff) | |
parent | e6887a5752774c18cf527477fdd3e57e4893ff3b (diff) |
Merge branch 'gallium-0.1' into gallium-0.2
A first attempt at moving gallium onto a branch directly off master...
It will be interesting to see how much work this takes to get running.
Have resolved the conflicts semi-arbitarily, not compiled or tested.
Conflicts:
.gitignore
Makefile
configs/config.mgw
configs/darwin
configs/darwin-x86ppc
configs/default
configs/freebsd-dri
configs/linux-dri
configs/linux-dri-xcb
configs/linux-fbdev
configs/linux-static
configs/linux-x86-64-static
configs/linux-x86-static
doxygen/Makefile
include/GL/gl.h
progs/demos/Makefile
progs/demos/descrip.mms
progs/demos/texenv.c
progs/egl/.gitignore
progs/egl/Makefile
progs/glsl/.gitignore
progs/glsl/Makefile
progs/glsl/convolutions.c
progs/samples/Makefile.mgw
progs/tests/.gitignore
progs/trivial/.gitignore
progs/trivial/point-param.c
progs/trivial/tri.c
progs/xdemos/.gitignore
progs/xdemos/glthreads.c
src/egl/drivers/demo/Makefile
src/egl/drivers/dri/Makefile
src/egl/main/Makefile
src/glu/Makefile
src/glu/sgi/Makefile
src/glu/sgi/Makefile.mgw
src/glut/glx/Makefile.mgw
src/glut/os2/WarpWin.cpp
src/glut/os2/glut_cindex.cpp
src/glut/os2/glut_gamemode.cpp
src/glut/os2/glut_win.cpp
src/glut/os2/glut_winmisc.cpp
src/glut/os2/os2_glx.cpp
src/glut/os2/os2_menu.cpp
src/glut/os2/os2_winproc.cpp
src/glw/Makefile
src/glx/x11/dri_glx.c
src/glx/x11/glxext.c
src/mesa/Makefile
src/mesa/Makefile.mgw
src/mesa/descrip.mms
src/mesa/drivers/beos/Makefile
src/mesa/drivers/common/descrip.mms
src/mesa/drivers/common/driverfuncs.c
src/mesa/drivers/directfb/Makefile
src/mesa/drivers/dri/Makefile.template
src/mesa/drivers/dri/common/dri_bufmgr.c
src/mesa/drivers/dri/common/dri_bufmgr.h
src/mesa/drivers/dri/common/dri_util.c
src/mesa/drivers/dri/common/extension_helper.h
src/mesa/drivers/dri/common/mmio.h
src/mesa/drivers/dri/common/utils.c
src/mesa/drivers/dri/common/utils.h
src/mesa/drivers/dri/glcore/Makefile
src/mesa/drivers/dri/i810/i810screen.c
src/mesa/drivers/dri/i915/intel_ioctl.c
src/mesa/drivers/dri/i915/intel_ioctl.h
src/mesa/drivers/dri/i915/intel_screen.c
src/mesa/drivers/dri/i915/server/i830_common.h
src/mesa/drivers/dri/i915/server/i830_dri.h
src/mesa/drivers/dri/i965/intel_screen.c
src/mesa/drivers/dri/i965/server/i830_common.h
src/mesa/drivers/dri/i965/server/i830_dri.h
src/mesa/drivers/dri/mach64/mach64_screen.c
src/mesa/drivers/dri/nouveau/nouveau_context.h
src/mesa/drivers/dri/nouveau/nouveau_fifo.c
src/mesa/drivers/dri/nouveau/nouveau_fifo.h
src/mesa/drivers/dri/nouveau/nouveau_screen.c
src/mesa/drivers/dri/nouveau/nouveau_screen.h
src/mesa/drivers/dri/r128/r128_tex.h
src/mesa/drivers/dri/savage/savageioctl.h
src/mesa/drivers/fbdev/Makefile
src/mesa/drivers/osmesa/Makefile
src/mesa/drivers/osmesa/descrip.mms
src/mesa/drivers/x11/Makefile
src/mesa/drivers/x11/descrip.mms
src/mesa/drivers/x11/xm_dd.c
src/mesa/glapi/glapi.c
src/mesa/glapi/glthread.c
src/mesa/main/api_validate.c
src/mesa/main/attrib.c
src/mesa/main/bufferobj.c
src/mesa/main/bufferobj.h
src/mesa/main/buffers.c
src/mesa/main/config.h
src/mesa/main/context.c
src/mesa/main/descrip.mms
src/mesa/main/drawpix.c
src/mesa/main/enums.c
src/mesa/main/fbobject.c
src/mesa/main/glheader.h
src/mesa/main/imports.c
src/mesa/main/mipmap.c
src/mesa/main/mm.c
src/mesa/main/mm.h
src/mesa/main/mtypes.h
src/mesa/main/points.c
src/mesa/main/sources
src/mesa/main/state.c
src/mesa/main/texcompress_fxt1.c
src/mesa/main/texenvprogram.c
src/mesa/main/texobj.c
src/mesa/main/texstate.c
src/mesa/main/texstore.c
src/mesa/math/descrip.mms
src/mesa/shader/arbprogram.c
src/mesa/shader/descrip.mms
src/mesa/shader/prog_execute.c
src/mesa/shader/prog_statevars.c
src/mesa/shader/prog_statevars.h
src/mesa/shader/prog_uniform.c
src/mesa/shader/program.c
src/mesa/shader/program.h
src/mesa/shader/shader_api.c
src/mesa/shader/slang/descrip.mms
src/mesa/shader/slang/library/slang_vertex_builtin_gc.h
src/mesa/sources
src/mesa/swrast/descrip.mms
src/mesa/swrast/s_drawpix.c
src/mesa/swrast/s_fragprog.c
src/mesa/swrast/s_readpix.c
src/mesa/swrast/s_span.c
src/mesa/swrast_setup/descrip.mms
src/mesa/tnl/descrip.mms
src/mesa/tnl/t_context.h
src/mesa/tnl/t_vp_build.c
src/mesa/tnl/tnl.h
src/mesa/vbo/descrip.mms
src/mesa/vbo/vbo_context.c
src/mesa/vbo/vbo_exec_array.c
src/mesa/x86-64/xform4.S
src/mesa/x86/rtasm/x86sse.c
src/mesa/x86/rtasm/x86sse.h
windows/VC6/progs/glut/glut.dsp
windows/VC7/mesa/gdi/gdi.vcproj
windows/VC7/mesa/glu/glu.vcproj
windows/VC7/mesa/mesa.sln
windows/VC7/mesa/mesa/mesa.vcproj
windows/VC7/mesa/osmesa/osmesa.vcproj
windows/VC7/progs/glut/glut.vcproj
windows/VC8/mesa/gdi/gdi.vcproj
windows/VC8/mesa/glu/glu.vcproj
windows/VC8/mesa/mesa.sln
windows/VC8/mesa/mesa/mesa.vcproj
windows/VC8/progs/glut/glut.vcproj
Diffstat (limited to 'src/egl/drivers/xdri/egl_xdri.c')
-rw-r--r-- | src/egl/drivers/xdri/egl_xdri.c | 912 |
1 files changed, 912 insertions, 0 deletions
diff --git a/src/egl/drivers/xdri/egl_xdri.c b/src/egl/drivers/xdri/egl_xdri.c new file mode 100644 index 00000000000..3681d9879a2 --- /dev/null +++ b/src/egl/drivers/xdri/egl_xdri.c @@ -0,0 +1,912 @@ +/************************************************************************** + * + * Copyright 2008 Tungsten Graphics, Inc., Cedar Park, Texas. + * All Rights Reserved. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the + * "Software"), to deal in the Software without restriction, including + * without limitation the rights to use, copy, modify, merge, publish, + * distribute, sub license, and/or sell copies of the Software, and to + * permit persons to whom the Software is furnished to do so, subject to + * the following conditions: + * + * The above copyright notice and this permission notice (including the + * next paragraph) shall be included in all copies or substantial portions + * of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS + * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. + * IN NO EVENT SHALL TUNGSTEN GRAPHICS AND/OR ITS SUPPLIERS BE LIABLE FOR + * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, + * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE + * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + * + **************************************************************************/ + + +/** + * Code to interface a DRI driver to libEGL. + * Note that unlike previous DRI/EGL interfaces, this one is meant to + * be used _with_ X. Applications will use eglCreateWindowSurface() + * to render into X-created windows. + * + * This is an EGL driver that, in turn, loads a regular DRI driver. + * There are some dependencies on code in libGL, but those could be + * removed with some effort. + * + * Authors: Brian Paul + */ + + +#include <assert.h> +#include <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) */ + + __GLXdisplayPrivate *glx_priv; + + + /* XXX we're not actually using these at this time: */ + int chipset; + int minor; + int drmFD; + + __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; +} + + + +/** Get size of given window */ +static Status +get_drawable_size(Display *dpy, Drawable d, uint *width, uint *height) +{ + Window root; + Status stat; + int xpos, ypos; + unsigned int w, h, bw, depth; + stat = XGetGeometry(dpy, d, &root, &xpos, &ypos, &w, &h, &bw, &depth); + *width = w; + *height = h; + return stat; +} + + +/** + * 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 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; + + 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_SAMPLES, m->samples); + SET_CONFIG_ATTRIB(&config->Base, EGL_SAMPLE_BUFFERS, m->sampleBuffers); + SET_CONFIG_ATTRIB(&config->Base, EGL_NATIVE_VISUAL_ID, m->visualID); + SET_CONFIG_ATTRIB(&config->Base, EGL_NATIVE_VISUAL_TYPE, m->visualType); + SET_CONFIG_ATTRIB(&config->Base, EGL_CONFORMANT, all_apis); + SET_CONFIG_ATTRIB(&config->Base, EGL_RENDERABLE_TYPE, all_apis); + /* XXX only window rendering allowed ATM */ + SET_CONFIG_ATTRIB(&config->Base, EGL_SURFACE_TYPE, EGL_WINDOW_BIT); + + /* XXX possibly other things to init... */ + + /* Ptr from EGL config to GLcontextMode. Used in CreateContext(). */ + config->mode = m; + + _eglAddConfig(disp, &config->Base); + } + } +} + + +/** + * 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) +{ + __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) +{ + __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; + } + 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()); + } + + /* 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; + } + + _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]; + + _eglLog(_EGL_DEBUG, "XDRI: eglInitialize"); + + if (!disp->Xdpy) { + disp->Xdpy = XOpenDisplay(NULL); + if (!disp->Xdpy) { + _eglLog(_EGL_WARNING, "XDRI: XOpenDisplay failed"); + return EGL_FALSE; + } + } + +#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; + + 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); +#if 0 + dlclose(xdri_drv->dri_driver_handle); +#endif + xdri_drv->dri_driver_handle = NULL; + + free((void*) xdri_drv->dri_driver_name); + + return EGL_TRUE; +} + + +/* + * Called from eglGetProcAddress() via drv->API.GetProcAddress(). + */ +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 +} + + +/** + * 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; + 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); + + { + 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 (!xdri_ctx->driContext.private) { + _eglLog(_EGL_DEBUG, "driScreen.createNewContext failed"); + 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 ? xdri_draw->driDrawable : 0; + __DRIid read = xdri_read ? xdri_read->driDrawable : 0; + int scrn = DefaultScreen(disp->Xdpy); + + if (!_eglMakeCurrent(drv, dpy, d, r, context)) + return EGL_FALSE; + + + if (xdri_ctx && + !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); + uint width, height; + + 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); + + get_drawable_size(disp->Xdpy, 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); +} + + +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); + 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; +} + + +/** + * 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; + + /* 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; + + xdri_drv->Base.API.GetProcAddress = xdri_eglGetProcAddress; + + 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 | + EGL_OPENGL_ES2_BIT | + EGL_OPENVG_BIT); + xdri_drv->Base.Name = "X/DRI"; + + _eglLog(_EGL_DEBUG, "XDRI: main(%s)", args); + + return &xdri_drv->Base; +} |