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
));
458 if (unlikely (surface
== NULL
))
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 cairo_directfb_surface_t
*surface
= abstract_surface
;
553 IDirectFBSurface
*buffer
= image_extra
;
555 D_DEBUG_AT (CairoDFB_Acquire
,
556 "%s( surface=%p ).\n", __FUNCTION__
, surface
);
558 buffer
->Unlock (buffer
);
560 cairo_surface_destroy (&image
->base
);
563 static cairo_status_t
564 _cairo_directfb_surface_acquire_dest_image (void *abstract_surface
,
565 cairo_rectangle_int_t
*interest_rect
,
566 cairo_image_surface_t
**image_out
,
567 cairo_rectangle_int_t
*image_rect_out
,
570 cairo_directfb_surface_t
*surface
= abstract_surface
;
572 D_DEBUG_AT (CairoDFB_Acquire
,
573 "%s( surface=%p (%dx%d), interest_rect={ %u %u %u %u } ).\n",
574 __FUNCTION__
, surface
, surface
->width
, surface
->height
,
575 interest_rect
? interest_rect
->x
: 0,
576 interest_rect
? interest_rect
->y
: 0,
577 interest_rect
? interest_rect
->width
: (unsigned) surface
->width
,
578 interest_rect
? interest_rect
->height
: (unsigned) surface
->height
);
580 return _directfb_acquire_surface (surface
, interest_rect
, image_out
,
581 image_rect_out
, image_extra
,
582 DSLF_READ
| DSLF_WRITE
);
586 _cairo_directfb_surface_release_dest_image (void *abstract_surface
,
587 cairo_rectangle_int_t
*interest_rect
,
588 cairo_image_surface_t
*image
,
589 cairo_rectangle_int_t
*image_rect
,
592 cairo_directfb_surface_t
*surface
= abstract_surface
;
593 IDirectFBSurface
*buffer
= image_extra
;
595 D_DEBUG_AT (CairoDFB_Acquire
,
596 "%s( surface=%p ).\n", __FUNCTION__
, surface
);
598 buffer
->Unlock (buffer
);
600 if (surface
->dfbsurface
!= buffer
) {
602 .x1
= interest_rect
->x
,
603 .y1
= interest_rect
->y
,
604 .x2
= interest_rect
->x
+ interest_rect
->width
- 1,
605 .y2
= interest_rect
->y
+ interest_rect
->height
- 1
607 surface
->dfbsurface
->SetBlittingFlags (surface
->dfbsurface
, DSBLIT_NOFX
);
608 RUN_CLIPPED (surface
, ®ion
,
609 surface
->dfbsurface
->Blit (surface
->dfbsurface
,
611 image_rect
->x
, image_rect
->y
));
614 cairo_surface_destroy (&image
->base
);
617 static cairo_status_t
618 _cairo_directfb_surface_clone_similar (void *abstract_surface
,
619 cairo_surface_t
*src
,
620 cairo_content_t content
,
627 cairo_surface_t
**clone_out
)
629 cairo_directfb_surface_t
*surface
= abstract_surface
;
630 cairo_directfb_surface_t
*clone
;
632 D_DEBUG_AT (CairoDFB_Surface
,
633 "%s( surface=%p, src=%p ).\n", __FUNCTION__
, surface
, src
);
635 if (src
->backend
== surface
->base
.backend
) {
638 *clone_out
= cairo_surface_reference (src
);
640 return CAIRO_STATUS_SUCCESS
;
641 } else if (_cairo_surface_is_image (src
)) {
642 cairo_image_surface_t
*image_src
= (cairo_image_surface_t
*) src
;
643 unsigned char *dst
, *src
= image_src
->data
;
648 clone
= (cairo_directfb_surface_t
*)
649 _cairo_directfb_surface_create_similar (surface
,
650 _cairo_content_from_format (image_src
->format
),
653 return CAIRO_INT_STATUS_UNSUPPORTED
;
654 if (clone
->base
.status
)
655 return clone
->base
.status
;
657 ret
= clone
->dfbsurface
->Lock (clone
->dfbsurface
,
658 DSLF_WRITE
, (void *)&dst
, &pitch
);
660 DirectFBError ("IDirectFBSurface::Lock()", ret
);
661 cairo_surface_destroy (&clone
->base
);
662 return _cairo_error (CAIRO_STATUS_NO_MEMORY
);
665 src
+= image_src
->stride
* src_y
;
666 if (image_src
->format
== CAIRO_FORMAT_A1
) {
669 for (i
= 0; i
< height
; i
++) {
670 for (j
= src_x
; j
< src_x
+ width
; j
++)
671 dst
[j
] = (src
[j
>>3] & (1 << (j
&7))) ? 0xff : 0x00;
673 src
+= image_src
->stride
;
678 if (image_src
->format
== CAIRO_FORMAT_A8
) {
686 for (i
= 0; i
< height
; i
++) {
687 direct_memcpy (dst
, src
, len
);
689 src
+= image_src
->stride
;
693 clone
->dfbsurface
->Unlock (clone
->dfbsurface
);
695 *clone_offset_x
= src_x
;
696 *clone_offset_y
= src_y
;
697 *clone_out
= &clone
->base
;
698 return CAIRO_STATUS_SUCCESS
;
701 return CAIRO_INT_STATUS_UNSUPPORTED
;
704 #if DFB_COMPOSITE || DFB_COMPOSITE_TRAPEZOIDS
705 static cairo_int_status_t
706 _directfb_prepare_composite (cairo_directfb_surface_t
*dst
,
707 const cairo_pattern_t
*src_pattern
,
708 const cairo_pattern_t
*mask_pattern
,
710 int *src_x
, int *src_y
,
711 int *mask_x
, int *mask_y
,
714 cairo_directfb_surface_t
**ret_src
,
715 cairo_surface_attributes_t
*ret_src_attr
)
717 cairo_directfb_surface_t
*src
;
718 cairo_surface_attributes_t src_attr
;
719 cairo_status_t status
;
720 DFBSurfaceBlittingFlags flags
;
721 DFBSurfaceBlendFunction sblend
;
722 DFBSurfaceBlendFunction dblend
;
723 const cairo_color_t
*color
;
725 /* XXX Unbounded operators are not handled correctly */
726 if (! _cairo_operator_bounded_by_source (op
))
727 return CAIRO_INT_STATUS_UNSUPPORTED
;
729 if (! _directfb_get_operator (op
, &sblend
, &dblend
))
730 return CAIRO_INT_STATUS_UNSUPPORTED
;
733 cairo_solid_pattern_t
*pattern
;
735 return CAIRO_INT_STATUS_UNSUPPORTED
;
736 if (mask_pattern
->type
!= CAIRO_PATTERN_TYPE_SOLID
) {
737 const cairo_pattern_t
*tmp
;
740 if (src_pattern
->type
!= CAIRO_PATTERN_TYPE_SOLID
||
741 sblend
== DSBF_INVDESTALPHA
) /* Doesn't work correctly */
742 return CAIRO_INT_STATUS_UNSUPPORTED
;
744 D_DEBUG_AT (CairoDFB_Render
, "Replacing src pattern by mask pattern.\n");
747 tmp_x
= *src_x
; tmp_y
= *src_y
;
749 src_pattern
= mask_pattern
;
750 *src_x
= *mask_x
; *src_y
= *mask_y
;
753 *mask_x
= tmp_x
; *mask_y
= tmp_y
;
755 if (sblend
== DSBF_ONE
) {
756 sblend
= DSBF_SRCALPHA
;
757 /*dblend = DSBF_INVSRCALPHA;*/
761 color
= &((cairo_solid_pattern_t
*) mask_pattern
)->color
;
763 color
= _cairo_stock_color (CAIRO_STOCK_WHITE
);
766 status
= _cairo_pattern_acquire_surface (src_pattern
, &dst
->base
,
767 CAIRO_CONTENT_COLOR_ALPHA
,
768 *src_x
, *src_y
, width
, height
,
769 CAIRO_PATTERN_ACQUIRE_NO_REFLECT
,
770 (cairo_surface_t
**) &src
,
775 if (src
->base
.backend
!= &_cairo_directfb_surface_backend
||
776 src
->dfb
!= dst
->dfb
)
778 _cairo_pattern_release_surface (src_pattern
, &src
->base
, &src_attr
);
779 return CAIRO_INT_STATUS_UNSUPPORTED
;
782 if (src
->content
== CAIRO_CONTENT_COLOR
) {
783 if (sblend
== DSBF_SRCALPHA
)
785 else if (sblend
== DSBF_INVSRCALPHA
)
788 if (dblend
== DSBF_SRCALPHA
)
790 else if (dblend
== DSBF_INVSRCALPHA
)
794 if (dst
->content
== CAIRO_CONTENT_COLOR
) {
795 if (sblend
== DSBF_DESTALPHA
)
797 else if (sblend
== DSBF_INVDESTALPHA
)
800 if (dblend
== DSBF_DESTALPHA
)
802 else if (dblend
== DSBF_INVDESTALPHA
)
806 flags
= (sblend
== DSBF_ONE
&& dblend
== DSBF_ZERO
)
807 ? DSBLIT_NOFX
: DSBLIT_BLEND_ALPHACHANNEL
;
808 if (! CAIRO_COLOR_IS_OPAQUE (color
))
809 flags
|= DSBLIT_BLEND_COLORALPHA
;
810 if (! _cairo_color_equal (color
, _cairo_stock_color (CAIRO_STOCK_WHITE
)))
811 flags
|= DSBLIT_COLORIZE
;
813 dst
->dfbsurface
->SetBlittingFlags (dst
->dfbsurface
, flags
);
815 if (flags
& (DSBLIT_BLEND_ALPHACHANNEL
| DSBLIT_BLEND_COLORALPHA
)) {
816 dst
->dfbsurface
->SetSrcBlendFunction (dst
->dfbsurface
, sblend
);
817 dst
->dfbsurface
->SetDstBlendFunction (dst
->dfbsurface
, dblend
);
820 if (flags
& (DSBLIT_BLEND_COLORALPHA
| DSBLIT_COLORIZE
)) {
821 if (dst
->blit_premultiplied
) {
822 dst
->dfbsurface
->SetColor (dst
->dfbsurface
,
823 color
->red_short
>> 8,
824 color
->green_short
>> 8,
825 color
->blue_short
>> 8,
826 color
->alpha_short
>> 8);
828 dst
->dfbsurface
->SetColor (dst
->dfbsurface
,
832 color
->alpha
* 0xff);
837 *ret_src_attr
= src_attr
;
839 return CAIRO_STATUS_SUCCESS
;
843 _directfb_finish_composite (cairo_directfb_surface_t
*dst
,
844 const cairo_pattern_t
*src_pattern
,
845 cairo_surface_t
*src
,
846 cairo_surface_attributes_t
*src_attr
)
848 _cairo_pattern_release_surface (src_pattern
, src
, src_attr
);
850 #endif /* DFB_COMPOSITE || DFB_COMPOSITE_TRAPEZOIDS */
853 static DFBAccelerationMask
854 _directfb_categorize_operation (cairo_surface_attributes_t
*src_attr
)
856 cairo_matrix_t
*m
= &src_attr
->matrix
;
858 if (m
->xy
!= 0 || m
->yx
!= 0 || m
->xx
< 0 || m
->yy
< 0) {
859 if (src_attr
->extend
!= CAIRO_EXTEND_NONE
)
862 return DFXL_TEXTRIANGLES
;
865 if (m
->xx
!= 1 || m
->yy
!= 1) {
866 if (src_attr
->extend
!= CAIRO_EXTEND_NONE
)
869 return DFXL_STRETCHBLIT
;
872 switch (src_attr
->extend
) {
873 case CAIRO_EXTEND_NONE
:
874 case CAIRO_EXTEND_REPEAT
:
875 if (_cairo_matrix_is_integer_translation (&src_attr
->matrix
,
882 return DFXL_STRETCHBLIT
;
886 case CAIRO_EXTEND_REFLECT
:
887 case CAIRO_EXTEND_PAD
:
892 static cairo_int_status_t
893 _cairo_directfb_surface_composite (cairo_operator_t op
,
894 const cairo_pattern_t
*src_pattern
,
895 const cairo_pattern_t
*mask_pattern
,
897 int src_x
, int src_y
,
898 int mask_x
, int mask_y
,
899 int dst_x
, int dst_y
,
903 cairo_directfb_surface_t
*dst
= abstract_dst
;
904 cairo_directfb_surface_t
*src
;
905 cairo_surface_attributes_t src_attr
;
906 cairo_bool_t is_integer_translation
;
907 DFBAccelerationMask accel
, mask
;
908 cairo_int_status_t status
;
911 D_DEBUG_AT (CairoDFB_Render
,
912 "%s( op=%d, src_pattern=%p, mask_pattern=%p, dst=%p,"
913 " src_x=%d, src_y=%d, mask_x=%d, mask_y=%d, dst_x=%d,"
914 " dst_y=%d, width=%u, height=%u ).\n",
915 __FUNCTION__
, op
, src_pattern
, mask_pattern
, dst
,
916 src_x
, src_y
, mask_x
, mask_y
, dst_x
, dst_y
, width
, height
);
918 status
= _directfb_prepare_composite (dst
, src_pattern
, mask_pattern
, op
,
919 &src_x
, &src_y
, &mask_x
, &mask_y
,
920 width
, height
, &src
, &src_attr
);
924 accel
= _directfb_categorize_operation (&src_attr
);
925 if (accel
== DFXL_NONE
) {
926 _directfb_finish_composite (dst
, src_pattern
, &src
->base
, &src_attr
);
927 return CAIRO_INT_STATUS_UNSUPPORTED
;
930 dst
->dfbsurface
->GetAccelerationMask (dst
->dfbsurface
,
933 if ((mask
& accel
) == 0) {
934 D_DEBUG_AT (CairoDFB_Render
, "No acceleration (%08x)!\n", accel
);
935 if (accel
!= DFXL_BLIT
) {
936 _directfb_finish_composite (dst
, src_pattern
, &src
->base
, &src_attr
);
937 return CAIRO_INT_STATUS_UNSUPPORTED
;
941 src_x
+= src_attr
.x_offset
;
942 src_y
+= src_attr
.y_offset
;
949 is_integer_translation
=
950 _cairo_matrix_is_integer_translation (&src_attr
.matrix
,
952 assert (is_integer_translation
);
959 if (src_attr
.extend
== CAIRO_EXTEND_NONE
) {
960 D_DEBUG_AT (CairoDFB_Render
, "Running Blit().\n");
962 RUN_CLIPPED (dst
, NULL
,
963 dst
->dfbsurface
->Blit (dst
->dfbsurface
,
967 } else if (src_attr
.extend
== CAIRO_EXTEND_REPEAT
) {
972 clip
.x2
= dst_x
+ width
- 1;
973 clip
.y2
= dst_y
+ height
- 1;
975 D_DEBUG_AT (CairoDFB_Render
, "Running TileBlit().\n");
977 RUN_CLIPPED (dst
, &clip
,
978 dst
->dfbsurface
->TileBlit (dst
->dfbsurface
,
986 case DFXL_STRETCHBLIT
:
989 double x1
, y1
, x2
, y2
;
991 TRANSFORM_POINT2X (src_attr
.matrix
,
992 src_x
, src_y
, x1
, y1
);
993 TRANSFORM_POINT2X (src_attr
.matrix
,
994 src_x
+width
, src_y
+height
, x2
, y2
);
998 sr
.w
= ceil (x2
) - sr
.x
;
999 sr
.h
= ceil (y2
) - sr
.y
;
1006 D_DEBUG_AT (CairoDFB_Render
, "Running StretchBlit().\n");
1008 RUN_CLIPPED (dst
, NULL
,
1009 dst
->dfbsurface
->StretchBlit (dst
->dfbsurface
,
1010 src
->dfbsurface
, &sr
, &dr
));
1014 case DFXL_TEXTRIANGLES
:
1018 float x1
, y1
, x2
, y2
;
1021 status
= cairo_matrix_invert (&src_attr
.matrix
);
1022 /* guaranteed by cairo_pattern_set_matrix (); */
1023 assert (status
== CAIRO_STATUS_SUCCESS
);
1030 src
->dfbsurface
->GetSize (src
->dfbsurface
, &w
, &h
);
1032 TRANSFORM_POINT3X (src_attr
.matrix
,
1033 x1
, y1
, v
[0].x
, v
[0].y
);
1039 TRANSFORM_POINT3X (src_attr
.matrix
,
1040 x2
, y1
, v
[1].x
, v
[1].y
);
1046 TRANSFORM_POINT3X (src_attr
.matrix
,
1047 x2
, y2
, v
[2].x
, v
[2].y
);
1053 TRANSFORM_POINT3X (src_attr
.matrix
,
1054 x1
, y2
, v
[3].x
, v
[3].y
);
1062 clip
.x2
= dst_x
+ width
- 1;
1063 clip
.y2
= dst_y
+ height
- 1;
1065 D_DEBUG_AT (CairoDFB_Render
, "Running TextureTriangles().\n");
1067 RUN_CLIPPED (dst
, &clip
,
1068 dst
->dfbsurface
->TextureTriangles (dst
->dfbsurface
,
1069 src
->dfbsurface
, v
, NULL
, 4, DTTF_FAN
));
1074 D_BUG ("Unexpected operation");
1078 _directfb_finish_composite (dst
, src_pattern
, &src
->base
, &src_attr
);
1082 #endif /* DFB_COMPOSITE */
1085 static cairo_int_status_t
1086 _cairo_directfb_surface_fill_rectangles (void *abstract_surface
,
1087 cairo_operator_t op
,
1088 const cairo_color_t
*color
,
1089 cairo_rectangle_int_t
*rects
,
1092 cairo_directfb_surface_t
*dst
= abstract_surface
;
1093 DFBSurfaceDrawingFlags flags
;
1094 DFBSurfaceBlendFunction sblend
;
1095 DFBSurfaceBlendFunction dblend
;
1096 DFBRectangle r
[n_rects
];
1099 D_DEBUG_AT (CairoDFB_Render
,
1100 "%s( dst=%p, op=%d, color=%p, rects=%p, n_rects=%d ).\n",
1101 __FUNCTION__
, dst
, op
, color
, rects
, n_rects
);
1103 if (! _cairo_operator_bounded_by_source (op
))
1104 return CAIRO_INT_STATUS_UNSUPPORTED
;
1106 if (! _directfb_get_operator (op
, &sblend
, &dblend
))
1107 return CAIRO_INT_STATUS_UNSUPPORTED
;
1109 if (CAIRO_COLOR_IS_OPAQUE (color
)) {
1110 if (sblend
== DSBF_SRCALPHA
)
1112 else if (sblend
== DSBF_INVSRCALPHA
)
1115 if (dblend
== DSBF_SRCALPHA
)
1117 else if (dblend
== DSBF_INVSRCALPHA
)
1120 if (dst
->content
== CAIRO_CONTENT_COLOR
) {
1121 if (sblend
== DSBF_DESTALPHA
)
1123 else if (sblend
== DSBF_INVDESTALPHA
)
1126 if (dblend
== DSBF_DESTALPHA
)
1128 else if (dblend
== DSBF_INVDESTALPHA
)
1132 flags
= (sblend
== DSBF_ONE
&& dblend
== DSBF_ZERO
) ? DSDRAW_NOFX
: DSDRAW_BLEND
;
1133 dst
->dfbsurface
->SetDrawingFlags (dst
->dfbsurface
, flags
);
1134 if (flags
& DSDRAW_BLEND
) {
1135 dst
->dfbsurface
->SetSrcBlendFunction (dst
->dfbsurface
, sblend
);
1136 dst
->dfbsurface
->SetDstBlendFunction (dst
->dfbsurface
, dblend
);
1139 dst
->dfbsurface
->SetColor (dst
->dfbsurface
,
1140 color
->red_short
>> 8,
1141 color
->green_short
>> 8,
1142 color
->blue_short
>> 8,
1143 color
->alpha_short
>> 8);
1145 for (i
= 0; i
< n_rects
; i
++) {
1146 r
[i
].x
= rects
[i
].x
;
1147 r
[i
].y
= rects
[i
].y
;
1148 r
[i
].w
= rects
[i
].width
;
1149 r
[i
].h
= rects
[i
].height
;
1152 RUN_CLIPPED (dst
, NULL
,
1153 dst
->dfbsurface
->FillRectangles (dst
->dfbsurface
, r
, n_rects
));
1155 return CAIRO_STATUS_SUCCESS
;
1159 #if DFB_COMPOSITE_TRAPEZOIDS
1160 static cairo_int_status_t
1161 _cairo_directfb_surface_composite_trapezoids (cairo_operator_t op
,
1162 const cairo_pattern_t
*pattern
,
1164 cairo_antialias_t antialias
,
1165 int src_x
, int src_y
,
1166 int dst_x
, int dst_y
,
1168 unsigned int height
,
1169 cairo_trapezoid_t
*traps
,
1172 cairo_directfb_surface_t
*dst
= abstract_dst
;
1173 cairo_directfb_surface_t
*src
;
1174 cairo_surface_attributes_t src_attr
;
1175 cairo_status_t status
;
1176 DFBAccelerationMask accel
;
1178 D_DEBUG_AT (CairoDFB_Render
,
1179 "%s( op=%d, pattern=%p, dst=%p, antialias=%d,"
1180 " src_x=%d, src_y=%d, dst_x=%d, dst_y=%d,"
1181 " width=%u, height=%u, traps=%p, num_traps=%d ).\n",
1182 __FUNCTION__
, op
, pattern
, dst
, antialias
,
1183 src_x
, src_y
, dst_x
, dst_y
, width
, height
, traps
, num_traps
);
1185 if (antialias
!= CAIRO_ANTIALIAS_NONE
)
1186 return CAIRO_INT_STATUS_UNSUPPORTED
;
1188 /* Textures are not supported yet. */
1189 if (pattern
->type
!= CAIRO_PATTERN_TYPE_SOLID
)
1190 return CAIRO_INT_STATUS_UNSUPPORTED
;
1192 status
= _directfb_prepare_composite (dst
, pattern
, NULL
, op
,
1193 &src_x
, &src_y
, NULL
, NULL
,
1194 width
, height
, &src
, &src_attr
);
1198 dst
->dfbsurface
->GetAccelerationMask (dst
->dfbsurface
,
1202 status
= CAIRO_INT_STATUS_UNSUPPORTED
;
1204 if (accel
& DFXL_TEXTRIANGLES
) {
1205 DFBVertex vertex
[6*num_traps
];
1206 DFBVertex
*v
= &vertex
[0];
1209 #define ADD_TRI_V(V, X, Y) do { \
1210 (V)->x = (X); (V)->y = (Y); (V)->w = 1; (V)->z = (V)->s = (V)->t = 0; \
1212 #define ADD_TRI(id, x1, y1, x2, y2, x3, y3) do {\
1213 const int p = (id)*3;\
1214 ADD_TRI_V (v+p+0, x1, y1); \
1215 ADD_TRI_V (v+p+1, x2, y2); \
1216 ADD_TRI_V (v+p+2, x3, y3); \
1218 while (num_traps
--) {
1219 double lx1
, ly1
, lx2
, ly2
;
1220 double rx1
, ry1
, rx2
, ry2
;
1222 lx1
= _cairo_fixed_to_double (traps
->left
.p1
.x
);
1223 ly1
= _cairo_fixed_to_double (traps
->left
.p1
.y
);
1224 lx2
= _cairo_fixed_to_double (traps
->left
.p2
.x
);
1225 ly2
= _cairo_fixed_to_double (traps
->left
.p2
.y
);
1226 rx1
= _cairo_fixed_to_double (traps
->right
.p1
.x
);
1227 ry1
= _cairo_fixed_to_double (traps
->right
.p1
.y
);
1228 rx2
= _cairo_fixed_to_double (traps
->right
.p2
.x
);
1229 ry2
= _cairo_fixed_to_double (traps
->right
.p2
.y
);
1231 if (traps
->left
.p1
.y
< traps
->top
) {
1232 double y
= _cairo_fixed_to_double (traps
->top
);
1234 lx1
= (y
- ly1
) * (lx2
- lx1
) / (ly2
- ly1
) + lx1
;
1237 if (traps
->left
.p2
.y
> traps
->bottom
) {
1238 double y
= _cairo_fixed_to_double (traps
->bottom
);
1240 lx2
= (y
- ly1
) * (lx2
- lx1
) / (ly2
- ly1
) + lx1
;
1244 if (traps
->right
.p1
.y
< traps
->top
) {
1245 double y
= _cairo_fixed_to_double (traps
->top
);
1247 rx1
= (y
- ry1
) * (rx2
- rx1
) / (ry2
- ry1
) + rx1
;
1250 if (traps
->right
.p2
.y
> traps
->bottom
) {
1251 double y
= _cairo_fixed_to_double (traps
->bottom
);
1253 rx2
= (y
- ry1
) * (rx2
- rx1
) / (ry2
- ry1
) + rx1
;
1257 if (lx1
== rx1
&& ly1
== ry1
) {
1258 ADD_TRI (0, lx2
, ly2
, lx1
, ly1
, rx2
, ry2
);
1261 } else if (lx2
== rx2
&& ly2
== ry2
) {
1262 ADD_TRI (0, lx1
, ly1
, lx2
, ly2
, rx1
, ry1
);
1266 ADD_TRI (0, lx1
, ly1
, rx1
, ry1
, lx2
, ly2
);
1267 ADD_TRI (1, lx2
, ly2
, rx1
, ry1
, rx2
, ry2
);
1277 D_DEBUG_AT (CairoDFB_Render
, "Running TextureTriangles().\n");
1279 RUN_CLIPPED (dst
, NULL
,
1280 dst
->dfbsurface
->TextureTriangles (dst
->dfbsurface
,
1285 status
= CAIRO_STATUS_SUCCESS
;
1288 _directfb_finish_composite (dst
, pattern
, &src
->base
, &src_attr
);
1292 #endif /* DFB_COMPOSITE_TRAPEZOIDS */
1294 static cairo_int_status_t
1295 _cairo_directfb_surface_set_clip_region (void *abstract_surface
,
1296 cairo_region_t
*region
)
1298 cairo_directfb_surface_t
*surface
= abstract_surface
;
1300 D_DEBUG_AT (CairoDFB_Clip
,
1301 "%s( surface=%p, region=%p ).\n",
1302 __FUNCTION__
, surface
, region
);
1306 cairo_status_t status
;
1309 surface
->has_clip
= TRUE
;
1311 n_rects
= cairo_region_num_rectangles (region
);
1314 return CAIRO_STATUS_SUCCESS
;
1316 if (surface
->n_clips
!= n_rects
) {
1318 free (surface
->clips
);
1320 surface
->clips
= _cairo_malloc_ab (n_rects
, sizeof (DFBRegion
));
1321 if (!surface
->clips
) {
1322 surface
->n_clips
= 0;
1323 return _cairo_error (CAIRO_STATUS_NO_MEMORY
);
1326 surface
->n_clips
= n_rects
;
1329 for (i
= 0; i
< n_rects
; i
++) {
1330 cairo_rectangle_int_t rect
;
1332 cairo_region_get_rectangle (region
, i
, &rect
);
1334 surface
->clips
[i
].x1
= rect
.x
;
1335 surface
->clips
[i
].y1
= rect
.y
;
1336 surface
->clips
[i
].x2
= rect
.x
+ rect
.width
- 1;
1337 surface
->clips
[i
].y2
= rect
.y
+ rect
.height
- 1;
1340 surface
->has_clip
= FALSE
;
1341 if (surface
->clips
) {
1342 free (surface
->clips
);
1343 surface
->clips
= NULL
;
1344 surface
->n_clips
= 0;
1348 return CAIRO_STATUS_SUCCESS
;
1351 static cairo_int_status_t
1352 _cairo_directfb_abstract_surface_get_extents (void *abstract_surface
,
1353 cairo_rectangle_int_t
*rectangle
)
1355 cairo_directfb_surface_t
*surface
= abstract_surface
;
1357 D_DEBUG_AT (CairoDFB_Surface
,
1358 "%s( surface=%p, rectangle=%p ).\n",
1359 __FUNCTION__
, surface
, rectangle
);
1361 if (!surface
->local
) {
1362 surface
->dfbsurface
->GetSize (surface
->dfbsurface
,
1363 &surface
->width
, &surface
->height
);
1368 rectangle
->width
= surface
->width
;
1369 rectangle
->height
= surface
->height
;
1371 return CAIRO_STATUS_SUCCESS
;
1375 static cairo_status_t
1376 _directfb_allocate_font_cache (IDirectFB
*dfb
,
1377 int width
, int height
,
1378 cairo_directfb_font_cache_t
**out
)
1380 cairo_directfb_font_cache_t
*cache
;
1381 cairo_status_t status
;
1383 cache
= calloc (1, sizeof (cairo_directfb_font_cache_t
));
1385 return _cairo_error (CAIRO_STATUS_NO_MEMORY
);
1388 status
= _directfb_buffer_surface_create (dfb
,
1389 _directfb_argb_font
? DSPF_ARGB
: DSPF_A8
,
1391 &cache
->dfbsurface
);
1397 cache
->width
= width
;
1398 cache
->height
= height
;
1400 return CAIRO_STATUS_SUCCESS
;
1404 _directfb_destroy_font_cache (cairo_directfb_font_cache_t
*cache
)
1406 cache
->dfbsurface
->Release (cache
->dfbsurface
);
1410 static cairo_status_t
1411 _directfb_acquire_font_cache (cairo_directfb_surface_t
*surface
,
1412 cairo_scaled_font_t
*scaled_font
,
1413 const cairo_glyph_t
*glyphs
,
1415 cairo_directfb_font_cache_t
**ret_cache
,
1416 DFBRectangle
*rects
,
1420 cairo_status_t status
;
1421 cairo_scaled_glyph_t
*chars
[num_glyphs
];
1423 cairo_directfb_font_cache_t
*cache
= NULL
;
1431 D_DEBUG_AT (CairoDFB_Font
, "%s( %p [%d] )\n", __FUNCTION__
, glyphs
, num_glyphs
);
1433 _cairo_scaled_font_freeze_cache (scaled_font
);
1435 if (scaled_font
->surface_private
) {
1436 cache
= scaled_font
->surface_private
;
1441 for (i
= 0; i
< num_glyphs
; i
++) {
1442 cairo_scaled_glyph_t
*scaled_glyph
;
1443 cairo_image_surface_t
*img
;
1445 D_DEBUG_AT (CairoDFB_Font
, " -> [%2d] = %4lu\n", i
, glyphs
[i
].index
);
1447 status
= _cairo_scaled_glyph_lookup (scaled_font
, glyphs
[i
].index
,
1448 CAIRO_SCALED_GLYPH_INFO_SURFACE
,
1451 _cairo_scaled_font_thaw_cache (scaled_font
);
1455 img
= scaled_glyph
->surface
;
1456 switch (img
->format
) {
1457 case CAIRO_FORMAT_A1
:
1458 case CAIRO_FORMAT_A8
:
1459 case CAIRO_FORMAT_ARGB32
:
1462 D_DEBUG_AT (CairoDFB_Font
,
1463 " -> Unsupported font format %d!\n", img
->format
);
1464 _cairo_scaled_font_thaw_cache (scaled_font
);
1465 return CAIRO_INT_STATUS_UNSUPPORTED
;
1468 points
[n
].x
= _cairo_lround (glyphs
[i
].x
- img
->base
.device_transform
.x0
);
1469 points
[n
].y
= _cairo_lround (glyphs
[i
].y
- img
->base
.device_transform
.y0
);
1471 // D_DEBUG_AT (CairoDFB_Font, " (%4d,%4d) [%2d]\n", points[n].x, points[n].y, n );
1473 if (points
[n
].x
>= surface
->width
||
1474 points
[n
].y
>= surface
->height
||
1475 points
[n
].x
+img
->width
<= 0 ||
1476 points
[n
].y
+img
->height
<= 0)
1481 if (scaled_glyph
->surface_private
== NULL
) {
1484 if (x
+img
->width
> 2048) {
1492 rects
[n
].w
= img
->width
;
1493 rects
[n
].h
= img
->height
;
1496 h
= MAX (h
, img
->height
);
1499 /* Remember glyph location */
1500 rect
= malloc (sizeof (DFBRectangle
));
1502 _cairo_scaled_font_thaw_cache (scaled_font
);
1503 return _cairo_error (CAIRO_STATUS_NO_MEMORY
);
1507 scaled_glyph
->surface_private
= rect
;
1508 chars
[num_chars
++] = scaled_glyph
;
1510 D_DEBUG_AT (CairoDFB_Font
, " -> loading at %4d,%2d <- rect %p, img %p, entry %p\n",
1511 rects
[n
].x
, rects
[n
].y
, rect
, scaled_glyph
->surface
, scaled_glyph
);
1513 rects
[n
] = *(DFBRectangle
*) scaled_glyph
->surface_private
;
1515 D_DEBUG_AT (CairoDFB_Font
, " -> exists at %4d,%2d\n", rects
[n
].x
, rects
[n
].y
);
1522 _cairo_scaled_font_thaw_cache (scaled_font
);
1523 return CAIRO_INT_STATUS_NOTHING_TO_DO
;
1530 /* XXX query maximum surface size */
1531 if (w
> 2048 || h
> 2048) {
1532 _cairo_scaled_font_thaw_cache (scaled_font
);
1533 return CAIRO_INT_STATUS_UNSUPPORTED
;
1537 if (cache
->width
< w
|| cache
->height
< h
) {
1538 cairo_directfb_font_cache_t
*new_cache
;
1540 w
= MAX (w
, cache
->width
);
1541 h
= MAX (h
, cache
->height
);
1543 D_DEBUG_AT (CairoDFB_Font
, " -> Reallocating font cache (%dx%d).\n", w
, h
);
1545 status
= _directfb_allocate_font_cache (surface
->dfb
,
1549 _cairo_scaled_font_thaw_cache (scaled_font
);
1553 new_cache
->dfbsurface
->Blit (new_cache
->dfbsurface
,
1554 cache
->dfbsurface
, NULL
, 0, 0);
1556 _directfb_destroy_font_cache (cache
);
1557 scaled_font
->surface_private
= cache
= new_cache
;
1560 D_DEBUG_AT (CairoDFB_Font
, " -> Allocating font cache (%dx%d).\n", w
, h
);
1562 status
= _directfb_allocate_font_cache (surface
->dfb
, w
, h
, &cache
);
1564 _cairo_scaled_font_thaw_cache (scaled_font
);
1568 scaled_font
->surface_backend
= &_cairo_directfb_surface_backend
;
1569 scaled_font
->surface_private
= cache
;
1573 unsigned char *data
;
1576 if (cache
->dfbsurface
->Lock (cache
->dfbsurface
,
1577 DSLF_WRITE
, (void *)&data
, &pitch
))
1579 _cairo_scaled_font_thaw_cache (scaled_font
);
1580 return _cairo_error (CAIRO_STATUS_NO_MEMORY
);
1583 D_DEBUG_AT (CairoDFB_Font
, " => %d chars to load, cache %dx%d\n", num_chars
, cache
->width
, cache
->height
);
1585 for (i
= 0; i
< num_chars
; i
++) {
1586 cairo_image_surface_t
*img
= chars
[i
]->surface
;
1587 DFBRectangle
*rect
= chars
[i
]->surface_private
;
1588 unsigned char *dst
= data
;
1592 D_DEBUG_AT (CairoDFB_Font
, " -> loading [%2d] <- rect %p, img %p, entry %p\n", i
, rect
, img
, chars
[i
]);
1596 D_DEBUG_AT (CairoDFB_Font
, " from %p\n", src
);
1598 dst
+= rect
->y
* pitch
+ (_directfb_argb_font
? (rect
->x
<<2) : rect
->x
);
1600 D_DEBUG_AT (CairoDFB_Font
, " to %4d,%2d (%p)\n", rect
->x
, rect
->y
, dst
);
1602 if (img
->format
== CAIRO_FORMAT_A1
) {
1603 for (h
= rect
->h
; h
; h
--) {
1604 if (_directfb_argb_font
) {
1605 for (j
= 0; j
< rect
->w
; j
++)
1606 ((uint32_t *) dst
)[j
] = (src
[j
>>3] & (1 << (j
&7))) ? 0xffffffff : 0;
1608 for (j
= 0; j
< rect
->w
; j
++)
1609 dst
[j
] = (src
[j
>>3] & (1 << (j
&7))) ? 0xff : 0;
1615 } else if (img
->format
== CAIRO_FORMAT_A8
) {
1616 for (h
= rect
->h
; h
; h
--) {
1617 if (_directfb_argb_font
) {
1618 for (j
= 0; j
< rect
->w
; j
++)
1619 ((uint32_t *) dst
)[j
] = src
[j
] * 0x01010101;
1621 direct_memcpy (dst
, src
, rect
->w
);
1627 } else { /* ARGB32 */
1628 for (h
= rect
->h
; h
; h
--) {
1629 if (_directfb_argb_font
) {
1630 direct_memcpy (dst
, src
, rect
->w
<<2);
1632 for (j
= 0; j
< rect
->w
; j
++)
1633 dst
[j
] = ((uint32_t *) src
)[j
] >> 24;
1642 cache
->dfbsurface
->Unlock (cache
->dfbsurface
);
1645 _cairo_scaled_font_thaw_cache (scaled_font
);
1650 D_DEBUG_AT (CairoDFB_Font
, " => cache %d,%d, %p [%d]\n", x
, y
, cache
, n
);
1655 return CAIRO_STATUS_SUCCESS
;
1659 _cairo_directfb_surface_scaled_font_fini (cairo_scaled_font_t
*scaled_font
)
1661 cairo_directfb_font_cache_t
*cache
= scaled_font
->surface_private
;
1663 D_DEBUG_AT (CairoDFB_Font
,
1664 "%s( scaled_font=%p ).\n", __FUNCTION__
, scaled_font
);
1666 if (cache
!= NULL
) {
1667 _directfb_destroy_font_cache (cache
);
1668 scaled_font
->surface_private
= NULL
;
1673 _cairo_directfb_surface_scaled_glyph_fini (cairo_scaled_glyph_t
*scaled_glyph
,
1674 cairo_scaled_font_t
*scaled_font
)
1676 D_DEBUG_AT (CairoDFB_Font
,
1677 "%s( scaled_glyph=%p, scaled_font=%p ).\n",
1678 __FUNCTION__
, scaled_glyph
, scaled_font
);
1680 if (scaled_glyph
->surface_private
!= NULL
) {
1681 free (scaled_glyph
->surface_private
);
1682 scaled_glyph
->surface_private
= NULL
;
1686 static cairo_int_status_t
1687 _cairo_directfb_surface_show_glyphs (void *abstract_dst
,
1688 cairo_operator_t op
,
1689 const cairo_pattern_t
*pattern
,
1690 cairo_glyph_t
*glyphs
,
1692 cairo_scaled_font_t
*scaled_font
,
1693 int *remaining_glyphs
,
1694 cairo_rectangle_int_t
*extents
)
1696 cairo_directfb_surface_t
*dst
= abstract_dst
;
1697 cairo_directfb_font_cache_t
*cache
;
1698 cairo_status_t status
;
1699 DFBSurfaceBlittingFlags flags
;
1700 DFBSurfaceBlendFunction sblend
;
1701 DFBSurfaceBlendFunction dblend
;
1702 DFBRectangle rects
[num_glyphs
];
1703 DFBPoint points
[num_glyphs
];
1705 const cairo_color_t
*color
;
1708 D_DEBUG_AT (CairoDFB_Font
,
1709 "%s( dst=%p, op=%d, pattern=%p, glyphs=%p, num_glyphs=%d, scaled_font=%p ).\n",
1710 __FUNCTION__
, dst
, op
, pattern
, glyphs
, num_glyphs
, scaled_font
);
1712 if (pattern
->type
!= CAIRO_PATTERN_TYPE_SOLID
)
1713 return CAIRO_INT_STATUS_UNSUPPORTED
;
1715 /* Fallback if we need to emulate clip regions */
1716 if (dst
->base
.clip
&&
1717 (dst
->base
.clip
->mode
!= CAIRO_CLIP_MODE_REGION
||
1718 dst
->base
.clip
->surface
!= NULL
))
1720 return CAIRO_INT_STATUS_UNSUPPORTED
;
1723 /* XXX Unbounded operators are not handled correctly */
1724 if (! _cairo_operator_bounded_by_mask (op
))
1725 return CAIRO_INT_STATUS_UNSUPPORTED
;
1726 if (! _cairo_operator_bounded_by_source (op
))
1727 return CAIRO_INT_STATUS_UNSUPPORTED
;
1729 if (! _directfb_get_operator (op
, &sblend
, &dblend
) ||
1730 sblend
== DSBF_DESTALPHA
|| sblend
== DSBF_INVDESTALPHA
)
1732 return CAIRO_INT_STATUS_UNSUPPORTED
;
1735 status
= _directfb_acquire_font_cache (dst
, scaled_font
, glyphs
, num_glyphs
,
1736 &cache
, &rects
[0], &points
[0], &num
);
1738 if (status
== CAIRO_INT_STATUS_NOTHING_TO_DO
)
1739 status
= CAIRO_STATUS_SUCCESS
;
1743 color
= &((cairo_solid_pattern_t
*) pattern
)->color
;
1745 flags
= DSBLIT_BLEND_ALPHACHANNEL
| DSBLIT_COLORIZE
;
1746 if (! CAIRO_COLOR_IS_OPAQUE (color
))
1747 flags
|= DSBLIT_BLEND_COLORALPHA
;
1749 if (!_directfb_argb_font
) {
1750 if (sblend
== DSBF_ONE
) {
1751 sblend
= DSBF_SRCALPHA
;
1752 if (dblend
== DSBF_ZERO
)
1753 dblend
= DSBF_INVSRCALPHA
;
1757 dst
->dfbsurface
->SetBlittingFlags (dst
->dfbsurface
, flags
);
1758 dst
->dfbsurface
->SetSrcBlendFunction (dst
->dfbsurface
, sblend
);
1759 dst
->dfbsurface
->SetDstBlendFunction (dst
->dfbsurface
, dblend
);
1760 if (dst
->blit_premultiplied
) {
1761 dst
->dfbsurface
->SetColor (dst
->dfbsurface
,
1762 color
->red_short
>> 8,
1763 color
->green_short
>> 8,
1764 color
->blue_short
>> 8,
1765 color
->alpha_short
>> 8);
1767 dst
->dfbsurface
->SetColor (dst
->dfbsurface
,
1769 color
->green
* 0xff,
1771 color
->alpha
* 0xff);
1774 D_DEBUG_AT (CairoDFB_Font
, "Running BatchBlit().\n");
1776 RUN_CLIPPED (dst
, NULL
,
1777 dst
->dfbsurface
->BatchBlit (dst
->dfbsurface
,
1778 cache
->dfbsurface
, rects
, points
, num
));
1780 return CAIRO_STATUS_SUCCESS
;
1782 #endif /* DFB_SHOW_GLYPHS */
1786 _cairo_directfb_surface_is_similar (void *surface_a
, void *surface_b
, cairo_content_t content
)
1788 cairo_directfb_surface_t
*a
= (cairo_directfb_surface_t
*) surface_a
;
1789 cairo_directfb_surface_t
*b
= (cairo_directfb_surface_t
*) surface_b
;
1791 return a
->dfb
== b
->dfb
;
1794 static cairo_surface_backend_t
1795 _cairo_directfb_surface_backend
= {
1796 CAIRO_SURFACE_TYPE_DIRECTFB
, /*type*/
1797 _cairo_directfb_surface_create_similar
,/*create_similar*/
1798 _cairo_directfb_surface_finish
, /*finish*/
1799 _cairo_directfb_surface_acquire_source_image
,/*acquire_source_image*/
1800 _cairo_directfb_surface_release_source_image
,/*release_source_image*/
1801 _cairo_directfb_surface_acquire_dest_image
,/*acquire_dest_image*/
1802 _cairo_directfb_surface_release_dest_image
,/*release_dest_image*/
1803 _cairo_directfb_surface_clone_similar
,/*clone_similar*/
1805 _cairo_directfb_surface_composite
,/*composite*/
1810 _cairo_directfb_surface_fill_rectangles
,/*fill_rectangles*/
1812 NULL
,/*fill_rectangles*/
1814 #if DFB_COMPOSITE_TRAPEZOIDS
1815 _cairo_directfb_surface_composite_trapezoids
,/*composite_trapezoids*/
1817 NULL
,/*composite_trapezoids*/
1819 NULL
, /* create_span_renderer */
1820 NULL
, /* check_span_renderer */
1821 NULL
, /* copy_page */
1822 NULL
, /* show_page */
1823 _cairo_directfb_surface_set_clip_region
,/* set_clip_region */
1824 NULL
, /* intersect_clip_path */
1825 _cairo_directfb_abstract_surface_get_extents
,/* get_extents */
1826 NULL
, /* old_show_glyphs */
1827 NULL
, /* get_font_options */
1829 NULL
, /* mark_dirty_rectangle */
1831 _cairo_directfb_surface_scaled_font_fini
,/* scaled_font_fini */
1832 _cairo_directfb_surface_scaled_glyph_fini
,/* scaled_glyph_fini */
1842 _cairo_directfb_surface_show_glyphs
,/* show_glyphs */
1844 NULL
, /* show_glyphs */
1846 NULL
, /* snapshot */
1847 _cairo_directfb_surface_is_similar
,
1853 cairo_directfb_surface_backend_init (IDirectFB
*dfb
)
1855 static int done
= 0;
1860 if (getenv ("CAIRO_DIRECTFB_NO_ACCEL")) {
1862 _cairo_directfb_surface_backend
.fill_rectangles
= NULL
;
1865 _cairo_directfb_surface_backend
.composite
= NULL
;
1867 #if DFB_COMPOSITE_TRAPEZOIDS
1868 _cairo_directfb_surface_backend
.composite_trapezoids
= NULL
;
1871 _cairo_directfb_surface_backend
.scaled_font_fini
= NULL
;
1872 _cairo_directfb_surface_backend
.scaled_glyph_fini
= NULL
;
1873 _cairo_directfb_surface_backend
.show_glyphs
= NULL
;
1875 D_DEBUG_AT (CairoDFB_Surface
, "Acceleration disabled.\n");
1877 DFBGraphicsDeviceDescription dsc
;
1879 dfb
->GetDeviceDescription (dfb
, &dsc
);
1882 // if (!(dsc.acceleration_mask & DFXL_BLIT))
1883 // _cairo_directfb_surface_backend.composite = NULL;
1886 #if DFB_COMPOSITE_TRAPEZOIDS
1887 // if (!(dsc.acceleration_mask & DFXL_TEXTRIANGLES))
1888 // _cairo_directfb_surface_backend.composite_trapezoids = NULL;
1892 if (getenv ("CAIRO_DIRECTFB_ARGB_FONT")) {
1893 _directfb_argb_font
= 1;
1894 D_DEBUG_AT (CairoDFB_Surface
, "Using ARGB fonts.\n");
1901 cairo_directfb_surface_create (IDirectFB
*dfb
, IDirectFBSurface
*dfbsurface
)
1903 cairo_directfb_surface_t
*surface
;
1904 DFBSurfacePixelFormat format
;
1905 DFBSurfaceCapabilities caps
;
1907 D_ASSERT (dfb
!= NULL
);
1908 D_ASSERT (dfbsurface
!= NULL
);
1910 cairo_directfb_surface_backend_init (dfb
);
1912 surface
= calloc (1, sizeof (cairo_directfb_surface_t
));
1913 if (surface
== NULL
)
1914 return _cairo_surface_create_in_error (_cairo_error (CAIRO_STATUS_NO_MEMORY
));
1916 dfbsurface
->AddRef (dfbsurface
);
1917 dfbsurface
->GetPixelFormat (dfbsurface
, &format
);
1918 dfbsurface
->GetSize (dfbsurface
, &surface
->width
, &surface
->height
);
1920 surface
->dfbsurface
= dfbsurface
;
1921 surface
->format
= _directfb_to_cairo_format (format
);
1922 surface
->content
= _directfb_format_to_content (format
);
1924 dfbsurface
->GetCapabilities (dfbsurface
, &caps
);
1925 if (caps
& DSCAPS_PREMULTIPLIED
)
1926 surface
->blit_premultiplied
= TRUE
;
1928 _cairo_surface_init (&surface
->base
,
1929 &_cairo_directfb_surface_backend
,
1932 return &surface
->base
;