/* (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 "x11.h" #include "x11image.h" #include "glx_surface_pool.h" #include "x11_surface_pool.h" D_DEBUG_DOMAIN( X11_Bridge, "X11/Bridge", "X11 System Surface Pool Bridge" ); /**********************************************************************************************************************/ typedef struct { } x11PoolBridgeData; typedef struct { DFBX11 *x11; Display *display; } x11PoolBridgeLocalData; typedef struct { } x11PoolTransferData; /**********************************************************************************************************************/ static int x11PoolBridgeDataSize( void ) { return sizeof(x11PoolBridgeData); } static int x11PoolBridgeLocalDataSize( void ) { return sizeof(x11PoolBridgeLocalData); } static int x11PoolTransferDataSize( void ) { return sizeof(x11PoolTransferData); } static DFBResult x11InitPoolBridge( CoreDFB *core, CoreSurfacePoolBridge *bridge, void *bridge_data, void *bridge_local, void *context, CoreSurfacePoolBridgeDescription *ret_desc ) { x11PoolBridgeLocalData *local = bridge_local; DFBX11 *x11 = context; D_DEBUG_AT( X11_Bridge, "%s()\n", __FUNCTION__ ); D_MAGIC_ASSERT( bridge, CoreSurfacePoolBridge ); D_ASSERT( bridge_local != NULL ); D_ASSERT( context != NULL ); D_ASSERT( ret_desc != NULL ); local->x11 = x11; local->display = x11->display; ret_desc->caps = CSPBCAPS_NONE; snprintf( ret_desc->name, DFB_SURFACE_POOL_BRIDGE_DESC_NAME_LENGTH, "X11 Pool Bridge" ); return DFB_OK; } static DFBResult x11JoinPoolBridge( CoreDFB *core, CoreSurfacePoolBridge *bridge, void *bridge_data, void *bridge_local, void *context ) { x11PoolBridgeLocalData *local = bridge_local; DFBX11 *x11 = context; D_DEBUG_AT( X11_Bridge, "%s()\n", __FUNCTION__ ); D_MAGIC_ASSERT( bridge, CoreSurfacePoolBridge ); D_ASSERT( bridge_local != NULL ); D_ASSERT( context != NULL ); local->x11 = x11; local->display = x11->display; return DFB_OK; } static DFBResult x11DestroyPoolBridge( CoreSurfacePoolBridge *bridge, void *bridge_data, void *bridge_local ) { D_DEBUG_AT( X11_Bridge, "%s()\n", __FUNCTION__ ); D_MAGIC_ASSERT( bridge, CoreSurfacePoolBridge ); return DFB_OK; } static DFBResult x11LeavePoolBridge( CoreSurfacePoolBridge *bridge, void *bridge_data, void *bridge_local ) { D_DEBUG_AT( X11_Bridge, "%s()\n", __FUNCTION__ ); D_MAGIC_ASSERT( bridge, CoreSurfacePoolBridge ); return DFB_OK; } static DFBResult x11CheckTransfer( CoreSurfacePoolBridge *bridge, void *bridge_data, void *bridge_local, CoreSurfaceBuffer *buffer, CoreSurfaceAllocation *from, CoreSurfaceAllocation *to ) { x11PoolBridgeLocalData *local = bridge_local; DFBX11 *x11 = local->x11; DFBX11Shared *shared = x11->shared; D_DEBUG_AT( X11_Bridge, "%s()\n", __FUNCTION__ ); if (from->pool == shared->x11image_pool && to->pool == shared->glx_pool) { x11AllocationData *alloc = from->data; if (alloc->real) { /* ARGB does not work (BadMatch) */ if (buffer->format == DSPF_RGB32) return DFB_OK; } } else if (from->pool == shared->glx_pool && to->pool == shared->x11image_pool) { x11AllocationData *alloc = to->data; if (alloc->real) { /* ARGB does not work (BadMatch) */ if (buffer->format == DSPF_RGB32) return DFB_OK; } } return DFB_UNSUPPORTED; } static DFBResult x11StartTransfer( CoreSurfacePoolBridge *bridge, void *bridge_data, void *bridge_local, CoreSurfacePoolTransfer *transfer, void *transfer_data ) { DFBResult ret; int i; CoreSurfaceBufferLock lock; LocalPixmap *pixmap; x11PoolBridgeLocalData *local = bridge_local; DFBX11 *x11 = local->x11; DFBX11Shared *shared = x11->shared; CoreSurfaceAllocation *from = transfer->from; CoreSurfaceAllocation *to = transfer->to; D_DEBUG_AT( X11_Bridge, "%s()\n", __FUNCTION__ ); if (from->pool == shared->x11image_pool && to->pool == shared->glx_pool) { x11AllocationData *alloc = from->data; D_ASSERT( alloc->real ); dfb_surface_buffer_lock_init( &lock, CSAID_ANY, CSAF_WRITE ); ret = dfb_surface_pool_lock( to->pool, to, &lock ); if (ret) { dfb_surface_buffer_lock_deinit( &lock ); return ret; } pixmap = lock.handle; D_MAGIC_ASSERT( pixmap, LocalPixmap ); XLockDisplay( local->display ); for (i=0; inum_rects; i++) { const DFBRectangle *rect = &transfer->rects[i]; D_DEBUG_AT( X11_Bridge, " -> XCopyArea( %4d,%4d-%4dx%4d )\n", rect->x, rect->y, rect->w, rect->h ); XCopyArea( local->display, alloc->image.pixmap, pixmap->pixmap, pixmap->gc, rect->x, rect->y, rect->w, rect->h, rect->x, rect->y ); } XFlush( local->display ); XUnlockDisplay( local->display ); dfb_surface_pool_unlock( to->pool, to, &lock ); dfb_surface_buffer_lock_deinit( &lock ); return DFB_OK; } if (from->pool == shared->glx_pool && to->pool == shared->x11image_pool) { x11AllocationData *alloc = to->data; D_ASSERT( alloc->real ); dfb_surface_buffer_lock_init( &lock, CSAID_ANY, CSAF_READ ); ret = dfb_surface_pool_lock( from->pool, from, &lock ); if (ret) { dfb_surface_buffer_lock_deinit( &lock ); return ret; } pixmap = lock.handle; D_MAGIC_ASSERT( pixmap, LocalPixmap ); XLockDisplay( local->display ); glFinish(); for (i=0; inum_rects; i++) { const DFBRectangle *rect = &transfer->rects[i]; D_DEBUG_AT( X11_Bridge, " -> XCopyArea( %4d,%4d-%4dx%4d )\n", rect->x, rect->y, rect->w, rect->h ); XCopyArea( local->display, pixmap->pixmap, alloc->image.pixmap, alloc->image.gc, rect->x, rect->y, rect->w, rect->h, rect->x, rect->y ); } XFlush( local->display ); XUnlockDisplay( local->display ); dfb_surface_pool_unlock( from->pool, from, &lock ); dfb_surface_buffer_lock_deinit( &lock ); return DFB_OK; } return DFB_BUG; } static DFBResult x11FinishTransfer( CoreSurfacePoolBridge *bridge, void *bridge_data, void *bridge_local, CoreSurfacePoolTransfer *transfer, void *transfer_data ) { x11PoolBridgeLocalData *local = bridge_local; D_DEBUG_AT( X11_Bridge, "%s()\n", __FUNCTION__ ); XLockDisplay( local->display ); XSync( local->display, False ); XUnlockDisplay( local->display ); return DFB_OK; } const SurfacePoolBridgeFuncs x11SurfacePoolBridgeFuncs = { .PoolBridgeDataSize = x11PoolBridgeDataSize, .PoolBridgeLocalDataSize = x11PoolBridgeLocalDataSize, .PoolTransferDataSize = x11PoolTransferDataSize, .InitPoolBridge = x11InitPoolBridge, .JoinPoolBridge = x11JoinPoolBridge, .DestroyPoolBridge = x11DestroyPoolBridge, .LeavePoolBridge = x11LeavePoolBridge, .CheckTransfer = x11CheckTransfer, .StartTransfer = x11StartTransfer, .FinishTransfer = x11FinishTransfer, };