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 
G_DEFINE_TYPE(GdkImage,gdk_image,G_TYPE_OBJECT)54 G_DEFINE_TYPE (GdkImage, gdk_image, G_TYPE_OBJECT)
55 
56 static void
57 gdk_image_init (GdkImage *image)
58 {
59   image->windowing_data = g_new0 (GdkImageDirectFB, 1);
60   image->mem = NULL;
61 
62   image_list = g_list_prepend (image_list, image);
63 }
64 
65 static void
gdk_image_class_init(GdkImageClass * klass)66 gdk_image_class_init (GdkImageClass *klass)
67 {
68   GObjectClass *object_class = G_OBJECT_CLASS (klass);
69 
70   parent_class = g_type_class_peek_parent (klass);
71 
72   object_class->finalize = gdk_image_finalize;
73 }
74 
75 static void
gdk_image_finalize(GObject * object)76 gdk_image_finalize (GObject *object)
77 {
78   GdkImage *image;
79 
80   image = GDK_IMAGE (object);
81 
82   image_list = g_list_remove (image_list, image);
83 
84   if (image->depth == 1)
85     g_free (image->mem);
86 
87   gdk_directfb_image_destroy (image);
88 
89   if (G_OBJECT_CLASS (parent_class)->finalize)
90     G_OBJECT_CLASS (parent_class)->finalize (object);
91 }
92 
93 
94 /* this function is called from the atexit handler! */
95 void
_gdk_image_exit(void)96 _gdk_image_exit (void)
97 {
98   GObject *image;
99 
100   while (image_list)
101     {
102       image = image_list->data;
103 
104       gdk_image_finalize (image);
105     }
106 }
107 
108 GdkImage *
gdk_image_new_bitmap(GdkVisual * visual,gpointer data,gint w,gint h)109 gdk_image_new_bitmap (GdkVisual *visual,
110                       gpointer   data,
111                       gint       w,
112                       gint       h)
113 {
114   GdkImage         *image;
115   GdkImageDirectFB *private;
116 
117   image = g_object_new (gdk_image_get_type (), NULL);
118   private = image->windowing_data;
119 
120   image->type   = GDK_IMAGE_SHARED;
121   image->visual = visual;
122   image->width  = w;
123   image->height = h;
124   image->depth  = 1;
125 
126   GDK_NOTE (MISC, g_print ("gdk_image_new_bitmap: %dx%d\n", w, h));
127 
128   g_message ("not fully implemented %s", G_STRFUNC);
129 
130   image->bpl = (w + 7) / 8;
131   image->mem = g_malloc (image->bpl * h);
132 #if G_BYTE_ORDER == G_BIG_ENDIAN
133   image->byte_order = GDK_MSB_FIRST;
134 #else
135   image->byte_order = GDK_LSB_FIRST;
136 #endif
137   image->bpp = 1;
138 
139   return image;
140 }
141 
142 void
_gdk_windowing_image_init(void)143 _gdk_windowing_image_init (void)
144 {
145 }
146 
147 GdkImage*
_gdk_image_new_for_depth(GdkScreen * screen,GdkImageType type,GdkVisual * visual,gint width,gint height,gint depth)148 _gdk_image_new_for_depth (GdkScreen    *screen,
149                           GdkImageType  type,
150                           GdkVisual    *visual,
151                           gint          width,
152                           gint          height,
153                           gint          depth)
154 {
155   GdkImage              *image;
156   GdkImageDirectFB      *private;
157   DFBResult              ret;
158   gint                   pitch;
159   DFBSurfacePixelFormat  format;
160   IDirectFBSurface      *surface;
161 
162   if (type == GDK_IMAGE_FASTEST || type == GDK_IMAGE_NORMAL)
163     type = GDK_IMAGE_SHARED;
164 
165   if (visual)
166     depth = visual->depth;
167 
168   switch (depth)
169     {
170     case 8:
171       format = DSPF_LUT8;
172       break;
173     case 15:
174       format = DSPF_ARGB1555;
175       break;
176     case 16:
177       format = DSPF_RGB16;
178       break;
179     case 24:
180       format = DSPF_RGB32;
181       break;
182     case 32:
183       format = DSPF_ARGB;
184       break;
185     default:
186       g_message ("unimplemented %s for depth %d", G_STRFUNC, depth);
187       return NULL;
188     }
189 
190   surface = gdk_display_dfb_create_surface (_gdk_display, format,
191                                             width, height);
192   if (!surface)
193     {
194       return NULL;
195     }
196   surface->GetPixelFormat (surface, &format);
197 
198   image = g_object_new (gdk_image_get_type (), NULL);
199   private = image->windowing_data;
200 
201   private->surface = surface;
202 
203   ret = surface->Lock (surface, DSLF_WRITE, &image->mem, &pitch);
204   if (ret)
205     {
206       DirectFBError ("IDirectFBSurface::Lock() for writing failed!\n", ret);
207       g_object_unref (image);
208       return NULL;
209     }
210 
211   image->type           = type;
212   image->visual         = visual;
213 #if G_BYTE_ORDER == G_BIG_ENDIAN
214   image->byte_order	= GDK_MSB_FIRST;
215 #else
216   image->byte_order 	= GDK_LSB_FIRST;
217 #endif
218   image->width          = width;
219   image->height         = height;
220   image->depth          = depth;
221   image->bpp            = DFB_BYTES_PER_PIXEL (format);
222   image->bpl            = pitch;
223   image->bits_per_pixel = DFB_BITS_PER_PIXEL (format);
224 
225   image_list = g_list_prepend (image_list, image);
226 
227   return image;
228 }
229 
230 
231 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)232 _gdk_directfb_copy_to_image (GdkDrawable *drawable,
233                              GdkImage    *image,
234                              gint         src_x,
235                              gint         src_y,
236                              gint         dest_x,
237                              gint         dest_y,
238                              gint         width,
239                              gint         height)
240 {
241   GdkDrawableImplDirectFB *impl;
242   GdkImageDirectFB        *private;
243   int                      pitch;
244   DFBRectangle             rect  = { src_x, src_y, width, height };
245   IDirectFBDisplayLayer   *layer = _gdk_display->layer;
246 
247   g_return_val_if_fail (GDK_IS_DRAWABLE_IMPL_DIRECTFB (drawable), NULL);
248   g_return_val_if_fail (image != NULL || (dest_x == 0 && dest_y == 0), NULL);
249 
250   impl = GDK_DRAWABLE_IMPL_DIRECTFB (drawable);
251 
252   if (impl->wrapper == _gdk_parent_root)
253     {
254       DFBResult ret;
255 
256       ret = layer->SetCooperativeLevel (layer, DLSCL_ADMINISTRATIVE);
257       if (ret)
258         {
259           DirectFBError ("_gdk_directfb_copy_to_image - SetCooperativeLevel",
260                          ret);
261           return NULL;
262         }
263 
264       ret = layer->GetSurface (layer, &impl->surface);
265       if (ret)
266         {
267           layer->SetCooperativeLevel (layer, DLSCL_SHARED);
268           DirectFBError ("_gdk_directfb_copy_to_image - GetSurface", ret);
269           return NULL;
270         }
271     }
272 
273   if (!impl->surface)
274     return NULL;
275 
276   if (!image)
277     image =  gdk_image_new (GDK_IMAGE_NORMAL,
278                             gdk_drawable_get_visual (drawable), width, height);
279 
280   private = image->windowing_data;
281 
282   private->surface->Unlock (private->surface);
283 
284   private->surface->Blit (private->surface,
285                           impl->surface, &rect, dest_x, dest_y);
286 
287   private->surface->Lock (private->surface,
288                           DSLF_READ | DSLF_WRITE,
289                           &image->mem, &pitch);
290   image->bpl = pitch;
291 
292   if (impl->wrapper == _gdk_parent_root)
293     {
294       impl->surface->Release (impl->surface);
295       impl->surface = NULL;
296       layer->SetCooperativeLevel (layer, DLSCL_SHARED);
297     }
298 
299   return image;
300 }
301 
302 guint32
gdk_image_get_pixel(GdkImage * image,gint x,gint y)303 gdk_image_get_pixel (GdkImage *image,
304                      gint      x,
305                      gint      y)
306 {
307   guint32 pixel = 0;
308 
309   g_return_val_if_fail (GDK_IS_IMAGE (image), 0);
310 
311   if (!(x >= 0 && x < image->width && y >= 0 && y < image->height))
312     return 0;
313 
314   if (image->depth == 1)
315     pixel = (((guchar *) image->mem)[y * image->bpl + (x >> 3)] & (1 << (7 - (x & 0x7)))) != 0;
316   else
317     {
318       guchar *pixelp = (guchar *) image->mem + y * image->bpl + x * image->bpp;
319 
320       switch (image->bpp)
321         {
322         case 1:
323           pixel = *pixelp;
324           break;
325 
326         case 2:
327           pixel = pixelp[0] | (pixelp[1] << 8);
328           break;
329 
330         case 3:
331           pixel = pixelp[0] | (pixelp[1] << 8) | (pixelp[2] << 16);
332           break;
333 
334         case 4:
335           pixel = pixelp[0] | (pixelp[1] << 8) | (pixelp[2] << 16);
336           break;
337         }
338     }
339 
340   return pixel;
341 }
342 
343 void
gdk_image_put_pixel(GdkImage * image,gint x,gint y,guint32 pixel)344 gdk_image_put_pixel (GdkImage *image,
345                      gint       x,
346                      gint       y,
347                      guint32    pixel)
348 {
349   g_return_if_fail (image != NULL);
350 
351   if (!(x >= 0 && x < image->width && y >= 0 && y < image->height))
352     return;
353 
354   if (image->depth == 1)
355     if (pixel & 1)
356       ((guchar *) image->mem)[y * image->bpl + (x >> 3)] |= (1 << (7 - (x & 0x7)));
357     else
358       ((guchar *) image->mem)[y * image->bpl + (x >> 3)] &= ~(1 << (7 - (x & 0x7)));
359   else
360     {
361       guchar *pixelp = (guchar *) image->mem + y * image->bpl + x * image->bpp;
362 
363       switch (image->bpp)
364         {
365         case 4:
366           pixelp[3] = 0xFF;
367         case 3:
368           pixelp[2] = ((pixel >> 16) & 0xFF);
369         case 2:
370           pixelp[1] = ((pixel >> 8) & 0xFF);
371         case 1:
372           pixelp[0] = (pixel & 0xFF);
373         }
374     }
375 }
376 
377 static void
gdk_directfb_image_destroy(GdkImage * image)378 gdk_directfb_image_destroy (GdkImage *image)
379 {
380   GdkImageDirectFB *private;
381 
382   g_return_if_fail (GDK_IS_IMAGE (image));
383 
384   private = image->windowing_data;
385 
386   if (!private)
387     return;
388 
389   GDK_NOTE (MISC, g_print ("gdk_directfb_image_destroy: %#lx\n",
390                            (gulong) private->surface));
391 
392   private->surface->Unlock (private->surface);
393   private->surface->Release (private->surface);
394 
395   g_free (private);
396   image->windowing_data = NULL;
397 }
398 
399 gint
_gdk_windowing_get_bits_for_depth(GdkDisplay * display,gint depth)400 _gdk_windowing_get_bits_for_depth (GdkDisplay *display,
401                                    gint        depth)
402 {
403   switch (depth)
404     {
405     case 1:
406     case 8:
407       return 8;
408     case 15:
409     case 16:
410       return 16;
411     case 24:
412     case 32:
413       return 32;
414     }
415 
416   return 0;
417 }
418 
419 #define __GDK_IMAGE_X11_C__
420 #include "gdkaliasdef.c"
421