From 2d20a49584786a983300b71b7df108e974516706 Mon Sep 17 00:00:00 2001 From: Attilio Fiandrotti Date: Sun, 9 Dec 2007 10:03:30 +0000 Subject: [PATCH] Committed several patches by Denis Oliver Knoppwhich are expected to improve the performance of the DirectFB backend svn path=/trunk/; revision=19132 --- ChangeLog | 13 + gdk/directfb/gdkdirectfb.h | 5 + gdk/directfb/gdkdrawable-directfb.c | 692 ++++++++++++++++++++++++---- gdk/directfb/gdkgc-directfb.c | 27 +- gdk/directfb/gdkprivate-directfb.h | 96 +++- gdk/directfb/gdkwindow-directfb.c | 293 +++++++----- 6 files changed, 907 insertions(+), 219 deletions(-) diff --git a/ChangeLog b/ChangeLog index 93932b57f1..27ab377642 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,16 @@ +2007-12-09 09:56:06 Attilio Fiandrotti + + * gdk/directfb/gdkgc-directfb.c: + * gdk/directfb/gdkdrawable-directfb.c: + * gdk/directfb/gdkdirectfb.h: + * gdk/directfb/gdkwindow-directfb.c: + * gdk/directfb/gdkprivate-directfb.h: Committed several patches + (window_flip_group, no_background_pixmap_fix, opt_temp_region2, + blit_after_cairo_fix, rect_clip_fix, fast_blend, opt_temp_region_etc, + opt_clip_region_and_fill_rects, no_state_resets) by Denis Oliver Knopp + which are expected to improve the performance of the DirectFB backend. + Experimental pieces of code (GDK_DIRECTFB_NO_EXPERIMENTS) are disabled. + 2007-12-07 Matthias Clasen * gtk/gtkcontainer.c: Correct the documentation of child diff --git a/gdk/directfb/gdkdirectfb.h b/gdk/directfb/gdkdirectfb.h index bf34802090..33dd8b8ac6 100644 --- a/gdk/directfb/gdkdirectfb.h +++ b/gdk/directfb/gdkdirectfb.h @@ -33,6 +33,11 @@ #ifndef __GDK_DIRECTFB_H__ #define __GDK_DIRECTFB_H__ +/* This define disables some experimental code + */ +#ifndef GDK_DIRECTFB_NO_EXPERIMENTS +#define GDK_DIRECTFB_NO_EXPERIMENTS + #include #include #include "gdk/gdkprivate.h" diff --git a/gdk/directfb/gdkdrawable-directfb.c b/gdk/directfb/gdkdrawable-directfb.c index 20126d97db..ff07d5d7fb 100644 --- a/gdk/directfb/gdkdrawable-directfb.c +++ b/gdk/directfb/gdkdrawable-directfb.c @@ -39,6 +39,8 @@ #include "gdkdirectfb.h" #include "gdkprivate-directfb.h" +#include "../../gdk-pixbuf/gdk-pixbuf-private.h" + #include "gdkinternals.h" @@ -57,6 +59,66 @@ }\ } + +/* From DirectFB's */ +#define DUFF_1() \ + case 1:\ + SET_PIXEL( D[0], S[0] ); + +#define DUFF_2() \ + case 3:\ + SET_PIXEL( D[2], S[2] );\ + case 2:\ + SET_PIXEL( D[1], S[1] );\ + DUFF_1() + +#define DUFF_3() \ + case 7:\ + SET_PIXEL( D[6], S[6] );\ + case 6:\ + SET_PIXEL( D[5], S[5] );\ + case 5:\ + SET_PIXEL( D[4], S[4] );\ + case 4:\ + SET_PIXEL( D[3], S[3] );\ + DUFF_2() + +#define DUFF_4() \ + case 15:\ + SET_PIXEL( D[14], S[14] );\ + case 14:\ + SET_PIXEL( D[13], S[13] );\ + case 13:\ + SET_PIXEL( D[12], S[12] );\ + case 12:\ + SET_PIXEL( D[11], S[11] );\ + case 11:\ + SET_PIXEL( D[10], S[10] );\ + case 10:\ + SET_PIXEL( D[9], S[9] );\ + case 9:\ + SET_PIXEL( D[8], S[8] );\ + case 8:\ + SET_PIXEL( D[7], S[7] );\ + DUFF_3() + +#define SET_PIXEL_DUFFS_DEVICE_N( D, S, w, n ) \ +do {\ + while (w) {\ + register int l = w & ((1 << n) - 1);\ + switch (l) {\ + default:\ + l = (1 << n);\ + SET_PIXEL( D[(1 << n)-1], S[(1 << n)-1] );\ + DUFF_##n()\ + }\ + D += l;\ + S += l;\ + w -= l;\ + }\ +} while(0) + + static GdkScreen * gdk_directfb_get_screen (GdkDrawable *drawable); static void gdk_drawable_impl_directfb_class_init (GdkDrawableImplDirectFBClass *klass); static void gdk_directfb_draw_lines (GdkDrawable *drawable, @@ -71,6 +133,19 @@ static gboolean accelerated_alpha_blending = FALSE; static gpointer parent_class = NULL; static const cairo_user_data_key_t gdk_directfb_cairo_key; +static void (*real_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); + /********************************************************** * DirectFB specific implementations of generic functions * @@ -145,18 +220,18 @@ gdk_directfb_get_visual (GdkDrawable *drawable) /* Calculates the real clipping region for a drawable, taking into account * other windows and the gc clip region. */ -static GdkRegion * +void gdk_directfb_clip_region (GdkDrawable *drawable, GdkGC *gc, - GdkRectangle *draw_rect) + GdkRectangle *draw_rect, + GdkRegion *ret_clip) { GdkDrawableImplDirectFB *private; - GdkRegion *clip_region; - GdkRegion *tmpreg; GdkRectangle rect; - g_return_val_if_fail (GDK_IS_DRAWABLE (drawable), NULL); - g_return_val_if_fail (GDK_IS_DRAWABLE_IMPL_DIRECTFB (drawable), NULL); + g_return_if_fail (GDK_IS_DRAWABLE (drawable)); + g_return_if_fail (GDK_IS_DRAWABLE_IMPL_DIRECTFB (drawable)); + g_return_if_fail (ret_clip != NULL); private = GDK_DRAWABLE_IMPL_DIRECTFB (drawable); @@ -170,42 +245,48 @@ gdk_directfb_clip_region (GdkDrawable *drawable, draw_rect = ▭ } - clip_region = gdk_region_rectangle (draw_rect); + temp_region_init_rectangle( ret_clip, draw_rect ); - if (private->buffered && private->paint_region) - gdk_region_intersect (clip_region, private->paint_region); + if (private->buffered) + gdk_region_intersect (ret_clip, &private->paint_region); if (gc) { GdkGCDirectFB *gc_private = GDK_GC_DIRECTFB (gc); - GdkRegion *region = gc_private->clip_region; + GdkRegion *region = &gc_private->clip_region; - if (region) + if (region->numRects) { if (gc->clip_x_origin || gc->clip_y_origin) { - tmpreg = gdk_region_copy (region); - - gdk_region_offset (tmpreg, gc->clip_x_origin, gc->clip_y_origin); - gdk_region_intersect (clip_region, tmpreg); - gdk_region_destroy (tmpreg); + gdk_region_offset (ret_clip, -gc->clip_x_origin, -gc->clip_y_origin); + gdk_region_intersect (ret_clip, region); + gdk_region_offset (ret_clip, gc->clip_x_origin, gc->clip_y_origin); } else { - gdk_region_intersect (clip_region, region); + gdk_region_intersect (ret_clip, region); } } if (gc_private->values_mask & GDK_GC_SUBWINDOW && gc_private->values.subwindow_mode == GDK_INCLUDE_INFERIORS) - return clip_region; + return; } + if (private->buffered) + return; + if (GDK_IS_WINDOW (private->wrapper) && GDK_WINDOW_IS_MAPPED (private->wrapper) && !GDK_WINDOW_OBJECT (private->wrapper)->input_only) { - GList *cur; + GList *cur; + GdkRegion temp; + + temp.numRects = 1; + temp.rects = &temp.extents; + temp.size = 1; for (cur = GDK_WINDOW_OBJECT (private->wrapper)->children; cur; @@ -221,18 +302,14 @@ gdk_directfb_clip_region (GdkDrawable *drawable, cur_impl = GDK_DRAWABLE_IMPL_DIRECTFB (cur_private->impl); - rect.x = cur_private->x; - rect.y = cur_private->y; - rect.width = cur_impl->width; - rect.height = cur_impl->height; + temp.extents.x1 = cur_private->x; + temp.extents.y1 = cur_private->y; + temp.extents.x2 = cur_private->x + cur_impl->width; + temp.extents.y2 = cur_private->y + cur_impl->height; - tmpreg = gdk_region_rectangle (&rect); - gdk_region_subtract (clip_region, tmpreg); - gdk_region_destroy (tmpreg); + gdk_region_subtract (ret_clip, &temp); } } - - return clip_region; } /* Drawing @@ -328,7 +405,7 @@ _gdk_directfb_draw_rectangle (GdkDrawable *drawable, gint height) { GdkDrawableImplDirectFB *impl; - GdkRegion *clip; + GdkRegion clip; GdkGCDirectFB *gc_private = NULL; IDirectFBSurface *surface = NULL; gint i; @@ -392,7 +469,7 @@ _gdk_directfb_draw_rectangle (GdkDrawable *drawable, { GdkRectangle rect = { x, y, width, height }; - clip = gdk_directfb_clip_region (drawable, gc, &rect); + gdk_directfb_clip_region (drawable, gc, &rect, &clip); if (gc_private && gc_private->values_mask & GDK_GC_FILL) { @@ -412,6 +489,8 @@ _gdk_directfb_draw_rectangle (GdkDrawable *drawable, gc_private->values.tile) { surface = GDK_DRAWABLE_IMPL_DIRECTFB (GDK_PIXMAP_OBJECT (gc_private->values.tile)->impl)->surface; + + impl->surface->SetBlittingFlags (impl->surface, DSBLIT_NOFX); } } @@ -422,33 +501,35 @@ _gdk_directfb_draw_rectangle (GdkDrawable *drawable, if (gc_private->values_mask & GDK_GC_TS_Y_ORIGIN) y = gc_private->values.ts_y_origin; - for (i = 0; i < clip->numRects; i++) + for (i = 0; i < clip.numRects; i++) { - DFBRegion reg = { clip->rects[i].x1, clip->rects[i].y1, - clip->rects[i].x2, clip->rects[i].y2 }; + DFBRegion reg = { clip.rects[i].x1, clip.rects[i].y1, + clip.rects[i].x2, clip.rects[i].y2 }; impl->surface->SetClip (impl->surface, ®); impl->surface->TileBlit (impl->surface, surface, NULL, x, y); } - - impl->surface->SetBlittingFlags (impl->surface, DSBLIT_NOFX); - impl->surface->SetClip (impl->surface, NULL); } else /* normal rectangle filling */ { - for (i = 0; i < clip->numRects; i++) - { - DFBRegion *region = (DFBRegion *) &clip->rects[i]; + DFBRectangle rects[clip.numRects]; - impl->surface->FillRectangle (impl->surface, - region->x1, - region->y1, - region->x2 - region->x1, - region->y2 - region->y1); + impl->surface->SetClip (impl->surface, NULL); + + for (i = 0; i < clip.numRects; i++) + { + GdkRegionBox *box = &clip.rects[i]; + + rects[i].x = box->x1; + rects[i].y = box->y1; + rects[i].w = box->x2 - box->x1; + rects[i].h = box->y2 - box->y1; } + + impl->surface->FillRectangles(impl->surface, rects, clip.numRects); } - gdk_region_destroy (clip); + temp_region_deinit( &clip ); } else { @@ -461,7 +542,6 @@ _gdk_directfb_draw_rectangle (GdkDrawable *drawable, X draws the rectangle one pixel taller and wider. */ impl->surface->DrawRectangle (impl->surface, x, y, width , height); - impl->surface->SetClip (impl->surface, NULL); } } @@ -499,7 +579,7 @@ gdk_directfb_draw_polygon (GdkDrawable *drawable, points[0].y == points[npoints-1].y)) { GdkDrawableImplDirectFB *impl; - GdkRegion *clip; + GdkRegion clip; gint i; impl = GDK_DRAWABLE_IMPL_DIRECTFB (drawable); @@ -507,12 +587,12 @@ gdk_directfb_draw_polygon (GdkDrawable *drawable, if (!gdk_directfb_setup_for_drawing (impl, GDK_GC_DIRECTFB (gc))) return; - clip = gdk_directfb_clip_region (drawable, gc, NULL); + gdk_directfb_clip_region (drawable, gc, NULL, &clip); - for (i = 0; i < clip->numRects; i++) + for (i = 0; i < clip.numRects; i++) { - DFBRegion reg = { clip->rects[i].x1, clip->rects[i].y1, - clip->rects[i].x2 , clip->rects[i].y2 }; + DFBRegion reg = { clip.rects[i].x1, clip.rects[i].y1, + clip.rects[i].x2 , clip.rects[i].y2 }; impl->surface->SetClip (impl->surface, ®); impl->surface->FillTriangle (impl->surface, @@ -521,8 +601,8 @@ gdk_directfb_draw_polygon (GdkDrawable *drawable, points[2].x, points[2].y); } - impl->surface->SetClip (impl->surface, NULL); - gdk_region_destroy (clip); + + temp_region_deinit( &clip ); return; } @@ -588,7 +668,7 @@ gdk_directfb_draw_drawable (GdkDrawable *drawable, { GdkDrawableImplDirectFB *impl; GdkDrawableImplDirectFB *src_impl; - GdkRegion *clip; + GdkRegion clip; GdkRectangle dest_rect = { xdest, ydest, xdest + width , @@ -611,19 +691,21 @@ gdk_directfb_draw_drawable (GdkDrawable *drawable, else return; - clip = gdk_directfb_clip_region (drawable, gc, &dest_rect); + gdk_directfb_clip_region (drawable, gc, &dest_rect, &clip); - for (i = 0; i < clip->numRects; i++) + impl->surface->SetBlittingFlags (impl->surface, DSBLIT_NOFX); + + for (i = 0; i < clip.numRects; i++) { - DFBRegion reg = { clip->rects[i].x1, clip->rects[i].y1, - clip->rects[i].x2 , clip->rects[i].y2 }; + DFBRegion reg = { clip.rects[i].x1, clip.rects[i].y1, + clip.rects[i].x2 , clip.rects[i].y2 }; impl->surface->SetClip (impl->surface, ®); impl->surface->Blit (impl->surface, src_impl->surface, &rect, xdest, ydest); } - impl->surface->SetClip (impl->surface, NULL); - gdk_region_destroy (clip); + + temp_region_deinit( &clip ); } static void @@ -633,7 +715,7 @@ gdk_directfb_draw_points (GdkDrawable *drawable, gint npoints) { GdkDrawableImplDirectFB *impl; - GdkRegion *clip; + GdkRegion clip; DFBRegion region = { points->x, points->y, points->x, points->y }; @@ -645,11 +727,11 @@ gdk_directfb_draw_points (GdkDrawable *drawable, if (!gdk_directfb_setup_for_drawing (impl, GDK_GC_DIRECTFB (gc))) return; - clip = gdk_directfb_clip_region (drawable, gc, NULL); + gdk_directfb_clip_region (drawable, gc, NULL, &clip); while (npoints > 0) { - if (gdk_region_point_in (clip, points->x, points->y)) + if (gdk_region_point_in (&clip, points->x, points->y)) { impl->surface->FillRectangle (impl->surface, points->x, points->y, 1, 1); @@ -669,7 +751,7 @@ gdk_directfb_draw_points (GdkDrawable *drawable, points++; } - gdk_region_destroy (clip); + temp_region_deinit( &clip ); } static void @@ -679,10 +761,10 @@ gdk_directfb_draw_segments (GdkDrawable *drawable, gint nsegs) { GdkDrawableImplDirectFB *impl; - GdkRegion *clip; + GdkRegion clip; gint i; - DFBRegion region = { segs->x1, segs->y1, segs->x2, segs->y2 }; +// DFBRegion region = { segs->x1, segs->y1, segs->x2, segs->y2 }; if (nsegs < 1) return; @@ -692,24 +774,22 @@ gdk_directfb_draw_segments (GdkDrawable *drawable, if (!gdk_directfb_setup_for_drawing (impl, GDK_GC_DIRECTFB (gc))) return; - clip = gdk_directfb_clip_region (drawable, gc, NULL); + gdk_directfb_clip_region (drawable, gc, NULL, &clip); - for (i = 0; i < clip->numRects; i++) + for (i = 0; i < clip.numRects; i++) { - DFBRegion reg = { clip->rects[i].x1, clip->rects[i].y1, - clip->rects[i].x2, clip->rects[i].y2 }; + DFBRegion reg = { clip.rects[i].x1, clip.rects[i].y1, + clip.rects[i].x2, clip.rects[i].y2 }; impl->surface->SetClip (impl->surface, ®); impl->surface->DrawLines (impl->surface, (DFBRegion *)segs, nsegs); } - impl->surface->SetClip (impl->surface, NULL); - - gdk_region_destroy (clip); + temp_region_deinit( &clip ); /* everything below can be omitted if the drawing is buffered */ - if (impl->buffered) +/* if (impl->buffered) return; if (region.x1 > region.x2) @@ -747,7 +827,7 @@ gdk_directfb_draw_segments (GdkDrawable *drawable, region.y2 = segs->y1; if (segs->y2 > region.y2) region.y2 = segs->y2; - } + }*/ } static void @@ -757,7 +837,7 @@ gdk_directfb_draw_lines (GdkDrawable *drawable, gint npoints) { GdkDrawableImplDirectFB *impl; - GdkRegion *clip; + GdkRegion clip; gint i; DFBRegion lines[npoints > 1 ? npoints - 1 : 1]; @@ -801,20 +881,18 @@ gdk_directfb_draw_lines (GdkDrawable *drawable, lines[i].x2 = points->x; lines[i].y2 = points->y; - clip = gdk_directfb_clip_region (drawable, gc, NULL); + gdk_directfb_clip_region (drawable, gc, NULL, &clip); - for (i = 0; i < clip->numRects; i++) + for (i = 0; i < clip.numRects; i++) { - DFBRegion reg = { clip->rects[i].x1, clip->rects[i].y1, - clip->rects[i].x2, clip->rects[i].y2 }; + DFBRegion reg = { clip.rects[i].x1, clip.rects[i].y1, + clip.rects[i].x2, clip.rects[i].y2 }; impl->surface->SetClip (impl->surface, ®); impl->surface->DrawLines (impl->surface, lines, npoints - 1); } - impl->surface->SetClip (impl->surface, NULL); - - gdk_region_destroy (clip); + temp_region_deinit( &clip ); } static void @@ -830,7 +908,7 @@ gdk_directfb_draw_image (GdkDrawable *drawable, { GdkDrawableImplDirectFB *impl; GdkImageDirectFB *image_private; - GdkRegion *clip; + GdkRegion clip; GdkRectangle dest_rect = { xdest, ydest, width, height }; gint pitch = 0; @@ -845,32 +923,462 @@ gdk_directfb_draw_image (GdkDrawable *drawable, if (!impl->surface) return; - clip = gdk_directfb_clip_region (drawable, gc, &dest_rect); + gdk_directfb_clip_region (drawable, gc, &dest_rect, &clip); - if (!gdk_region_empty (clip)) + if (!gdk_region_empty (&clip)) { DFBRectangle src_rect = { xsrc, ysrc, width, height }; image_private->surface->Unlock (image_private->surface); - for (i = 0; i < clip->numRects; i++) + impl->surface->SetBlittingFlags (impl->surface, DSBLIT_NOFX); + + for (i = 0; i < clip.numRects; i++) { - DFBRegion reg = { clip->rects[i].x1, clip->rects[i].y1, - clip->rects[i].x2 , clip->rects[i].y2 }; + DFBRegion reg = { clip.rects[i].x1, clip.rects[i].y1, + clip.rects[i].x2 , clip.rects[i].y2 }; impl->surface->SetClip (impl->surface, ®); impl->surface->Blit (impl->surface, image_private->surface, &src_rect, xdest, ydest); } - impl->surface->SetClip (impl->surface, NULL); image_private->surface->Lock (image_private->surface, DSLF_WRITE, &image->mem, &pitch); image->bpl = pitch; } + temp_region_deinit( &clip ); +} + +static void +composite (guchar *src_buf, + gint src_rowstride, + guchar *dest_buf, + gint dest_rowstride, + gint width, + gint height) +{ + guchar *src = src_buf; + guchar *dest = dest_buf; + + while (height--) + { + gint twidth = width; + guchar *p = src; + guchar *q = dest; + + while (twidth--) + { + guchar a = p[3]; + guint t; + + t = a * p[0] + (255 - a) * q[0] + 0x80; + q[0] = (t + (t >> 8)) >> 8; + t = a * p[1] + (255 - a) * q[1] + 0x80; + q[1] = (t + (t >> 8)) >> 8; + t = a * p[2] + (255 - a) * q[2] + 0x80; + q[2] = (t + (t >> 8)) >> 8; + + p += 4; + q += 3; + } + + src += src_rowstride; + dest += dest_rowstride; + } +} + +static void +composite_0888 (guchar *src_buf, + gint src_rowstride, + guchar *dest_buf, + gint dest_rowstride, + GdkByteOrder dest_byte_order, + gint width, + gint height) +{ + guchar *src = src_buf; + guchar *dest = dest_buf; + + while (height--) + { + gint twidth = width; + guchar *p = src; + guchar *q = dest; + + if (dest_byte_order == GDK_LSB_FIRST) + { + while (twidth--) + { + guint t; + + t = p[3] * p[2] + (255 - p[3]) * q[0] + 0x80; + q[0] = (t + (t >> 8)) >> 8; + t = p[3] * p[1] + (255 - p[3]) * q[1] + 0x80; + q[1] = (t + (t >> 8)) >> 8; + t = p[3] * p[0] + (255 - p[3]) * q[2] + 0x80; + q[2] = (t + (t >> 8)) >> 8; + p += 4; + q += 4; + } + } + else + { + while (twidth--) + { + guint t; + + t = p[3] * p[0] + (255 - p[3]) * q[1] + 0x80; + q[1] = (t + (t >> 8)) >> 8; + t = p[3] * p[1] + (255 - p[3]) * q[2] + 0x80; + q[2] = (t + (t >> 8)) >> 8; + t = p[3] * p[2] + (255 - p[3]) * q[3] + 0x80; + q[3] = (t + (t >> 8)) >> 8; + p += 4; + q += 4; + } + } + + src += src_rowstride; + dest += dest_rowstride; + } +} + +/* change the last value to adjust the size of the device (1-4) */ +#define SET_PIXEL_DUFFS_DEVICE( D, S, w ) \ + SET_PIXEL_DUFFS_DEVICE_N( D, S, w, 2 ) + +/* From DirectFB's gfx/generic/generic.c" */ +#define SET_PIXEL( D, S ) \ + switch (S >> 26) { \ + case 0: \ + break; \ + case 0x3f: \ + D = ((S << 8) & 0xF800) | \ + ((S >> 5) & 0x07E0) | \ + ((S >> 19) & 0x001F); \ + break; \ + default: \ + D = (((( (((S<<8) & 0xf800) | ((S>>19) & 0x001f)) \ + - (D & 0xf81f)) * ((S>>26)+1) + ((D & 0xf81f)<<6)) & 0x003e07c0) \ + + \ + ((( ((S>>5) & 0x07e0) \ + - (D & 0x07e0)) * ((S>>26)+1) + ((D & 0x07e0)<<6)) & 0x0001f800)) >> 6; \ + } + +static void +composite_565 (guchar *src_buf, + gint src_rowstride, + guchar *dest_buf, + gint dest_rowstride, + GdkByteOrder dest_byte_order, + gint width, + gint height) +{ + while (height--) { + int w = width; + u16 *D = (u16*) dest_buf; + u32 *S = (u32*) src_buf; +#if 1 + if ((unsigned long)D & 2) { + SET_PIXEL( D[0], S[0] ); + w--; + D++; + S++; + } + + int i; + int w2 = w / 2; + u32 *D32 = (u32*) D; + + for (i=0; i> 26) == 0x3f && (S1 >> 26) == 0x3f) { + D32[i] = ((S0 << 8) & 0x0000F800) | + ((S0 >> 5) & 0x000007E0) | + ((S0 >> 19) & 0x0000001F) | + ((S1 << 24) & 0xF8000000) | + ((S1 << 11) & 0x07E00000) | + ((S1 >> 3) & 0x001F0000); + } + else { + SET_PIXEL( D[(i << 1) + 0], S0 ); + SET_PIXEL( D[(i << 1) + 1], S1 ); + } + } + + if (w & 1) + SET_PIXEL( D[w-1], S[w-1] ); +#else + SET_PIXEL_DUFFS_DEVICE( D, S, w ); +#endif + + dest_buf += dest_rowstride; + src_buf += src_rowstride; + } +} + +#undef SET_PIXEL +#undef SET_PIXEL_DUFFS_DEVICE + +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) +{ + GdkPixbuf *composited = NULL; +#if 0 + GdkRegion *clip; + GdkRegion *drect; + GdkRectangle tmp_rect; +#endif + GdkDrawableImplDirectFB *impl = GDK_DRAWABLE_IMPL_DIRECTFB (drawable); + + g_return_if_fail (GDK_IS_PIXBUF (pixbuf)); + g_return_if_fail (pixbuf->colorspace == GDK_COLORSPACE_RGB); + g_return_if_fail (pixbuf->n_channels == 3 || pixbuf->n_channels == 4); + g_return_if_fail (pixbuf->bits_per_sample == 8); + + g_return_if_fail (drawable != NULL); + + if (width == -1) + width = pixbuf->width; + if (height == -1) + height = pixbuf->height; + + g_return_if_fail (width >= 0 && height >= 0); + g_return_if_fail (src_x >= 0 && src_x + width <= pixbuf->width); + g_return_if_fail (src_y >= 0 && src_y + height <= pixbuf->height); + + /* Clip to the drawable; this is required for get_from_drawable() so + * can't be done implicitly + */ + + if (dest_x < 0) + { + src_x -= dest_x; + width += dest_x; + dest_x = 0; + } + + if (dest_y < 0) + { + src_y -= dest_y; + height += dest_y; + dest_y = 0; + } + + if ((dest_x + width) > impl->width) + width = impl->width - dest_x; + + if ((dest_y + height) > impl->height) + height = impl->height - dest_y; + + if (width <= 0 || height <= 0) + return; + +#if 0 + /* Clip to the clip region; this avoids getting more + * image data from the server than we need to. + */ + + tmp_rect.x = dest_x; + tmp_rect.y = dest_y; + tmp_rect.width = width; + tmp_rect.height = height; + + drect = gdk_region_rectangle (&tmp_rect); + clip = gdk_drawable_get_clip_region (drawable); + + gdk_region_intersect (drect, clip); + + gdk_region_get_clipbox (drect, &tmp_rect); + + gdk_region_destroy (drect); gdk_region_destroy (clip); + + if (tmp_rect.width == 0 || + tmp_rect.height == 0) + return; +#endif + + if (pixbuf->has_alpha && impl->format == DSPF_RGB16) { + void *data; + int pitch; + + if (impl->surface->Lock( impl->surface, DSLF_READ | DSLF_WRITE, &data, &pitch ) == DFB_OK) { + composite_565( pixbuf->pixels + src_y * pixbuf->rowstride + src_x * 4, + pixbuf->rowstride, + data + dest_y * pitch + dest_x * 2, + pitch, + #if G_BYTE_ORDER == G_BIG_ENDIAN + GDK_MSB_FIRST, + #else + GDK_LSB_FIRST, + #endif + width, height ); + + impl->surface->Unlock( impl->surface ); + + return; + } + } + + /* Actually draw */ + if (!gc) + gc = _gdk_drawable_get_scratch_gc (drawable, FALSE); + + if (pixbuf->has_alpha) + { + GdkVisual *visual = gdk_drawable_get_visual (drawable); + void (*composite_func) (guchar *src_buf, + gint src_rowstride, + guchar *dest_buf, + gint dest_rowstride, + GdkByteOrder dest_byte_order, + gint width, + gint height) = NULL; + + /* First we see if we have a visual-specific composition function that can composite + * the pixbuf data directly onto the image + */ + if (visual) + { + gint bits_per_pixel = _gdk_windowing_get_bits_for_depth (gdk_drawable_get_display (drawable), + visual->depth); + + if (visual->byte_order == (G_BYTE_ORDER == G_BIG_ENDIAN ? GDK_MSB_FIRST : GDK_LSB_FIRST) && + visual->depth == 16 && + visual->red_mask == 0xf800 && + visual->green_mask == 0x07e0 && + visual->blue_mask == 0x001f) + composite_func = composite_565; + else if (visual->depth == 24 && bits_per_pixel == 32 && + visual->red_mask == 0xff0000 && + visual->green_mask == 0x00ff00 && + visual->blue_mask == 0x0000ff) + composite_func = composite_0888; + } + + /* We can't use our composite func if we are required to dither + */ + if (composite_func && !(dither == GDK_RGB_DITHER_MAX && visual->depth != 24)) + { +#if 0 + gint x0, y0; + for (y0 = 0; y0 < height; y0 += GDK_SCRATCH_IMAGE_HEIGHT) + { + gint height1 = MIN (height - y0, GDK_SCRATCH_IMAGE_HEIGHT); + for (x0 = 0; x0 < width; x0 += GDK_SCRATCH_IMAGE_WIDTH) + { + gint xs0, ys0; + + gint width1 = MIN (width - x0, GDK_SCRATCH_IMAGE_WIDTH); + + GdkImage *image = _gdk_image_get_scratch (gdk_drawable_get_screen (drawable), + width1, height1, + gdk_drawable_get_depth (drawable), &xs0, &ys0); + + gdk_drawable_copy_to_image (drawable, image, + dest_x + x0, dest_y + y0, + xs0, ys0, + width1, height1); + (*composite_func) (pixbuf->pixels + (src_y + y0) * pixbuf->rowstride + (src_x + x0) * 4, + pixbuf->rowstride, + (guchar*)image->mem + ys0 * image->bpl + xs0 * image->bpp, + image->bpl, + visual->byte_order, + width1, height1); + gdk_draw_image (drawable, gc, image, + xs0, ys0, + dest_x + x0, dest_y + y0, + width1, height1); + } + } +#else + void *data; + int pitch; + + if (impl->surface->Lock( impl->surface, DSLF_READ | DSLF_WRITE, &data, &pitch ) == DFB_OK) { + (*composite_func) (pixbuf->pixels + src_y * pixbuf->rowstride + src_x * 4, + pixbuf->rowstride, + data + dest_y * pitch + DFB_BYTES_PER_LINE( impl->format, dest_x ), + pitch, + visual->byte_order, + width, height); + + impl->surface->Unlock( impl->surface ); + } +#endif + goto out; + } + else + { + /* No special composition func, convert dest to 24 bit RGB data, composite against + * that, and convert back. + */ + composited = gdk_pixbuf_get_from_drawable (NULL, + drawable, + NULL, + dest_x, dest_y, + 0, 0, + width, height); + + if (composited) + composite (pixbuf->pixels + src_y * pixbuf->rowstride + src_x * 4, + pixbuf->rowstride, + composited->pixels, + composited->rowstride, + width, height); + } + } + + if (composited) + { + src_x = 0; + src_y = 0; + pixbuf = composited; + } + + if (pixbuf->n_channels == 4) + { + guchar *buf = pixbuf->pixels + src_y * pixbuf->rowstride + src_x * 4; + + gdk_draw_rgb_32_image_dithalign (drawable, gc, + dest_x, dest_y, + width, height, + dither, + buf, pixbuf->rowstride, + x_dither, y_dither); + } + else /* n_channels == 3 */ + { + guchar *buf = pixbuf->pixels + src_y * pixbuf->rowstride + src_x * 3; + + gdk_draw_rgb_image_dithalign (drawable, gc, + dest_x, dest_y, + width, height, + dither, + buf, pixbuf->rowstride, + x_dither, y_dither); + } + + out: + if (composited) + g_object_unref (composited); } static inline void @@ -976,6 +1484,10 @@ gdk_drawable_impl_directfb_class_init (GdkDrawableImplDirectFBClass *klass) drawable_class->_copy_to_image = _gdk_directfb_copy_to_image; drawable_class->get_screen = gdk_directfb_get_screen; + + real_draw_pixbuf = drawable_class->draw_pixbuf; + drawable_class->draw_pixbuf = gdk_directfb_draw_pixbuf; + /* check for hardware-accelerated alpha-blending */ { DFBGraphicsDeviceDescription desc; diff --git a/gdk/directfb/gdkgc-directfb.c b/gdk/directfb/gdkgc-directfb.c index c8d5293647..9e20ebcd3b 100644 --- a/gdk/directfb/gdkgc-directfb.c +++ b/gdk/directfb/gdkgc-directfb.c @@ -113,8 +113,8 @@ gdk_gc_directfb_finalize (GObject *object) GdkGC *gc = GDK_GC (object); GdkGCDirectFB *private = GDK_GC_DIRECTFB (gc); - if (private->clip_region) - gdk_region_destroy (private->clip_region); + if (private->clip_region.numRects) + temp_region_deinit (&private->clip_region); if (private->values.clip_mask) g_object_unref (private->values.clip_mask); if (private->values.stipple) @@ -262,11 +262,7 @@ gdk_directfb_gc_set_values (GdkGC *gc, if (oldpm) g_object_unref (oldpm); - if (private->clip_region) - { - gdk_region_destroy (private->clip_region); - private->clip_region = NULL; - } + temp_region_reset (&private->clip_region); } if (values_mask & GDK_GC_SUBWINDOW) @@ -363,17 +359,13 @@ _gdk_windowing_gc_set_clip_region (GdkGC *gc, data = GDK_GC_DIRECTFB (gc); - if (region == data->clip_region) + if (region == &data->clip_region) return; - if (data->clip_region) - { - gdk_region_destroy (data->clip_region); - data->clip_region = NULL; - } - if (region) - data->clip_region = gdk_region_copy (region); + temp_region_init_copy (&data->clip_region, region); + else + temp_region_reset (&data->clip_region); gc->clip_x_origin = 0; gc->clip_y_origin = 0; @@ -394,8 +386,7 @@ _gdk_windowing_gc_copy (GdkGC *dst_gc, dst_private = GDK_GC_DIRECTFB (dst_gc); - if (dst_private->clip_region) - gdk_region_destroy(dst_private->clip_region); + temp_region_reset(&dst_private->clip_region); if (dst_private->values_mask & GDK_GC_FONT) gdk_font_unref (dst_private->values.font); @@ -415,8 +406,6 @@ _gdk_windowing_gc_copy (GdkGC *dst_gc, g_object_ref (dst_private->values.stipple); if (dst_private->values_mask & GDK_GC_CLIP_MASK) g_object_ref (dst_private->values.clip_mask); - if (dst_private->clip_region) - dst_private->clip_region = gdk_region_copy (dst_private->clip_region); } /** diff --git a/gdk/directfb/gdkprivate-directfb.h b/gdk/directfb/gdkprivate-directfb.h index b645057f32..38b89d6735 100644 --- a/gdk/directfb/gdkprivate-directfb.h +++ b/gdk/directfb/gdkprivate-directfb.h @@ -38,8 +38,12 @@ #include "gdkinternals.h" #include "gdkcursor.h" #include "gdkdisplay-directfb.h" +#include "gdkregion-generic.h" #include +#include + +#include #define GDK_TYPE_DRAWABLE_IMPL_DIRECTFB (gdk_drawable_impl_directfb_get_type ()) @@ -68,13 +72,15 @@ struct _GdkDrawableImplDirectFB gboolean buffered; - GdkRegion *paint_region; + GdkRegion paint_region; gint paint_depth; gint width; gint height; gint abs_x; gint abs_y; + GdkRegion clip_region; + GdkColormap *colormap; IDirectFBSurface *surface; @@ -151,6 +157,9 @@ struct _GdkWindowImplDirectFB guint8 opacity; GdkWindowTypeHint type_hint; + + DFBUpdates flips; + DFBRegion flip_regions[4]; }; typedef struct @@ -204,7 +213,7 @@ typedef struct { GdkGC parent_instance; - GdkRegion *clip_region; + GdkRegion clip_region; GdkGCValuesMask values_mask; GdkGCValues values; @@ -317,5 +326,88 @@ void gdk_fb_window_set_child_handler (GdkWindow *window, GdkWindowChildGetPos get_pos, gpointer user_data); +void gdk_directfb_clip_region (GdkDrawable *drawable, + GdkGC *gc, + GdkRectangle *draw_rect, + GdkRegion *ret_clip); + + +/* Utilities for avoiding mallocs */ + +static inline void +temp_region_init_copy( GdkRegion *region, + const GdkRegion *source) +{ + if (region != source) /* don't want to copy to itself */ + { + if (region->size < source->numRects) + { + if (region->rects && region->rects != ®ion->extents) + g_free( region->rects ); + + region->rects = g_new (GdkRegionBox, source->numRects); + region->size = source->numRects; + } + + region->numRects = source->numRects; + region->extents = source->extents; + + memcpy( region->rects, source->rects, source->numRects * sizeof (GdkRegionBox) ); + } +} + +static inline void +temp_region_init_rectangle( GdkRegion *region, + const GdkRectangle *rect ) +{ + region->numRects = 1; + region->rects = ®ion->extents; + region->extents.x1 = rect->x; + region->extents.y1 = rect->y; + region->extents.x2 = rect->x + rect->width; + region->extents.y2 = rect->y + rect->height; + region->size = 1; +} + +static inline void +temp_region_init_rectangle_vals( GdkRegion *region, + int x, + int y, + int w, + int h ) +{ + region->numRects = 1; + region->rects = ®ion->extents; + region->extents.x1 = x; + region->extents.y1 = y; + region->extents.x2 = x + w; + region->extents.y2 = y + h; + region->size = 1; +} + +static inline void +temp_region_reset( GdkRegion *region ) +{ + if (region->size > 32 && region->rects && region->rects != ®ion->extents) { + g_free( region->rects ); + + region->size = 1; + region->rects = ®ion->extents; + } + + region->numRects = 0; +} + +static inline void +temp_region_deinit( GdkRegion *region ) +{ + if (region->rects && region->rects != ®ion->extents) { + g_free( region->rects ); + region->rects = NULL; + } + + region->numRects = 0; +} + #endif /* __GDK_PRIVATE_DIRECTFB_H__ */ diff --git a/gdk/directfb/gdkwindow-directfb.c b/gdk/directfb/gdkwindow-directfb.c index 4337cf98ef..db07bdd32e 100644 --- a/gdk/directfb/gdkwindow-directfb.c +++ b/gdk/directfb/gdkwindow-directfb.c @@ -46,6 +46,8 @@ #include "cairo.h" #include +#include + static GdkRegion * gdk_window_impl_directfb_get_visible_region (GdkDrawable *drawable); static void gdk_window_impl_directfb_set_colormap (GdkDrawable *drawable, GdkColormap *colormap); @@ -93,6 +95,35 @@ gdk_window_directfb_process_all_updates (void) tmp_list = tmp_list->next; } + +#ifndef GDK_DIRECTFB_NO_EXPERIMENTS + tmp_list = old_update_windows; + + g_slist_foreach (old_update_windows, (GFunc)g_object_ref, NULL); + + while (tmp_list) { + GdkWindowObject *top = GDK_WINDOW_OBJECT( gdk_window_get_toplevel( tmp_list->data ) ); + + if (top) { + GdkWindowImplDirectFB *wimpl = GDK_WINDOW_IMPL_DIRECTFB (top->impl); + + if (wimpl->flips.num_regions) { + //direct_log_printf( NULL, "Flipping bounding box of paints: %d,%d - %dx%d (top %p, wimpl %p)\n", + // DFB_RECTANGLE_VALS_FROM_REGION( &wimpl->flips.bounding ), top, wimpl ); + + wimpl->drawable.surface->Flip( wimpl->drawable.surface, &wimpl->flips.bounding, DSFLIP_NONE ); + + dfb_updates_reset( &wimpl->flips ); + } + } + + + g_object_unref (tmp_list->data); + tmp_list = tmp_list->next; + } +#endif + + g_slist_free (old_update_windows); } @@ -311,6 +342,12 @@ create_directfb_window (GdkWindowImplDirectFB *impl, impl->window = window; +#ifndef GDK_DIRECTFB_NO_EXPERIMENTS + //direct_log_printf( NULL, "Initializing (window %p, wimpl %p)\n", win, impl ); + + dfb_updates_init( &impl->flips, impl->flip_regions, G_N_ELEMENTS(impl->flip_regions) ); +#endif + return TRUE; } @@ -333,7 +370,7 @@ _gdk_windowing_window_init (void) private->window_type = GDK_WINDOW_ROOT; private->state = 0; private->children = NULL; - impl->drawable.paint_region = NULL; +// impl->drawable.paint_region = NULL; impl->gdkWindow = _gdk_parent_root; impl->window = NULL; impl->drawable.abs_x = 0; @@ -1797,10 +1834,15 @@ gdk_window_set_back_pixmap (GdkWindow *window, } else { - if (pixmap && pixmap != GDK_NO_BG && pixmap != GDK_PARENT_RELATIVE_BG) - g_object_ref (pixmap); - - private->bg_pixmap = pixmap; + if (pixmap) + { + g_object_ref (pixmap); + private->bg_pixmap = pixmap; + } + else + { + private->bg_pixmap = GDK_NO_BG; + } } } @@ -2777,9 +2819,9 @@ gdk_window_set_urgency_hint (GdkWindow *window, static void gdk_window_impl_directfb_invalidate_maybe_recurse (GdkPaintable *paintable, - GdkRegion *region, - gboolean (*child_func) (GdkWindow *, gpointer), - gpointer user_data) + GdkRegion *region, + gboolean (*child_func) (GdkWindow *, gpointer), + gpointer user_data) { GdkWindow *window; GdkWindowObject *private; @@ -2791,7 +2833,7 @@ gdk_window_impl_directfb_invalidate_maybe_recurse (GdkPaintable *paintable, window = wimpl->gdkWindow; private = (GdkWindowObject *)window; - GdkRegion *visible_region; + GdkRegion visible_region; GList *tmp_list; g_return_if_fail (window != NULL); @@ -2803,69 +2845,65 @@ gdk_window_impl_directfb_invalidate_maybe_recurse (GdkPaintable *paintable, if (private->input_only || !GDK_WINDOW_IS_MAPPED (window)) return; - visible_region = gdk_drawable_get_visible_region (window); - gdk_region_intersect (visible_region, region); + temp_region_init_rectangle_vals( &visible_region, 0, 0, impl->width, impl->height ); + gdk_region_intersect (&visible_region, region); tmp_list = private->children; while (tmp_list) { - GdkWindowObject *child = tmp_list->data; + GdkWindowObject *child = tmp_list->data; + GdkDrawableImplDirectFB *cimpl = (GdkDrawableImplDirectFB *) child->impl; if (!child->input_only) - { - GdkRegion *child_region; - GdkRectangle child_rect; - - gdk_window_get_position ((GdkWindow *)child, - &child_rect.x, &child_rect.y); - gdk_drawable_get_size ((GdkDrawable *)child, - &child_rect.width, &child_rect.height); + { + GdkRegion child_region; + + temp_region_init_rectangle_vals( &child_region, child->x, child->y, cimpl->width, cimpl->height ); + + /* remove child area from the invalid area of the parent */ + if (GDK_WINDOW_IS_MAPPED (child) && !child->shaped) + gdk_region_subtract (&visible_region, &child_region); + + if (child_func && (*child_func) ((GdkWindow *)child, user_data)) + { + gdk_region_offset (region, - child->x, - child->y); + gdk_region_offset (&child_region, - child->x, - child->y); + gdk_region_intersect (&child_region, region); + + gdk_window_invalidate_maybe_recurse ((GdkWindow *)child, + &child_region, child_func, user_data); + + gdk_region_offset (region, child->x, child->y); + } - child_region = gdk_region_rectangle (&child_rect); - - /* remove child area from the invalid area of the parent */ - if (GDK_WINDOW_IS_MAPPED (child) && !child->shaped) - gdk_region_subtract (visible_region, child_region); - - if (child_func && (*child_func) ((GdkWindow *)child, user_data)) - { - gdk_region_offset (region, - child_rect.x, - child_rect.y); - gdk_region_offset (child_region, - child_rect.x, - child_rect.y); - gdk_region_intersect (child_region, region); - - gdk_window_invalidate_maybe_recurse ((GdkWindow *)child, - child_region, child_func, user_data); - - gdk_region_offset (region, child_rect.x, child_rect.y); - } - - gdk_region_destroy (child_region); - } + temp_region_deinit( &child_region ); + } tmp_list = tmp_list->next; } - if (!gdk_region_empty (visible_region)) + if (!gdk_region_empty (&visible_region)) { if (private->update_area) - { - gdk_region_union (private->update_area, visible_region); - } + { + gdk_region_union (private->update_area, &visible_region); + } else - { - update_windows = g_slist_prepend (update_windows, window); - private->update_area = gdk_region_copy (visible_region); - gdk_window_schedule_update (window); - } + { + update_windows = g_slist_prepend (update_windows, window); + private->update_area = gdk_region_copy (&visible_region); + gdk_window_schedule_update (window); + } } - gdk_region_destroy (visible_region); + + temp_region_deinit( &visible_region ); } static void gdk_window_impl_directfb_process_updates (GdkPaintable *paintable, - gboolean update_children) + gboolean update_children) { GdkWindow *window; GdkWindowObject *private; @@ -2888,58 +2926,49 @@ gdk_window_impl_directfb_process_updates (GdkPaintable *paintable, private->update_area = NULL; if (_gdk_event_func && gdk_window_is_viewable (window)) - { - GdkRectangle window_rect; - GdkRegion *expose_region; - GdkRegion *window_region; - gint width, height; - save_region = _gdk_windowing_window_queue_antiexpose (window, update_area); + { + GdkRegion *expose_region; + GdkRegion window_region; + save_region = _gdk_windowing_window_queue_antiexpose (window, update_area); - if (save_region) - expose_region = gdk_region_copy (update_area); - else - expose_region = update_area; - - gdk_drawable_get_size (GDK_DRAWABLE (private), &width, &height); + if (save_region) + expose_region = gdk_region_copy (update_area); + else + expose_region = update_area; + + temp_region_init_rectangle_vals( &window_region, 0, 0, impl->width, impl->height ); + gdk_region_intersect (expose_region, + &window_region); + temp_region_deinit (&window_region); + + if (!gdk_region_empty (expose_region) && + (private->event_mask & GDK_EXPOSURE_MASK)) + { + GdkEvent event; + + event.expose.type = GDK_EXPOSE; + event.expose.window = g_object_ref (window); + event.expose.send_event = FALSE; + event.expose.count = 0; + event.expose.region = expose_region; + gdk_region_get_clipbox (expose_region, &event.expose.area); + (*_gdk_event_func) (&event, _gdk_event_data); + + g_object_unref (window); + } - window_rect.x = 0; - window_rect.y = 0; - window_rect.width = width; - window_rect.height = height; - - window_region = gdk_region_rectangle (&window_rect); - gdk_region_intersect (expose_region, - window_region); - gdk_region_destroy (window_region); - - if (!gdk_region_empty (expose_region) && - (private->event_mask & GDK_EXPOSURE_MASK)) - { - GdkEvent event; - - event.expose.type = GDK_EXPOSE; - event.expose.window = g_object_ref (window); - event.expose.send_event = FALSE; - event.expose.count = 0; - event.expose.region = expose_region; - gdk_region_get_clipbox (expose_region, &event.expose.area); - (*_gdk_event_func) (&event, _gdk_event_data); - - g_object_unref (window); - } - - if (expose_region != update_area) - gdk_region_destroy (expose_region); - } + if (expose_region != update_area) + gdk_region_destroy (expose_region); + } if (!save_region) - gdk_region_destroy (update_area); + gdk_region_destroy (update_area); } } static void gdk_window_impl_directfb_begin_paint_region (GdkPaintable *paintable, - GdkRegion *region) + GdkRegion *region) { GdkDrawableImplDirectFB *impl; GdkWindowImplDirectFB *wimpl; @@ -2949,16 +2978,29 @@ gdk_window_impl_directfb_begin_paint_region (GdkPaintable *paintable, g_assert (region != NULL ); wimpl = GDK_WINDOW_IMPL_DIRECTFB (paintable); impl = (GdkDrawableImplDirectFB *)wimpl; - impl->buffered = TRUE; - impl->paint_depth++; if (!region) return; - if (impl->paint_region) - gdk_region_union (impl->paint_region, region); - else - impl->paint_region = gdk_region_copy (region); + if (impl->buffered) { + g_assert( impl->paint_depth > 0 ); + + gdk_region_union (&impl->paint_region, region); + } + else { + g_assert( impl->paint_depth == 0 ); + + gdk_directfb_clip_region( GDK_DRAWABLE(paintable), NULL, NULL, &impl->clip_region ); + + temp_region_init_copy( &impl->paint_region, region ); + + impl->buffered = TRUE; + } + + gdk_region_intersect (&impl->paint_region, &impl->clip_region); + + impl->paint_depth++; + for (i = 0; i < region->numRects; i++) { @@ -2982,24 +3024,59 @@ gdk_window_impl_directfb_end_paint (GdkPaintable *paintable) g_return_if_fail (impl->paint_depth > 0); + g_assert( impl->buffered ); + impl->paint_depth--; +#ifdef GDK_DIRECTFB_NO_EXPERIMENTS if (impl->paint_depth == 0) { impl->buffered = FALSE; - if (impl->paint_region) + if (impl->paint_region.numRects) { - DFBRegion reg = { impl->paint_region->extents.x1, - impl->paint_region->extents.y1, - impl->paint_region->extents.x2 , - impl->paint_region->extents.y2 }; + DFBRegion reg = { impl->paint_region.extents.x1, + impl->paint_region.extents.y1, + impl->paint_region.extents.x2 , + impl->paint_region.extents.y2 }; - impl->surface->Flip(impl->surface, ®,0); - gdk_region_destroy (impl->paint_region); - impl->paint_region = NULL; + impl->surface->Flip( impl->surface, ®, 0 ); + + temp_region_reset( &impl->paint_region ); } } +#else + if (impl->paint_depth == 0) { + impl->buffered = FALSE; + + temp_region_deinit( &impl->clip_region ); + + if (impl->paint_region.numRects) { + GdkWindow *window = GDK_WINDOW( impl->wrapper ); + + if (GDK_IS_WINDOW(window)) { + GdkWindowObject *top = GDK_WINDOW_OBJECT( gdk_window_get_toplevel( window ) ); + + if (top) { + DFBRegion reg; + GdkWindowImplDirectFB *wimpl = GDK_WINDOW_IMPL_DIRECTFB (top->impl); + + reg.x1 = impl->abs_x - top->x + impl->paint_region.extents.x1; + reg.y1 = impl->abs_y - top->y + impl->paint_region.extents.y1; + reg.x2 = impl->abs_x - top->x + impl->paint_region.extents.x2 - 1; + reg.y2 = impl->abs_y - top->y + impl->paint_region.extents.y2 - 1; + + //direct_log_printf( NULL, "Adding bounding box of paint: %d,%d - %dx%d (top %p, wimpl %p)\n", + // DFB_RECTANGLE_VALS_FROM_REGION( ® ), top, wimpl ); + + dfb_updates_add( &wimpl->flips, ® ); + } + } + + temp_region_reset( &impl->paint_region ); + } + } +#endif }