1 /* GDK - The GIMP Drawing Kit
2 * Copyright (C) 1995-1997 Peter Mattis, Spencer Kimball and Josh MacDonald
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.
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.
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.
21 * Modified by the GTK+ Team and others 1997-2000. See the AUTHORS
22 * file for a list of people on the GTK+ Team.
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>
39 #include "gdkdirectfb.h"
40 #include "gdkprivate-directfb.h"
42 #include "../../gdk-pixbuf/gdk-pixbuf-private.h"
44 #include "gdkinternals.h"
47 #include "gdkregion-generic.h"
50 #include "cairo-directfb.h"
53 #include <direct/debug.h>
54 #include <direct/messages.h>
57 * There can be multiple domains in one file and one domain (same same) in multiple files.
59 D_DEBUG_DOMAIN( GDKDFB_Drawable, "GDKDFB/Drawable", "GDK DirectFB Drawable" );
60 D_DEBUG_DOMAIN( GDKDFB_DrawClip, "GDKDFB/DrawClip", "GDK DirectFB Drawable Clip Region" );
63 /* From DirectFB's <gfx/generix/duffs_device.h> */
66 SET_PIXEL( D[0], S[0] );
70 SET_PIXEL( D[2], S[2] );\
72 SET_PIXEL( D[1], S[1] );\
77 SET_PIXEL( D[6], S[6] );\
79 SET_PIXEL( D[5], S[5] );\
81 SET_PIXEL( D[4], S[4] );\
83 SET_PIXEL( D[3], S[3] );\
88 SET_PIXEL( D[14], S[14] );\
90 SET_PIXEL( D[13], S[13] );\
92 SET_PIXEL( D[12], S[12] );\
94 SET_PIXEL( D[11], S[11] );\
96 SET_PIXEL( D[10], S[10] );\
98 SET_PIXEL( D[9], S[9] );\
100 SET_PIXEL( D[8], S[8] );\
102 SET_PIXEL( D[7], S[7] );\
105 #define SET_PIXEL_DUFFS_DEVICE_N( D, S, w, n ) \
108 register int l = w & ((1 << n) - 1);\
112 SET_PIXEL( D[(1 << n)-1], S[(1 << n)-1] );\
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,
129 static cairo_surface_t *gdk_directfb_ref_cairo_surface (GdkDrawable *drawable);
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;
136 static void (*real_draw_pixbuf) (GdkDrawable *drawable,
150 /**********************************************************
151 * DirectFB specific implementations of generic functions *
152 **********************************************************/
156 gdk_directfb_set_colormap (GdkDrawable *drawable,
157 GdkColormap *colormap)
159 GdkDrawableImplDirectFB *impl;
161 impl = GDK_DRAWABLE_IMPL_DIRECTFB (drawable);
163 D_DEBUG_AT( GDKDFB_Drawable, "%s( %p, %p ) <- old %p\n", G_STRFUNC, drawable, colormap, impl->colormap );
165 if (impl->colormap == colormap)
169 g_object_unref (impl->colormap);
171 impl->colormap = colormap;
174 g_object_ref (colormap);
178 gdk_directfb_get_colormap (GdkDrawable *drawable)
182 retval = GDK_DRAWABLE_IMPL_DIRECTFB (drawable)->colormap;
185 retval = gdk_colormap_get_system ();
186 gdk_directfb_set_colormap(drawable,retval);
193 gdk_directfb_get_depth (GdkDrawable *drawable)
195 GdkDrawableImplDirectFB *impl = GDK_DRAWABLE_IMPL_DIRECTFB (drawable);
197 return DFB_BITS_PER_PIXEL (impl->format);
201 gdk_directfb_get_size (GdkDrawable *drawable,
205 GdkDrawableImplDirectFB *impl;
207 impl = GDK_DRAWABLE_IMPL_DIRECTFB (drawable);
210 *width = impl->width;
213 *height = impl->height;
217 gdk_directfb_get_visual (GdkDrawable *drawable)
219 return gdk_visual_get_system ();
222 /* Calculates the real clipping region for a drawable, taking into account
223 * other windows and the gc clip region.
226 gdk_directfb_clip_region (GdkDrawable *drawable,
228 GdkRectangle *draw_rect,
231 GdkDrawableImplDirectFB *private;
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);
238 D_DEBUG_AT( GDKDFB_DrawClip, "%s( %p, %p, %p )\n", G_STRFUNC, drawable, gc, draw_rect );
240 private = GDK_DRAWABLE_IMPL_DIRECTFB (drawable);
246 rect.width = private->width;
247 rect.height = private->height;
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 );
254 temp_region_init_rectangle( ret_clip, draw_rect );
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 );
261 gdk_region_intersect (ret_clip, &private->paint_region);
266 GdkGCDirectFB *gc_private = GDK_GC_DIRECTFB (gc);
267 GdkRegion *region = &gc_private->clip_region;
269 if (region->numRects)
271 D_DEBUG_AT( GDKDFB_DrawClip, " -> clipping region > %4d,%4d - %4dx%4d < (%ld boxes)\n",
272 GDKDFB_RECTANGLE_VALS_FROM_BOX( ®ion->extents ), region->numRects );
274 if (gc->clip_x_origin || gc->clip_y_origin)
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);
282 gdk_region_intersect (ret_clip, region);
286 if (gc_private->values_mask & GDK_GC_SUBWINDOW &&
287 gc_private->values.subwindow_mode == GDK_INCLUDE_INFERIORS)
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 );
297 if (GDK_IS_WINDOW (private->wrapper) &&
298 GDK_WINDOW_IS_MAPPED (private->wrapper) &&
299 !GDK_WINDOW_OBJECT (private->wrapper)->input_only)
305 temp.rects = &temp.extents;
308 for (cur = GDK_WINDOW_OBJECT (private->wrapper)->children;
312 GdkWindowObject *cur_private;
313 GdkDrawableImplDirectFB *cur_impl;
315 cur_private = GDK_WINDOW_OBJECT (cur->data);
317 if (!GDK_WINDOW_IS_MAPPED (cur_private) || cur_private->input_only)
320 cur_impl = GDK_DRAWABLE_IMPL_DIRECTFB (cur_private->impl);
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;
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 );
330 gdk_region_subtract (ret_clip, &temp);
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 );
342 gdk_directfb_set_color (GdkDrawableImplDirectFB *impl,
346 if (DFB_PIXELFORMAT_IS_INDEXED (impl->format))
348 impl->surface->SetColorIndex (impl->surface, color->pixel);
352 impl->surface->SetColor (impl->surface,
361 gdk_directfb_setup_for_drawing (GdkDrawableImplDirectFB *impl,
362 GdkGCDirectFB *gc_private)
364 DFBSurfaceDrawingFlags flags = DSDRAW_NOFX;
365 GdkColor color = { 0, 0, 0, 0 };
371 if (gc_private && gc_private->values_mask & GDK_GC_FOREGROUND)
372 color = gc_private->values.foreground;
374 if (gc_private && gc_private->values_mask & GDK_GC_FUNCTION)
376 switch (gc_private->values.function)
383 color.red = color.green = color.blue = 0xFFFF;
394 color.red = color.green = color.blue = 0x0;
402 color.red = color.green = color.blue = 0xFFFF;
407 g_message ("unsupported GC function %d",
408 gc_private->values.function);
414 gdk_directfb_set_color (impl, &color, alpha);
416 impl->surface->SetDrawingFlags (impl->surface, flags);
422 gdk_directfb_draw_rectangle (GdkDrawable *drawable,
430 GdkDrawableImplDirectFB *impl;
432 GdkGCDirectFB *gc_private = NULL;
433 IDirectFBSurface *surface = NULL;
436 g_return_if_fail (GDK_IS_DRAWABLE (drawable));
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 );
441 impl = GDK_DRAWABLE_IMPL_DIRECTFB (drawable);
447 gc_private = GDK_GC_DIRECTFB (gc);
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)
456 if (DFB_PIXELFORMAT_IS_INDEXED (impl->format))
457 impl->surface->SetColorIndex (impl->surface, 255);
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);
467 if (!gdk_directfb_setup_for_drawing (impl, gc_private)){
474 GdkWindowObject *win = GDK_WINDOW_OBJECT (impl->wrapper);
476 if (gdk_directfb_enable_color_keying)
478 if (DFB_PIXELFORMAT_IS_INDEXED (impl->format))
479 impl->surface->SetColorIndex (impl->surface, 255);
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);
489 gdk_directfb_set_color (impl, &win->bg_color, 0xFF);
495 GdkRectangle rect = { x, y, width, height };
497 gdk_directfb_clip_region (drawable, gc, &rect, &clip);
499 if (gc_private && gc_private->values_mask & GDK_GC_FILL)
501 if (gc_private->values.fill == GDK_STIPPLED &&
502 gc_private->values_mask & GDK_GC_STIPPLE &&
503 gc_private->values.stipple)
505 surface = GDK_DRAWABLE_IMPL_DIRECTFB (GDK_PIXMAP_OBJECT (gc_private->values.stipple)->impl)->surface;
508 impl->surface->SetBlittingFlags (impl->surface,
509 (DSBLIT_BLEND_ALPHACHANNEL |
512 else if (gc_private->values.fill == GDK_TILED &&
513 gc_private->values_mask & GDK_GC_TILE &&
514 gc_private->values.tile)
516 surface = GDK_DRAWABLE_IMPL_DIRECTFB (GDK_PIXMAP_OBJECT (gc_private->values.tile)->impl)->surface;
518 impl->surface->SetBlittingFlags (impl->surface, DSBLIT_NOFX);
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;
529 for (i = 0; i < clip.numRects; i++)
531 DFBRegion reg = { clip.rects[i].x1, clip.rects[i].y1,
532 clip.rects[i].x2, clip.rects[i].y2 };
534 impl->surface->SetClip (impl->surface, ®);
535 impl->surface->TileBlit (impl->surface, surface, NULL, x, y);
538 else /* normal rectangle filling */
540 DFBRectangle rects[clip.numRects];
542 impl->surface->SetClip (impl->surface, NULL);
544 for (i = 0; i < clip.numRects; i++)
546 GdkRegionBox *box = &clip.rects[i];
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;
554 impl->surface->FillRectangles(impl->surface, rects, clip.numRects);
557 temp_region_deinit( &clip );
562 DFBRegion region = { x, y, x + width, y + height };
563 impl->surface->SetClip (impl->surface, ®ion);
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);
574 gdk_directfb_draw_arc (GdkDrawable *drawable,
588 gdk_directfb_draw_polygon (GdkDrawable *drawable,
594 g_return_if_fail (GDK_IS_DRAWABLE (drawable));
596 D_DEBUG_AT( GDKDFB_Drawable, "%s( %p, %p, %s, %p, %d )\n", G_STRFUNC,
597 drawable, gc, filled ? " filled" : "outline", points, npoints );
604 if (npoints == 3 || (npoints == 4 &&
605 points[0].x == points[npoints-1].x &&
606 points[0].y == points[npoints-1].y))
608 GdkDrawableImplDirectFB *impl;
612 impl = GDK_DRAWABLE_IMPL_DIRECTFB (drawable);
614 if (!gdk_directfb_setup_for_drawing (impl, GDK_GC_DIRECTFB (gc)))
617 gdk_directfb_clip_region (drawable, gc, NULL, &clip);
619 for (i = 0; i < clip.numRects; i++)
621 DFBRegion reg = { clip.rects[i].x1, clip.rects[i].y1,
622 clip.rects[i].x2 , clip.rects[i].y2 };
624 impl->surface->SetClip (impl->surface, ®);
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);
632 temp_region_deinit( &clip );
637 g_message ("filled polygons with n > 3 are not yet supported, "
641 if (points[0].x != points[npoints-1].x ||
642 points[0].y != points[npoints-1].y)
644 GdkPoint *tmp_points;
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;
651 gdk_directfb_draw_lines (drawable, gc, tmp_points, npoints + 1);
657 gdk_directfb_draw_lines (drawable, gc, points, npoints);
662 gdk_directfb_draw_text (GdkDrawable *drawable,
674 gdk_directfb_draw_text_wc (GdkDrawable *drawable,
679 const GdkWChar *text,
686 gdk_directfb_draw_drawable (GdkDrawable *drawable,
696 GdkDrawableImplDirectFB *impl;
697 GdkDrawableImplDirectFB *src_impl;
699 GdkRectangle dest_rect = { xdest,
704 DFBRectangle rect = { xsrc, ysrc, width, height };
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 );
710 impl = GDK_DRAWABLE_IMPL_DIRECTFB (drawable);
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);
724 gdk_directfb_clip_region (drawable, gc, &dest_rect, &clip);
726 impl->surface->SetBlittingFlags (impl->surface, DSBLIT_NOFX);
728 for (i = 0; i < clip.numRects; i++)
730 DFBRegion reg = { clip.rects[i].x1, clip.rects[i].y1,
731 clip.rects[i].x2 , clip.rects[i].y2 };
733 impl->surface->SetClip (impl->surface, ®);
734 impl->surface->Blit (impl->surface, src_impl->surface, &rect,
738 temp_region_deinit( &clip );
742 gdk_directfb_draw_points (GdkDrawable *drawable,
747 GdkDrawableImplDirectFB *impl;
750 DFBRegion region = { points->x, points->y, points->x, points->y };
752 D_DEBUG_AT( GDKDFB_Drawable, "%s( %p, %p, %p, %d )\n", G_STRFUNC, drawable, gc, points, npoints );
757 impl = GDK_DRAWABLE_IMPL_DIRECTFB (drawable);
759 if (!gdk_directfb_setup_for_drawing (impl, GDK_GC_DIRECTFB (gc)))
762 gdk_directfb_clip_region (drawable, gc, NULL, &clip);
766 if (gdk_region_point_in (&clip, points->x, points->y))
768 impl->surface->FillRectangle (impl->surface,
769 points->x, points->y, 1, 1);
771 if (points->x < region.x1)
772 region.x1 = points->x;
773 if (points->x > region.x2)
774 region.x2 = points->x;
776 if (points->y < region.y1)
777 region.y1 = points->y;
778 if (points->y > region.y2)
779 region.y2 = points->y;
786 temp_region_deinit( &clip );
790 gdk_directfb_draw_segments (GdkDrawable *drawable,
795 GdkDrawableImplDirectFB *impl;
799 // DFBRegion region = { segs->x1, segs->y1, segs->x2, segs->y2 };
801 D_DEBUG_AT( GDKDFB_Drawable, "%s( %p, %p, %p, %d )\n", G_STRFUNC, drawable, gc, segs, nsegs );
806 impl = GDK_DRAWABLE_IMPL_DIRECTFB (drawable);
808 if (!gdk_directfb_setup_for_drawing (impl, GDK_GC_DIRECTFB (gc)))
811 gdk_directfb_clip_region (drawable, gc, NULL, &clip);
813 for (i = 0; i < clip.numRects; i++)
815 DFBRegion reg = { clip.rects[i].x1, clip.rects[i].y1,
816 clip.rects[i].x2, clip.rects[i].y2 };
818 impl->surface->SetClip (impl->surface, ®);
820 impl->surface->DrawLines (impl->surface, (DFBRegion *)segs, nsegs);
823 temp_region_deinit( &clip );
825 /* everything below can be omitted if the drawing is buffered */
826 /* if (impl->buffered)
829 if (region.x1 > region.x2)
831 region.x1 = segs->x2;
832 region.x2 = segs->x1;
834 if (region.y1 > region.y2)
836 region.y1 = segs->y2;
837 region.y2 = segs->y1;
845 if (segs->x1 < region.x1)
846 region.x1 = segs->x1;
847 if (segs->x2 < region.x1)
848 region.x1 = segs->x2;
850 if (segs->y1 < region.y1)
851 region.y1 = segs->y1;
852 if (segs->y2 < region.y1)
853 region.y1 = segs->y2;
855 if (segs->x1 > region.x2)
856 region.x2 = segs->x1;
857 if (segs->x2 > region.x2)
858 region.x2 = segs->x2;
860 if (segs->y1 > region.y2)
861 region.y2 = segs->y1;
862 if (segs->y2 > region.y2)
863 region.y2 = segs->y2;
868 gdk_directfb_draw_lines (GdkDrawable *drawable,
873 GdkDrawableImplDirectFB *impl;
877 DFBRegion lines[npoints > 1 ? npoints - 1 : 1];
879 DFBRegion region = { points->x, points->y, points->x, points->y };
881 D_DEBUG_AT( GDKDFB_Drawable, "%s( %p, %p, %p, %d )\n", G_STRFUNC, drawable, gc, points, npoints );
886 impl = GDK_DRAWABLE_IMPL_DIRECTFB (drawable);
888 if (!gdk_directfb_setup_for_drawing (impl, GDK_GC_DIRECTFB (gc)))
891 /* create an array of DFBRegions so we can use DrawLines */
893 lines[0].x1 = points->x;
894 lines[0].y1 = points->y;
896 for (i = 0; i < npoints - 2; i++)
900 lines[i].x2 = lines[i+1].x1 = points->x;
901 lines[i].y2 = lines[i+1].y1 = points->y;
903 if (points->x < region.x1)
904 region.x1 = points->x;
906 if (points->y < region.y1)
907 region.y1 = points->y;
909 if (points->x > region.x2)
910 region.x2 = points->x;
912 if (points->y > region.y2)
913 region.y2 = points->y;
917 lines[i].x2 = points->x;
918 lines[i].y2 = points->y;
920 gdk_directfb_clip_region (drawable, gc, NULL, &clip);
922 for (i = 0; i < clip.numRects; i++)
924 DFBRegion reg = { clip.rects[i].x1, clip.rects[i].y1,
925 clip.rects[i].x2, clip.rects[i].y2 };
927 impl->surface->SetClip (impl->surface, ®);
928 impl->surface->DrawLines (impl->surface, lines, npoints - 1);
931 temp_region_deinit( &clip );
935 gdk_directfb_draw_image (GdkDrawable *drawable,
945 GdkDrawableImplDirectFB *impl;
946 GdkImageDirectFB *image_private;
948 GdkRectangle dest_rect = { xdest, ydest, width, height };
953 g_return_if_fail (GDK_IS_DRAWABLE (drawable));
954 g_return_if_fail (image != NULL);
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 );
959 impl = GDK_DRAWABLE_IMPL_DIRECTFB (drawable);
960 image_private = image->windowing_data;
965 gdk_directfb_clip_region (drawable, gc, &dest_rect, &clip);
967 if (!gdk_region_empty (&clip))
969 DFBRectangle src_rect = { xsrc, ysrc, width, height };
971 image_private->surface->Unlock (image_private->surface);
973 impl->surface->SetBlittingFlags (impl->surface, DSBLIT_NOFX);
975 for (i = 0; i < clip.numRects; i++)
977 DFBRegion reg = { clip.rects[i].x1, clip.rects[i].y1,
978 clip.rects[i].x2 , clip.rects[i].y2 };
980 impl->surface->SetClip (impl->surface, ®);
981 impl->surface->Blit (impl->surface,
982 image_private->surface, &src_rect,
986 image_private->surface->Lock (image_private->surface, DSLF_WRITE,
987 &image->mem, &pitch);
991 temp_region_deinit( &clip );
995 composite (guchar *src_buf,
1002 guchar *src = src_buf;
1003 guchar *dest = dest_buf;
1007 gint twidth = width;
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;
1027 src += src_rowstride;
1028 dest += dest_rowstride;
1033 composite_0888 (guchar *src_buf,
1036 gint dest_rowstride,
1037 GdkByteOrder dest_byte_order,
1041 guchar *src = src_buf;
1042 guchar *dest = dest_buf;
1046 gint twidth = width;
1050 if (dest_byte_order == GDK_LSB_FIRST)
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;
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;
1083 src += src_rowstride;
1084 dest += dest_rowstride;
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 )
1092 /* From DirectFB's gfx/generic/generic.c" */
1093 #define SET_PIXEL( D, S ) \
1094 switch (S >> 26) { \
1098 D = ((S << 8) & 0xF800) | \
1099 ((S >> 5) & 0x07E0) | \
1100 ((S >> 19) & 0x001F); \
1103 D = (((( (((S<<8) & 0xf800) | ((S>>19) & 0x001f)) \
1104 - (D & 0xf81f)) * ((S>>26)+1) + ((D & 0xf81f)<<6)) & 0x003e07c0) \
1106 ((( ((S>>5) & 0x07e0) \
1107 - (D & 0x07e0)) * ((S>>26)+1) + ((D & 0x07e0)<<6)) & 0x0001f800)) >> 6; \
1111 composite_565 (guchar *src_buf,
1114 gint dest_rowstride,
1115 GdkByteOrder dest_byte_order,
1121 u16 *D = (u16*) dest_buf;
1122 u32 *S = (u32*) src_buf;
1124 if ((unsigned long)D & 2) {
1125 SET_PIXEL( D[0], S[0] );
1133 u32 *D32 = (u32*) D;
1135 for (i=0; i<w2; i++) {
1136 register u32 S0 = S[(i << 1) + 0];
1137 register u32 S1 = S[(i << 1) + 1];
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);
1148 SET_PIXEL( D[(i << 1) + 0], S0 );
1149 SET_PIXEL( D[(i << 1) + 1], S1 );
1154 SET_PIXEL( D[w-1], S[w-1] );
1156 SET_PIXEL_DUFFS_DEVICE( D, S, w );
1159 dest_buf += dest_rowstride;
1160 src_buf += src_rowstride;
1165 #undef SET_PIXEL_DUFFS_DEVICE
1168 gdk_directfb_draw_pixbuf (GdkDrawable *drawable,
1177 GdkRgbDither dither,
1181 GdkPixbuf *composited = NULL;
1185 GdkRectangle tmp_rect;
1187 GdkDrawableImplDirectFB *impl = GDK_DRAWABLE_IMPL_DIRECTFB (drawable);
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);
1194 g_return_if_fail (drawable != NULL);
1197 width = pixbuf->width;
1199 height = pixbuf->height;
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);
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 );
1208 /* Clip to the drawable; this is required for get_from_drawable() so
1209 * can't be done implicitly
1226 if ((dest_x + width) > impl->width)
1227 width = impl->width - dest_x;
1229 if ((dest_y + height) > impl->height)
1230 height = impl->height - dest_y;
1232 if (width <= 0 || height <= 0)
1236 /* Clip to the clip region; this avoids getting more
1237 * image data from the server than we need to.
1240 tmp_rect.x = dest_x;
1241 tmp_rect.y = dest_y;
1242 tmp_rect.width = width;
1243 tmp_rect.height = height;
1245 drect = gdk_region_rectangle (&tmp_rect);
1246 clip = gdk_drawable_get_clip_region (drawable);
1248 gdk_region_intersect (drect, clip);
1250 gdk_region_get_clipbox (drect, &tmp_rect);
1252 gdk_region_destroy (drect);
1253 gdk_region_destroy (clip);
1255 if (tmp_rect.width == 0 ||
1256 tmp_rect.height == 0)
1260 if (pixbuf->has_alpha && impl->format == DSPF_RGB16) {
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,
1267 data + dest_y * pitch + dest_x * 2,
1269 #if G_BYTE_ORDER == G_BIG_ENDIAN
1276 impl->surface->Unlock( impl->surface );
1284 gc = _gdk_drawable_get_scratch_gc (drawable, FALSE);
1286 if (pixbuf->has_alpha)
1288 GdkVisual *visual = gdk_drawable_get_visual (drawable);
1289 void (*composite_func) (guchar *src_buf,
1292 gint dest_rowstride,
1293 GdkByteOrder dest_byte_order,
1295 gint height) = NULL;
1297 /* First we see if we have a visual-specific composition function that can composite
1298 * the pixbuf data directly onto the image
1302 gint bits_per_pixel = _gdk_windowing_get_bits_for_depth (gdk_drawable_get_display (drawable),
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;
1318 /* We can't use our composite func if we are required to dither
1320 if (composite_func && !(dither == GDK_RGB_DITHER_MAX && visual->depth != 24))
1324 for (y0 = 0; y0 < height; y0 += GDK_SCRATCH_IMAGE_HEIGHT)
1326 gint height1 = MIN (height - y0, GDK_SCRATCH_IMAGE_HEIGHT);
1327 for (x0 = 0; x0 < width; x0 += GDK_SCRATCH_IMAGE_WIDTH)
1331 gint width1 = MIN (width - x0, GDK_SCRATCH_IMAGE_WIDTH);
1333 GdkImage *image = _gdk_image_get_scratch (gdk_drawable_get_screen (drawable),
1335 gdk_drawable_get_depth (drawable), &xs0, &ys0);
1337 gdk_drawable_copy_to_image (drawable, image,
1338 dest_x + x0, dest_y + y0,
1341 (*composite_func) (pixbuf->pixels + (src_y + y0) * pixbuf->rowstride + (src_x + x0) * 4,
1343 (guchar*)image->mem + ys0 * image->bpl + xs0 * image->bpp,
1347 gdk_draw_image (drawable, gc, image,
1349 dest_x + x0, dest_y + y0,
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,
1360 data + dest_y * pitch + DFB_BYTES_PER_LINE( impl->format, dest_x ),
1365 impl->surface->Unlock( impl->surface );
1372 /* No special composition func, convert dest to 24 bit RGB data, composite against
1373 * that, and convert back.
1375 composited = gdk_pixbuf_get_from_drawable (NULL,
1383 composite (pixbuf->pixels + src_y * pixbuf->rowstride + src_x * 4,
1386 composited->rowstride,
1395 pixbuf = composited;
1398 if (pixbuf->n_channels == 4)
1400 guchar *buf = pixbuf->pixels + src_y * pixbuf->rowstride + src_x * 4;
1402 gdk_draw_rgb_32_image_dithalign (drawable, gc,
1406 buf, pixbuf->rowstride,
1407 x_dither, y_dither);
1409 else /* n_channels == 3 */
1411 guchar *buf = pixbuf->pixels + src_y * pixbuf->rowstride + src_x * 3;
1413 gdk_draw_rgb_image_dithalign (drawable, gc,
1417 buf, pixbuf->rowstride,
1418 x_dither, y_dither);
1423 g_object_unref (composited);
1427 convert_rgba_pixbuf_to_image (guint32 *src,
1438 for (i = 0; i < width; i++)
1440 guint32 pixel = GUINT32_FROM_BE (src[i]);
1441 dest[i] = (pixel >> 8) | (pixel << 24);
1450 convert_rgb_pixbuf_to_image (guchar *src,
1464 for (i = 0; i < width; i++, s += 3)
1465 dest[i] = 0xFF000000 | (s[0] << 16) | (s[1] << 8) | s[2];
1475 static inline const char *
1476 drawable_impl_type_name( GObject *object )
1478 if (GDK_IS_PIXMAP (object))
1481 if (GDK_IS_WINDOW (object))
1484 if (GDK_IS_DRAWABLE_IMPL_DIRECTFB (object))
1492 gdk_drawable_impl_directfb_finalize (GObject *object)
1494 GdkDrawableImplDirectFB *impl;
1495 impl = GDK_DRAWABLE_IMPL_DIRECTFB (object);
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 );
1502 gdk_directfb_set_colormap (GDK_DRAWABLE (object), NULL);
1503 if( impl->cairo_surface ) {
1504 cairo_surface_finish(impl->cairo_surface);
1507 impl->surface->Release (impl->surface);
1508 G_OBJECT_CLASS (parent_class)->finalize (object);
1512 gdk_drawable_impl_directfb_class_init (GdkDrawableImplDirectFBClass *klass)
1514 GdkDrawableClass *drawable_class = GDK_DRAWABLE_CLASS (klass);
1515 GObjectClass *object_class = G_OBJECT_CLASS (klass);
1517 parent_class = g_type_class_peek_parent (klass);
1519 object_class->finalize = gdk_drawable_impl_directfb_finalize;
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;
1532 drawable_class->draw_glyphs = NULL;
1533 drawable_class->draw_glyphs_transformed = NULL;
1535 drawable_class->draw_image = gdk_directfb_draw_image;
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;
1541 drawable_class->get_depth = gdk_directfb_get_depth;
1542 drawable_class->get_visual = gdk_directfb_get_visual;
1544 drawable_class->get_size = gdk_directfb_get_size;
1546 drawable_class->_copy_to_image = _gdk_directfb_copy_to_image;
1547 drawable_class->get_screen = gdk_directfb_get_screen;
1550 real_draw_pixbuf = drawable_class->draw_pixbuf;
1551 drawable_class->draw_pixbuf = gdk_directfb_draw_pixbuf;
1553 /* check for hardware-accelerated alpha-blending */
1555 DFBGraphicsDeviceDescription desc;
1556 _gdk_display->directfb->GetDeviceDescription ( _gdk_display->directfb, &desc);
1558 accelerated_alpha_blending =
1559 ((desc.acceleration_mask & DFXL_BLIT) &&
1560 (desc.blitting_flags & DSBLIT_BLEND_ALPHACHANNEL));
1565 gdk_drawable_impl_directfb_get_type (void)
1567 static GType object_type = 0;
1571 const GTypeInfo object_info =
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,
1584 object_type = g_type_register_static (GDK_TYPE_DRAWABLE,
1585 "GdkDrawableImplDirectFB",
1592 static GdkScreen * gdk_directfb_get_screen (GdkDrawable *drawable){
1593 return gdk_screen_get_default();
1597 gdk_directfb_cairo_surface_destroy (void *data)
1599 GdkDrawableImplDirectFB *impl = data;
1600 impl->cairo_surface = NULL;
1604 _gdk_windowing_set_cairo_surface_size (cairo_surface_t *surface,
1611 _gdk_windowing_create_cairo_surface (GdkDrawable *drawable,
1615 GdkDrawableImplDirectFB *impl;
1617 cairo_surface_t *ret;
1619 impl = GDK_DRAWABLE_IMPL_DIRECTFB (drawable);
1620 dfb = GDK_DISPLAY_DFB (gdk_drawable_get_display (drawable))->directfb;
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);
1630 static cairo_surface_t *
1631 gdk_directfb_ref_cairo_surface (GdkDrawable *drawable)
1633 GdkDrawableImplDirectFB *impl;
1636 g_return_val_if_fail (GDK_IS_DRAWABLE (drawable), NULL);
1637 g_return_val_if_fail (GDK_IS_DRAWABLE_IMPL_DIRECTFB (drawable), NULL);
1639 impl = GDK_DRAWABLE_IMPL_DIRECTFB (drawable);
1640 dfb = GDK_DISPLAY_DFB(gdk_drawable_get_display(drawable))->directfb;
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);
1648 surface = impl->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);
1657 #if defined(CAIRO_VERSION) && CAIRO_VERSION >= CAIRO_VERSION_ENCODE(1,5,5)
1658 surface->Release (surface);
1662 cairo_surface_reference (impl->cairo_surface);
1665 g_assert (impl->cairo_surface != NULL);
1666 return impl->cairo_surface;
1669 #define __GDK_DRAWABLE_X11_C__
1670 #include "gdkaliasdef.c"