summaryrefslogtreecommitdiff
path: root/Source/DirectFB/systems/x11/x11image.c
diff options
context:
space:
mode:
Diffstat (limited to 'Source/DirectFB/systems/x11/x11image.c')
-rwxr-xr-xSource/DirectFB/systems/x11/x11image.c231
1 files changed, 231 insertions, 0 deletions
diff --git a/Source/DirectFB/systems/x11/x11image.c b/Source/DirectFB/systems/x11/x11image.c
new file mode 100755
index 0000000..acf36f0
--- /dev/null
+++ b/Source/DirectFB/systems/x11/x11image.c
@@ -0,0 +1,231 @@
+/*
+ (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.
+*/
+
+#include <config.h>
+
+#include <string.h>
+#include <stdlib.h>
+#include <stdio.h>
+
+#include "x11.h"
+#include "x11image.h"
+
+/**********************************************************************************************************************/
+
+DFBResult x11ImageInit( DFBX11 *x11,
+ x11Image *image,
+ int width,
+ int height,
+ DFBSurfacePixelFormat format )
+{
+ int ret;
+ Visual *visual;
+ DFBX11Shared *shared = x11->shared;
+
+ if (!x11->use_shm)
+ return DFB_UNSUPPORTED;
+
+ /* Lookup visual. */
+ visual = x11->visuals[DFB_PIXELFORMAT_INDEX(format)];
+ if (!visual)
+ return DFB_UNSUPPORTED;
+
+ /* For probing. */
+ if (!image)
+ return DFB_OK;
+
+ image->width = width;
+ image->height = height;
+ image->format = format;
+ image->depth = DFB_COLOR_BITS_PER_PIXEL( format );
+
+ D_MAGIC_SET( image, x11Image );
+
+ if (fusion_call_execute( &shared->call, FCEF_NONE, X11_IMAGE_INIT, image, &ret )) {
+ D_MAGIC_CLEAR( image );
+ return DFB_FUSION;
+ }
+
+ if (ret) {
+ D_DERROR( ret, "X11/Image: X11_IMAGE_INIT call failed!\n" );
+ D_MAGIC_CLEAR( image );
+ return ret;
+ }
+
+ return DFB_OK;
+}
+
+DFBResult
+x11ImageDestroy( DFBX11 *x11,
+ x11Image *image )
+{
+ int ret;
+ DFBX11Shared *shared = x11->shared;
+
+ D_MAGIC_ASSERT( image, x11Image );
+
+ if (fusion_call_execute( &shared->call, FCEF_NONE, X11_IMAGE_DESTROY, image, &ret ))
+ return DFB_FUSION;
+
+ if (ret) {
+ D_DERROR( ret, "X11/Image: X11_IMAGE_DESTROY call failed!\n" );
+ return ret;
+ }
+
+ D_MAGIC_CLEAR( image );
+
+ return DFB_OK;
+}
+
+DFBResult
+x11ImageAttach( x11Image *image,
+ void **ret_addr )
+{
+ void *addr;
+
+ D_MAGIC_ASSERT( image, x11Image );
+ D_ASSERT( ret_addr != NULL );
+
+ /* FIXME: We also need to DETACH! */
+
+ addr = shmat( image->seginfo.shmid, NULL, 0 );
+ if (!addr) {
+ int erno = errno;
+
+ D_PERROR( "X11/Image: shmat( %d ) failed!\n", image->seginfo.shmid );
+
+ return errno2result( erno );
+ }
+
+ *ret_addr = addr;
+
+ return DFB_OK;
+}
+
+/**********************************************************************************************************************/
+
+DFBResult
+dfb_x11_image_init_handler( DFBX11 *x11, x11Image *image )
+{
+ Visual *visual;
+ XImage *ximage;
+
+ D_MAGIC_ASSERT( image, x11Image );
+
+ if (!x11->use_shm)
+ return DFB_UNSUPPORTED;
+
+ /* Lookup visual. */
+ visual = x11->visuals[DFB_PIXELFORMAT_INDEX(image->format)];
+ if (!visual)
+ return DFB_UNSUPPORTED;
+
+ image->visual = visual;
+
+ XLockDisplay( x11->display );
+
+ ximage = XShmCreateImage( x11->display, image->visual, image->depth,
+ ZPixmap, NULL, &image->seginfo, image->width, image->height );
+ if (!ximage) {
+ D_ERROR( "X11/ShmImage: Error creating shared image (XShmCreateImage)!\n");
+ XUnlockDisplay( x11->display );
+ return DFB_FAILURE;
+ }
+
+ /* we firstly create our shared memory segment with the size we need, and
+ correct permissions for the owner, the group and the world --> 0777 */
+ image->seginfo.shmid = shmget( IPC_PRIVATE,
+ ximage->bytes_per_line * ximage->height,
+ IPC_CREAT | 0777 );
+ if (image->seginfo.shmid < 0)
+ goto error;
+
+ /* Then, we have to attach the segment to our process, and we let the
+ function search the correct memory place --> NULL. It's safest ! */
+ image->seginfo.shmaddr = shmat( image->seginfo.shmid, NULL, 0 );
+ if (!image->seginfo.shmaddr)
+ goto error_shmat;
+
+ ximage->data = image->seginfo.shmaddr;
+
+ /* We set the buffer in Read and Write mode */
+ image->seginfo.readOnly = False;
+
+ if (!XShmAttach( x11->display, &image->seginfo ))
+ goto error_xshmattach;
+
+ image->ximage = ximage;
+ image->pitch = ximage->bytes_per_line;
+
+ image->pixmap = XShmCreatePixmap( x11->display, DefaultRootWindow(x11->display), ximage->data,
+ &image->seginfo, image->width, image->height, image->depth );
+
+ image->gc = XCreateGC( x11->display, image->pixmap, 0, NULL );
+
+ XUnlockDisplay( x11->display );
+
+ return DFB_OK;
+
+
+error_xshmattach:
+ shmdt( image->seginfo.shmaddr );
+
+error_shmat:
+ shmctl( image->seginfo.shmid, IPC_RMID, NULL );
+
+error:
+ XDestroyImage( ximage );
+
+ XUnlockDisplay( x11->display );
+
+ return DFB_FAILURE;
+}
+
+DFBResult
+dfb_x11_image_destroy_handler( DFBX11 *x11, x11Image *image )
+{
+ D_MAGIC_ASSERT( image, x11Image );
+
+ XLockDisplay( x11->display );
+
+ XFreeGC( x11->display, image->gc );
+ XFreePixmap( x11->display, image->pixmap );
+
+ XShmDetach( x11->display, &image->seginfo );
+
+ XDestroyImage( image->ximage );
+
+ XUnlockDisplay( x11->display );
+
+ shmdt( image->seginfo.shmaddr );
+
+ shmctl( image->seginfo.shmid, IPC_RMID, NULL );
+
+ return DFB_OK;
+}
+