From 7fe60435bce6595a9c58a9bfd8244d74b5320e96 Mon Sep 17 00:00:00 2001 From: Benjamin Franzke Date: Tue, 15 Jan 2013 08:46:13 +0100 Subject: Import DirectFB141_2k11R3_beta5 --- Source/DirectFB/systems/x11/glx_surface_pool.c | 838 +++++++++++++++++++++++++ 1 file changed, 838 insertions(+) create mode 100755 Source/DirectFB/systems/x11/glx_surface_pool.c (limited to 'Source/DirectFB/systems/x11/glx_surface_pool.c') 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 , + Andreas Hundt , + Sven Neumann , + Ville Syrjälä and + Claudio Ciccani . + + 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 + +#include + +#include +#include +#include + +#include + +#include + +#include +#include + +#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; inum_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, +}; + -- cgit