]> Pileus Git - ~andy/gtk/blob - gdk/directfb/gdkimage-directfb.c
gdk/directfb/gdkdirectfb.h gdk/directfb/gdkdisplay-directfb.c
[~andy/gtk] / gdk / directfb / gdkimage-directfb.c
1 /* GDK - The GIMP Drawing Kit
2  * Copyright (C) 1995-1997 Peter Mattis, Spencer Kimball and Josh MacDonald
3  *
4  * This library is free software; you can redistribute it and/or
5  * modify it under the terms of the GNU Lesser General Public
6  * License as published by the Free Software Foundation; either
7  * version 2 of the License, or (at your option) any later version.
8  *
9  * This library is distributed in the hope that it will be useful,
10  * but WITHOUT ANY WARRANTY; without even the implied warranty of
11  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
12  * Lesser General Public License for more details.
13  *
14  * You should have received a copy of the GNU Lesser General Public
15  * License along with this library; if not, write to the
16  * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
17  * Boston, MA 02111-1307, USA.
18  */
19
20 /*
21  * Modified by the GTK+ Team and others 1997-2000.  See the AUTHORS
22  * file for a list of people on the GTK+ Team.
23  */
24
25 /*
26  * GTK+ DirectFB backend
27  * Copyright (C) 2001-2002  convergence integrated media GmbH
28  * Copyright (C) 2002-2004  convergence GmbH
29  * Written by Denis Oliver Kropp <dok@convergence.de> and
30  *            Sven Neumann <sven@convergence.de>
31  */
32
33 #include <config.h>
34 #include "gdk.h"
35
36
37 #include "gdkdirectfb.h"
38 #include "gdkprivate-directfb.h"
39
40 #include "gdkinternals.h"
41
42 #include "gdkimage.h"
43 #include "gdkalias.h"
44
45
46 static GList    *image_list   = NULL;
47 static gpointer  parent_class = NULL;
48
49 static void gdk_directfb_image_destroy (GdkImage      *image);
50 static void gdk_image_init             (GdkImage      *image);
51 static void gdk_image_class_init       (GdkImageClass *klass);
52 static void gdk_image_finalize         (GObject       *object);
53
54 GType
55 gdk_image_get_type (void)
56 {
57   static GType object_type = 0;
58
59   if (!object_type)
60     {
61       static const GTypeInfo object_info =
62         {
63           sizeof (GdkImageClass),
64           (GBaseInitFunc) NULL,
65           (GBaseFinalizeFunc) NULL,
66           (GClassInitFunc) gdk_image_class_init,
67           NULL,           /* class_finalize */
68           NULL,           /* class_data */
69           sizeof (GdkImage),
70           0,              /* n_preallocs */
71           (GInstanceInitFunc) gdk_image_init,
72         };
73
74       object_type = g_type_register_static (G_TYPE_OBJECT,
75                                             "GdkImage",
76                                             &object_info, 0);
77     }
78
79   return object_type;
80 }
81
82 static void
83 gdk_image_init (GdkImage *image)
84 {
85   image->windowing_data = g_new0 (GdkImageDirectFB, 1);
86   image->mem = NULL;
87
88   image_list = g_list_prepend (image_list, image);
89 }
90
91 static void
92 gdk_image_class_init (GdkImageClass *klass)
93 {
94   GObjectClass *object_class = G_OBJECT_CLASS (klass);
95
96   parent_class = g_type_class_peek_parent (klass);
97
98   object_class->finalize = gdk_image_finalize;
99 }
100
101 static void
102 gdk_image_finalize (GObject *object)
103 {
104   GdkImage *image;
105
106   image = GDK_IMAGE (object);
107
108   image_list = g_list_remove (image_list, image);
109
110   if (image->depth == 1)
111     g_free (image->mem);
112
113   gdk_directfb_image_destroy (image);
114
115   if (G_OBJECT_CLASS (parent_class)->finalize)
116     G_OBJECT_CLASS (parent_class)->finalize (object);
117 }
118
119
120 /* this function is called from the atexit handler! */
121 void
122 _gdk_image_exit (void)
123 {
124   GObject *image;
125
126   while (image_list)
127     {
128       image = image_list->data;
129
130       gdk_image_finalize (image);
131     }
132 }
133
134 GdkImage *
135 gdk_image_new_bitmap (GdkVisual *visual,
136                       gpointer   data,
137                       gint       w,
138                       gint       h)
139 {
140   GdkImage         *image;
141   GdkImageDirectFB *private;
142
143   image = g_object_new (gdk_image_get_type (), NULL);
144   private = image->windowing_data;
145
146   image->type   = GDK_IMAGE_SHARED;
147   image->visual = visual;
148   image->width  = w;
149   image->height = h;
150   image->depth  = 1;
151
152   GDK_NOTE (MISC, g_print ("gdk_image_new_bitmap: %dx%d\n", w, h));
153
154   g_message ("not fully implemented %s", __FUNCTION__);
155
156   image->bpl = (w + 7) / 8;
157   image->mem = g_malloc (image->bpl * h);
158 #if G_BYTE_ORDER == G_BIG_ENDIAN
159   image->byte_order = GDK_MSB_FIRST;
160 #else
161   image->byte_order = GDK_LSB_FIRST;
162 #endif
163   image->bpp = 1;
164
165   return image;
166 }
167
168 void
169 _gdk_windowing_image_init (void)
170 {
171 }
172
173 GdkImage*
174 _gdk_image_new_for_depth (GdkScreen    *screen,
175                           GdkImageType  type,
176                           GdkVisual    *visual,
177                           gint          width,
178                           gint          height,
179                           gint          depth)
180 {
181   GdkImage              *image;
182   GdkImageDirectFB      *private;
183   DFBResult              ret;
184   gint                   pitch;
185   DFBSurfacePixelFormat  format;
186   IDirectFBSurface      *surface;
187
188   if (type == GDK_IMAGE_FASTEST || type == GDK_IMAGE_NORMAL)
189     type = GDK_IMAGE_SHARED;
190
191   if (visual)
192     depth = visual->depth;
193
194   switch (depth)
195     {
196     case 8:
197       format = DSPF_LUT8;
198       break;
199     case 15:
200       format = DSPF_ARGB1555;
201       break;
202     case 16:
203       format = DSPF_RGB16;
204       break;
205     case 24:
206       format = DSPF_RGB32;
207       break;
208     case 32:
209       format = DSPF_ARGB;
210       break;
211     default:
212       g_message ("unimplemented %s for depth %d", __FUNCTION__, depth);
213       return NULL;
214     }
215
216   surface = gdk_display_dfb_create_surface(_gdk_display,format,width,height);
217   if (!surface)
218     {
219       return NULL;
220     }
221   surface->GetPixelFormat( surface, &format );
222
223   image = g_object_new (gdk_image_get_type (), NULL);
224   private = image->windowing_data;
225
226   private->surface = surface;
227
228   ret = surface->Lock( surface, DSLF_WRITE, &image->mem, &pitch );
229   if (ret)
230     {
231       DirectFBError( "IDirectFBSurface::Lock() for writing failed!\n", ret );
232       gdk_image_unref( image );
233       return NULL;
234     }
235
236   image->type           = type;
237   image->visual         = visual;
238 #if G_BYTE_ORDER == G_BIG_ENDIAN
239   image->byte_order             = GDK_MSB_FIRST;
240 #else
241   image->byte_order     = GDK_LSB_FIRST;
242 #endif
243   image->width          = width;
244   image->height         = height;
245   image->depth          = depth;
246   image->bpp            = DFB_BYTES_PER_PIXEL (format);
247   image->bpl            = pitch;
248   image->bits_per_pixel = DFB_BITS_PER_PIXEL (format);
249
250   image_list = g_list_prepend (image_list, image);
251
252   return image;
253 }
254
255
256 GdkImage*
257 _gdk_directfb_copy_to_image (GdkDrawable *drawable,
258                              GdkImage    *image,
259                              gint         src_x,
260                              gint         src_y,
261                              gint         dest_x,
262                              gint         dest_y,
263                              gint         width,
264                              gint         height)
265 {
266   GdkDrawableImplDirectFB *impl;
267   GdkImageDirectFB        *private;
268   int                      pitch;
269   DFBRectangle             rect = { src_x, src_y, width, height };
270   IDirectFBDisplayLayer *layer = _gdk_display->layer;
271
272   g_return_val_if_fail (GDK_IS_DRAWABLE_IMPL_DIRECTFB (drawable), NULL);
273   g_return_val_if_fail (image != NULL || (dest_x == 0 && dest_y == 0), NULL);
274
275   impl = GDK_DRAWABLE_IMPL_DIRECTFB (drawable);
276
277   if (impl->wrapper == _gdk_parent_root)
278     {
279       DFBResult ret;
280
281       ret = layer->SetCooperativeLevel (layer, DLSCL_EXCLUSIVE);
282       if (ret)
283         {
284           DirectFBError ("_gdk_directfb_copy_to_image - SetCooperativeLevel",
285                          ret);
286           return NULL;
287         }
288
289       ret = layer->GetSurface (layer, &impl->surface);
290       if (ret)
291         {
292           layer->SetCooperativeLevel (layer, DLSCL_SHARED);
293           DirectFBError ("_gdk_directfb_copy_to_image - GetSurface", ret);
294           return NULL;
295         }
296     }
297
298   if (! impl->surface)
299     return NULL;
300
301   if (!image)
302     image =  gdk_image_new (GDK_IMAGE_NORMAL,
303                             gdk_visual_get_system (), width, height);
304
305   private = image->windowing_data;
306
307   private->surface->Unlock( private->surface );
308
309   private->surface->Blit( private->surface,
310                           impl->surface, &rect, dest_x, dest_y );
311
312   private->surface->Lock( private->surface, DSLF_WRITE, &image->mem, &pitch );
313   image->bpl = pitch;
314
315   if (impl->wrapper == _gdk_parent_root)
316     {
317       impl->surface->Release (impl->surface);
318       impl->surface = NULL;
319       layer->SetCooperativeLevel (layer, DLSCL_SHARED);
320     }
321
322   return image;
323 }
324
325 guint32
326 gdk_image_get_pixel (GdkImage *image,
327                      gint      x,
328                      gint      y)
329 {
330   guint32 pixel = 0;
331
332   g_return_val_if_fail (GDK_IS_IMAGE (image), 0);
333
334   if (!(x >= 0 && x < image->width && y >= 0 && y < image->height))
335     return 0;
336
337   if (image->depth == 1)
338     pixel = (((guchar *) image->mem)[y * image->bpl + (x >> 3)] & (1 << (7 - (x & 0x7)))) != 0;
339   else
340     {
341       guchar *pixelp = (guchar *) image->mem + y * image->bpl + x * image->bpp;
342
343       switch (image->bpp)
344         {
345         case 1:
346           pixel = *pixelp;
347           break;
348
349         case 2:
350           pixel = pixelp[0] | (pixelp[1] << 8);
351           break;
352
353         case 3:
354           pixel = pixelp[0] | (pixelp[1] << 8) | (pixelp[2] << 16);
355           break;
356
357         case 4:
358           pixel = pixelp[0] | (pixelp[1] << 8) | (pixelp[2] << 16);
359           break;
360         }
361     }
362
363   return pixel;
364 }
365
366 void
367 gdk_image_put_pixel (GdkImage *image,
368                      gint       x,
369                      gint       y,
370                      guint32    pixel)
371 {
372   g_return_if_fail (image != NULL);
373
374   if  (!(x >= 0 && x < image->width && y >= 0 && y < image->height))
375     return;
376
377   if (image->depth == 1)
378     if (pixel & 1)
379       ((guchar *) image->mem)[y * image->bpl + (x >> 3)] |= (1 << (7 - (x & 0x7)));
380     else
381       ((guchar *) image->mem)[y * image->bpl + (x >> 3)] &= ~(1 << (7 - (x & 0x7)));
382   else
383     {
384       guchar *pixelp = (guchar *) image->mem + y * image->bpl + x * image->bpp;
385
386       switch (image->bpp)
387         {
388         case 4:
389           pixelp[3] = 0xFF;
390         case 3:
391           pixelp[2] = ((pixel >> 16) & 0xFF);
392         case 2:
393           pixelp[1] = ((pixel >> 8) & 0xFF);
394         case 1:
395           pixelp[0] = (pixel & 0xFF);
396         }
397     }
398 }
399
400 static void
401 gdk_directfb_image_destroy (GdkImage *image)
402 {
403   GdkImageDirectFB *private;
404
405   g_return_if_fail (GDK_IS_IMAGE (image));
406
407   private = image->windowing_data;
408
409   if (!private)
410     return;
411
412   GDK_NOTE (MISC, g_print ("gdk_directfb_image_destroy: %#lx\n",
413                            (gulong) private->surface));
414
415   private->surface->Unlock( private->surface );
416   private->surface->Release( private->surface );
417
418   g_free (private);
419   image->windowing_data = NULL;
420 }
421
422 gint
423 _gdk_windowing_get_bits_for_depth (GdkDisplay *display,
424                                    gint        depth)
425 {
426   switch (depth)
427     {
428     case 1:
429     case 8:
430       return 8;
431     case 15:
432     case 16:
433       return 16;
434     case 24:
435     case 32:
436       return 32;
437     }
438
439   return 0;
440 }
441
442 #define __GDK_IMAGE_X11_C__
443 #include "gdkaliasdef.c"