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