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