/* GDK - The GIMP Drawing Kit * Copyright (C) 1995-1997 Peter Mattis, Spencer Kimball and Josh MacDonald * * 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. */ /* * Modified by the GTK+ Team and others 1997-2000. See the AUTHORS * file for a list of people on the GTK+ Team. */ /* * GTK+ DirectFB backend * Copyright (C) 2001-2002 convergence integrated media GmbH * Copyright (C) 2002-2004 convergence GmbH * Written by Denis Oliver Kropp and * Sven Neumann */ #include "config.h" #include "gdk.h" #include "gdkdirectfb.h" #include "gdkprivate-directfb.h" #include "gdkinternals.h" #include "gdkimage.h" static GList *image_list = NULL; static gpointer parent_class = NULL; static void gdk_directfb_image_destroy (GdkImage *image); static void gdk_image_init (GdkImage *image); static void gdk_image_class_init (GdkImageClass *klass); static void gdk_image_finalize (GObject *object); GType gdk_image_get_type (void) { static GType object_type = 0; if (!object_type) { const GTypeInfo object_info = { sizeof (GdkImageClass), (GBaseInitFunc) NULL, (GBaseFinalizeFunc) NULL, (GClassInitFunc) gdk_image_class_init, NULL, /* class_finalize */ NULL, /* class_data */ sizeof (GdkImage), 0, /* n_preallocs */ (GInstanceInitFunc) gdk_image_init, }; object_type = g_type_register_static (G_TYPE_OBJECT, "GdkImage", &object_info, 0); } return object_type; } static void gdk_image_init (GdkImage *image) { image->windowing_data = g_new0 (GdkImageDirectFB, 1); image->mem = NULL; image_list = g_list_prepend (image_list, image); } static void gdk_image_class_init (GdkImageClass *klass) { GObjectClass *object_class = G_OBJECT_CLASS (klass); parent_class = g_type_class_peek_parent (klass); object_class->finalize = gdk_image_finalize; } static void gdk_image_finalize (GObject *object) { GdkImage *image; image = GDK_IMAGE (object); image_list = g_list_remove (image_list, image); if (image->depth == 1) g_free (image->mem); gdk_directfb_image_destroy (image); if (G_OBJECT_CLASS (parent_class)->finalize) G_OBJECT_CLASS (parent_class)->finalize (object); } /* this function is called from the atexit handler! */ void _gdk_image_exit (void) { GObject *image; while (image_list) { image = image_list->data; gdk_image_finalize (image); } } void _gdk_windowing_image_init (void) { } GdkImage* _gdk_image_new_for_depth (GdkScreen *screen, GdkImageType type, GdkVisual *visual, gint width, gint height, gint depth) { GdkImage *image; GdkImageDirectFB *private; DFBResult ret; gint pitch; DFBSurfacePixelFormat format; IDirectFBSurface *surface; if (type == GDK_IMAGE_FASTEST || type == GDK_IMAGE_NORMAL) type = GDK_IMAGE_SHARED; if (visual) depth = visual->depth; switch (depth) { case 8: format = DSPF_LUT8; break; case 15: format = DSPF_ARGB1555; break; case 16: format = DSPF_RGB16; break; case 24: format = DSPF_RGB32; break; case 32: format = DSPF_ARGB; break; default: g_message ("unimplemented %s for depth %d", G_STRFUNC, depth); return NULL; } surface = gdk_display_dfb_create_surface(_gdk_display,format,width,height); if (!surface) { return NULL; } surface->GetPixelFormat( surface, &format ); image = g_object_new (gdk_image_get_type (), NULL); private = image->windowing_data; private->surface = surface; ret = surface->Lock( surface, DSLF_WRITE, &image->mem, &pitch ); if (ret) { DirectFBError( "IDirectFBSurface::Lock() for writing failed!\n", ret ); g_object_unref( image ); return NULL; } image->type = type; image->visual = visual; #if G_BYTE_ORDER == G_BIG_ENDIAN image->byte_order = GDK_MSB_FIRST; #else image->byte_order = GDK_LSB_FIRST; #endif image->width = width; image->height = height; image->depth = depth; image->bpp = DFB_BYTES_PER_PIXEL (format); image->bpl = pitch; image->bits_per_pixel = DFB_BITS_PER_PIXEL (format); image_list = g_list_prepend (image_list, image); return image; } GdkImage* _gdk_directfb_copy_to_image (GdkDrawable *drawable, GdkImage *image, gint src_x, gint src_y, gint dest_x, gint dest_y, gint width, gint height) { GdkDrawableImplDirectFB *impl; GdkImageDirectFB *private; int pitch; DFBRectangle rect = { src_x, src_y, width, height }; IDirectFBDisplayLayer *layer = _gdk_display->layer; g_return_val_if_fail (GDK_IS_DRAWABLE_IMPL_DIRECTFB (drawable), NULL); g_return_val_if_fail (image != NULL || (dest_x == 0 && dest_y == 0), NULL); impl = GDK_DRAWABLE_IMPL_DIRECTFB (drawable); if (impl->wrapper == _gdk_parent_root) { DFBResult ret; ret = layer->SetCooperativeLevel (layer, DLSCL_ADMINISTRATIVE); if (ret) { DirectFBError ("_gdk_directfb_copy_to_image - SetCooperativeLevel", ret); return NULL; } ret = layer->GetSurface (layer, &impl->surface); if (ret) { layer->SetCooperativeLevel (layer, DLSCL_SHARED); DirectFBError ("_gdk_directfb_copy_to_image - GetSurface", ret); return NULL; } } if (! impl->surface) return NULL; if (!image) image = gdk_image_new (GDK_IMAGE_NORMAL, gdk_drawable_get_visual (drawable), width, height); private = image->windowing_data; private->surface->Unlock( private->surface ); private->surface->Blit( private->surface, impl->surface, &rect, dest_x, dest_y ); private->surface->Lock( private->surface, DSLF_READ | DSLF_WRITE, &image->mem, &pitch ); image->bpl = pitch; if (impl->wrapper == _gdk_parent_root) { impl->surface->Release (impl->surface); impl->surface = NULL; layer->SetCooperativeLevel (layer, DLSCL_SHARED); } return image; } guint32 gdk_image_get_pixel (GdkImage *image, gint x, gint y) { guint32 pixel = 0; g_return_val_if_fail (GDK_IS_IMAGE (image), 0); if (!(x >= 0 && x < image->width && y >= 0 && y < image->height)) return 0; if (image->depth == 1) pixel = (((guchar *) image->mem)[y * image->bpl + (x >> 3)] & (1 << (7 - (x & 0x7)))) != 0; else { guchar *pixelp = (guchar *) image->mem + y * image->bpl + x * image->bpp; switch (image->bpp) { case 1: pixel = *pixelp; break; case 2: pixel = pixelp[0] | (pixelp[1] << 8); break; case 3: pixel = pixelp[0] | (pixelp[1] << 8) | (pixelp[2] << 16); break; case 4: pixel = pixelp[0] | (pixelp[1] << 8) | (pixelp[2] << 16); break; } } return pixel; } void gdk_image_put_pixel (GdkImage *image, gint x, gint y, guint32 pixel) { g_return_if_fail (image != NULL); if (!(x >= 0 && x < image->width && y >= 0 && y < image->height)) return; if (image->depth == 1) if (pixel & 1) ((guchar *) image->mem)[y * image->bpl + (x >> 3)] |= (1 << (7 - (x & 0x7))); else ((guchar *) image->mem)[y * image->bpl + (x >> 3)] &= ~(1 << (7 - (x & 0x7))); else { guchar *pixelp = (guchar *) image->mem + y * image->bpl + x * image->bpp; switch (image->bpp) { case 4: pixelp[3] = 0xFF; case 3: pixelp[2] = ((pixel >> 16) & 0xFF); case 2: pixelp[1] = ((pixel >> 8) & 0xFF); case 1: pixelp[0] = (pixel & 0xFF); } } } static void gdk_directfb_image_destroy (GdkImage *image) { GdkImageDirectFB *private; g_return_if_fail (GDK_IS_IMAGE (image)); private = image->windowing_data; if (!private) return; GDK_NOTE (MISC, g_print ("gdk_directfb_image_destroy: %#lx\n", (gulong) private->surface)); private->surface->Unlock( private->surface ); private->surface->Release( private->surface ); g_free (private); image->windowing_data = NULL; } gint _gdk_windowing_get_bits_for_depth (GdkDisplay *display, gint depth) { switch (depth) { case 1: case 8: return 8; case 15: case 16: return 16; case 24: case 32: return 32; } return 0; }