1 /* cairo - a vector graphics library with display and print output
3 * Copyright © 2003 University of Southern California
5 * This library is free software; you can redistribute it and/or
6 * modify it either under the terms of the GNU Lesser General Public
7 * License version 2.1 as published by the Free Software Foundation
8 * (the "LGPL") or, at your option, under the terms of the Mozilla
9 * Public License Version 1.1 (the "MPL"). If you do not alter this
10 * notice, a recipient may use your version of this file under either
11 * the MPL or the LGPL.
13 * You should have received a copy of the LGPL along with this library
14 * in the file COPYING-LGPL-2.1; if not, write to the Free Software
15 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
16 * You should have received a copy of the MPL along with this library
17 * in the file COPYING-MPL-1.1
19 * The contents of this file are subject to the Mozilla Public License
20 * Version 1.1 (the "License"); you may not use this file except in
21 * compliance with the License. You may obtain a copy of the License at
22 * http://www.mozilla.org/MPL/
24 * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY
25 * OF ANY KIND, either express or implied. See the LGPL or the MPL for
26 * the specific language governing rights and limitations.
28 * The Original Code is the cairo graphics library.
30 * The Initial Developer of the Original Code is University of Southern
34 * Michael Emmel <mike.emmel@gmail.com>
35 * Claudio Ciccani <klan@users.sf.net>
39 #include "cairo-directfb.h"
42 #include <direct/types.h>
43 #include <direct/debug.h>
44 #include <direct/memcpy.h>
45 #include <direct/util.h>
47 #include "cairo-clip-private.h"
50 * Rectangle works fine.
51 * Bugs 361377, 359553, 359243 in Gnome BTS are caused
52 * by GDK/DirectFB, not by Cairo/DirectFB.
54 #define DFB_RECTANGLES 1
57 * Composite works fine.
59 #define DFB_COMPOSITE 1
62 * CompositeTrapezoids works (without antialiasing).
64 #define DFB_COMPOSITE_TRAPEZOIDS 1
67 * ShowGlyphs works fine.
69 #define DFB_SHOW_GLYPHS 1
72 D_DEBUG_DOMAIN (CairoDFB_Acquire
, "CairoDFB/Acquire", "Cairo DirectFB Acquire");
73 D_DEBUG_DOMAIN (CairoDFB_Clip
, "CairoDFB/Clip", "Cairo DirectFB Clipping");
74 D_DEBUG_DOMAIN (CairoDFB_Font
, "CairoDFB/Font", "Cairo DirectFB Font Rendering");
75 D_DEBUG_DOMAIN (CairoDFB_Render
, "CairoDFB/Render", "Cairo DirectFB Rendering");
76 D_DEBUG_DOMAIN (CairoDFB_Surface
, "CairoDFB/Surface", "Cairo DirectFB Surface");
78 /*****************************************************************************/
80 typedef struct _cairo_directfb_surface
{
82 cairo_format_t format
;
83 cairo_content_t content
;
86 IDirectFBSurface
*dfbsurface
;
87 IDirectFBSurface
*tmpsurface
;
89 cairo_bool_t has_clip
;
97 unsigned blit_premultiplied
: 1;
98 } cairo_directfb_surface_t
;
101 typedef struct _cairo_directfb_font_cache
{
103 IDirectFBSurface
*dfbsurface
;
108 /* coordinates within the surface
109 * of the last loaded glyph */
112 } cairo_directfb_font_cache_t
;
114 static cairo_surface_backend_t _cairo_directfb_surface_backend
;
116 /*****************************************************************************/
118 static int _directfb_argb_font
= 0;
120 /*****************************************************************************/
122 #define RUN_CLIPPED(surface, clip, func) {\
123 if ((surface)->has_clip) {\
125 for (k = 0; k < (surface)->n_clips; k++) {\
127 DFBRegion reg = (surface)->clips[k];\
128 DFBRegion *cli = (clip);\
129 if (reg.x2 < cli->x1 || reg.y2 < cli->y1 ||\
130 reg.x1 > cli->x2 || reg.y1 > cli->y2)\
132 if (reg.x1 < cli->x1)\
134 if (reg.y1 < cli->y1)\
136 if (reg.x2 > cli->x2)\
138 if (reg.y2 > cli->y2)\
140 (surface)->dfbsurface->SetClip ((surface)->dfbsurface, ®);\
142 (surface)->dfbsurface->SetClip ((surface)->dfbsurface,\
143 &(surface)->clips[k]);\
148 (surface)->dfbsurface->SetClip ((surface)->dfbsurface, clip);\
153 #define TRANSFORM_POINT2X(m, x, y, ret_x, ret_y) {\
156 (ret_x) = (_x * (m).xx + (m).x0);\
157 (ret_y) = (_y * (m).yy + (m).y0);\
160 #define TRANSFORM_POINT3X(m, x, y, ret_x, ret_y) {\
163 (ret_x) = (_x * (m).xx + _y * (m).xy + (m).x0);\
164 (ret_y) = (_x * (m).yx + _y * (m).yy + (m).y0);\
167 /* XXX: A1 has a different bits ordering in cairo.
168 * Probably we should drop it.
171 static cairo_content_t
172 _directfb_format_to_content (DFBSurfacePixelFormat format
)
174 if (DFB_PIXELFORMAT_HAS_ALPHA (format
)) {
175 if (DFB_COLOR_BITS_PER_PIXEL (format
))
176 return CAIRO_CONTENT_COLOR_ALPHA
;
178 return CAIRO_CONTENT_ALPHA
;
181 return CAIRO_CONTENT_COLOR
;
184 static inline DFBSurfacePixelFormat
185 _cairo_to_directfb_format (cairo_format_t format
)
188 case CAIRO_FORMAT_RGB24
:
190 case CAIRO_FORMAT_ARGB32
:
192 case CAIRO_FORMAT_A8
:
194 case CAIRO_FORMAT_A1
:
203 static inline cairo_format_t
204 _directfb_to_cairo_format (DFBSurfacePixelFormat format
)
208 return CAIRO_FORMAT_RGB24
;
210 return CAIRO_FORMAT_ARGB32
;
212 return CAIRO_FORMAT_A8
;
214 return CAIRO_FORMAT_A1
;
223 _directfb_get_operator (cairo_operator_t
operator,
224 DFBSurfaceBlendFunction
*ret_srcblend
,
225 DFBSurfaceBlendFunction
*ret_dstblend
)
227 DFBSurfaceBlendFunction srcblend
= DSBF_ONE
;
228 DFBSurfaceBlendFunction dstblend
= DSBF_ZERO
;
231 case CAIRO_OPERATOR_CLEAR
:
232 srcblend
= DSBF_ZERO
;
233 dstblend
= DSBF_ZERO
;
235 case CAIRO_OPERATOR_SOURCE
:
237 dstblend
= DSBF_ZERO
;
239 case CAIRO_OPERATOR_OVER
:
241 dstblend
= DSBF_INVSRCALPHA
;
243 case CAIRO_OPERATOR_IN
:
244 srcblend
= DSBF_DESTALPHA
;
245 dstblend
= DSBF_ZERO
;
247 case CAIRO_OPERATOR_OUT
:
248 srcblend
= DSBF_INVDESTALPHA
;
249 dstblend
= DSBF_ZERO
;
251 case CAIRO_OPERATOR_ATOP
:
252 srcblend
= DSBF_DESTALPHA
;
253 dstblend
= DSBF_INVSRCALPHA
;
255 case CAIRO_OPERATOR_DEST
:
256 srcblend
= DSBF_ZERO
;
259 case CAIRO_OPERATOR_DEST_OVER
:
260 srcblend
= DSBF_INVDESTALPHA
;
263 case CAIRO_OPERATOR_DEST_IN
:
264 srcblend
= DSBF_ZERO
;
265 dstblend
= DSBF_SRCALPHA
;
267 case CAIRO_OPERATOR_DEST_OUT
:
268 srcblend
= DSBF_ZERO
;
269 dstblend
= DSBF_INVSRCALPHA
;
271 case CAIRO_OPERATOR_DEST_ATOP
:
272 srcblend
= DSBF_INVDESTALPHA
;
273 dstblend
= DSBF_SRCALPHA
;
275 case CAIRO_OPERATOR_XOR
:
276 srcblend
= DSBF_INVDESTALPHA
;
277 dstblend
= DSBF_INVSRCALPHA
;
279 case CAIRO_OPERATOR_ADD
:
283 case CAIRO_OPERATOR_SATURATE
:
284 /* XXX This does not work. */
286 srcblend
= DSBF_SRCALPHASAT
;
294 *ret_srcblend
= srcblend
;
295 *ret_dstblend
= dstblend
;
300 static cairo_status_t
301 _directfb_buffer_surface_create (IDirectFB
*dfb
,
302 DFBSurfacePixelFormat format
,
305 IDirectFBSurface
**out
)
307 IDirectFBSurface
*buffer
;
308 DFBSurfaceDescription dsc
;
311 dsc
.flags
= DSDESC_WIDTH
| DSDESC_HEIGHT
| DSDESC_PIXELFORMAT
;
312 dsc
.caps
= DSCAPS_PREMULTIPLIED
;
315 dsc
.pixelformat
= format
;
317 ret
= dfb
->CreateSurface (dfb
, &dsc
, &buffer
);
319 DirectFBError ("IDirectFB::CreateSurface()", ret
);
320 return _cairo_error (CAIRO_STATUS_NO_MEMORY
);
324 return CAIRO_STATUS_SUCCESS
;
327 static cairo_status_t
328 _directfb_acquire_surface (cairo_directfb_surface_t
*surface
,
329 cairo_rectangle_int_t
*intrest_rec
,
330 cairo_image_surface_t
**image_out
,
331 cairo_rectangle_int_t
*image_rect_out
,
333 DFBSurfaceLockFlags lock_flags
)
335 IDirectFBSurface
*buffer
= NULL
;
336 DFBRectangle source_rect
;
337 cairo_surface_t
*image
;
338 cairo_format_t cairo_format
;
339 cairo_status_t status
;
343 if (surface
->format
== (cairo_format_t
) -1 ||
344 (lock_flags
& DSLF_WRITE
&& surface
->has_clip
))
346 DFBSurfaceCapabilities caps
;
349 source_rect
.x
= intrest_rec
->x
;
350 source_rect
.y
= intrest_rec
->y
;
351 source_rect
.w
= intrest_rec
->width
;
352 source_rect
.h
= intrest_rec
->height
;
356 surface
->dfbsurface
->GetSize (surface
->dfbsurface
,
357 &source_rect
.w
, &source_rect
.h
);
360 if (surface
->tmpsurface
) {
362 surface
->tmpsurface
->GetSize (surface
->tmpsurface
, &w
, &h
);
363 if (w
< source_rect
.w
|| h
< source_rect
.h
) {
364 surface
->tmpsurface
->Release (surface
->tmpsurface
);
365 surface
->tmpsurface
= NULL
;
369 cairo_format
= _cairo_format_from_content (surface
->content
);
370 if (!surface
->tmpsurface
) {
371 D_DEBUG_AT (CairoDFB_Acquire
, "Allocating buffer for surface %p.\n", surface
);
374 _directfb_buffer_surface_create (surface
->dfb
,
375 _cairo_to_directfb_format (cairo_format
),
376 source_rect
.w
, source_rect
.h
,
377 &surface
->tmpsurface
);
381 buffer
= surface
->tmpsurface
;
383 /* surface->dfbsurface->GetCapabilities (surface->dfbsurface, &caps);
384 if (caps & DSCAPS_FLIPPING) {
385 DFBRegion region = { .x1 = source_rect.x, .y1 = source_rect.y,
386 .x2 = source_rect.x + source_rect.w - 1,
387 .y2 = source_rect.y + source_rect.h - 1 };
388 surface->dfbsurface->Flip (surface->dfbsurface, ®ion, DSFLIP_BLIT);
390 buffer
->Blit (buffer
, surface
->dfbsurface
, &source_rect
, 0, 0);
392 /*might be a subsurface get the offset*/
393 surface
->dfbsurface
->GetVisibleRectangle (surface
->dfbsurface
, &source_rect
);
394 cairo_format
= surface
->format
;
395 buffer
= surface
->dfbsurface
;
398 if (buffer
->Lock (buffer
, lock_flags
, &data
, &pitch
)) {
399 D_DEBUG_AT (CairoDFB_Acquire
, "Couldn't lock surface!\n");
400 status
= _cairo_error (CAIRO_STATUS_NO_MEMORY
);
404 image
= cairo_image_surface_create_for_data (data
, cairo_format
,
405 source_rect
.w
, source_rect
.h
,
407 status
= image
->status
;
411 if (image_rect_out
) {
412 image_rect_out
->x
= source_rect
.x
;
413 image_rect_out
->y
= source_rect
.y
;
414 image_rect_out
->width
= source_rect
.w
;
415 image_rect_out
->height
= source_rect
.h
;
418 /* might be a subsurface */
419 if (buffer
== surface
->dfbsurface
) {
420 cairo_surface_set_device_offset (image
,
421 source_rect
.x
, source_rect
.y
);
425 *image_extra
= buffer
;
426 *image_out
= (cairo_image_surface_t
*) image
;
427 return CAIRO_STATUS_SUCCESS
;
431 buffer
->Unlock (buffer
);
432 if (buffer
!= surface
->dfbsurface
)
433 buffer
->Release (buffer
);
438 static cairo_surface_t
*
439 _cairo_directfb_surface_create_similar (void *abstract_src
,
440 cairo_content_t content
,
444 cairo_directfb_surface_t
*source
= abstract_src
;
445 cairo_directfb_surface_t
*surface
;
446 cairo_format_t format
;
447 cairo_status_t status
;
449 D_DEBUG_AT (CairoDFB_Surface
,
450 "%s( src=%p, content=0x%x, width=%d, height=%d).\n",
451 __FUNCTION__
, source
, content
, width
, height
);
453 width
= (width
<= 0) ? 1 : width
;
454 height
= (height
<= 0) ? 1 : height
;
456 format
= _cairo_format_from_content (content
);
457 surface
= calloc (1, sizeof (cairo_directfb_surface_t
));
459 return _cairo_surface_create_in_error (_cairo_error (CAIRO_STATUS_NO_MEMORY
));
461 surface
->dfb
= source
->dfb
;
463 if (width
< 8 || height
< 8) {
464 IDirectFBSurface
*tmp
;
465 DFBRectangle rect
= { .x
=0, .y
=0, .w
=width
, .h
=height
};
467 /* Some cards (e.g. Matrox) don't support surfaces smaller than 8x8 */
468 status
= _directfb_buffer_surface_create (surface
->dfb
,
469 _cairo_to_directfb_format (format
),
470 MAX (width
, 8), MAX (height
, 8),
474 return _cairo_surface_create_in_error (status
);
477 tmp
->GetSubSurface (tmp
, &rect
, &surface
->dfbsurface
);
481 _directfb_buffer_surface_create (surface
->dfb
,
482 _cairo_to_directfb_format (format
),
484 &surface
->dfbsurface
);
487 return _cairo_surface_create_in_error (status
);
491 _cairo_surface_init (&surface
->base
,
492 &_cairo_directfb_surface_backend
,
494 surface
->format
= format
;
495 surface
->content
= content
;
496 surface
->width
= width
;
497 surface
->height
= height
;
498 surface
->local
= TRUE
;
499 surface
->blit_premultiplied
= TRUE
;
501 return &surface
->base
;
504 static cairo_status_t
505 _cairo_directfb_surface_finish (void *data
)
507 cairo_directfb_surface_t
*surface
= (cairo_directfb_surface_t
*)data
;
509 D_DEBUG_AT (CairoDFB_Surface
, "%s( surface=%p ).\n", __FUNCTION__
, surface
);
511 if (surface
->clips
) {
512 free (surface
->clips
);
513 surface
->clips
= NULL
;
514 surface
->n_clips
= 0;
517 if (surface
->tmpsurface
) {
518 surface
->tmpsurface
->Release (surface
->tmpsurface
);
519 surface
->tmpsurface
= NULL
;
522 if (surface
->dfbsurface
) {
523 surface
->dfbsurface
->Release (surface
->dfbsurface
);
524 surface
->dfbsurface
= NULL
;
530 return CAIRO_STATUS_SUCCESS
;
533 static cairo_status_t
534 _cairo_directfb_surface_acquire_source_image (void *abstract_surface
,
535 cairo_image_surface_t
**image_out
,
538 cairo_directfb_surface_t
*surface
= abstract_surface
;
540 D_DEBUG_AT (CairoDFB_Acquire
,
541 "%s( surface=%p ).\n", __FUNCTION__
, surface
);
543 return _directfb_acquire_surface (surface
, NULL
, image_out
,
544 NULL
, image_extra
, DSLF_READ
);
548 _cairo_directfb_surface_release_source_image (void *abstract_surface
,
549 cairo_image_surface_t
*image
,
552 IDirectFBSurface
*buffer
= image_extra
;
554 D_DEBUG_AT (CairoDFB_Acquire
,
555 "%s( surface=%p ).\n", __FUNCTION__
, surface
);
557 buffer
->Unlock (buffer
);
559 cairo_surface_destroy (&image
->base
);
562 static cairo_status_t
563 _cairo_directfb_surface_acquire_dest_image (void *abstract_surface
,
564 cairo_rectangle_int_t
*interest_rect
,
565 cairo_image_surface_t
**image_out
,
566 cairo_rectangle_int_t
*image_rect_out
,
569 cairo_directfb_surface_t
*surface
= abstract_surface
;
571 D_DEBUG_AT (CairoDFB_Acquire
,
572 "%s( surface=%p (%dx%d), interest_rect={ %u %u %u %u } ).\n",
573 __FUNCTION__
, surface
, surface
->width
, surface
->height
,
574 interest_rect
? interest_rect
->x
: 0,
575 interest_rect
? interest_rect
->y
: 0,
576 interest_rect
? interest_rect
->width
: (unsigned) surface
->width
,
577 interest_rect
? interest_rect
->height
: (unsigned) surface
->height
);
579 return _directfb_acquire_surface (surface
, interest_rect
, image_out
,
580 image_rect_out
, image_extra
,
581 DSLF_READ
| DSLF_WRITE
);
585 _cairo_directfb_surface_release_dest_image (void *abstract_surface
,
586 cairo_rectangle_int_t
*interest_rect
,
587 cairo_image_surface_t
*image
,
588 cairo_rectangle_int_t
*image_rect
,
591 cairo_directfb_surface_t
*surface
= abstract_surface
;
592 IDirectFBSurface
*buffer
= image_extra
;
594 D_DEBUG_AT (CairoDFB_Acquire
,
595 "%s( surface=%p ).\n", __FUNCTION__
, surface
);
597 buffer
->Unlock (buffer
);
599 if (surface
->dfbsurface
!= buffer
) {
601 .x1
= interest_rect
->x
,
602 .y1
= interest_rect
->y
,
603 .x2
= interest_rect
->x
+ interest_rect
->width
- 1,
604 .y2
= interest_rect
->y
+ interest_rect
->height
- 1
606 surface
->dfbsurface
->SetBlittingFlags (surface
->dfbsurface
, DSBLIT_NOFX
);
607 RUN_CLIPPED (surface
, ®ion
,
608 surface
->dfbsurface
->Blit (surface
->dfbsurface
,
610 image_rect
->x
, image_rect
->y
));
613 cairo_surface_destroy (&image
->base
);
616 static cairo_status_t
617 _cairo_directfb_surface_clone_similar (void *abstract_surface
,
618 cairo_surface_t
*src
,
625 cairo_surface_t
**clone_out
)
627 cairo_directfb_surface_t
*surface
= abstract_surface
;
628 cairo_directfb_surface_t
*clone
;
630 D_DEBUG_AT (CairoDFB_Surface
,
631 "%s( surface=%p, src=%p ).\n", __FUNCTION__
, surface
, src
);
633 if (src
->backend
== surface
->base
.backend
) {
636 *clone_out
= cairo_surface_reference (src
);
638 return CAIRO_STATUS_SUCCESS
;
639 } else if (_cairo_surface_is_image (src
)) {
640 cairo_image_surface_t
*image_src
= (cairo_image_surface_t
*) src
;
641 unsigned char *dst
, *src
= image_src
->data
;
646 clone
= (cairo_directfb_surface_t
*)
647 _cairo_directfb_surface_create_similar (surface
,
648 _cairo_content_from_format (image_src
->format
),
651 return CAIRO_INT_STATUS_UNSUPPORTED
;
652 if (clone
->base
.status
)
653 return clone
->base
.status
;
655 ret
= clone
->dfbsurface
->Lock (clone
->dfbsurface
,
656 DSLF_WRITE
, (void *)&dst
, &pitch
);
658 DirectFBError ("IDirectFBSurface::Lock()", ret
);
659 cairo_surface_destroy (&clone
->base
);
660 return _cairo_error (CAIRO_STATUS_NO_MEMORY
);
663 src
+= image_src
->stride
* src_y
;
664 if (image_src
->format
== CAIRO_FORMAT_A1
) {
667 for (i
= 0; i
< height
; i
++) {
668 for (j
= src_x
; j
< src_x
+ width
; j
++)
669 dst
[j
] = (src
[j
>>3] & (1 << (j
&7))) ? 0xff : 0x00;
671 src
+= image_src
->stride
;
676 if (image_src
->format
== CAIRO_FORMAT_A8
) {
684 for (i
= 0; i
< height
; i
++) {
685 direct_memcpy (dst
, src
, len
);
687 src
+= image_src
->stride
;
691 clone
->dfbsurface
->Unlock (clone
->dfbsurface
);
693 *clone_offset_x
= src_x
;
694 *clone_offset_y
= src_y
;
695 *clone_out
= &clone
->base
;
696 return CAIRO_STATUS_SUCCESS
;
699 return CAIRO_INT_STATUS_UNSUPPORTED
;
702 #if DFB_COMPOSITE || DFB_COMPOSITE_TRAPEZOIDS
703 static cairo_int_status_t
704 _directfb_prepare_composite (cairo_directfb_surface_t
*dst
,
705 cairo_pattern_t
*src_pattern
,
706 cairo_pattern_t
*mask_pattern
,
708 int *src_x
, int *src_y
,
709 int *mask_x
, int *mask_y
,
712 cairo_directfb_surface_t
**ret_src
,
713 cairo_surface_attributes_t
*ret_src_attr
)
715 cairo_directfb_surface_t
*src
;
716 cairo_surface_attributes_t src_attr
;
717 cairo_status_t status
;
718 DFBSurfaceBlittingFlags flags
;
719 DFBSurfaceBlendFunction sblend
;
720 DFBSurfaceBlendFunction dblend
;
721 const cairo_color_t
*color
;
723 /* XXX Unbounded operators are not handled correctly */
724 if (! _cairo_operator_bounded_by_source (op
))
725 return CAIRO_INT_STATUS_UNSUPPORTED
;
727 if (! _directfb_get_operator (op
, &sblend
, &dblend
))
728 return CAIRO_INT_STATUS_UNSUPPORTED
;
731 cairo_solid_pattern_t
*pattern
;
733 return CAIRO_INT_STATUS_UNSUPPORTED
;
734 if (mask_pattern
->type
!= CAIRO_PATTERN_TYPE_SOLID
) {
735 cairo_pattern_t
*tmp
;
738 if (src_pattern
->type
!= CAIRO_PATTERN_TYPE_SOLID
||
739 sblend
== DSBF_INVDESTALPHA
) /* Doesn't work correctly */
740 return CAIRO_INT_STATUS_UNSUPPORTED
;
742 D_DEBUG_AT (CairoDFB_Render
, "Replacing src pattern by mask pattern.\n");
745 tmp_x
= *src_x
; tmp_y
= *src_y
;
747 src_pattern
= mask_pattern
;
748 *src_x
= *mask_x
; *src_y
= *mask_y
;
751 *mask_x
= tmp_x
; *mask_y
= tmp_y
;
753 if (sblend
== DSBF_ONE
) {
754 sblend
= DSBF_SRCALPHA
;
755 /*dblend = DSBF_INVSRCALPHA;*/
759 color
= &((cairo_solid_pattern_t
*) mask_pattern
)->color
;
761 color
= _cairo_stock_color (CAIRO_STOCK_WHITE
);
764 /* XXX DirectFB currently does not support filtering, so force NEAREST
765 * in order to hit optimisations inside core.
767 src_pattern
->filter
= CAIRO_FILTER_NEAREST
;
769 status
= _cairo_pattern_acquire_surface (src_pattern
, &dst
->base
,
770 *src_x
, *src_y
, width
, height
,
771 (cairo_surface_t
**) &src
,
776 if (src
->base
.backend
!= &_cairo_directfb_surface_backend
||
777 src
->dfb
!= dst
->dfb
)
779 _cairo_pattern_release_surface (src_pattern
, &src
->base
, &src_attr
);
780 return CAIRO_INT_STATUS_UNSUPPORTED
;
783 if (src
->content
== CAIRO_CONTENT_COLOR
) {
784 if (sblend
== DSBF_SRCALPHA
)
786 else if (sblend
== DSBF_INVSRCALPHA
)
789 if (dblend
== DSBF_SRCALPHA
)
791 else if (dblend
== DSBF_INVSRCALPHA
)
795 if (dst
->content
== CAIRO_CONTENT_COLOR
) {
796 if (sblend
== DSBF_DESTALPHA
)
798 else if (sblend
== DSBF_INVDESTALPHA
)
801 if (dblend
== DSBF_DESTALPHA
)
803 else if (dblend
== DSBF_INVDESTALPHA
)
807 flags
= (sblend
== DSBF_ONE
&& dblend
== DSBF_ZERO
)
808 ? DSBLIT_NOFX
: DSBLIT_BLEND_ALPHACHANNEL
;
809 if (! CAIRO_COLOR_IS_OPAQUE (color
))
810 flags
|= DSBLIT_BLEND_COLORALPHA
;
811 if (! _cairo_color_equal (color
, _cairo_stock_color (CAIRO_STOCK_WHITE
)))
812 flags
|= DSBLIT_COLORIZE
;
814 dst
->dfbsurface
->SetBlittingFlags (dst
->dfbsurface
, flags
);
816 if (flags
& (DSBLIT_BLEND_ALPHACHANNEL
| DSBLIT_BLEND_COLORALPHA
)) {
817 dst
->dfbsurface
->SetSrcBlendFunction (dst
->dfbsurface
, sblend
);
818 dst
->dfbsurface
->SetDstBlendFunction (dst
->dfbsurface
, dblend
);
821 if (flags
& (DSBLIT_BLEND_COLORALPHA
| DSBLIT_COLORIZE
)) {
822 if (dst
->blit_premultiplied
) {
823 dst
->dfbsurface
->SetColor (dst
->dfbsurface
,
824 color
->red_short
>> 8,
825 color
->green_short
>> 8,
826 color
->blue_short
>> 8,
827 color
->alpha_short
>> 8);
829 dst
->dfbsurface
->SetColor (dst
->dfbsurface
,
833 color
->alpha
* 0xff);
838 *ret_src_attr
= src_attr
;
840 return CAIRO_STATUS_SUCCESS
;
844 _directfb_finish_composite (cairo_directfb_surface_t
*dst
,
845 cairo_pattern_t
*src_pattern
,
846 cairo_surface_t
*src
,
847 cairo_surface_attributes_t
*src_attr
)
849 _cairo_pattern_release_surface (src_pattern
, src
, src_attr
);
851 #endif /* DFB_COMPOSITE || DFB_COMPOSITE_TRAPEZOIDS */
854 static DFBAccelerationMask
855 _directfb_categorize_operation (cairo_surface_attributes_t
*src_attr
)
857 cairo_matrix_t
*m
= &src_attr
->matrix
;
859 if (m
->xy
!= 0 || m
->yx
!= 0 || m
->xx
< 0 || m
->yy
< 0) {
860 if (src_attr
->extend
!= CAIRO_EXTEND_NONE
)
863 return DFXL_TEXTRIANGLES
;
866 if (m
->xx
!= 1 || m
->yy
!= 1) {
867 if (src_attr
->extend
!= CAIRO_EXTEND_NONE
)
870 return DFXL_STRETCHBLIT
;
873 switch (src_attr
->extend
) {
874 case CAIRO_EXTEND_NONE
:
875 case CAIRO_EXTEND_REPEAT
:
876 if (_cairo_matrix_is_integer_translation (&src_attr
->matrix
,
883 return DFXL_STRETCHBLIT
;
887 case CAIRO_EXTEND_REFLECT
:
888 case CAIRO_EXTEND_PAD
:
893 static cairo_int_status_t
894 _cairo_directfb_surface_composite (cairo_operator_t op
,
895 cairo_pattern_t
*src_pattern
,
896 cairo_pattern_t
*mask_pattern
,
898 int src_x
, int src_y
,
899 int mask_x
, int mask_y
,
900 int dst_x
, int dst_y
,
904 cairo_directfb_surface_t
*dst
= abstract_dst
;
905 cairo_directfb_surface_t
*src
;
906 cairo_surface_attributes_t src_attr
;
907 cairo_bool_t is_integer_translation
;
908 DFBAccelerationMask accel
, mask
;
909 cairo_int_status_t status
;
912 D_DEBUG_AT (CairoDFB_Render
,
913 "%s( op=%d, src_pattern=%p, mask_pattern=%p, dst=%p,"
914 " src_x=%d, src_y=%d, mask_x=%d, mask_y=%d, dst_x=%d,"
915 " dst_y=%d, width=%u, height=%u ).\n",
916 __FUNCTION__
, op
, src_pattern
, mask_pattern
, dst
,
917 src_x
, src_y
, mask_x
, mask_y
, dst_x
, dst_y
, width
, height
);
919 status
= _directfb_prepare_composite (dst
, src_pattern
, mask_pattern
, op
,
920 &src_x
, &src_y
, &mask_x
, &mask_y
,
921 width
, height
, &src
, &src_attr
);
925 accel
= _directfb_categorize_operation (&src_attr
);
926 if (accel
== DFXL_NONE
) {
927 _directfb_finish_composite (dst
, src_pattern
, &src
->base
, &src_attr
);
928 return CAIRO_INT_STATUS_UNSUPPORTED
;
931 dst
->dfbsurface
->GetAccelerationMask (dst
->dfbsurface
,
934 if ((mask
& accel
) == 0) {
935 D_DEBUG_AT (CairoDFB_Render
, "No acceleration (%08x)!\n", accel
);
936 if (accel
!= DFXL_BLIT
) {
937 _directfb_finish_composite (dst
, src_pattern
, &src
->base
, &src_attr
);
938 return CAIRO_INT_STATUS_UNSUPPORTED
;
942 src_x
+= src_attr
.x_offset
;
943 src_y
+= src_attr
.y_offset
;
950 is_integer_translation
=
951 _cairo_matrix_is_integer_translation (&src_attr
.matrix
,
953 assert (is_integer_translation
);
960 if (src_attr
.extend
== CAIRO_EXTEND_NONE
) {
961 D_DEBUG_AT (CairoDFB_Render
, "Running Blit().\n");
963 RUN_CLIPPED (dst
, NULL
,
964 dst
->dfbsurface
->Blit (dst
->dfbsurface
,
968 } else if (src_attr
.extend
== CAIRO_EXTEND_REPEAT
) {
973 clip
.x2
= dst_x
+ width
- 1;
974 clip
.y2
= dst_y
+ height
- 1;
976 D_DEBUG_AT (CairoDFB_Render
, "Running TileBlit().\n");
978 RUN_CLIPPED (dst
, &clip
,
979 dst
->dfbsurface
->TileBlit (dst
->dfbsurface
,
987 case DFXL_STRETCHBLIT
:
990 double x1
, y1
, x2
, y2
;
992 TRANSFORM_POINT2X (src_attr
.matrix
,
993 src_x
, src_y
, x1
, y1
);
994 TRANSFORM_POINT2X (src_attr
.matrix
,
995 src_x
+width
, src_y
+height
, x2
, y2
);
999 sr
.w
= ceil (x2
) - sr
.x
;
1000 sr
.h
= ceil (y2
) - sr
.y
;
1007 D_DEBUG_AT (CairoDFB_Render
, "Running StretchBlit().\n");
1009 RUN_CLIPPED (dst
, NULL
,
1010 dst
->dfbsurface
->StretchBlit (dst
->dfbsurface
,
1011 src
->dfbsurface
, &sr
, &dr
));
1015 case DFXL_TEXTRIANGLES
:
1019 float x1
, y1
, x2
, y2
;
1022 status
= cairo_matrix_invert (&src_attr
.matrix
);
1023 /* guaranteed by cairo_pattern_set_matrix (); */
1024 assert (status
== CAIRO_STATUS_SUCCESS
);
1031 src
->dfbsurface
->GetSize (src
->dfbsurface
, &w
, &h
);
1033 TRANSFORM_POINT3X (src_attr
.matrix
,
1034 x1
, y1
, v
[0].x
, v
[0].y
);
1040 TRANSFORM_POINT3X (src_attr
.matrix
,
1041 x2
, y1
, v
[1].x
, v
[1].y
);
1047 TRANSFORM_POINT3X (src_attr
.matrix
,
1048 x2
, y2
, v
[2].x
, v
[2].y
);
1054 TRANSFORM_POINT3X (src_attr
.matrix
,
1055 x1
, y2
, v
[3].x
, v
[3].y
);
1063 clip
.x2
= dst_x
+ width
- 1;
1064 clip
.y2
= dst_y
+ height
- 1;
1066 D_DEBUG_AT (CairoDFB_Render
, "Running TextureTriangles().\n");
1068 RUN_CLIPPED (dst
, &clip
,
1069 dst
->dfbsurface
->TextureTriangles (dst
->dfbsurface
,
1070 src
->dfbsurface
, v
, NULL
, 4, DTTF_FAN
));
1075 D_BUG ("Unexpected operation");
1079 _directfb_finish_composite (dst
, src_pattern
, &src
->base
, &src_attr
);
1083 #endif /* DFB_COMPOSITE */
1086 static cairo_int_status_t
1087 _cairo_directfb_surface_fill_rectangles (void *abstract_surface
,
1088 cairo_operator_t op
,
1089 const cairo_color_t
*color
,
1090 cairo_rectangle_int_t
*rects
,
1093 cairo_directfb_surface_t
*dst
= abstract_surface
;
1094 DFBSurfaceDrawingFlags flags
;
1095 DFBSurfaceBlendFunction sblend
;
1096 DFBSurfaceBlendFunction dblend
;
1097 DFBRectangle r
[n_rects
];
1100 D_DEBUG_AT (CairoDFB_Render
,
1101 "%s( dst=%p, op=%d, color=%p, rects=%p, n_rects=%d ).\n",
1102 __FUNCTION__
, dst
, op
, color
, rects
, n_rects
);
1104 if (! _cairo_operator_bounded_by_source (op
))
1105 return CAIRO_INT_STATUS_UNSUPPORTED
;
1107 if (! _directfb_get_operator (op
, &sblend
, &dblend
))
1108 return CAIRO_INT_STATUS_UNSUPPORTED
;
1110 if (CAIRO_COLOR_IS_OPAQUE (color
)) {
1111 if (sblend
== DSBF_SRCALPHA
)
1113 else if (sblend
== DSBF_INVSRCALPHA
)
1116 if (dblend
== DSBF_SRCALPHA
)
1118 else if (dblend
== DSBF_INVSRCALPHA
)
1121 if (dst
->content
== CAIRO_CONTENT_COLOR
) {
1122 if (sblend
== DSBF_DESTALPHA
)
1124 else if (sblend
== DSBF_INVDESTALPHA
)
1127 if (dblend
== DSBF_DESTALPHA
)
1129 else if (dblend
== DSBF_INVDESTALPHA
)
1133 flags
= (sblend
== DSBF_ONE
&& dblend
== DSBF_ZERO
) ? DSDRAW_NOFX
: DSDRAW_BLEND
;
1134 dst
->dfbsurface
->SetDrawingFlags (dst
->dfbsurface
, flags
);
1135 if (flags
& DSDRAW_BLEND
) {
1136 dst
->dfbsurface
->SetSrcBlendFunction (dst
->dfbsurface
, sblend
);
1137 dst
->dfbsurface
->SetDstBlendFunction (dst
->dfbsurface
, dblend
);
1140 dst
->dfbsurface
->SetColor (dst
->dfbsurface
,
1141 color
->red_short
>> 8,
1142 color
->green_short
>> 8,
1143 color
->blue_short
>> 8,
1144 color
->alpha_short
>> 8);
1146 for (i
= 0; i
< n_rects
; i
++) {
1147 r
[i
].x
= rects
[i
].x
;
1148 r
[i
].y
= rects
[i
].y
;
1149 r
[i
].w
= rects
[i
].width
;
1150 r
[i
].h
= rects
[i
].height
;
1153 RUN_CLIPPED (dst
, NULL
,
1154 dst
->dfbsurface
->FillRectangles (dst
->dfbsurface
, r
, n_rects
));
1156 return CAIRO_STATUS_SUCCESS
;
1160 #if DFB_COMPOSITE_TRAPEZOIDS
1161 static cairo_int_status_t
1162 _cairo_directfb_surface_composite_trapezoids (cairo_operator_t op
,
1163 cairo_pattern_t
*pattern
,
1165 cairo_antialias_t antialias
,
1166 int src_x
, int src_y
,
1167 int dst_x
, int dst_y
,
1169 unsigned int height
,
1170 cairo_trapezoid_t
*traps
,
1173 cairo_directfb_surface_t
*dst
= abstract_dst
;
1174 cairo_directfb_surface_t
*src
;
1175 cairo_surface_attributes_t src_attr
;
1176 cairo_status_t status
;
1177 DFBAccelerationMask accel
;
1179 D_DEBUG_AT (CairoDFB_Render
,
1180 "%s( op=%d, pattern=%p, dst=%p, antialias=%d,"
1181 " src_x=%d, src_y=%d, dst_x=%d, dst_y=%d,"
1182 " width=%u, height=%u, traps=%p, num_traps=%d ).\n",
1183 __FUNCTION__
, op
, pattern
, dst
, antialias
,
1184 src_x
, src_y
, dst_x
, dst_y
, width
, height
, traps
, num_traps
);
1186 if (antialias
!= CAIRO_ANTIALIAS_NONE
)
1187 return CAIRO_INT_STATUS_UNSUPPORTED
;
1189 /* Textures are not supported yet. */
1190 if (pattern
->type
!= CAIRO_PATTERN_TYPE_SOLID
)
1191 return CAIRO_INT_STATUS_UNSUPPORTED
;
1193 status
= _directfb_prepare_composite (dst
, pattern
, NULL
, op
,
1194 &src_x
, &src_y
, NULL
, NULL
,
1195 width
, height
, &src
, &src_attr
);
1199 dst
->dfbsurface
->GetAccelerationMask (dst
->dfbsurface
,
1203 status
= CAIRO_INT_STATUS_UNSUPPORTED
;
1205 if (accel
& DFXL_TEXTRIANGLES
) {
1206 DFBVertex vertex
[6*num_traps
];
1207 DFBVertex
*v
= &vertex
[0];
1210 #define ADD_TRI_V(V, X, Y) do { \
1211 (V)->x = (X); (V)->y = (Y); (V)->w = 1; (V)->z = (V)->s = (V)->t = 0; \
1213 #define ADD_TRI(id, x1, y1, x2, y2, x3, y3) do {\
1214 const int p = (id)*3;\
1215 ADD_TRI_V (v+p+0, x1, y1); \
1216 ADD_TRI_V (v+p+1, x2, y2); \
1217 ADD_TRI_V (v+p+2, x3, y3); \
1219 while (num_traps
--) {
1220 double lx1
, ly1
, lx2
, ly2
;
1221 double rx1
, ry1
, rx2
, ry2
;
1223 lx1
= _cairo_fixed_to_double (traps
->left
.p1
.x
);
1224 ly1
= _cairo_fixed_to_double (traps
->left
.p1
.y
);
1225 lx2
= _cairo_fixed_to_double (traps
->left
.p2
.x
);
1226 ly2
= _cairo_fixed_to_double (traps
->left
.p2
.y
);
1227 rx1
= _cairo_fixed_to_double (traps
->right
.p1
.x
);
1228 ry1
= _cairo_fixed_to_double (traps
->right
.p1
.y
);
1229 rx2
= _cairo_fixed_to_double (traps
->right
.p2
.x
);
1230 ry2
= _cairo_fixed_to_double (traps
->right
.p2
.y
);
1232 if (traps
->left
.p1
.y
< traps
->top
) {
1233 double y
= _cairo_fixed_to_double (traps
->top
);
1235 lx1
= (y
- ly1
) * (lx2
- lx1
) / (ly2
- ly1
) + lx1
;
1238 if (traps
->left
.p2
.y
> traps
->bottom
) {
1239 double y
= _cairo_fixed_to_double (traps
->bottom
);
1241 lx2
= (y
- ly1
) * (lx2
- lx1
) / (ly2
- ly1
) + lx1
;
1245 if (traps
->right
.p1
.y
< traps
->top
) {
1246 double y
= _cairo_fixed_to_double (traps
->top
);
1248 rx1
= (y
- ry1
) * (rx2
- rx1
) / (ry2
- ry1
) + rx1
;
1251 if (traps
->right
.p2
.y
> traps
->bottom
) {
1252 double y
= _cairo_fixed_to_double (traps
->bottom
);
1254 rx2
= (y
- ry1
) * (rx2
- rx1
) / (ry2
- ry1
) + rx1
;
1258 if (lx1
== rx1
&& ly1
== ry1
) {
1259 ADD_TRI (0, lx2
, ly2
, lx1
, ly1
, rx2
, ry2
);
1262 } else if (lx2
== rx2
&& ly2
== ry2
) {
1263 ADD_TRI (0, lx1
, ly1
, lx2
, ly2
, rx1
, ry1
);
1267 ADD_TRI (0, lx1
, ly1
, rx1
, ry1
, lx2
, ly2
);
1268 ADD_TRI (1, lx2
, ly2
, rx1
, ry1
, rx2
, ry2
);
1278 D_DEBUG_AT (CairoDFB_Render
, "Running TextureTriangles().\n");
1280 RUN_CLIPPED (dst
, NULL
,
1281 dst
->dfbsurface
->TextureTriangles (dst
->dfbsurface
,
1286 status
= CAIRO_STATUS_SUCCESS
;
1289 _directfb_finish_composite (dst
, pattern
, &src
->base
, &src_attr
);
1293 #endif /* DFB_COMPOSITE_TRAPEZOIDS */
1295 static cairo_int_status_t
1296 _cairo_directfb_surface_set_clip_region (void *abstract_surface
,
1297 cairo_region_t
*region
)
1299 cairo_directfb_surface_t
*surface
= abstract_surface
;
1301 D_DEBUG_AT (CairoDFB_Clip
,
1302 "%s( surface=%p, region=%p ).\n",
1303 __FUNCTION__
, surface
, region
);
1306 cairo_box_int_t
*boxes
;
1308 cairo_status_t status
;
1311 surface
->has_clip
= TRUE
;
1313 status
= _cairo_region_get_boxes (region
, &n_boxes
, &boxes
);
1315 return CAIRO_STATUS_SUCCESS
;
1319 if (surface
->n_clips
!= n_boxes
) {
1321 free (surface
->clips
);
1323 surface
->clips
= _cairo_malloc_ab (n_boxes
, sizeof (DFBRegion
));
1324 if (!surface
->clips
) {
1325 surface
->n_clips
= 0;
1326 _cairo_region_boxes_fini (region
, boxes
);
1327 return _cairo_error (CAIRO_STATUS_NO_MEMORY
);
1330 surface
->n_clips
= n_boxes
;
1333 for (i
= 0; i
< n_boxes
; i
++) {
1334 surface
->clips
[i
].x1
= boxes
[i
].p1
.x
;
1335 surface
->clips
[i
].y1
= boxes
[i
].p1
.y
;
1336 surface
->clips
[i
].x2
= boxes
[i
].p2
.x
- 1;
1337 surface
->clips
[i
].y2
= boxes
[i
].p2
.y
- 1;
1340 _cairo_region_boxes_fini (region
, boxes
);
1342 surface
->has_clip
= FALSE
;
1343 if (surface
->clips
) {
1344 free (surface
->clips
);
1345 surface
->clips
= NULL
;
1346 surface
->n_clips
= 0;
1350 return CAIRO_STATUS_SUCCESS
;
1353 static cairo_int_status_t
1354 _cairo_directfb_abstract_surface_get_extents (void *abstract_surface
,
1355 cairo_rectangle_int_t
*rectangle
)
1357 cairo_directfb_surface_t
*surface
= abstract_surface
;
1359 D_DEBUG_AT (CairoDFB_Surface
,
1360 "%s( surface=%p, rectangle=%p ).\n",
1361 __FUNCTION__
, surface
, rectangle
);
1363 if (!surface
->local
) {
1364 surface
->dfbsurface
->GetSize (surface
->dfbsurface
,
1365 &surface
->width
, &surface
->height
);
1370 rectangle
->width
= surface
->width
;
1371 rectangle
->height
= surface
->height
;
1373 return CAIRO_STATUS_SUCCESS
;
1377 static cairo_status_t
1378 _directfb_allocate_font_cache (IDirectFB
*dfb
,
1379 int width
, int height
,
1380 cairo_directfb_font_cache_t
**out
)
1382 cairo_directfb_font_cache_t
*cache
;
1383 cairo_status_t status
;
1385 cache
= calloc (1, sizeof (cairo_directfb_font_cache_t
));
1387 return _cairo_error (CAIRO_STATUS_NO_MEMORY
);
1390 status
= _directfb_buffer_surface_create (dfb
,
1391 _directfb_argb_font
? DSPF_ARGB
: DSPF_A8
,
1393 &cache
->dfbsurface
);
1399 cache
->width
= width
;
1400 cache
->height
= height
;
1402 return CAIRO_STATUS_SUCCESS
;
1406 _directfb_destroy_font_cache (cairo_directfb_font_cache_t
*cache
)
1408 cache
->dfbsurface
->Release (cache
->dfbsurface
);
1412 static cairo_status_t
1413 _directfb_acquire_font_cache (cairo_directfb_surface_t
*surface
,
1414 cairo_scaled_font_t
*scaled_font
,
1415 const cairo_glyph_t
*glyphs
,
1417 cairo_directfb_font_cache_t
**ret_cache
,
1418 DFBRectangle
*rects
,
1422 cairo_status_t status
;
1423 cairo_scaled_glyph_t
*chars
[num_glyphs
];
1425 cairo_directfb_font_cache_t
*cache
= NULL
;
1433 D_DEBUG_AT (CairoDFB_Font
, "%s( %p [%d] )\n", __FUNCTION__
, glyphs
, num_glyphs
);
1435 _cairo_cache_freeze (scaled_font
->glyphs
);
1437 if (scaled_font
->surface_private
) {
1438 cache
= scaled_font
->surface_private
;
1443 for (i
= 0; i
< num_glyphs
; i
++) {
1444 cairo_scaled_glyph_t
*scaled_glyph
;
1445 cairo_image_surface_t
*img
;
1447 D_DEBUG_AT (CairoDFB_Font
, " -> [%2d] = %4lu\n", i
, glyphs
[i
].index
);
1449 status
= _cairo_scaled_glyph_lookup (scaled_font
, glyphs
[i
].index
,
1450 CAIRO_SCALED_GLYPH_INFO_SURFACE
,
1453 _cairo_cache_thaw (scaled_font
->glyphs
);
1457 img
= scaled_glyph
->surface
;
1458 switch (img
->format
) {
1459 case CAIRO_FORMAT_A1
:
1460 case CAIRO_FORMAT_A8
:
1461 case CAIRO_FORMAT_ARGB32
:
1464 D_DEBUG_AT (CairoDFB_Font
,
1465 " -> Unsupported font format %d!\n", img
->format
);
1466 _cairo_cache_thaw (scaled_font
->glyphs
);
1467 return CAIRO_INT_STATUS_UNSUPPORTED
;
1470 points
[n
].x
= _cairo_lround (glyphs
[i
].x
- img
->base
.device_transform
.x0
);
1471 points
[n
].y
= _cairo_lround (glyphs
[i
].y
- img
->base
.device_transform
.y0
);
1473 // D_DEBUG_AT (CairoDFB_Font, " (%4d,%4d) [%2d]\n", points[n].x, points[n].y, n );
1475 if (points
[n
].x
>= surface
->width
||
1476 points
[n
].y
>= surface
->height
||
1477 points
[n
].x
+img
->width
<= 0 ||
1478 points
[n
].y
+img
->height
<= 0)
1483 if (scaled_glyph
->surface_private
== NULL
) {
1486 if (x
+img
->width
> 2048) {
1494 rects
[n
].w
= img
->width
;
1495 rects
[n
].h
= img
->height
;
1498 h
= MAX (h
, img
->height
);
1501 /* Remember glyph location */
1502 rect
= malloc (sizeof (DFBRectangle
));
1504 _cairo_cache_thaw (scaled_font
->glyphs
);
1505 return _cairo_error (CAIRO_STATUS_NO_MEMORY
);
1509 scaled_glyph
->surface_private
= rect
;
1510 chars
[num_chars
++] = scaled_glyph
;
1512 D_DEBUG_AT (CairoDFB_Font
, " -> loading at %4d,%2d <- rect %p, img %p, entry %p\n",
1513 rects
[n
].x
, rects
[n
].y
, rect
, scaled_glyph
->surface
, scaled_glyph
);
1515 rects
[n
] = *(DFBRectangle
*) scaled_glyph
->surface_private
;
1517 D_DEBUG_AT (CairoDFB_Font
, " -> exists at %4d,%2d\n", rects
[n
].x
, rects
[n
].y
);
1524 _cairo_cache_thaw (scaled_font
->glyphs
);
1525 return CAIRO_INT_STATUS_NOTHING_TO_DO
;
1532 /* XXX query maximum surface size */
1533 if (w
> 2048 || h
> 2048) {
1534 _cairo_cache_thaw (scaled_font
->glyphs
);
1535 return CAIRO_INT_STATUS_UNSUPPORTED
;
1539 if (cache
->width
< w
|| cache
->height
< h
) {
1540 cairo_directfb_font_cache_t
*new_cache
;
1542 w
= MAX (w
, cache
->width
);
1543 h
= MAX (h
, cache
->height
);
1545 D_DEBUG_AT (CairoDFB_Font
, " -> Reallocating font cache (%dx%d).\n", w
, h
);
1547 status
= _directfb_allocate_font_cache (surface
->dfb
,
1551 _cairo_cache_thaw (scaled_font
->glyphs
);
1555 new_cache
->dfbsurface
->Blit (new_cache
->dfbsurface
,
1556 cache
->dfbsurface
, NULL
, 0, 0);
1558 _directfb_destroy_font_cache (cache
);
1559 scaled_font
->surface_private
= cache
= new_cache
;
1562 D_DEBUG_AT (CairoDFB_Font
, " -> Allocating font cache (%dx%d).\n", w
, h
);
1564 status
= _directfb_allocate_font_cache (surface
->dfb
, w
, h
, &cache
);
1566 _cairo_cache_thaw (scaled_font
->glyphs
);
1570 scaled_font
->surface_backend
= &_cairo_directfb_surface_backend
;
1571 scaled_font
->surface_private
= cache
;
1575 unsigned char *data
;
1578 if (cache
->dfbsurface
->Lock (cache
->dfbsurface
,
1579 DSLF_WRITE
, (void *)&data
, &pitch
))
1581 _cairo_cache_thaw (scaled_font
->glyphs
);
1582 return _cairo_error (CAIRO_STATUS_NO_MEMORY
);
1585 D_DEBUG_AT (CairoDFB_Font
, " => %d chars to load, cache %dx%d\n", num_chars
, cache
->width
, cache
->height
);
1587 for (i
= 0; i
< num_chars
; i
++) {
1588 cairo_image_surface_t
*img
= chars
[i
]->surface
;
1589 DFBRectangle
*rect
= chars
[i
]->surface_private
;
1590 unsigned char *dst
= data
;
1594 D_DEBUG_AT (CairoDFB_Font
, " -> loading [%2d] <- rect %p, img %p, entry %p\n", i
, rect
, img
, chars
[i
]);
1598 D_DEBUG_AT (CairoDFB_Font
, " from %p\n", src
);
1600 dst
+= rect
->y
* pitch
+ (_directfb_argb_font
? (rect
->x
<<2) : rect
->x
);
1602 D_DEBUG_AT (CairoDFB_Font
, " to %4d,%2d (%p)\n", rect
->x
, rect
->y
, dst
);
1604 if (img
->format
== CAIRO_FORMAT_A1
) {
1605 for (h
= rect
->h
; h
; h
--) {
1606 if (_directfb_argb_font
) {
1607 for (j
= 0; j
< rect
->w
; j
++)
1608 ((uint32_t *) dst
)[j
] = (src
[j
>>3] & (1 << (j
&7))) ? 0xffffffff : 0;
1610 for (j
= 0; j
< rect
->w
; j
++)
1611 dst
[j
] = (src
[j
>>3] & (1 << (j
&7))) ? 0xff : 0;
1617 } else if (img
->format
== CAIRO_FORMAT_A8
) {
1618 for (h
= rect
->h
; h
; h
--) {
1619 if (_directfb_argb_font
) {
1620 for (j
= 0; j
< rect
->w
; j
++)
1621 ((uint32_t *) dst
)[j
] = src
[j
] * 0x01010101;
1623 direct_memcpy (dst
, src
, rect
->w
);
1629 } else { /* ARGB32 */
1630 for (h
= rect
->h
; h
; h
--) {
1631 if (_directfb_argb_font
) {
1632 direct_memcpy (dst
, src
, rect
->w
<<2);
1634 for (j
= 0; j
< rect
->w
; j
++)
1635 dst
[j
] = ((uint32_t *) src
)[j
] >> 24;
1644 cache
->dfbsurface
->Unlock (cache
->dfbsurface
);
1647 _cairo_cache_thaw (scaled_font
->glyphs
);
1652 D_DEBUG_AT (CairoDFB_Font
, " => cache %d,%d, %p [%d]\n", x
, y
, cache
, n
);
1657 return CAIRO_STATUS_SUCCESS
;
1661 _cairo_directfb_surface_scaled_font_fini (cairo_scaled_font_t
*scaled_font
)
1663 cairo_directfb_font_cache_t
*cache
= scaled_font
->surface_private
;
1665 D_DEBUG_AT (CairoDFB_Font
,
1666 "%s( scaled_font=%p ).\n", __FUNCTION__
, scaled_font
);
1668 if (cache
!= NULL
) {
1669 _directfb_destroy_font_cache (cache
);
1670 scaled_font
->surface_private
= NULL
;
1675 _cairo_directfb_surface_scaled_glyph_fini (cairo_scaled_glyph_t
*scaled_glyph
,
1676 cairo_scaled_font_t
*scaled_font
)
1678 D_DEBUG_AT (CairoDFB_Font
,
1679 "%s( scaled_glyph=%p, scaled_font=%p ).\n",
1680 __FUNCTION__
, scaled_glyph
, scaled_font
);
1682 if (scaled_glyph
->surface_private
!= NULL
) {
1683 free (scaled_glyph
->surface_private
);
1684 scaled_glyph
->surface_private
= NULL
;
1688 static cairo_int_status_t
1689 _cairo_directfb_surface_show_glyphs (void *abstract_dst
,
1690 cairo_operator_t op
,
1691 cairo_pattern_t
*pattern
,
1692 cairo_glyph_t
*glyphs
,
1694 cairo_scaled_font_t
*scaled_font
,
1695 int *remaining_glyphs
)
1697 cairo_directfb_surface_t
*dst
= abstract_dst
;
1698 cairo_directfb_font_cache_t
*cache
;
1699 cairo_status_t status
;
1700 DFBSurfaceBlittingFlags flags
;
1701 DFBSurfaceBlendFunction sblend
;
1702 DFBSurfaceBlendFunction dblend
;
1703 DFBRectangle rects
[num_glyphs
];
1704 DFBPoint points
[num_glyphs
];
1706 const cairo_color_t
*color
;
1709 D_DEBUG_AT (CairoDFB_Font
,
1710 "%s( dst=%p, op=%d, pattern=%p, glyphs=%p, num_glyphs=%d, scaled_font=%p ).\n",
1711 __FUNCTION__
, dst
, op
, pattern
, glyphs
, num_glyphs
, scaled_font
);
1713 if (pattern
->type
!= CAIRO_PATTERN_TYPE_SOLID
)
1714 return CAIRO_INT_STATUS_UNSUPPORTED
;
1716 /* Fallback if we need to emulate clip regions */
1717 if (dst
->base
.clip
&&
1718 (dst
->base
.clip
->mode
!= CAIRO_CLIP_MODE_REGION
||
1719 dst
->base
.clip
->surface
!= NULL
))
1721 return CAIRO_INT_STATUS_UNSUPPORTED
;
1724 /* XXX Unbounded operators are not handled correctly */
1725 if (! _cairo_operator_bounded_by_mask (op
))
1726 return CAIRO_INT_STATUS_UNSUPPORTED
;
1727 if (! _cairo_operator_bounded_by_source (op
))
1728 return CAIRO_INT_STATUS_UNSUPPORTED
;
1730 if (! _directfb_get_operator (op
, &sblend
, &dblend
) ||
1731 sblend
== DSBF_DESTALPHA
|| sblend
== DSBF_INVDESTALPHA
)
1733 return CAIRO_INT_STATUS_UNSUPPORTED
;
1736 status
= _directfb_acquire_font_cache (dst
, scaled_font
, glyphs
, num_glyphs
,
1737 &cache
, &rects
[0], &points
[0], &num
);
1739 if (status
== CAIRO_INT_STATUS_NOTHING_TO_DO
)
1740 status
= CAIRO_STATUS_SUCCESS
;
1744 color
= &((cairo_solid_pattern_t
*) pattern
)->color
;
1746 flags
= DSBLIT_BLEND_ALPHACHANNEL
| DSBLIT_COLORIZE
;
1747 if (! CAIRO_COLOR_IS_OPAQUE (color
))
1748 flags
|= DSBLIT_BLEND_COLORALPHA
;
1750 if (!_directfb_argb_font
) {
1751 if (sblend
== DSBF_ONE
) {
1752 sblend
= DSBF_SRCALPHA
;
1753 if (dblend
== DSBF_ZERO
)
1754 dblend
= DSBF_INVSRCALPHA
;
1758 dst
->dfbsurface
->SetBlittingFlags (dst
->dfbsurface
, flags
);
1759 dst
->dfbsurface
->SetSrcBlendFunction (dst
->dfbsurface
, sblend
);
1760 dst
->dfbsurface
->SetDstBlendFunction (dst
->dfbsurface
, dblend
);
1761 if (dst
->blit_premultiplied
) {
1762 dst
->dfbsurface
->SetColor (dst
->dfbsurface
,
1763 color
->red_short
>> 8,
1764 color
->green_short
>> 8,
1765 color
->blue_short
>> 8,
1766 color
->alpha_short
>> 8);
1768 dst
->dfbsurface
->SetColor (dst
->dfbsurface
,
1770 color
->green
* 0xff,
1772 color
->alpha
* 0xff);
1775 D_DEBUG_AT (CairoDFB_Font
, "Running BatchBlit().\n");
1777 RUN_CLIPPED (dst
, NULL
,
1778 dst
->dfbsurface
->BatchBlit (dst
->dfbsurface
,
1779 cache
->dfbsurface
, rects
, points
, num
));
1781 return CAIRO_STATUS_SUCCESS
;
1783 #endif /* DFB_SHOW_GLYPHS */
1787 _cairo_directfb_surface_is_similar (void *surface_a
, void *surface_b
, cairo_content_t content
)
1789 cairo_directfb_surface_t
*a
= (cairo_directfb_surface_t
*) surface_a
;
1790 cairo_directfb_surface_t
*b
= (cairo_directfb_surface_t
*) surface_b
;
1792 return a
->dfb
== b
->dfb
;
1795 static cairo_surface_backend_t
1796 _cairo_directfb_surface_backend
= {
1797 CAIRO_SURFACE_TYPE_DIRECTFB
, /*type*/
1798 _cairo_directfb_surface_create_similar
,/*create_similar*/
1799 _cairo_directfb_surface_finish
, /*finish*/
1800 _cairo_directfb_surface_acquire_source_image
,/*acquire_source_image*/
1801 _cairo_directfb_surface_release_source_image
,/*release_source_image*/
1802 _cairo_directfb_surface_acquire_dest_image
,/*acquire_dest_image*/
1803 _cairo_directfb_surface_release_dest_image
,/*release_dest_image*/
1804 _cairo_directfb_surface_clone_similar
,/*clone_similar*/
1806 _cairo_directfb_surface_composite
,/*composite*/
1811 _cairo_directfb_surface_fill_rectangles
,/*fill_rectangles*/
1813 NULL
,/*fill_rectangles*/
1815 #if DFB_COMPOSITE_TRAPEZOIDS
1816 _cairo_directfb_surface_composite_trapezoids
,/*composite_trapezoids*/
1818 NULL
,/*composite_trapezoids*/
1820 NULL
, /* copy_page */
1821 NULL
, /* show_page */
1822 _cairo_directfb_surface_set_clip_region
,/* set_clip_region */
1823 NULL
, /* intersect_clip_path */
1824 _cairo_directfb_abstract_surface_get_extents
,/* get_extents */
1825 NULL
, /* old_show_glyphs */
1826 NULL
, /* get_font_options */
1828 NULL
, /* mark_dirty_rectangle */
1830 _cairo_directfb_surface_scaled_font_fini
,/* scaled_font_fini */
1831 _cairo_directfb_surface_scaled_glyph_fini
,/* scaled_glyph_fini */
1841 _cairo_directfb_surface_show_glyphs
,/* show_glyphs */
1843 NULL
, /* show_glyphs */
1845 NULL
, /* snapshot */
1846 _cairo_directfb_surface_is_similar
,
1852 cairo_directfb_surface_backend_init (IDirectFB
*dfb
)
1854 static int done
= 0;
1859 if (getenv ("CAIRO_DIRECTFB_NO_ACCEL")) {
1861 _cairo_directfb_surface_backend
.fill_rectangles
= NULL
;
1864 _cairo_directfb_surface_backend
.composite
= NULL
;
1866 #if DFB_COMPOSITE_TRAPEZOIDS
1867 _cairo_directfb_surface_backend
.composite_trapezoids
= NULL
;
1870 _cairo_directfb_surface_backend
.scaled_font_fini
= NULL
;
1871 _cairo_directfb_surface_backend
.scaled_glyph_fini
= NULL
;
1872 _cairo_directfb_surface_backend
.show_glyphs
= NULL
;
1874 D_DEBUG_AT (CairoDFB_Surface
, "Acceleration disabled.\n");
1876 DFBGraphicsDeviceDescription dsc
;
1878 dfb
->GetDeviceDescription (dfb
, &dsc
);
1881 // if (!(dsc.acceleration_mask & DFXL_BLIT))
1882 // _cairo_directfb_surface_backend.composite = NULL;
1885 #if DFB_COMPOSITE_TRAPEZOIDS
1886 // if (!(dsc.acceleration_mask & DFXL_TEXTRIANGLES))
1887 // _cairo_directfb_surface_backend.composite_trapezoids = NULL;
1891 if (getenv ("CAIRO_DIRECTFB_ARGB_FONT")) {
1892 _directfb_argb_font
= 1;
1893 D_DEBUG_AT (CairoDFB_Surface
, "Using ARGB fonts.\n");
1900 cairo_directfb_surface_create (IDirectFB
*dfb
, IDirectFBSurface
*dfbsurface
)
1902 cairo_directfb_surface_t
*surface
;
1903 DFBSurfacePixelFormat format
;
1904 DFBSurfaceCapabilities caps
;
1906 D_ASSERT (dfb
!= NULL
);
1907 D_ASSERT (dfbsurface
!= NULL
);
1909 cairo_directfb_surface_backend_init (dfb
);
1911 surface
= calloc (1, sizeof (cairo_directfb_surface_t
));
1912 if (surface
== NULL
)
1913 return _cairo_surface_create_in_error (_cairo_error (CAIRO_STATUS_NO_MEMORY
));
1915 dfbsurface
->AddRef (dfbsurface
);
1916 dfbsurface
->GetPixelFormat (dfbsurface
, &format
);
1917 dfbsurface
->GetSize (dfbsurface
, &surface
->width
, &surface
->height
);
1919 surface
->dfbsurface
= dfbsurface
;
1920 surface
->format
= _directfb_to_cairo_format (format
);
1921 surface
->content
= _directfb_format_to_content (format
);
1923 dfbsurface
->GetCapabilities (dfbsurface
, &caps
);
1924 if (caps
& DSCAPS_PREMULTIPLIED
)
1925 surface
->blit_premultiplied
= TRUE
;
1927 _cairo_surface_init (&surface
->base
,
1928 &_cairo_directfb_surface_backend
,
1931 return &surface
->base
;