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 = ▭
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 (®ion->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, ®);
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, ®ion);
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, ®);
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, ®);
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, ®);
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, ®);
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, ®);
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