]> Pileus Git - ~andy/gtk/blob - gdk/directfb/gdkdrawable-directfb.c
gdk/directfb: fix _gdk_windowing_pointer_grab()
[~andy/gtk] / gdk / directfb / gdkdrawable-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 #include <assert.h>
36
37 #include <string.h>
38
39 #include "gdkdirectfb.h"
40 #include "gdkprivate-directfb.h"
41
42 #include "../../gdk-pixbuf/gdk-pixbuf-private.h"
43
44 #include "gdkinternals.h"
45
46
47 #include "gdkregion-generic.h"
48 #include "gdkalias.h"
49
50 #include "cairo-directfb.h"
51
52
53 #include <direct/debug.h>
54 #include <direct/messages.h>
55
56 /*
57  * There can be multiple domains in one file and one domain (same same) in multiple files.
58  */
59 D_DEBUG_DOMAIN( GDKDFB_Drawable, "GDKDFB/Drawable", "GDK DirectFB Drawable" );
60 D_DEBUG_DOMAIN( GDKDFB_DrawClip, "GDKDFB/DrawClip", "GDK DirectFB Drawable Clip Region" );
61
62
63 /* From DirectFB's <gfx/generix/duffs_device.h> */
64 #define DUFF_1() \
65                case 1:\
66                     SET_PIXEL( D[0], S[0] );
67
68 #define DUFF_2() \
69                case 3:\
70                     SET_PIXEL( D[2], S[2] );\
71                case 2:\
72                     SET_PIXEL( D[1], S[1] );\
73                DUFF_1()
74
75 #define DUFF_3() \
76                case 7:\
77                     SET_PIXEL( D[6], S[6] );\
78                case 6:\
79                     SET_PIXEL( D[5], S[5] );\
80                case 5:\
81                     SET_PIXEL( D[4], S[4] );\
82                case 4:\
83                     SET_PIXEL( D[3], S[3] );\
84                DUFF_2()
85
86 #define DUFF_4() \
87                case 15:\
88                     SET_PIXEL( D[14], S[14] );\
89                case 14:\
90                     SET_PIXEL( D[13], S[13] );\
91                case 13:\
92                     SET_PIXEL( D[12], S[12] );\
93                case 12:\
94                     SET_PIXEL( D[11], S[11] );\
95                case 11:\
96                     SET_PIXEL( D[10], S[10] );\
97                case 10:\
98                     SET_PIXEL( D[9], S[9] );\
99                case 9:\
100                     SET_PIXEL( D[8], S[8] );\
101                case 8:\
102                     SET_PIXEL( D[7], S[7] );\
103                DUFF_3()
104
105 #define SET_PIXEL_DUFFS_DEVICE_N( D, S, w, n ) \
106 do {\
107      while (w) {\
108           register int l = w & ((1 << n) - 1);\
109           switch (l) {\
110                default:\
111                     l = (1 << n);\
112                     SET_PIXEL( D[(1 << n)-1], S[(1 << n)-1] );\
113                DUFF_##n()\
114           }\
115           D += l;\
116           S += l;\
117           w -= l;\
118      }\
119 } while(0)
120
121
122 static GdkScreen * gdk_directfb_get_screen (GdkDrawable    *drawable);
123 static void gdk_drawable_impl_directfb_class_init (GdkDrawableImplDirectFBClass *klass);
124 static void gdk_directfb_draw_lines (GdkDrawable *drawable,
125                                      GdkGC       *gc,
126                                      GdkPoint    *points,
127                                      gint         npoints);
128
129 static cairo_surface_t *gdk_directfb_ref_cairo_surface (GdkDrawable *drawable);
130
131
132 static gboolean  accelerated_alpha_blending = FALSE;
133 static gpointer  parent_class               = NULL;
134 static const cairo_user_data_key_t gdk_directfb_cairo_key;
135
136 static void (*real_draw_pixbuf) (GdkDrawable *drawable,
137                                  GdkGC       *gc,
138                                  GdkPixbuf   *pixbuf,
139                                  gint         src_x,
140                                  gint         src_y,
141                                  gint         dest_x,
142                                  gint         dest_y,
143                                  gint         width,
144                                  gint         height,
145                                  GdkRgbDither dither,
146                                  gint         x_dither,
147                                  gint         y_dither);
148
149
150 /**********************************************************
151  * DirectFB specific implementations of generic functions *
152  **********************************************************/
153
154
155 static void
156 gdk_directfb_set_colormap (GdkDrawable *drawable,
157                            GdkColormap *colormap)
158 {
159   GdkDrawableImplDirectFB *impl;
160
161   impl = GDK_DRAWABLE_IMPL_DIRECTFB (drawable);
162
163   D_DEBUG_AT( GDKDFB_Drawable, "%s( %p, %p ) <- old %p\n", G_STRFUNC, drawable, colormap, impl->colormap );
164
165   if (impl->colormap == colormap)
166     return;
167
168   if (impl->colormap)
169     g_object_unref (impl->colormap);
170
171   impl->colormap = colormap;
172
173   if (colormap)
174     g_object_ref (colormap);
175 }
176
177 static GdkColormap*
178 gdk_directfb_get_colormap (GdkDrawable *drawable)
179 {
180   GdkColormap *retval;
181
182   retval = GDK_DRAWABLE_IMPL_DIRECTFB (drawable)->colormap;
183
184   if (!retval) {
185     retval = gdk_colormap_get_system ();
186         gdk_directfb_set_colormap(drawable,retval);
187   }
188
189   return retval;
190 }
191
192 static gint
193 gdk_directfb_get_depth (GdkDrawable *drawable)
194 {
195   GdkDrawableImplDirectFB *impl = GDK_DRAWABLE_IMPL_DIRECTFB (drawable);
196
197   return DFB_BITS_PER_PIXEL (impl->format);
198 }
199
200 static void
201 gdk_directfb_get_size (GdkDrawable *drawable,
202                        gint        *width,
203                        gint        *height)
204 {
205   GdkDrawableImplDirectFB *impl;
206
207   impl = GDK_DRAWABLE_IMPL_DIRECTFB (drawable);
208
209   if (width)
210     *width = impl->width;
211
212   if (height)
213     *height = impl->height;
214 }
215
216 static GdkVisual*
217 gdk_directfb_get_visual (GdkDrawable *drawable)
218 {
219   return gdk_visual_get_system ();
220 }
221
222 /* Calculates the real clipping region for a drawable, taking into account
223  * other windows and the gc clip region.
224  */
225 void
226 gdk_directfb_clip_region (GdkDrawable  *drawable,
227                           GdkGC        *gc,
228                           GdkRectangle *draw_rect,
229                           GdkRegion    *ret_clip)
230 {
231   GdkDrawableImplDirectFB *private;
232   GdkRectangle             rect;
233
234   g_return_if_fail (GDK_IS_DRAWABLE (drawable));
235   g_return_if_fail (GDK_IS_DRAWABLE_IMPL_DIRECTFB (drawable));
236   g_return_if_fail (ret_clip != NULL);
237
238   D_DEBUG_AT( GDKDFB_DrawClip, "%s( %p, %p, %p )\n", G_STRFUNC, drawable, gc, draw_rect );
239
240   private = GDK_DRAWABLE_IMPL_DIRECTFB (drawable);
241
242   if (!draw_rect)
243     {
244       rect.x      = 0;
245       rect.y      = 0;
246       rect.width  = private->width;
247       rect.height = private->height;
248
249       draw_rect = &rect;
250     }
251   D_DEBUG_AT( GDKDFB_DrawClip, "  -> draw rectangle   == %4d,%4d - %4dx%4d =\n",
252               draw_rect->x, draw_rect->y, draw_rect->width, draw_rect->height );
253
254   temp_region_init_rectangle( ret_clip, draw_rect );
255
256   if (private->buffered) {
257        D_DEBUG_AT( GDKDFB_DrawClip, "  -> buffered region   > %4d,%4d - %4dx%4d <  (%ld boxes)\n",
258                    GDKDFB_RECTANGLE_VALS_FROM_BOX( &private->paint_region.extents ),
259                    private->paint_region.numRects );
260
261     gdk_region_intersect (ret_clip, &private->paint_region);
262   }
263
264   if (gc)
265     {
266       GdkGCDirectFB *gc_private = GDK_GC_DIRECTFB (gc);
267       GdkRegion     *region     = &gc_private->clip_region;
268
269       if (region->numRects)
270         {
271           D_DEBUG_AT( GDKDFB_DrawClip, "  -> clipping region   > %4d,%4d - %4dx%4d <  (%ld boxes)\n",
272                       GDKDFB_RECTANGLE_VALS_FROM_BOX( &region->extents ), region->numRects );
273
274           if (gc->clip_x_origin || gc->clip_y_origin)
275             {
276               gdk_region_offset (ret_clip, -gc->clip_x_origin, -gc->clip_y_origin);
277               gdk_region_intersect (ret_clip, region);
278               gdk_region_offset (ret_clip, gc->clip_x_origin, gc->clip_y_origin);
279             }
280           else
281             {
282               gdk_region_intersect (ret_clip, region);
283             }
284         }
285
286       if (gc_private->values_mask & GDK_GC_SUBWINDOW &&
287           gc_private->values.subwindow_mode == GDK_INCLUDE_INFERIORS)
288         return;
289     }
290
291   if (private->buffered) {
292        D_DEBUG_AT( GDKDFB_DrawClip, "  => returning clip   >> %4d,%4d - %4dx%4d << (%ld boxes)\n",
293                    GDKDFB_RECTANGLE_VALS_FROM_BOX( &ret_clip->extents ), ret_clip->numRects );
294     return;
295   }
296
297   if (GDK_IS_WINDOW (private->wrapper) &&
298       GDK_WINDOW_IS_MAPPED (private->wrapper) &&
299       !GDK_WINDOW_OBJECT (private->wrapper)->input_only)
300     {
301       GList     *cur;
302       GdkRegion  temp;
303
304       temp.numRects = 1;
305       temp.rects = &temp.extents;
306       temp.size = 1;
307
308       for (cur = GDK_WINDOW_OBJECT (private->wrapper)->children;
309            cur;
310            cur = cur->next)
311         {
312           GdkWindowObject         *cur_private;
313           GdkDrawableImplDirectFB *cur_impl;
314
315           cur_private = GDK_WINDOW_OBJECT (cur->data);
316
317           if (!GDK_WINDOW_IS_MAPPED (cur_private) || cur_private->input_only)
318             continue;
319
320           cur_impl = GDK_DRAWABLE_IMPL_DIRECTFB (cur_private->impl);
321
322           temp.extents.x1 = cur_private->x;
323           temp.extents.y1 = cur_private->y;
324           temp.extents.x2 = cur_private->x + cur_impl->width;
325           temp.extents.y2 = cur_private->y + cur_impl->height;
326
327           D_DEBUG_AT( GDKDFB_DrawClip, "  -> clipping child    [ %4d,%4d - %4dx%4d ]  (%ld boxes)\n",
328                       GDKDFB_RECTANGLE_VALS_FROM_BOX( &temp.extents ), temp.numRects );
329
330           gdk_region_subtract (ret_clip, &temp);
331         }
332     }
333
334   D_DEBUG_AT( GDKDFB_DrawClip, "  => returning clip   >> %4d,%4d - %4dx%4d << (%ld boxes)\n",
335               GDKDFB_RECTANGLE_VALS_FROM_BOX( &ret_clip->extents ), ret_clip->numRects );
336 }
337
338 /* Drawing
339  */
340
341 static inline void
342 gdk_directfb_set_color (GdkDrawableImplDirectFB *impl,
343                         GdkColor                *color,
344                         guchar                   alpha)
345 {
346   if (DFB_PIXELFORMAT_IS_INDEXED (impl->format))
347     {
348       impl->surface->SetColorIndex (impl->surface, color->pixel);
349     }
350   else
351     {
352       impl->surface->SetColor (impl->surface,
353                                color->red   >> 8,
354                                color->green >> 8,
355                                color->blue  >> 8,
356                                alpha);
357     }
358 }
359
360 static gboolean
361 gdk_directfb_setup_for_drawing (GdkDrawableImplDirectFB *impl,
362                                 GdkGCDirectFB           *gc_private)
363 {
364   DFBSurfaceDrawingFlags flags = DSDRAW_NOFX;
365   GdkColor               color = { 0, 0, 0, 0 };
366   guchar                 alpha = 0xFF;
367
368   if (!impl->surface)
369     return FALSE;
370
371   if (gc_private && gc_private->values_mask & GDK_GC_FOREGROUND)
372     color = gc_private->values.foreground;
373
374   if (gc_private && gc_private->values_mask & GDK_GC_FUNCTION)
375     {
376       switch (gc_private->values.function)
377         {
378         case GDK_COPY:
379           flags = DSDRAW_NOFX;
380           break;
381
382         case GDK_INVERT:
383           color.red = color.green = color.blue = 0xFFFF;
384           alpha = 0x0;
385           flags = DSDRAW_XOR;
386           break;
387
388         case GDK_XOR:
389           alpha = 0x0;
390           flags = DSDRAW_XOR;
391           break;
392
393         case GDK_CLEAR:
394           color.red = color.green = color.blue = 0x0;
395           flags = DSDRAW_NOFX;
396           break;
397
398         case GDK_NOOP:
399           return FALSE;
400
401         case GDK_SET:
402           color.red = color.green = color.blue = 0xFFFF;
403           flags = DSDRAW_NOFX;
404           break;
405
406         default:
407           g_message ("unsupported GC function %d",
408                      gc_private->values.function);
409           flags = DSDRAW_NOFX;
410           break;
411         }
412     }
413
414   gdk_directfb_set_color (impl, &color, alpha);
415
416   impl->surface->SetDrawingFlags (impl->surface, flags);
417
418   return TRUE;
419 }
420
421 static void
422 gdk_directfb_draw_rectangle (GdkDrawable *drawable,
423                              GdkGC       *gc,
424                              gint         filled,
425                              gint         x,
426                              gint         y,
427                              gint         width,
428                              gint         height)
429 {
430   GdkDrawableImplDirectFB *impl;
431   GdkRegion                clip;
432   GdkGCDirectFB           *gc_private = NULL;
433   IDirectFBSurface        *surface    = NULL;
434   gint  i;
435
436   g_return_if_fail (GDK_IS_DRAWABLE (drawable));
437
438   D_DEBUG_AT( GDKDFB_Drawable, "%s( %p, %p, %s, %4d,%4d - %4dx%4d )\n", G_STRFUNC,
439               drawable, gc, filled ? " filled" : "outline", x, y, width, height );
440
441   impl = GDK_DRAWABLE_IMPL_DIRECTFB (drawable);
442
443   if (!impl->surface)
444     return;
445
446   if (gc)
447     gc_private = GDK_GC_DIRECTFB (gc);
448
449   if (gc_private)
450     {
451       if (gdk_directfb_enable_color_keying &&
452           (gc_private->values.foreground.red   >> 8) == gdk_directfb_bg_color_key.r &&
453           (gc_private->values.foreground.green >> 8) == gdk_directfb_bg_color_key.g &&
454           (gc_private->values.foreground.blue  >> 8) == gdk_directfb_bg_color_key.b)
455         {
456           if (DFB_PIXELFORMAT_IS_INDEXED (impl->format))
457             impl->surface->SetColorIndex (impl->surface, 255);
458           else
459             impl->surface->SetColor (impl->surface,
460                                      gdk_directfb_bg_color.r,
461                                      gdk_directfb_bg_color.g,
462                                      gdk_directfb_bg_color.b,
463                                      gdk_directfb_bg_color.a);
464         }
465       else
466         {
467           if (!gdk_directfb_setup_for_drawing (impl, gc_private)){
468             return;
469                   }
470         }
471     }
472   else
473     {
474       GdkWindowObject *win = GDK_WINDOW_OBJECT (impl->wrapper);
475
476       if (gdk_directfb_enable_color_keying)
477         {
478           if (DFB_PIXELFORMAT_IS_INDEXED (impl->format))
479             impl->surface->SetColorIndex (impl->surface, 255);
480           else
481             impl->surface->SetColor (impl->surface,
482                                      gdk_directfb_bg_color.r,
483                                      gdk_directfb_bg_color.b,
484                                      gdk_directfb_bg_color.g,
485                                      gdk_directfb_bg_color.a);
486         }
487       else
488         {
489           gdk_directfb_set_color (impl, &win->bg_color, 0xFF);
490         }
491     }
492
493   if (filled)
494     {
495       GdkRectangle  rect = { x, y, width, height };
496
497       gdk_directfb_clip_region (drawable, gc, &rect, &clip);
498
499       if (gc_private && gc_private->values_mask & GDK_GC_FILL)
500         {
501           if (gc_private->values.fill == GDK_STIPPLED  &&
502               gc_private->values_mask & GDK_GC_STIPPLE &&
503               gc_private->values.stipple)
504             {
505               surface = GDK_DRAWABLE_IMPL_DIRECTFB (GDK_PIXMAP_OBJECT (gc_private->values.stipple)->impl)->surface;
506
507               if (surface)
508                 impl->surface->SetBlittingFlags (impl->surface,
509                                                  (DSBLIT_BLEND_ALPHACHANNEL |
510                                                   DSBLIT_COLORIZE));
511             }
512           else if (gc_private->values.fill == GDK_TILED  &&
513                    gc_private->values_mask & GDK_GC_TILE &&
514                    gc_private->values.tile)
515             {
516               surface = GDK_DRAWABLE_IMPL_DIRECTFB (GDK_PIXMAP_OBJECT (gc_private->values.tile)->impl)->surface;
517
518               impl->surface->SetBlittingFlags (impl->surface, DSBLIT_NOFX);
519             }
520         }
521
522       if (surface)
523         {
524           if (gc_private->values_mask & GDK_GC_TS_X_ORIGIN)
525             x = gc_private->values.ts_x_origin;
526           if (gc_private->values_mask & GDK_GC_TS_Y_ORIGIN)
527             y = gc_private->values.ts_y_origin;
528
529           for (i = 0; i < clip.numRects; i++)
530             {
531               DFBRegion reg = { clip.rects[i].x1,     clip.rects[i].y1,
532                                 clip.rects[i].x2, clip.rects[i].y2 };
533
534               impl->surface->SetClip (impl->surface, &reg);
535               impl->surface->TileBlit (impl->surface, surface, NULL, x, y);
536             }
537         }
538       else  /* normal rectangle filling */
539         {
540           DFBRectangle rects[clip.numRects];
541
542           impl->surface->SetClip (impl->surface, NULL);
543
544           for (i = 0; i < clip.numRects; i++)
545             {
546               GdkRegionBox *box = &clip.rects[i];
547
548               rects[i].x = box->x1;
549               rects[i].y = box->y1;
550               rects[i].w = box->x2 - box->x1;
551               rects[i].h = box->y2 - box->y1;
552             }
553
554           impl->surface->FillRectangles(impl->surface, rects, clip.numRects);
555         }
556
557       temp_region_deinit( &clip );
558     }
559   else
560     {
561
562       DFBRegion region = { x, y, x + width, y + height };
563       impl->surface->SetClip (impl->surface, &region);
564
565       /*  DirectFB does not draw rectangles the X way. Using DirectFB,
566           a filled Rectangle has the same size as a drawn one, while
567           X draws the rectangle one pixel taller and wider.  */
568       impl->surface->DrawRectangle (impl->surface,
569                                     x, y, width , height);
570     }
571 }
572
573 static void
574 gdk_directfb_draw_arc (GdkDrawable *drawable,
575                        GdkGC       *gc,
576                        gint         filled,
577                        gint         x,
578                        gint         y,
579                        gint         width,
580                        gint         height,
581                        gint         angle1,
582                        gint         angle2)
583 {
584   D_UNIMPLEMENTED();
585 }
586
587 static void
588 gdk_directfb_draw_polygon (GdkDrawable *drawable,
589                            GdkGC       *gc,
590                            gint         filled,
591                            GdkPoint    *points,
592                            gint         npoints)
593 {
594   g_return_if_fail (GDK_IS_DRAWABLE (drawable));
595
596   D_DEBUG_AT( GDKDFB_Drawable, "%s( %p, %p, %s, %p, %d )\n", G_STRFUNC,
597               drawable, gc, filled ? " filled" : "outline", points, npoints );
598
599   if (npoints < 3)
600     return;
601
602   if (filled)
603     {
604       if (npoints == 3 || (npoints == 4 && 
605                                  points[0].x == points[npoints-1].x &&
606                                  points[0].y == points[npoints-1].y))
607           {
608             GdkDrawableImplDirectFB *impl;
609             GdkRegion                clip;
610             gint                     i;
611
612             impl = GDK_DRAWABLE_IMPL_DIRECTFB (drawable);
613
614             if (!gdk_directfb_setup_for_drawing (impl, GDK_GC_DIRECTFB (gc)))
615               return;
616
617             gdk_directfb_clip_region (drawable, gc, NULL, &clip);
618
619             for (i = 0; i < clip.numRects; i++)
620               {
621                                 DFBRegion reg = { clip.rects[i].x1,     clip.rects[i].y1, 
622                     clip.rects[i].x2 , clip.rects[i].y2  };
623
624                 impl->surface->SetClip (impl->surface, &reg);
625                 impl->surface->FillTriangle (impl->surface,
626                                              points[0].x, points[0].y,
627                                              points[1].x, points[1].y,
628                                              points[2].x, points[2].y);
629
630               }
631
632             temp_region_deinit( &clip );
633
634             return;
635           }
636                 else
637                         g_message ("filled polygons with n > 3 are not yet supported, "
638                      "drawing outlines");
639     }
640
641   if (points[0].x != points[npoints-1].x ||
642       points[0].y != points[npoints-1].y)
643     {
644       GdkPoint *tmp_points;
645
646       tmp_points = g_new (GdkPoint, npoints + 1);
647       memcpy (tmp_points, points, npoints * sizeof (GdkPoint));
648       tmp_points[npoints].x = points[0].x;
649       tmp_points[npoints].y = points[0].y;
650
651       gdk_directfb_draw_lines (drawable, gc, tmp_points, npoints + 1);
652
653       g_free (tmp_points);
654     }
655   else
656     {
657       gdk_directfb_draw_lines (drawable, gc, points, npoints);
658     }
659 }
660
661 static void
662 gdk_directfb_draw_text (GdkDrawable *drawable,
663                         GdkFont     *font,
664                         GdkGC       *gc,
665                         gint         x,
666                         gint         y,
667                         const gchar *text,
668                         gint         text_length)
669 {
670   D_UNIMPLEMENTED();
671 }
672
673 static void
674 gdk_directfb_draw_text_wc (GdkDrawable    *drawable,
675                            GdkFont        *font,
676                            GdkGC          *gc,
677                            gint            x,
678                            gint            y,
679                            const GdkWChar *text,
680                            gint            text_length)
681 {
682   D_UNIMPLEMENTED();
683 }
684
685 static void
686 gdk_directfb_draw_drawable (GdkDrawable *drawable,
687                             GdkGC       *gc,
688                             GdkDrawable *src,
689                             gint         xsrc,
690                             gint         ysrc,
691                             gint         xdest,
692                             gint         ydest,
693                             gint         width,
694                             gint         height)
695 {
696   GdkDrawableImplDirectFB *impl;
697   GdkDrawableImplDirectFB *src_impl;
698   GdkRegion                clip;
699   GdkRectangle             dest_rect = { xdest,
700                                          ydest,
701                 xdest + width ,
702                 ydest + height};
703
704   DFBRectangle rect = { xsrc, ysrc, width, height };
705   gint i;
706
707   D_DEBUG_AT( GDKDFB_Drawable, "%s( %p, %p, %p, %4d,%4d -> %4d,%4d - %dx%d )\n", G_STRFUNC,
708               drawable, gc, src, xsrc, ysrc, xdest, ydest, width, height );
709
710   impl = GDK_DRAWABLE_IMPL_DIRECTFB (drawable);
711
712   if (!impl->surface)
713     return;
714
715   if (GDK_IS_PIXMAP (src))
716     src_impl = GDK_DRAWABLE_IMPL_DIRECTFB (GDK_PIXMAP_OBJECT (src)->impl);
717   else if (GDK_IS_WINDOW (src))
718     src_impl = GDK_DRAWABLE_IMPL_DIRECTFB (GDK_WINDOW_OBJECT (src)->impl);
719   else if (GDK_IS_DRAWABLE_IMPL_DIRECTFB (src))
720     src_impl = GDK_DRAWABLE_IMPL_DIRECTFB (src);
721   else
722     return;
723
724   gdk_directfb_clip_region (drawable, gc, &dest_rect, &clip);
725
726   impl->surface->SetBlittingFlags (impl->surface, DSBLIT_NOFX);
727
728   for (i = 0; i < clip.numRects; i++)
729     {
730       DFBRegion reg = { clip.rects[i].x1,     clip.rects[i].y1,
731                         clip.rects[i].x2 , clip.rects[i].y2 };
732
733       impl->surface->SetClip (impl->surface, &reg);
734       impl->surface->Blit (impl->surface, src_impl->surface, &rect,
735                            xdest, ydest);
736     }
737
738   temp_region_deinit( &clip );
739 }
740
741 static void
742 gdk_directfb_draw_points (GdkDrawable *drawable,
743                           GdkGC       *gc,
744                           GdkPoint    *points,
745                           gint         npoints)
746 {
747   GdkDrawableImplDirectFB *impl;
748   GdkRegion                clip;
749
750   DFBRegion region = { points->x, points->y, points->x, points->y };
751
752   D_DEBUG_AT( GDKDFB_Drawable, "%s( %p, %p, %p, %d )\n", G_STRFUNC, drawable, gc, points, npoints );
753
754   if (npoints < 1)
755     return;
756
757   impl = GDK_DRAWABLE_IMPL_DIRECTFB (drawable);
758
759   if (!gdk_directfb_setup_for_drawing (impl, GDK_GC_DIRECTFB (gc)))
760     return;
761
762   gdk_directfb_clip_region (drawable, gc, NULL, &clip);
763
764   while (npoints > 0)
765     {
766       if (gdk_region_point_in (&clip, points->x, points->y))
767         {
768           impl->surface->FillRectangle (impl->surface,
769                                         points->x, points->y, 1, 1);
770
771           if (points->x < region.x1)
772             region.x1 = points->x;
773           if (points->x > region.x2)
774             region.x2 = points->x;
775
776           if (points->y < region.y1)
777             region.y1 = points->y;
778           if (points->y > region.y2)
779             region.y2 = points->y;
780         }
781
782       npoints--;
783       points++;
784     }
785
786   temp_region_deinit( &clip );
787 }
788
789 static void
790 gdk_directfb_draw_segments (GdkDrawable *drawable,
791                             GdkGC       *gc,
792                             GdkSegment  *segs,
793                             gint         nsegs)
794 {
795   GdkDrawableImplDirectFB *impl;
796   GdkRegion                clip;
797   gint                     i;
798
799 //  DFBRegion region = { segs->x1, segs->y1, segs->x2, segs->y2 };
800
801   D_DEBUG_AT( GDKDFB_Drawable, "%s( %p, %p, %p, %d )\n", G_STRFUNC, drawable, gc, segs, nsegs );
802
803   if (nsegs < 1)
804     return;
805
806   impl = GDK_DRAWABLE_IMPL_DIRECTFB (drawable);
807
808   if (!gdk_directfb_setup_for_drawing (impl, GDK_GC_DIRECTFB (gc)))
809     return;
810
811   gdk_directfb_clip_region (drawable, gc, NULL, &clip);
812
813   for (i = 0; i < clip.numRects; i++)
814     {
815       DFBRegion reg = { clip.rects[i].x1,   clip.rects[i].y1,
816                         clip.rects[i].x2, clip.rects[i].y2 };
817
818       impl->surface->SetClip (impl->surface, &reg);
819
820       impl->surface->DrawLines (impl->surface, (DFBRegion *)segs, nsegs);
821     }
822
823   temp_region_deinit( &clip );
824
825   /* everything below can be omitted if the drawing is buffered */
826 /*  if (impl->buffered)
827     return;
828
829   if (region.x1 > region.x2)
830     {
831       region.x1 = segs->x2;
832       region.x2 = segs->x1;
833     }
834   if (region.y1 > region.y2)
835     {
836       region.y1 = segs->y2;
837       region.y2 = segs->y1;
838     }
839
840   while (nsegs > 1)
841     {
842       nsegs--;
843       segs++;
844
845       if (segs->x1 < region.x1)
846         region.x1 = segs->x1;
847       if (segs->x2 < region.x1)
848         region.x1 = segs->x2;
849
850       if (segs->y1 < region.y1)
851         region.y1 = segs->y1;
852       if (segs->y2 < region.y1)
853         region.y1 = segs->y2;
854
855       if (segs->x1 > region.x2)
856         region.x2 = segs->x1;
857       if (segs->x2 > region.x2)
858         region.x2 = segs->x2;
859
860       if (segs->y1 > region.y2)
861         region.y2 = segs->y1;
862       if (segs->y2 > region.y2)
863         region.y2 = segs->y2;
864     }*/
865 }
866
867 static void
868 gdk_directfb_draw_lines (GdkDrawable *drawable,
869                          GdkGC       *gc,
870                          GdkPoint    *points,
871                          gint         npoints)
872 {
873   GdkDrawableImplDirectFB *impl;
874   GdkRegion                clip;
875   gint                     i;
876
877   DFBRegion lines[npoints > 1 ? npoints - 1 : 1];
878
879   DFBRegion region = { points->x, points->y, points->x, points->y };
880
881   D_DEBUG_AT( GDKDFB_Drawable, "%s( %p, %p, %p, %d )\n", G_STRFUNC, drawable, gc, points, npoints );
882
883   if (npoints < 2)
884     return;
885
886   impl = GDK_DRAWABLE_IMPL_DIRECTFB (drawable);
887
888   if (!gdk_directfb_setup_for_drawing (impl, GDK_GC_DIRECTFB (gc)))
889     return;
890
891   /* create an array of DFBRegions so we can use DrawLines */
892
893   lines[0].x1 = points->x;
894   lines[0].y1 = points->y;
895
896   for (i = 0; i < npoints - 2; i++)
897     {
898       points++;
899
900       lines[i].x2 = lines[i+1].x1 = points->x;
901       lines[i].y2 = lines[i+1].y1 = points->y;
902
903       if (points->x < region.x1)
904         region.x1 = points->x;
905
906       if (points->y < region.y1)
907         region.y1 = points->y;
908
909       if (points->x > region.x2)
910         region.x2 = points->x;
911
912       if (points->y > region.y2)
913         region.y2 = points->y;
914     }
915
916   points++;
917   lines[i].x2 = points->x;
918   lines[i].y2 = points->y;
919
920   gdk_directfb_clip_region (drawable, gc, NULL, &clip);
921
922   for (i = 0; i < clip.numRects; i++)
923     {
924       DFBRegion reg = { clip.rects[i].x1,   clip.rects[i].y1,
925                         clip.rects[i].x2, clip.rects[i].y2 };
926
927       impl->surface->SetClip (impl->surface, &reg);
928       impl->surface->DrawLines (impl->surface, lines, npoints - 1);
929     }
930
931   temp_region_deinit( &clip );
932 }
933
934 static void
935 gdk_directfb_draw_image (GdkDrawable *drawable,
936                          GdkGC       *gc,
937                          GdkImage    *image,
938                          gint         xsrc,
939                          gint         ysrc,
940                          gint         xdest,
941                          gint         ydest,
942                          gint         width,
943                          gint         height)
944 {
945   GdkDrawableImplDirectFB *impl;
946   GdkImageDirectFB        *image_private;
947   GdkRegion                clip;
948   GdkRectangle             dest_rect = { xdest, ydest, width, height };
949
950   gint pitch = 0;
951   gint i;
952
953   g_return_if_fail (GDK_IS_DRAWABLE (drawable));
954   g_return_if_fail (image != NULL);
955
956   D_DEBUG_AT( GDKDFB_Drawable, "%s( %p, %p, %p, %4d,%4d -> %4d,%4d - %dx%d )\n", G_STRFUNC,
957               drawable, gc, image, xsrc, ysrc, xdest, ydest, width, height );
958
959   impl = GDK_DRAWABLE_IMPL_DIRECTFB (drawable);
960   image_private = image->windowing_data;
961
962   if (!impl->surface)
963     return;
964
965   gdk_directfb_clip_region (drawable, gc, &dest_rect, &clip);
966
967   if (!gdk_region_empty (&clip))
968     {
969       DFBRectangle  src_rect = { xsrc, ysrc, width, height };
970
971       image_private->surface->Unlock (image_private->surface);
972
973       impl->surface->SetBlittingFlags (impl->surface, DSBLIT_NOFX);
974
975       for (i = 0; i < clip.numRects; i++)
976         {
977           DFBRegion reg = { clip.rects[i].x1,     clip.rects[i].y1,
978                             clip.rects[i].x2 , clip.rects[i].y2  };
979
980           impl->surface->SetClip (impl->surface, &reg);
981           impl->surface->Blit (impl->surface,
982                                image_private->surface, &src_rect,
983                                xdest, ydest);
984         }
985
986       image_private->surface->Lock (image_private->surface, DSLF_WRITE,
987                                     &image->mem, &pitch);
988       image->bpl = pitch;
989     }
990
991   temp_region_deinit( &clip );
992 }
993
994 static void
995 composite (guchar *src_buf,
996            gint    src_rowstride,
997            guchar *dest_buf,
998            gint    dest_rowstride,
999            gint    width,
1000            gint    height)
1001 {
1002   guchar *src = src_buf;
1003   guchar *dest = dest_buf;
1004
1005   while (height--)
1006     {
1007       gint twidth = width;
1008       guchar *p = src;
1009       guchar *q = dest;
1010
1011       while (twidth--)
1012         {
1013           guchar a = p[3];
1014           guint t;
1015
1016           t = a * p[0] + (255 - a) * q[0] + 0x80;
1017           q[0] = (t + (t >> 8)) >> 8;
1018           t = a * p[1] + (255 - a) * q[1] + 0x80;
1019           q[1] = (t + (t >> 8)) >> 8;
1020           t = a * p[2] + (255 - a) * q[2] + 0x80;
1021           q[2] = (t + (t >> 8)) >> 8;
1022
1023           p += 4;
1024           q += 3;
1025         }
1026       
1027       src += src_rowstride;
1028       dest += dest_rowstride;
1029     }
1030 }
1031
1032 static void
1033 composite_0888 (guchar      *src_buf,
1034                 gint         src_rowstride,
1035                 guchar      *dest_buf,
1036                 gint         dest_rowstride,
1037                 GdkByteOrder dest_byte_order,
1038                 gint         width,
1039                 gint         height)
1040 {
1041   guchar *src = src_buf;
1042   guchar *dest = dest_buf;
1043
1044   while (height--)
1045     {
1046       gint twidth = width;
1047       guchar *p = src;
1048       guchar *q = dest;
1049
1050       if (dest_byte_order == GDK_LSB_FIRST)
1051         {
1052           while (twidth--)
1053             {
1054               guint t;
1055               
1056               t = p[3] * p[2] + (255 - p[3]) * q[0] + 0x80;
1057               q[0] = (t + (t >> 8)) >> 8;
1058               t = p[3] * p[1] + (255 - p[3]) * q[1] + 0x80;
1059               q[1] = (t + (t >> 8)) >> 8;
1060               t = p[3] * p[0] + (255 - p[3]) * q[2] + 0x80;
1061               q[2] = (t + (t >> 8)) >> 8;
1062               p += 4;
1063               q += 4;
1064             }
1065         }
1066       else
1067         {
1068           while (twidth--)
1069             {
1070               guint t;
1071               
1072               t = p[3] * p[0] + (255 - p[3]) * q[1] + 0x80;
1073               q[1] = (t + (t >> 8)) >> 8;
1074               t = p[3] * p[1] + (255 - p[3]) * q[2] + 0x80;
1075               q[2] = (t + (t >> 8)) >> 8;
1076               t = p[3] * p[2] + (255 - p[3]) * q[3] + 0x80;
1077               q[3] = (t + (t >> 8)) >> 8;
1078               p += 4;
1079               q += 4;
1080             }
1081         }
1082       
1083       src += src_rowstride;
1084       dest += dest_rowstride;
1085     }
1086 }
1087
1088 /* change the last value to adjust the size of the device (1-4) */
1089 #define SET_PIXEL_DUFFS_DEVICE( D, S, w ) \
1090      SET_PIXEL_DUFFS_DEVICE_N( D, S, w, 2 )
1091
1092 /* From DirectFB's gfx/generic/generic.c" */
1093 #define SET_PIXEL( D, S )                    \
1094      switch (S >> 26) {                      \
1095           case 0:                            \
1096                break;                        \
1097           case 0x3f:                         \
1098                D = ((S <<  8) & 0xF800) |    \
1099                    ((S >>  5) & 0x07E0) |    \
1100                    ((S >> 19) & 0x001F);     \
1101                break;                        \
1102           default:                           \
1103                D = (((( (((S<<8) & 0xf800) | ((S>>19) & 0x001f))                                    \
1104                         - (D & 0xf81f)) * ((S>>26)+1) + ((D & 0xf81f)<<6)) & 0x003e07c0)            \
1105                       +                                                                             \
1106                     ((( ((S>>5) & 0x07e0)                                                           \
1107                         - (D & 0x07e0)) * ((S>>26)+1) + ((D & 0x07e0)<<6)) & 0x0001f800)) >> 6;     \
1108      }
1109
1110 static void
1111 composite_565 (guchar      *src_buf,
1112                gint         src_rowstride,
1113                guchar      *dest_buf,
1114                gint         dest_rowstride,
1115                GdkByteOrder dest_byte_order,
1116                gint         width,
1117                gint         height)
1118 {
1119      while (height--) {
1120           int  w = width;
1121           u16 *D = (u16*) dest_buf;
1122           u32 *S = (u32*) src_buf;
1123 #if 1
1124           if ((unsigned long)D & 2) {
1125                SET_PIXEL( D[0], S[0] );
1126                w--;
1127                D++;
1128                S++;
1129           }
1130
1131           int  i;
1132           int  w2  = w / 2;
1133           u32 *D32 = (u32*) D;
1134
1135           for (i=0; i<w2; i++) {
1136                register u32 S0 = S[(i << 1) + 0];
1137                register u32 S1 = S[(i << 1) + 1];
1138
1139                if ((S0 >> 26) == 0x3f && (S1 >> 26) == 0x3f) {
1140                     D32[i] = ((S0 <<  8) & 0x0000F800) |
1141                              ((S0 >>  5) & 0x000007E0) |
1142                              ((S0 >> 19) & 0x0000001F) |
1143                              ((S1 << 24) & 0xF8000000) |
1144                              ((S1 << 11) & 0x07E00000) |
1145                              ((S1 >>  3) & 0x001F0000);
1146                }
1147                else {
1148                     SET_PIXEL( D[(i << 1) + 0], S0 );
1149                     SET_PIXEL( D[(i << 1) + 1], S1 );
1150                }
1151           }
1152
1153           if (w & 1)
1154                SET_PIXEL( D[w-1], S[w-1] );
1155 #else
1156           SET_PIXEL_DUFFS_DEVICE( D, S, w );
1157 #endif
1158
1159           dest_buf += dest_rowstride;
1160           src_buf += src_rowstride;
1161      }
1162 }
1163
1164 #undef SET_PIXEL
1165 #undef SET_PIXEL_DUFFS_DEVICE
1166
1167 static void
1168 gdk_directfb_draw_pixbuf (GdkDrawable  *drawable,
1169                           GdkGC        *gc,
1170                           GdkPixbuf    *pixbuf,
1171                           gint          src_x,
1172                           gint          src_y,
1173                           gint          dest_x,
1174                           gint          dest_y,
1175                           gint          width,
1176                           gint          height,
1177                           GdkRgbDither  dither,
1178                           gint          x_dither,
1179                           gint          y_dither)
1180 {
1181   GdkPixbuf *composited = NULL;
1182 #if 0
1183   GdkRegion *clip;
1184   GdkRegion *drect;
1185   GdkRectangle tmp_rect;
1186 #endif
1187   GdkDrawableImplDirectFB *impl = GDK_DRAWABLE_IMPL_DIRECTFB (drawable);
1188
1189   g_return_if_fail (GDK_IS_PIXBUF (pixbuf));
1190   g_return_if_fail (pixbuf->colorspace == GDK_COLORSPACE_RGB);
1191   g_return_if_fail (pixbuf->n_channels == 3 || pixbuf->n_channels == 4);
1192   g_return_if_fail (pixbuf->bits_per_sample == 8);
1193
1194   g_return_if_fail (drawable != NULL);
1195
1196   if (width == -1) 
1197     width = pixbuf->width;
1198   if (height == -1)
1199     height = pixbuf->height;
1200
1201   g_return_if_fail (width >= 0 && height >= 0);
1202   g_return_if_fail (src_x >= 0 && src_x + width <= pixbuf->width);
1203   g_return_if_fail (src_y >= 0 && src_y + height <= pixbuf->height);
1204
1205   D_DEBUG_AT( GDKDFB_Drawable, "%s( %p, %p, %p, %4d,%4d -> %4d,%4d - %dx%d )\n", G_STRFUNC,
1206               drawable, gc, pixbuf, src_x, src_y, dest_x, dest_y, width, height );
1207
1208   /* Clip to the drawable; this is required for get_from_drawable() so
1209    * can't be done implicitly
1210    */
1211   
1212   if (dest_x < 0)
1213     {
1214       src_x -= dest_x;
1215       width += dest_x;
1216       dest_x = 0;
1217     }
1218
1219   if (dest_y < 0)
1220     {
1221       src_y -= dest_y;
1222       height += dest_y;
1223       dest_y = 0;
1224     }
1225
1226   if ((dest_x + width) > impl->width)
1227     width = impl->width - dest_x;
1228
1229   if ((dest_y + height) > impl->height)
1230     height = impl->height - dest_y;
1231
1232   if (width <= 0 || height <= 0)
1233     return;
1234
1235 #if 0
1236   /* Clip to the clip region; this avoids getting more
1237    * image data from the server than we need to.
1238    */
1239   
1240   tmp_rect.x = dest_x;
1241   tmp_rect.y = dest_y;
1242   tmp_rect.width = width;
1243   tmp_rect.height = height;
1244
1245   drect = gdk_region_rectangle (&tmp_rect);
1246   clip = gdk_drawable_get_clip_region (drawable);
1247
1248   gdk_region_intersect (drect, clip);
1249
1250   gdk_region_get_clipbox (drect, &tmp_rect);
1251   
1252   gdk_region_destroy (drect);
1253   gdk_region_destroy (clip);
1254
1255   if (tmp_rect.width == 0 ||
1256       tmp_rect.height == 0)
1257     return;
1258 #endif
1259
1260   if (pixbuf->has_alpha && impl->format == DSPF_RGB16) {
1261        void *data;
1262        int   pitch;
1263
1264        if (impl->surface->Lock( impl->surface, DSLF_READ | DSLF_WRITE, &data, &pitch ) == DFB_OK) {
1265             composite_565( pixbuf->pixels + src_y * pixbuf->rowstride + src_x * 4,
1266                            pixbuf->rowstride,
1267                            data + dest_y * pitch + dest_x * 2,
1268                            pitch,
1269                          #if G_BYTE_ORDER == G_BIG_ENDIAN
1270                            GDK_MSB_FIRST,
1271                          #else
1272                            GDK_LSB_FIRST,
1273                          #endif
1274                            width, height );
1275
1276             impl->surface->Unlock( impl->surface );
1277
1278             return;
1279        }
1280   }
1281
1282   /* Actually draw */
1283   if (!gc)
1284     gc = _gdk_drawable_get_scratch_gc (drawable, FALSE);
1285
1286   if (pixbuf->has_alpha)
1287     {
1288       GdkVisual *visual = gdk_drawable_get_visual (drawable);
1289       void (*composite_func) (guchar       *src_buf,
1290                               gint          src_rowstride,
1291                               guchar       *dest_buf,
1292                               gint          dest_rowstride,
1293                               GdkByteOrder  dest_byte_order,
1294                               gint          width,
1295                               gint          height) = NULL;
1296
1297       /* First we see if we have a visual-specific composition function that can composite
1298        * the pixbuf data directly onto the image
1299        */
1300       if (visual)
1301         {
1302           gint bits_per_pixel = _gdk_windowing_get_bits_for_depth (gdk_drawable_get_display (drawable),
1303                                                                    visual->depth);
1304           
1305           if (visual->byte_order == (G_BYTE_ORDER == G_BIG_ENDIAN ? GDK_MSB_FIRST : GDK_LSB_FIRST) &&
1306               visual->depth == 16 &&
1307               visual->red_mask   == 0xf800 &&
1308               visual->green_mask == 0x07e0 &&
1309               visual->blue_mask  == 0x001f)
1310             composite_func = composite_565;
1311           else if (visual->depth == 24 && bits_per_pixel == 32 &&
1312                    visual->red_mask   == 0xff0000 &&
1313                    visual->green_mask == 0x00ff00 &&
1314                    visual->blue_mask  == 0x0000ff)
1315             composite_func = composite_0888;
1316         }
1317
1318       /* We can't use our composite func if we are required to dither
1319        */
1320       if (composite_func && !(dither == GDK_RGB_DITHER_MAX && visual->depth != 24))
1321         {
1322 #if 0
1323           gint x0, y0;
1324           for (y0 = 0; y0 < height; y0 += GDK_SCRATCH_IMAGE_HEIGHT)
1325             {
1326               gint height1 = MIN (height - y0, GDK_SCRATCH_IMAGE_HEIGHT);
1327               for (x0 = 0; x0 < width; x0 += GDK_SCRATCH_IMAGE_WIDTH)
1328                 {
1329                   gint xs0, ys0;
1330                   
1331                   gint width1 = MIN (width - x0, GDK_SCRATCH_IMAGE_WIDTH);
1332                   
1333                   GdkImage *image = _gdk_image_get_scratch (gdk_drawable_get_screen (drawable),
1334                                                             width1, height1,
1335                                                             gdk_drawable_get_depth (drawable), &xs0, &ys0);
1336                   
1337                   gdk_drawable_copy_to_image (drawable, image,
1338                                               dest_x + x0, dest_y + y0,
1339                                               xs0, ys0,
1340                                               width1, height1);
1341                   (*composite_func) (pixbuf->pixels + (src_y + y0) * pixbuf->rowstride + (src_x + x0) * 4,
1342                                      pixbuf->rowstride,
1343                                      (guchar*)image->mem + ys0 * image->bpl + xs0 * image->bpp,
1344                                      image->bpl,
1345                                      visual->byte_order,
1346                                      width1, height1);
1347                   gdk_draw_image (drawable, gc, image,
1348                                   xs0, ys0,
1349                                   dest_x + x0, dest_y + y0,
1350                                   width1, height1);
1351                 }
1352             }
1353 #else
1354           void *data;
1355           int   pitch;
1356
1357           if (impl->surface->Lock( impl->surface, DSLF_READ | DSLF_WRITE, &data, &pitch ) == DFB_OK) {
1358                (*composite_func) (pixbuf->pixels + src_y * pixbuf->rowstride + src_x * 4,
1359                                   pixbuf->rowstride,
1360                                   data + dest_y * pitch + DFB_BYTES_PER_LINE( impl->format, dest_x ),
1361                                   pitch,
1362                                   visual->byte_order,
1363                                   width, height);
1364
1365                impl->surface->Unlock( impl->surface );
1366           }
1367 #endif          
1368           goto out;
1369         }
1370       else
1371         {
1372           /* No special composition func, convert dest to 24 bit RGB data, composite against
1373            * that, and convert back.
1374            */
1375           composited = gdk_pixbuf_get_from_drawable (NULL,
1376                                                      drawable,
1377                                                      NULL,
1378                                                      dest_x, dest_y,
1379                                                      0, 0,
1380                                                      width, height);
1381           
1382           if (composited)
1383             composite (pixbuf->pixels + src_y * pixbuf->rowstride + src_x * 4,
1384                        pixbuf->rowstride,
1385                        composited->pixels,
1386                        composited->rowstride,
1387                        width, height);
1388         }
1389     }
1390
1391   if (composited)
1392     {
1393       src_x = 0;
1394       src_y = 0;
1395       pixbuf = composited;
1396     }
1397   
1398   if (pixbuf->n_channels == 4)
1399     {
1400       guchar *buf = pixbuf->pixels + src_y * pixbuf->rowstride + src_x * 4;
1401
1402       gdk_draw_rgb_32_image_dithalign (drawable, gc,
1403                                        dest_x, dest_y,
1404                                        width, height,
1405                                        dither,
1406                                        buf, pixbuf->rowstride,
1407                                        x_dither, y_dither);
1408     }
1409   else                                /* n_channels == 3 */
1410     {
1411       guchar *buf = pixbuf->pixels + src_y * pixbuf->rowstride + src_x * 3;
1412
1413       gdk_draw_rgb_image_dithalign (drawable, gc,
1414                                     dest_x, dest_y,
1415                                     width, height,
1416                                     dither,
1417                                     buf, pixbuf->rowstride,
1418                                     x_dither, y_dither);
1419     }
1420
1421  out:
1422   if (composited)
1423     g_object_unref (composited);
1424 }
1425
1426 static inline void
1427 convert_rgba_pixbuf_to_image (guint32 *src,
1428                               guint    src_pitch,
1429                               guint32 *dest,
1430                               guint    dest_pitch,
1431                               guint    width,
1432                               guint    height)
1433 {
1434   guint i;
1435
1436   while (height--)
1437     {
1438       for (i = 0; i < width; i++)
1439         {
1440           guint32 pixel = GUINT32_FROM_BE (src[i]);
1441           dest[i] = (pixel >> 8) | (pixel << 24);
1442         }
1443
1444       src  += src_pitch;
1445       dest += dest_pitch;
1446     }
1447 }
1448
1449 static inline void
1450 convert_rgb_pixbuf_to_image (guchar  *src,
1451                              guint    src_pitch,
1452                              guint32 *dest,
1453                              guint    dest_pitch,
1454                              guint    width,
1455                              guint    height)
1456 {
1457   guint   i;
1458   guchar *s;
1459
1460   while (height--)
1461     {
1462       s = src;
1463
1464       for (i = 0; i < width; i++, s += 3)
1465         dest[i] = 0xFF000000 | (s[0] << 16) | (s[1] << 8) | s[2];
1466
1467       src  += src_pitch;
1468       dest += dest_pitch;
1469     }
1470 }
1471
1472 /*
1473  * Object stuff
1474  */
1475 static inline const char *
1476 drawable_impl_type_name( GObject *object )
1477 {
1478      if (GDK_IS_PIXMAP (object))
1479           return "PIXMAP";
1480
1481      if (GDK_IS_WINDOW (object))
1482           return "WINDOW";
1483
1484      if (GDK_IS_DRAWABLE_IMPL_DIRECTFB (object))
1485           return "DRAWABLE";
1486
1487      return "unknown";
1488 }
1489
1490
1491 static void
1492 gdk_drawable_impl_directfb_finalize (GObject *object)
1493 {
1494   GdkDrawableImplDirectFB *impl;
1495   impl = GDK_DRAWABLE_IMPL_DIRECTFB (object);
1496
1497   D_DEBUG_AT( GDKDFB_Drawable, "%s( %p ) <- %dx%d (%s at %4d,%4d)\n", G_STRFUNC,
1498               object, impl->width, impl->height,
1499               drawable_impl_type_name( object ),
1500               impl->abs_x, impl->abs_y );
1501
1502   gdk_directfb_set_colormap (GDK_DRAWABLE (object), NULL);
1503   if( impl->cairo_surface ) {
1504         cairo_surface_finish(impl->cairo_surface);
1505   }
1506   if( impl->surface )
1507         impl->surface->Release (impl->surface);
1508   G_OBJECT_CLASS (parent_class)->finalize (object);
1509 }
1510
1511 static void
1512 gdk_drawable_impl_directfb_class_init (GdkDrawableImplDirectFBClass *klass)
1513 {
1514   GdkDrawableClass *drawable_class = GDK_DRAWABLE_CLASS (klass);
1515   GObjectClass     *object_class   = G_OBJECT_CLASS (klass);
1516
1517   parent_class = g_type_class_peek_parent (klass);
1518
1519   object_class->finalize = gdk_drawable_impl_directfb_finalize;
1520
1521   drawable_class->create_gc      = _gdk_directfb_gc_new;
1522   drawable_class->draw_rectangle = gdk_directfb_draw_rectangle;
1523   drawable_class->draw_arc       = gdk_directfb_draw_arc;
1524   drawable_class->draw_polygon   = gdk_directfb_draw_polygon;
1525   drawable_class->draw_text      = gdk_directfb_draw_text;
1526   drawable_class->draw_text_wc   = gdk_directfb_draw_text_wc;
1527   drawable_class->draw_drawable  = gdk_directfb_draw_drawable;
1528   drawable_class->draw_points    = gdk_directfb_draw_points;
1529   drawable_class->draw_segments  = gdk_directfb_draw_segments;
1530   drawable_class->draw_lines     = gdk_directfb_draw_lines;
1531 #if 0
1532   drawable_class->draw_glyphs    = NULL;
1533   drawable_class->draw_glyphs_transformed    = NULL;
1534 #endif
1535   drawable_class->draw_image     = gdk_directfb_draw_image;
1536
1537   drawable_class->ref_cairo_surface = gdk_directfb_ref_cairo_surface;
1538   drawable_class->set_colormap   = gdk_directfb_set_colormap;
1539   drawable_class->get_colormap   = gdk_directfb_get_colormap;
1540
1541   drawable_class->get_depth      = gdk_directfb_get_depth;
1542   drawable_class->get_visual     = gdk_directfb_get_visual;
1543
1544   drawable_class->get_size       = gdk_directfb_get_size;
1545
1546   drawable_class->_copy_to_image = _gdk_directfb_copy_to_image;
1547         drawable_class->get_screen = gdk_directfb_get_screen;
1548
1549
1550   real_draw_pixbuf = drawable_class->draw_pixbuf;
1551   drawable_class->draw_pixbuf = gdk_directfb_draw_pixbuf;
1552
1553   /* check for hardware-accelerated alpha-blending */
1554   {
1555     DFBGraphicsDeviceDescription desc;
1556                 _gdk_display->directfb->GetDeviceDescription ( _gdk_display->directfb, &desc);
1557
1558     accelerated_alpha_blending =
1559       ((desc.acceleration_mask & DFXL_BLIT) &&
1560        (desc.blitting_flags & DSBLIT_BLEND_ALPHACHANNEL));
1561   }
1562 }
1563
1564 GType
1565 gdk_drawable_impl_directfb_get_type (void)
1566 {
1567   static GType object_type = 0;
1568
1569   if (!object_type)
1570     {
1571       const GTypeInfo object_info =
1572         {
1573           sizeof (GdkDrawableImplDirectFBClass),
1574           (GBaseInitFunc) NULL,
1575           (GBaseFinalizeFunc) NULL,
1576           (GClassInitFunc) gdk_drawable_impl_directfb_class_init,
1577           NULL,           /* class_finalize */
1578           NULL,           /* class_data */
1579           sizeof (GdkDrawableImplDirectFB),
1580           0,              /* n_preallocs */
1581           (GInstanceInitFunc) NULL,
1582         };
1583
1584       object_type = g_type_register_static (GDK_TYPE_DRAWABLE,
1585                                             "GdkDrawableImplDirectFB",
1586                                             &object_info, 0);
1587     }
1588
1589   return object_type;
1590 }
1591
1592 static GdkScreen * gdk_directfb_get_screen (GdkDrawable    *drawable){
1593         return gdk_screen_get_default();
1594 }
1595
1596 static void
1597 gdk_directfb_cairo_surface_destroy (void *data)
1598 {
1599   GdkDrawableImplDirectFB *impl = data;
1600   impl->cairo_surface = NULL;
1601 }
1602
1603 void
1604 _gdk_windowing_set_cairo_surface_size (cairo_surface_t *surface,
1605                                        int width,
1606                                        int height)
1607 {
1608 }
1609
1610 cairo_surface_t *
1611 _gdk_windowing_create_cairo_surface (GdkDrawable *drawable,
1612                                      int width,
1613                                      int height)
1614 {
1615   GdkDrawableImplDirectFB *impl;
1616   IDirectFB *dfb;
1617   cairo_surface_t *ret;
1618
1619   impl = GDK_DRAWABLE_IMPL_DIRECTFB (drawable);
1620   dfb = GDK_DISPLAY_DFB (gdk_drawable_get_display (drawable))->directfb;
1621
1622   ret = cairo_directfb_surface_create (dfb, impl->surface);
1623   cairo_surface_set_user_data (ret,
1624                                &gdk_directfb_cairo_key, drawable,
1625                                gdk_directfb_cairo_surface_destroy);
1626
1627   return ret;
1628 }
1629
1630 static cairo_surface_t *
1631 gdk_directfb_ref_cairo_surface (GdkDrawable *drawable)
1632 {
1633   GdkDrawableImplDirectFB *impl;
1634   IDirectFB               *dfb;
1635   
1636   g_return_val_if_fail (GDK_IS_DRAWABLE (drawable), NULL);
1637   g_return_val_if_fail (GDK_IS_DRAWABLE_IMPL_DIRECTFB (drawable), NULL);
1638
1639   impl = GDK_DRAWABLE_IMPL_DIRECTFB (drawable);
1640   dfb = GDK_DISPLAY_DFB(gdk_drawable_get_display(drawable))->directfb;
1641   
1642   if (!impl->cairo_surface) {
1643     IDirectFBSurface *surface;
1644     g_assert (impl->surface != NULL);
1645 #if defined(CAIRO_VERSION) && CAIRO_VERSION >= CAIRO_VERSION_ENCODE(1,5,5)
1646     impl->surface->GetSubSurface (impl->surface, NULL, &surface);
1647 #else
1648     surface = impl->surface;
1649 #endif
1650     if (surface) {
1651       impl->cairo_surface = cairo_directfb_surface_create (dfb, surface);
1652       if (impl->cairo_surface) {
1653         cairo_surface_set_user_data (impl->cairo_surface, 
1654                                      &gdk_directfb_cairo_key, drawable, 
1655                                      gdk_directfb_cairo_surface_destroy);
1656       }
1657 #if defined(CAIRO_VERSION) && CAIRO_VERSION >= CAIRO_VERSION_ENCODE(1,5,5)
1658       surface->Release (surface);
1659 #endif
1660     }
1661   } else {
1662     cairo_surface_reference (impl->cairo_surface);
1663   }
1664   
1665   g_assert (impl->cairo_surface != NULL);
1666   return impl->cairo_surface;
1667 }
1668
1669 #define __GDK_DRAWABLE_X11_C__
1670 #include "gdkaliasdef.c"