summaryrefslogtreecommitdiff
path: root/Source/DirectFB/systems/x11/glx_surface_pool.c
diff options
context:
space:
mode:
Diffstat (limited to 'Source/DirectFB/systems/x11/glx_surface_pool.c')
-rwxr-xr-xSource/DirectFB/systems/x11/glx_surface_pool.c838
1 files changed, 838 insertions, 0 deletions
diff --git a/Source/DirectFB/systems/x11/glx_surface_pool.c b/Source/DirectFB/systems/x11/glx_surface_pool.c
new file mode 100755
index 0000000..98b909d
--- /dev/null
+++ b/Source/DirectFB/systems/x11/glx_surface_pool.c
@@ -0,0 +1,838 @@
+/*
+ (c) Copyright 2001-2009 The world wide DirectFB Open Source Community (directfb.org)
+ (c) Copyright 2000-2004 Convergence (integrated media) GmbH
+
+ All rights reserved.
+
+ Written by Denis Oliver Kropp <dok@directfb.org>,
+ Andreas Hundt <andi@fischlustig.de>,
+ Sven Neumann <neo@directfb.org>,
+ Ville Syrjälä <syrjala@sci.fi> and
+ Claudio Ciccani <klan@users.sf.net>.
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Lesser General Public
+ License as published by the Free Software Foundation; either
+ version 2 of the License, or (at your option) any later version.
+
+ This library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public
+ License along with this library; if not, write to the
+ Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ Boston, MA 02111-1307, USA.
+*/
+
+//#define DIRECT_ENABLE_DEBUG
+
+#include <config.h>
+
+#include <directfb_util.h>
+
+#include <direct/debug.h>
+#include <direct/hash.h>
+#include <direct/mem.h>
+
+#include <fusion/shmalloc.h>
+
+#include <core/surface_pool.h>
+
+#include <GL/glx.h>
+#include <GL/glxext.h>
+
+#include "x11.h"
+
+#include "glx_surface_pool.h"
+#include "x11_surface_pool.h"
+
+D_DEBUG_DOMAIN( GLX_Surfaces, "GLX/Surfaces", "GLX Surface Pool" );
+D_DEBUG_DOMAIN( GLX_Pixmaps, "GLX/Pixmaps", "GLX Surface Pool Pixmaps" );
+
+/**********************************************************************************************************************/
+
+typedef void (*GLXBindTexImageEXTProc) ( Display *dpy, GLXDrawable drawable, int buffer, const int *attrib_list );
+typedef void (*GLXReleaseTexImageEXTProc)( Display *dpy, GLXDrawable drawable, int buffer );
+
+typedef struct {
+ int magic;
+
+ Display *display;
+
+ GLXFBConfig *configs;
+ int num_configs;
+
+ GLXFBConfig config24;
+ Visual *visual24;
+
+ GLXFBConfig config32;
+ Visual *visual32;
+
+ GLXBindTexImageEXTProc BindTexImageEXT;
+ GLXReleaseTexImageEXTProc ReleaseTexImageEXT;
+
+ DirectHash *pixmaps;
+
+ /* Every thread needs its own context! */
+ pthread_key_t context_key;
+ pthread_key_t context_key2;
+} glxPoolLocalData;
+
+typedef struct {
+} glxPoolData;
+
+/**********************************************************************************************************************/
+
+static void
+destroy_context( void *arg )
+{
+ ThreadContext *ctx = arg;
+
+ XLockDisplay( ctx->display );
+
+ glXDestroyContext( ctx->display, ctx->context );
+
+ XUnlockDisplay( ctx->display );
+
+ D_FREE( ctx );
+}
+
+/**********************************************************************************************************************/
+
+static DFBResult
+InitLocal( glxPoolLocalData *local,
+ DFBX11 *x11 )
+{
+ DFBResult ret;
+
+ int i;
+ int attribs[] = {
+ GLX_DOUBLEBUFFER,
+ False,
+
+ GLX_DRAWABLE_TYPE,
+ GLX_PIXMAP_BIT,
+
+ GLX_X_RENDERABLE,
+ True,
+
+ GLX_RED_SIZE,
+ 8,
+
+ GLX_GREEN_SIZE,
+ 8,
+
+ GLX_BLUE_SIZE,
+ 8,
+
+ GLX_ALPHA_SIZE,
+ 8,
+
+ GLX_DEPTH_SIZE,
+ 8,
+
+ GLX_X_VISUAL_TYPE,
+ GLX_TRUE_COLOR,
+
+ None
+ };
+
+
+ local->display = x11->display;
+
+ local->BindTexImageEXT = (GLXBindTexImageEXTProc) glXGetProcAddress( (unsigned char*) "glXBindTexImageEXT" );
+ if (!local->BindTexImageEXT) {
+ D_ERROR( "glXGetProcAddress( 'glXBindTexImageEXT' ) failed!\n" );
+ return DFB_UNSUPPORTED;
+ }
+
+ local->ReleaseTexImageEXT = (GLXReleaseTexImageEXTProc) glXGetProcAddress( (unsigned char*) "glXReleaseTexImageEXT" );
+ if (!local->ReleaseTexImageEXT) {
+ D_ERROR( "glXGetProcAddress( 'glXReleaseTexImageEXT' ) failed!\n" );
+ return DFB_UNSUPPORTED;
+ }
+
+
+ ret = direct_hash_create( 7, &local->pixmaps );
+ if (ret)
+ return ret;
+
+
+ XLockDisplay( local->display );
+
+
+ local->configs = glXChooseFBConfig( local->display, DefaultScreen(local->display), attribs, &local->num_configs );
+
+ D_DEBUG_AT( GLX_Surfaces, " -> found %d configs\n", local->num_configs );
+
+ for (i=0; i<local->num_configs; i++) {
+ int depth;
+ XVisualInfo *info = glXGetVisualFromFBConfig( local->display, local->configs[i] );
+
+ glXGetFBConfigAttrib( local->display, local->configs[i], GLX_DEPTH_SIZE, &depth );
+
+ D_DEBUG_AT( GLX_Surfaces, " [%2d] ID 0x%02lx, depth %d, RGB 0x%06lx/0x%06lx/0x%06lx {%d}, class %d, z %d\n",
+ i, info->visualid, info->depth,
+ info->red_mask, info->green_mask, info->blue_mask,
+ info->bits_per_rgb, info->class, depth );
+
+ if (depth >= 8 && info->class == TrueColor) {
+ switch (info->depth) {
+ case 32:
+ local->config32 = local->configs[i];
+ local->visual32 = info->visual;
+ break;
+
+ case 24:
+ local->config24 = local->configs[i];
+ local->visual24 = info->visual;
+ break;
+ }
+ }
+ }
+
+ if (!local->config24 || !local->config32) {
+ D_ERROR( "GLX/Surfaces: Could not find useful visuals!\n" );
+ direct_hash_destroy( local->pixmaps );
+ XUnlockDisplay( local->display );
+ return DFB_UNSUPPORTED;
+ }
+
+ XVisualInfo *info24 = glXGetVisualFromFBConfig( local->display, local->config24 );
+ XVisualInfo *info32 = glXGetVisualFromFBConfig( local->display, local->config32 );
+
+ D_INFO( "GLX/Surfaces: Using visual 0x%02lx (24bit) and 0x%02lx (32bit)\n", info24->visualid, info32->visualid );
+
+ XUnlockDisplay( local->display );
+
+
+ pthread_key_create( &local->context_key, destroy_context );
+ pthread_key_create( &local->context_key2, destroy_context );
+
+ D_MAGIC_SET( local, glxPoolLocalData );
+
+ return DFB_OK;
+}
+
+static DFBResult
+GetLocalPixmap( glxPoolLocalData *local,
+ glxAllocationData *alloc,
+ CoreSurfaceAllocation *allocation,
+ LocalPixmap **ret_pixmap )
+{
+ LocalPixmap *pixmap;
+ CoreSurface *surface;
+ CoreSurfaceBuffer *buffer;
+
+ surface = allocation->surface;
+ D_MAGIC_ASSERT( surface, CoreSurface );
+
+ buffer = allocation->buffer;
+ D_MAGIC_ASSERT( buffer, CoreSurfaceBuffer );
+
+ pixmap = direct_hash_lookup( local->pixmaps, alloc->pixmap );
+ if (!pixmap) {
+ pixmap = D_CALLOC( 1, sizeof(LocalPixmap) );
+ if (!pixmap)
+ return D_OOM();
+
+ pixmap->pixmap = alloc->pixmap;
+ pixmap->config = (alloc->depth == 24) ? local->config24 : local->config32;
+
+ /*
+ * Create a GLXPixmap
+ */
+ int attribs[] = {
+ GLX_TEXTURE_FORMAT_EXT, (alloc->depth == 24) ? GLX_TEXTURE_FORMAT_RGB_EXT : GLX_TEXTURE_FORMAT_RGBA_EXT,
+ GLX_TEXTURE_TARGET_EXT, GLX_TEXTURE_RECTANGLE_EXT,
+ None
+ };
+
+
+ XLockDisplay( local->display );
+
+ pixmap->drawable = glXCreatePixmap( local->display, pixmap->config, alloc->pixmap, attribs );
+ if (!pixmap->drawable) {
+ D_ERROR( "GLX/Surfaces: Could not create %dx%d (depth %d) GLXPixmap!\n",
+ surface->config.size.w, surface->config.size.h, alloc->depth );
+ XUnlockDisplay( local->display );
+ D_FREE( pixmap );
+ return DFB_FAILURE;
+ }
+
+ D_DEBUG_AT( GLX_Surfaces, " -> drawable 0x%lx\n", pixmap->drawable );
+
+ /*
+ * Create a GC (for writing to pixmap)
+ */
+ pixmap->gc = XCreateGC( local->display, alloc->pixmap, 0, NULL );
+
+ D_DEBUG_AT( GLX_Surfaces, " -> gc 0x%lx\n", pixmap->drawable );
+
+ XUnlockDisplay( local->display );
+
+
+ /*
+ * Create a texture object
+ */
+ glGenTextures( 1, &pixmap->buffer.texture );
+
+
+ D_DEBUG_AT( GLX_Pixmaps, " NEW GLXPixmap 0x%lx for 0x%lx [%4dx%4d] %-10s\n", pixmap->drawable, alloc->pixmap,
+ surface->config.size.w, surface->config.size.h, dfb_pixelformat_name(buffer->format) );
+ D_DEBUG_AT( GLX_Surfaces, " -> GLXPixmap 0x%lx [%4dx%4d] %-10s (%u)\n", pixmap->drawable,
+ surface->config.size.w, surface->config.size.h, dfb_pixelformat_name(buffer->format),
+ pixmap->buffer.texture );
+
+ D_MAGIC_SET( pixmap, LocalPixmap );
+ D_MAGIC_SET( &pixmap->buffer, GLBufferData );
+
+ direct_hash_insert( local->pixmaps, alloc->pixmap, pixmap );
+ }
+ else
+ D_MAGIC_ASSERT( pixmap, LocalPixmap );
+
+ *ret_pixmap = pixmap;
+
+ return DFB_OK;
+}
+
+static void
+ReleasePixmap( glxPoolLocalData *local,
+ LocalPixmap *pixmap )
+{
+ D_MAGIC_ASSERT( local, glxPoolLocalData );
+ D_MAGIC_ASSERT( pixmap, LocalPixmap );
+
+ if (pixmap->bound) {
+ D_DEBUG_AT( GLX_Pixmaps, " RELEASE 0x%08lx from %p\n", pixmap->drawable, pixmap->bound );
+
+ local->ReleaseTexImageEXT( local->display, pixmap->drawable, GLX_FRONT_EXT );
+
+ pixmap->bound = NULL;
+ }
+}
+
+static void
+DestroyPixmap( glxPoolLocalData *local,
+ LocalPixmap *pixmap )
+{
+ D_MAGIC_ASSERT( local, glxPoolLocalData );
+ D_MAGIC_ASSERT( pixmap, LocalPixmap );
+
+ D_DEBUG_AT( GLX_Pixmaps, " DESTROY 0x%08lx (%d)\n", pixmap->drawable, pixmap->buffer.texture );
+
+ glXWaitGL();
+
+ ReleasePixmap( local, pixmap );
+
+ glXWaitX();
+
+ glDeleteTextures( 1, &pixmap->buffer.texture );
+
+ XFreeGC( local->display, pixmap->gc );
+
+ glXDestroyPixmap( local->display, pixmap->drawable );
+
+ direct_hash_remove( local->pixmaps, pixmap->pixmap );
+
+ D_MAGIC_CLEAR( pixmap );
+ D_MAGIC_CLEAR( &pixmap->buffer );
+
+ D_FREE( pixmap );
+}
+
+/**********************************************************************************************************************/
+
+static int
+glxPoolDataSize( void )
+{
+ return sizeof(glxPoolData);
+}
+
+static int
+glxPoolLocalDataSize( void )
+{
+ return sizeof(glxPoolLocalData);
+}
+
+static int
+glxAllocationDataSize( void )
+{
+ return sizeof(glxAllocationData);
+}
+
+static DFBResult
+glxInitPool( CoreDFB *core,
+ CoreSurfacePool *pool,
+ void *pool_data,
+ void *pool_local,
+ void *system_data,
+ CoreSurfacePoolDescription *ret_desc )
+{
+ glxPoolLocalData *local = pool_local;
+ DFBX11 *x11 = system_data;
+
+ D_DEBUG_AT( GLX_Surfaces, "%s()\n", __FUNCTION__ );
+
+ D_MAGIC_ASSERT( pool, CoreSurfacePool );
+ D_ASSERT( ret_desc != NULL );
+
+ ret_desc->caps = CSPCAPS_NONE;
+ ret_desc->access[CSAID_GPU] = CSAF_READ | CSAF_WRITE;
+ ret_desc->types = CSTF_LAYER | CSTF_WINDOW | CSTF_CURSOR | CSTF_FONT | CSTF_SHARED | CSTF_EXTERNAL;
+ ret_desc->priority = CSPP_DEFAULT;
+
+ /* For showing our X11 window */
+ ret_desc->access[CSAID_LAYER0] = CSAF_READ;
+
+ /* For user contexts via DirectFBGL */
+ ret_desc->access[CSAID_ACCEL1] = CSAF_READ | CSAF_WRITE;
+
+ snprintf( ret_desc->name, DFB_SURFACE_POOL_DESC_NAME_LENGTH, "GLX Drawables" );
+
+
+ return InitLocal( local, x11 );
+}
+
+static DFBResult
+glxJoinPool( CoreDFB *core,
+ CoreSurfacePool *pool,
+ void *pool_data,
+ void *pool_local,
+ void *system_data )
+{
+ glxPoolLocalData *local = pool_local;
+ DFBX11 *x11 = system_data;
+
+ D_DEBUG_AT( GLX_Surfaces, "%s()\n", __FUNCTION__ );
+
+ D_MAGIC_ASSERT( pool, CoreSurfacePool );
+
+
+ return InitLocal( local, x11 );
+}
+
+static DFBResult
+glxDestroyPool( CoreSurfacePool *pool,
+ void *pool_data,
+ void *pool_local )
+{
+ D_DEBUG_AT( GLX_Surfaces, "%s()\n", __FUNCTION__ );
+
+ D_MAGIC_ASSERT( pool, CoreSurfacePool );
+
+ return DFB_OK;
+}
+
+static DFBResult
+glxLeavePool( CoreSurfacePool *pool,
+ void *pool_data,
+ void *pool_local )
+{
+ D_DEBUG_AT( GLX_Surfaces, "%s()\n", __FUNCTION__ );
+
+ D_MAGIC_ASSERT( pool, CoreSurfacePool );
+
+ return DFB_OK;
+}
+
+static DFBResult
+glxTestConfig( CoreSurfacePool *pool,
+ void *pool_data,
+ void *pool_local,
+ CoreSurfaceBuffer *buffer,
+ const CoreSurfaceConfig *config )
+{
+ glxPoolLocalData *local = pool_local;
+
+ D_MAGIC_ASSERT( local, glxPoolLocalData );
+
+ if (!local->configs)
+ return DFB_UNSUPPORTED;
+
+ return DFB_OK;
+}
+
+static DFBResult
+glxAllocateBuffer( CoreSurfacePool *pool,
+ void *pool_data,
+ void *pool_local,
+ CoreSurfaceBuffer *buffer,
+ CoreSurfaceAllocation *allocation,
+ void *alloc_data )
+{
+ CoreSurface *surface;
+ glxPoolLocalData *local = pool_local;
+ glxAllocationData *alloc = alloc_data;
+
+ D_DEBUG_AT( GLX_Surfaces, "%s()\n", __FUNCTION__ );
+
+ D_MAGIC_ASSERT( pool, CoreSurfacePool );
+ D_MAGIC_ASSERT( local, glxPoolLocalData );
+ D_MAGIC_ASSERT( buffer, CoreSurfaceBuffer );
+
+ surface = buffer->surface;
+ D_MAGIC_ASSERT( surface, CoreSurface );
+
+ XLockDisplay( local->display );
+
+ alloc->depth = DFB_COLOR_BITS_PER_PIXEL( buffer->format ) + DFB_ALPHA_BITS_PER_PIXEL( buffer->format );
+
+ /*
+ * Create a pixmap
+ */
+ alloc->pixmap = XCreatePixmap( local->display, DefaultRootWindow( local->display ),
+ surface->config.size.w, surface->config.size.h, alloc->depth );
+ if (!alloc->pixmap) {
+ D_ERROR( "GLX/Surfaces: Could not create %dx%d (depth %d) pixmap!\n",
+ surface->config.size.w, surface->config.size.h, alloc->depth );
+
+ XUnlockDisplay( local->display );
+
+ return DFB_FAILURE;
+ }
+
+ D_DEBUG_AT( GLX_Surfaces, " -> pixmap 0x%lx\n", alloc->pixmap );
+
+ D_DEBUG_AT( GLX_Pixmaps, " NEW Pixmap 0x%lx [%4dx%4d] %-10s\n", alloc->pixmap,
+ surface->config.size.w, surface->config.size.h, dfb_pixelformat_name(buffer->format) );
+
+ XUnlockDisplay( local->display );
+
+
+ /* Pseudo calculation */
+ dfb_surface_calc_buffer_size( surface, 8, 2, NULL, &allocation->size );
+
+ D_MAGIC_SET( alloc, glxAllocationData );
+
+ return DFB_OK;
+}
+
+static DFBResult
+glxDeallocateBuffer( CoreSurfacePool *pool,
+ void *pool_data,
+ void *pool_local,
+ CoreSurfaceBuffer *buffer,
+ CoreSurfaceAllocation *allocation,
+ void *alloc_data )
+{
+ LocalPixmap *pixmap;
+ glxPoolLocalData *local = pool_local;
+ glxAllocationData *alloc = alloc_data;
+
+ D_DEBUG_AT( GLX_Surfaces, "%s()\n", __FUNCTION__ );
+
+ D_MAGIC_ASSERT( pool, CoreSurfacePool );
+ D_MAGIC_ASSERT( local, glxPoolLocalData );
+ D_MAGIC_ASSERT( buffer, CoreSurfaceBuffer );
+ D_MAGIC_ASSERT( alloc, glxAllocationData );
+
+ CORE_SURFACE_ALLOCATION_ASSERT( allocation );
+
+ XLockDisplay( local->display );
+
+ pixmap = direct_hash_lookup( local->pixmaps, alloc->pixmap );
+ if (pixmap)
+ DestroyPixmap( local, pixmap );
+
+ XFreePixmap( local->display, alloc->pixmap );
+
+ XUnlockDisplay( local->display );
+
+ D_MAGIC_CLEAR( alloc );
+
+ return DFB_OK;
+}
+
+static DFBResult
+glxLock( CoreSurfacePool *pool,
+ void *pool_data,
+ void *pool_local,
+ CoreSurfaceAllocation *allocation,
+ void *alloc_data,
+ CoreSurfaceBufferLock *lock )
+{
+ DFBResult ret;
+ LocalPixmap *pixmap;
+ glxPoolLocalData *local = pool_local;
+ glxAllocationData *alloc = alloc_data;
+
+ D_DEBUG_AT( GLX_Surfaces, "%s( %p )\n", __FUNCTION__, allocation );
+
+ D_MAGIC_ASSERT( pool, CoreSurfacePool );
+ D_MAGIC_ASSERT( local, glxPoolLocalData );
+ D_MAGIC_ASSERT( allocation, CoreSurfaceAllocation );
+ D_MAGIC_ASSERT( alloc, glxAllocationData );
+ D_MAGIC_ASSERT( lock, CoreSurfaceBufferLock );
+
+ ret = GetLocalPixmap( local, alloc, allocation, &pixmap );
+ if (ret)
+ return ret;
+
+ if (lock->accessor == CSAID_GPU || lock->accessor == CSAID_ACCEL1) {
+ ThreadContext *ctx;
+
+ ctx = pthread_getspecific( (lock->accessor == CSAID_GPU) ? local->context_key : local->context_key2 );
+ if (!ctx) {
+ ctx = D_CALLOC( 1, sizeof(ThreadContext) );
+ if (!ctx)
+ return D_OOM();
+
+ ctx->display = local->display;
+
+ XLockDisplay( local->display );
+
+ ctx->context = glXCreateNewContext( local->display, pixmap->config, GLX_RGBA_TYPE, NULL, GL_TRUE );
+ if (!ctx->context) {
+ D_ERROR( "GLX: Could not create GLXContext!\n" );
+ XUnlockDisplay( local->display );
+ D_FREE( ctx );
+ return DFB_FAILURE;
+ }
+
+ XUnlockDisplay( local->display );
+
+ pthread_setspecific( (lock->accessor == CSAID_GPU) ? local->context_key : local->context_key2, ctx );
+
+ D_DEBUG_AT( GLX_Surfaces, " -> NEW CONTEXT %p\n", ctx->context );
+ }
+
+ if (lock->access & CSAF_WRITE) {
+ if (ctx->context != glXGetCurrentContext() || ctx->drawable != pixmap->drawable) {
+ D_DEBUG_AT( GLX_Surfaces, " -> MAKE CURRENT 0x%08lx <- 0x%08lx\n", pixmap->drawable, glXGetCurrentDrawable() );
+
+ if (ctx->drawable != pixmap->drawable) {
+ ctx->drawable = pixmap->drawable;
+
+ pixmap->buffer.flags |= GLBF_UPDATE_TARGET;
+ }
+
+ XLockDisplay( local->display );
+
+ glXMakeContextCurrent( local->display, pixmap->drawable, pixmap->drawable, ctx->context );
+ pixmap->current = ctx->context;
+
+ ReleasePixmap( local, pixmap );
+
+ XUnlockDisplay( local->display );
+ }
+ }
+ else {
+ if (pixmap->bound != ctx->context) {
+ D_DEBUG_AT( GLX_Surfaces, " -> BIND TEXTURE 0x%08lx (%d)\n", pixmap->drawable, pixmap->buffer.texture );
+
+ XLockDisplay( local->display );
+
+ ReleasePixmap( local, pixmap );
+
+ glEnable( GL_TEXTURE_RECTANGLE_ARB );
+ glBindTexture( GL_TEXTURE_RECTANGLE_ARB, pixmap->buffer.texture );
+
+ local->BindTexImageEXT( local->display, pixmap->drawable, GLX_FRONT_EXT, NULL );
+ pixmap->bound = ctx->context;
+
+ XUnlockDisplay( local->display );
+
+ pixmap->buffer.flags |= GLBF_UPDATE_TEXTURE;
+ }
+ }
+
+ lock->handle = &pixmap->buffer;
+ }
+ else
+ lock->handle = pixmap;
+
+ return DFB_OK;
+}
+
+static DFBResult
+glxUnlock( CoreSurfacePool *pool,
+ void *pool_data,
+ void *pool_local,
+ CoreSurfaceAllocation *allocation,
+ void *alloc_data,
+ CoreSurfaceBufferLock *lock )
+{
+#if 0
+ DFBResult ret;
+ LocalPixmap *pixmap;
+ glxPoolLocalData *local = pool_local;
+ glxAllocationData *alloc = alloc_data;
+
+ D_DEBUG_AT( GLX_Surfaces, "%s( %p )\n", __FUNCTION__, allocation );
+
+ D_MAGIC_ASSERT( pool, CoreSurfacePool );
+ D_MAGIC_ASSERT( local, glxPoolLocalData );
+ D_MAGIC_ASSERT( allocation, CoreSurfaceAllocation );
+ D_MAGIC_ASSERT( alloc, glxAllocationData );
+ D_MAGIC_ASSERT( lock, CoreSurfaceBufferLock );
+
+ ret = GetLocalPixmap( local, alloc, allocation, &pixmap );
+ if (ret)
+ return ret;
+
+ if (lock->accessor == CSAID_GPU) {
+ XLockDisplay( local->display );
+
+ if (lock->access & CSAF_WRITE) {
+// D_DEBUG_AT( GLX_Surfaces, " -> UNMAKE CURRENT 0x%08lx <- 0x%08lx\n", pixmap->drawable, glXGetCurrentDrawable() );
+
+// glXMakeContextCurrent( local->display, None, None, NULL );
+// pixmap->current = NULL;
+ }
+ else {
+ D_DEBUG_AT( GLX_Surfaces, " -> UNBIND TEXTURE 0x%08lx (%d)\n", pixmap->drawable, pixmap->buffer.texture );
+
+ ReleasePixmap( local, pixmap );
+ }
+
+ XUnlockDisplay( local->display );
+ }
+
+#endif
+ return DFB_OK;
+}
+
+static DFBResult
+glxRead( CoreSurfacePool *pool,
+ void *pool_data,
+ void *pool_local,
+ CoreSurfaceAllocation *allocation,
+ void *alloc_data,
+ void *destination,
+ int pitch,
+ const DFBRectangle *rect )
+{
+ XImage *image;
+ XImage *sub;
+ glxPoolLocalData *local = pool_local;
+ glxAllocationData *alloc = alloc_data;
+
+ D_DEBUG_AT( GLX_Surfaces, "%s( %p )\n", __FUNCTION__, allocation );
+
+ D_MAGIC_ASSERT( pool, CoreSurfacePool );
+ D_MAGIC_ASSERT( local, glxPoolLocalData );
+ D_MAGIC_ASSERT( allocation, CoreSurfaceAllocation );
+ D_MAGIC_ASSERT( alloc, glxAllocationData );
+ D_ASSERT( destination != NULL );
+ D_ASSERT( pitch >= 0 );
+ DFB_RECTANGLE_ASSERT( rect );
+
+ D_DEBUG_AT( GLX_Surfaces, " => %p 0x%08lx [%4d,%4d-%4dx%4d]\n", alloc, alloc->pixmap, DFB_RECTANGLE_VALS(rect) );
+
+ XLockDisplay( local->display );
+
+ image = XCreateImage( local->display, (alloc->depth == 24) ? local->visual24 : local->visual32,
+ alloc->depth, ZPixmap, 0, destination, rect->w, rect->h, 32, pitch );
+ if (!image) {
+ D_ERROR( "GLX/Surfaces: XCreateImage( %dx%d, depth %d ) failed!\n", rect->w, rect->h, alloc->depth );
+ XUnlockDisplay( local->display );
+ return DFB_FAILURE;
+ }
+
+ glXWaitGL();
+
+ sub = XGetSubImage( local->display, alloc->pixmap, rect->x, rect->y, rect->w, rect->h, ~0, ZPixmap, image, 0, 0 );
+
+ glXWaitX();
+
+ /* FIXME: Why the X-hell is XDestroyImage() freeing *MY* data? */
+ image->data = NULL;
+ XDestroyImage( image );
+
+ XUnlockDisplay( local->display );
+
+ if (!sub) {
+ D_ERROR( "GLX/Surfaces: XGetSubImage( %d,%d-%dx%d ) failed!\n", DFB_RECTANGLE_VALS(rect) );
+ return DFB_FAILURE;
+ }
+
+ return DFB_OK;
+}
+
+static DFBResult
+glxWrite( CoreSurfacePool *pool,
+ void *pool_data,
+ void *pool_local,
+ CoreSurfaceAllocation *allocation,
+ void *alloc_data,
+ const void *source,
+ int pitch,
+ const DFBRectangle *rect )
+{
+ DFBResult ret;
+ LocalPixmap *pixmap;
+ CoreSurface *surface;
+ XImage *image;
+ glxPoolLocalData *local = pool_local;
+ glxAllocationData *alloc = alloc_data;
+
+ D_DEBUG_AT( GLX_Surfaces, "%s( %p )\n", __FUNCTION__, allocation );
+
+ D_MAGIC_ASSERT( pool, CoreSurfacePool );
+ D_MAGIC_ASSERT( local, glxPoolLocalData );
+ D_MAGIC_ASSERT( allocation, CoreSurfaceAllocation );
+ D_MAGIC_ASSERT( alloc, glxAllocationData );
+ D_ASSERT( source != NULL );
+ D_ASSERT( pitch >= 0 );
+ DFB_RECTANGLE_ASSERT( rect );
+
+ D_DEBUG_AT( GLX_Surfaces, " <= %p 0x%08lx [%4d,%4d-%4dx%4d]\n", alloc, alloc->pixmap, DFB_RECTANGLE_VALS(rect) );
+
+ surface = allocation->surface;
+ D_MAGIC_ASSERT( surface, CoreSurface );
+
+ ret = GetLocalPixmap( local, alloc, allocation, &pixmap );
+ if (ret)
+ return ret;
+
+ XLockDisplay( local->display );
+
+ image = XCreateImage( local->display, (alloc->depth == 24) ? local->visual24 : local->visual32,
+ alloc->depth, ZPixmap, 0, (void*) source, rect->w, rect->h, 32, pitch );
+ if (!image) {
+ D_ERROR( "GLX/Surfaces: XCreateImage( %dx%d, depth %d ) failed!\n", rect->w, rect->h, alloc->depth );
+ XUnlockDisplay( local->display );
+ return DFB_FAILURE;
+ }
+
+ glXWaitGL();
+
+ XPutImage( local->display, alloc->pixmap, pixmap->gc, image, 0, 0, rect->x, rect->y, rect->w, rect->h );
+
+ glXWaitX();
+
+ /* FIXME: Why the X-hell is XDestroyImage() freeing *MY* data? */
+ image->data = NULL;
+ XDestroyImage( image );
+
+ XUnlockDisplay( local->display );
+
+ return DFB_OK;
+}
+
+const SurfacePoolFuncs glxSurfacePoolFuncs = {
+ .PoolDataSize = glxPoolDataSize,
+ .PoolLocalDataSize = glxPoolLocalDataSize,
+ .AllocationDataSize = glxAllocationDataSize,
+
+ .InitPool = glxInitPool,
+ .JoinPool = glxJoinPool,
+ .DestroyPool = glxDestroyPool,
+ .LeavePool = glxLeavePool,
+
+ .TestConfig = glxTestConfig,
+
+ .AllocateBuffer = glxAllocateBuffer,
+ .DeallocateBuffer = glxDeallocateBuffer,
+
+ .Lock = glxLock,
+ .Unlock = glxUnlock,
+
+ .Read = glxRead,
+ .Write = glxWrite,
+};
+