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/primary.c | 664 ++++++++++++++++++++++++++++++++++ 1 file changed, 664 insertions(+) create mode 100755 Source/DirectFB/systems/x11/primary.c (limited to 'Source/DirectFB/systems/x11/primary.c') diff --git a/Source/DirectFB/systems/x11/primary.c b/Source/DirectFB/systems/x11/primary.c new file mode 100755 index 0000000..2e12d8a --- /dev/null +++ b/Source/DirectFB/systems/x11/primary.c @@ -0,0 +1,664 @@ +/* + (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 +#include +#include +#include +#include +#include + +#include + +#include + +#include +#include + +#include +#include + +#ifdef USE_GLX +#include +#include "glx_surface_pool.h" +#endif + +#include "xwindow.h" +#include "x11.h" +#include "primary.h" + + +D_DEBUG_DOMAIN( X11_Layer, "X11/Layer", "X11 Layer" ); +D_DEBUG_DOMAIN( X11_Update, "X11/Update", "X11 Update" ); + +/**********************************************************************************************************************/ + +static DFBResult +dfb_x11_create_window( DFBX11 *x11, const CoreLayerRegionConfig *config ) +{ + int ret; + DFBX11Shared *shared = x11->shared; + + D_ASSERT( config != NULL ); + + shared->setmode.config = *config; + + if (fusion_call_execute( &shared->call, FCEF_NONE, X11_CREATE_WINDOW, &shared->setmode, &ret )) + return DFB_FUSION; + + return ret; +} + +static DFBResult +dfb_x11_destroy_window( DFBX11 *x11 ) +{ + int ret; + DFBX11Shared *shared = x11->shared; + + if (fusion_call_execute( &shared->call, FCEF_NONE, X11_DESTROY_WINDOW, NULL, &ret )) + return DFB_FUSION; + + return ret; +} + +static DFBResult +dfb_x11_update_screen( DFBX11 *x11, const DFBRegion *region, CoreSurfaceBufferLock *lock ) +{ + int ret; + DFBX11Shared *shared = x11->shared; + + DFB_REGION_ASSERT( region ); + D_ASSERT( lock != NULL ); + + /* FIXME: Just a hot fix! */ + while (shared->update.lock) + usleep( 10000 ); + + shared->update.region = *region; + shared->update.lock = lock; + + if (fusion_call_execute( &shared->call, FCEF_NODIRECT, X11_UPDATE_SCREEN, &shared->update, &ret )) + return DFB_FUSION; + + return ret; +} + +static DFBResult +dfb_x11_set_palette( DFBX11 *x11, CorePalette *palette ) +{ + int ret; + DFBX11Shared *shared = x11->shared; + + D_ASSERT( palette != NULL ); + + if (fusion_call_execute( &shared->call, FCEF_NONE, X11_SET_PALETTE, palette, &ret )) + return DFB_FUSION; + + return ret; +} + +/**********************************************************************************************************************/ + +static DFBResult +primaryInitScreen( CoreScreen *screen, + CoreGraphicsDevice *device, + void *driver_data, + void *screen_data, + DFBScreenDescription *description ) +{ + D_DEBUG_AT( X11_Layer, "%s()\n", __FUNCTION__ ); + + /* Set the screen capabilities. */ + description->caps = DSCCAPS_NONE; + + /* Set the screen name. */ + snprintf( description->name, + DFB_SCREEN_DESC_NAME_LENGTH, "X11 Primary Screen" ); + + return DFB_OK; +} + +static DFBResult +primaryGetScreenSize( CoreScreen *screen, + void *driver_data, + void *screen_data, + int *ret_width, + int *ret_height ) +{ + DFBX11 *x11 = driver_data; + DFBX11Shared *shared = x11->shared; + + D_DEBUG_AT( X11_Layer, "%s()\n", __FUNCTION__ ); + + *ret_width = shared->screen_size.w; + *ret_height = shared->screen_size.h; + + return DFB_OK; +} + +ScreenFuncs x11PrimaryScreenFuncs = { + .InitScreen = primaryInitScreen, + .GetScreenSize = primaryGetScreenSize, +}; + +/******************************************************************************/ + +static int +primaryLayerDataSize( void ) +{ + return 0; +} + +static int +primaryRegionDataSize( void ) +{ + return 0; +} + +static DFBResult +primaryInitLayer( CoreLayer *layer, + void *driver_data, + void *layer_data, + DFBDisplayLayerDescription *description, + DFBDisplayLayerConfig *config, + DFBColorAdjustment *adjustment ) +{ + DFBX11 *x11 = driver_data; + DFBX11Shared *shared = x11->shared; + + D_DEBUG_AT( X11_Layer, "%s()\n", __FUNCTION__ ); + + /* set capabilities and type */ + description->caps = DLCAPS_SURFACE; + description->type = DLTF_GRAPHICS; + + /* set name */ + snprintf( description->name, + DFB_DISPLAY_LAYER_DESC_NAME_LENGTH, "X11 Primary Layer" ); + + /* fill out the default configuration */ + config->flags = DLCONF_WIDTH | DLCONF_HEIGHT | + DLCONF_PIXELFORMAT | DLCONF_BUFFERMODE; + config->buffermode = DLBM_FRONTONLY; + + if (dfb_config->mode.width) + config->width = dfb_config->mode.width; + else + config->width = shared->screen_size.w; + + if (dfb_config->mode.height) + config->height = dfb_config->mode.height; + else + config->height = shared->screen_size.h; + + if (dfb_config->mode.format != DSPF_UNKNOWN) + config->pixelformat = dfb_config->mode.format; + else if (dfb_config->mode.depth > 0) + config->pixelformat = dfb_pixelformat_for_depth( dfb_config->mode.depth ); + else { + int depth = DefaultDepthOfScreen( x11->screenptr ); + + switch (depth) { + case 15: + config->pixelformat = DSPF_RGB555; + break; + case 16: + config->pixelformat = DSPF_RGB16; + break; + case 24: + config->pixelformat = DSPF_RGB32; + break; + case 32: + config->pixelformat = DSPF_ARGB; + break; + default: + printf(" Unsupported X11 screen depth %d \n",depth); + return DFB_UNSUPPORTED; + } + } + + return DFB_OK; +} + +static DFBResult +primaryTestRegion( CoreLayer *layer, + void *driver_data, + void *layer_data, + CoreLayerRegionConfig *config, + CoreLayerRegionConfigFlags *failed ) +{ + CoreLayerRegionConfigFlags fail = 0; + + D_DEBUG_AT( X11_Layer, "%s()\n", __FUNCTION__ ); + + switch (config->buffermode) { + case DLBM_FRONTONLY: + case DLBM_BACKSYSTEM: + case DLBM_BACKVIDEO: + case DLBM_TRIPLE: + break; + + default: + fail |= CLRCF_BUFFERMODE; + break; + } + + switch (config->format) { + case DSPF_RGB16: + case DSPF_NV16: + case DSPF_RGB444: + case DSPF_ARGB4444: + case DSPF_RGBA4444: + case DSPF_RGB555: + case DSPF_ARGB1555: + case DSPF_BGR555: + case DSPF_RGB24: + case DSPF_RGB32: + case DSPF_ARGB: + case DSPF_AYUV: + break; + + default: + fail |= CLRCF_FORMAT; + break; + } + + if (config->options) + fail |= CLRCF_OPTIONS; + + if (failed) + *failed = fail; + + if (fail) + return DFB_UNSUPPORTED; + + return DFB_OK; +} + +static DFBResult +primaryAddRegion( CoreLayer *layer, + void *driver_data, + void *layer_data, + void *region_data, + CoreLayerRegionConfig *config ) +{ + return DFB_OK; +} + +static DFBResult +primarySetRegion( CoreLayer *layer, + void *driver_data, + void *layer_data, + void *region_data, + CoreLayerRegionConfig *config, + CoreLayerRegionConfigFlags updated, + CoreSurface *surface, + CorePalette *palette, + CoreSurfaceBufferLock *lock ) +{ + DFBResult ret; + DFBX11 *x11 = driver_data; + + D_DEBUG_AT( X11_Layer, "%s()\n", __FUNCTION__ ); + + ret = dfb_x11_create_window( x11, config ); + if (ret) + return ret; + + if (palette) + dfb_x11_set_palette( x11, palette ); + + return DFB_OK; +} + +static DFBResult +primaryRemoveRegion( CoreLayer *layer, + void *driver_data, + void *layer_data, + void *region_data ) +{ + DFBX11 *x11 = driver_data; + + D_DEBUG_AT( X11_Layer, "%s()\n", __FUNCTION__ ); + + dfb_x11_destroy_window( x11 ); + + return DFB_OK; +} + +static DFBResult +primaryFlipRegion( CoreLayer *layer, + void *driver_data, + void *layer_data, + void *region_data, + CoreSurface *surface, + DFBSurfaceFlipFlags flags, + CoreSurfaceBufferLock *lock ) +{ + DFBX11 *x11 = driver_data; + DFBRegion region = DFB_REGION_INIT_FROM_DIMENSION( &surface->config.size ); + + D_DEBUG_AT( X11_Layer, "%s()\n", __FUNCTION__ ); + + dfb_surface_flip( surface, false ); + + return dfb_x11_update_screen( x11, ®ion, lock ); +} + +static DFBResult +primaryUpdateRegion( CoreLayer *layer, + void *driver_data, + void *layer_data, + void *region_data, + CoreSurface *surface, + const DFBRegion *update, + CoreSurfaceBufferLock *lock ) +{ + DFBX11 *x11 = driver_data; + DFBRegion region = DFB_REGION_INIT_FROM_DIMENSION( &surface->config.size ); + + D_DEBUG_AT( X11_Layer, "%s()\n", __FUNCTION__ ); + + if (update && !dfb_region_region_intersect( ®ion, update )) + return DFB_OK; + + return dfb_x11_update_screen( x11, ®ion, lock ); +} + +DisplayLayerFuncs x11PrimaryLayerFuncs = { + .LayerDataSize = primaryLayerDataSize, + .RegionDataSize = primaryRegionDataSize, + .InitLayer = primaryInitLayer, + + .TestRegion = primaryTestRegion, + .AddRegion = primaryAddRegion, + .SetRegion = primarySetRegion, + .RemoveRegion = primaryRemoveRegion, + .FlipRegion = primaryFlipRegion, + .UpdateRegion = primaryUpdateRegion, +}; + +/******************************************************************************/ + +static DFBResult +update_screen( DFBX11 *x11, const DFBRectangle *clip, CoreSurfaceBufferLock *lock ) +{ + void *dst; + void *src; + unsigned int offset = 0; + XWindow *xw; + XImage *ximage; + CoreSurface *surface; + CoreSurfaceAllocation *allocation; + DFBX11Shared *shared; + DFBRectangle rect; + bool direct = false; + + D_ASSERT( x11 != NULL ); + DFB_RECTANGLE_ASSERT( clip ); + + D_DEBUG_AT( X11_Update, "%s( %4d,%4d-%4dx%4d )\n", __FUNCTION__, DFB_RECTANGLE_VALS( clip ) ); + + CORE_SURFACE_BUFFER_LOCK_ASSERT( lock ); + + shared = x11->shared; + D_ASSERT( shared != NULL ); + + XLockDisplay( x11->display ); + + xw = shared->xw; + if (!xw) { + XUnlockDisplay( x11->display ); + return DFB_OK; + } + + allocation = lock->allocation; + CORE_SURFACE_ALLOCATION_ASSERT( allocation ); + + surface = allocation->surface; + D_ASSERT( surface != NULL ); + + + rect.x = rect.y = 0; + rect.w = xw->width; + rect.h = xw->height; + + if (!dfb_rectangle_intersect( &rect, clip )) { + XUnlockDisplay( x11->display ); + return DFB_OK; + } + + D_DEBUG_AT( X11_Update, " -> %4d,%4d-%4dx%4d\n", DFB_RECTANGLE_VALS( &rect ) ); + +#ifdef USE_GLX + /* Check for GLX allocation... */ + if (allocation->pool == shared->glx_pool && lock->handle) { + LocalPixmap *pixmap = lock->handle; + + D_MAGIC_ASSERT( pixmap, LocalPixmap ); + + /* ...and just call SwapBuffers... */ + //D_DEBUG_AT( X11_Update, " -> Calling glXSwapBuffers( 0x%lx )...\n", alloc->drawable ); + //glXSwapBuffers( x11->display, alloc->drawable ); + + + D_DEBUG_AT( X11_Update, " -> Copying from GLXPixmap...\n" ); + + glXWaitGL(); + + XCopyArea( x11->display, pixmap->pixmap, xw->window, xw->gc, + rect.x, rect.y, rect.w, rect.h, rect.x, rect.y ); + + glXWaitX(); + + XUnlockDisplay( x11->display ); + + return DFB_OK; + } +#endif + + /* Check for our special native allocation... */ + if (allocation->pool == shared->x11image_pool && lock->handle) { + x11Image *image = lock->handle; + + D_MAGIC_ASSERT( image, x11Image ); + + /* ...and directly XShmPutImage from that. */ + ximage = image->ximage; + + direct = true; + } + else { + /* ...or copy or convert into XShmImage or XImage allocated with the XWindow. */ + ximage = xw->ximage; + offset = xw->ximage_offset; + + xw->ximage_offset = (offset ? 0 : ximage->height / 2); + + dst = xw->virtualscreen + rect.x * xw->bpp + (rect.y + offset) * ximage->bytes_per_line; + src = lock->addr + DFB_BYTES_PER_LINE( surface->config.format, rect.x ) + rect.y * lock->pitch; + + switch (xw->depth) { + case 32: + dfb_convert_to_argb( surface->config.format, src, lock->pitch, + surface->config.size.h, dst, ximage->bytes_per_line, rect.w, rect.h ); + break; + + case 24: + dfb_convert_to_rgb32( surface->config.format, src, lock->pitch, + surface->config.size.h, dst, ximage->bytes_per_line, rect.w, rect.h ); + break; + + case 16: + dfb_convert_to_rgb16( surface->config.format, src, lock->pitch, + surface->config.size.h, dst, ximage->bytes_per_line, rect.w, rect.h ); + break; + + case 15: + dfb_convert_to_rgb555( surface->config.format, src, lock->pitch, + surface->config.size.h, dst, ximage->bytes_per_line, rect.w, rect.h ); + break; + + default: + D_ONCE( "unsupported depth %d", xw->depth ); + } + } + + D_ASSERT( ximage != NULL ); + + + /* Wait for previous data to be processed... */ + XSync( x11->display, False ); + + /* ...and immediately queue or send the next! */ + if (x11->use_shm) { + /* Just queue the command, it's XShm :) */ + XShmPutImage( xw->display, xw->window, xw->gc, ximage, + rect.x, rect.y + offset, rect.x, rect.y, rect.w, rect.h, False ); + + /* Make sure the queue has really happened! */ + XFlush( x11->display ); + } + else + /* Initiate transfer of buffer... */ + XPutImage( xw->display, xw->window, xw->gc, ximage, + rect.x, rect.y + offset, rect.x, rect.y, rect.w, rect.h ); + + /* Wait for display if single buffered and not converted... */ + if (direct && !(surface->config.caps & DSCAPS_FLIPPING)) + XSync( x11->display, False ); + + XUnlockDisplay( x11->display ); + + return DFB_OK; +} + +/******************************************************************************/ + +DFBResult +dfb_x11_create_window_handler( DFBX11 *x11, CoreLayerRegionConfig *config ) +{ + XWindow *xw; + DFBX11Shared *shared = x11->shared; + + D_DEBUG_AT( X11_Layer, "%s( %p )\n", __FUNCTION__, config ); + + D_DEBUG_AT( X11_Layer, " -> %4dx%4d %s\n", config->width, config->height, dfb_pixelformat_name(config->format) ); + + XLockDisplay( x11->display ); + + xw = shared->xw; + if (xw != NULL) { + if (xw->width == config->width && xw->height == config->height) { + XUnlockDisplay( x11->display ); + return DFB_OK; + } + + shared->xw = NULL; + dfb_x11_close_window( x11, xw ); + } + + bool bSucces = dfb_x11_open_window( x11, &xw, 0, 0, config->width, config->height, config->format ); + + /* Set video mode */ + if ( !bSucces ) { + D_ERROR( "DirectFB/X11: Couldn't open %dx%d window!\n", config->width, config->height ); + + XUnlockDisplay( x11->display ); + return DFB_FAILURE; + } + else + shared->xw = xw; + + XUnlockDisplay( x11->display ); + return DFB_OK; +} + +DFBResult +dfb_x11_destroy_window_handler( DFBX11 *x11 ) +{ + DFBX11Shared *shared = x11->shared; + + D_DEBUG_AT( X11_Layer, "%s()\n", __FUNCTION__ ); + + XLockDisplay( x11->display ); + + if (shared->xw) { + XWindow *xw = shared->xw; + + shared->xw = NULL; + + dfb_x11_close_window( x11, xw ); + } + + XSync( x11->display, False ); + + XUnlockDisplay( x11->display ); + + return DFB_OK; +} + +DFBResult +dfb_x11_update_screen_handler( DFBX11 *x11, UpdateScreenData *data ) +{ + DFBRectangle rect; + + D_DEBUG_AT( X11_Update, "%s( %p )\n", __FUNCTION__, data ); + + rect = DFB_RECTANGLE_INIT_FROM_REGION( &data->region ); + + if (data->lock) + update_screen( x11, &rect, data->lock ); + + data->lock = NULL; + + return DFB_OK; +} + +DFBResult +dfb_x11_set_palette_handler( DFBX11 *x11, CorePalette *palette ) +{ + return DFB_OK; +} + -- cgit