1 /* cairo - a vector graphics library with display and print output
2 *
3 * Copyright © 2003 University of Southern California
4 *
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.
12 *
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., 51 Franklin Street, Suite 500, Boston, MA 02110-1335, USA
16 * You should have received a copy of the MPL along with this library
17 * in the file COPYING-MPL-1.1
18 *
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/
23 *
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.
27 *
28 * The Original Code is the cairo graphics library.
29 *
30 * The Initial Developer of the Original Code is University of Southern
31 * California.
32 *
33 * Contributor(s):
34 * Michael Emmel <mike.emmel@gmail.com>
35 * Claudio Ciccani <klan@users.sf.net>
36 */
37
38 #include "cairoint.h"
39 #include "cairo-directfb.h"
40
41 #include "cairo-clip-private.h"
42 #include "cairo-error-private.h"
43
44 #include <pixman.h>
45
46 #include <directfb.h>
47 #include <direct/types.h>
48 #include <direct/debug.h>
49 #include <direct/memcpy.h>
50 #include <direct/util.h>
51
52 /*
53 * Rectangle works fine.
54 * Bugs 361377, 359553, 359243 in Gnome BTS are caused
55 * by GDK/DirectFB, not by Cairo/DirectFB.
56 */
57 #define DFB_RECTANGLES 1
58
59 /*
60 * Composite works fine.
61 */
62 #define DFB_COMPOSITE 1
63
64 /*
65 * CompositeTrapezoids works (without antialiasing).
66 */
67 #define DFB_COMPOSITE_TRAPEZOIDS 1
68
69 /*
70 * ShowGlyphs works fine.
71 */
72 #define DFB_SHOW_GLYPHS 1
73
74 #define PIXMAN_invalid (pixman_format_code_t) 0
75
76
77 D_DEBUG_DOMAIN (CairoDFB_Acquire, "CairoDFB/Acquire", "Cairo DirectFB Acquire");
78 D_DEBUG_DOMAIN (CairoDFB_Clip, "CairoDFB/Clip", "Cairo DirectFB Clipping");
79 D_DEBUG_DOMAIN (CairoDFB_Font, "CairoDFB/Font", "Cairo DirectFB Font Rendering");
80 D_DEBUG_DOMAIN (CairoDFB_Render, "CairoDFB/Render", "Cairo DirectFB Rendering");
81 D_DEBUG_DOMAIN (CairoDFB_Surface, "CairoDFB/Surface", "Cairo DirectFB Surface");
82
83 /*****************************************************************************/
84
85 typedef struct _cairo_directfb_surface {
86 cairo_surface_t base;
87
88 pixman_format_code_t pixman_format;
89 cairo_bool_t supported_destination;
90
91 IDirectFB *dfb;
92 IDirectFBSurface *dfbsurface;
93 IDirectFBSurface *tmpsurface;
94 pixman_format_code_t tmpformat;
95
96 int width;
97 int height;
98
99 unsigned local : 1;
100 unsigned blit_premultiplied : 1;
101 } cairo_directfb_surface_t;
102
103
104 typedef struct _cairo_directfb_font_cache {
105 IDirectFB *dfb;
106 IDirectFBSurface *dfbsurface;
107
108 int width;
109 int height;
110
111 /* coordinates within the surface
112 * of the last loaded glyph */
113 int x;
114 int y;
115 } cairo_directfb_font_cache_t;
116
117 static cairo_surface_backend_t _cairo_directfb_surface_backend;
118
119 /*****************************************************************************/
120
121 static int _directfb_argb_font = 0;
122
123 /*****************************************************************************/
124
125 #define RUN_CLIPPED(surface, clip_region, clip, func) {\
126 if ((clip_region) != NULL) {\
127 int n_clips = cairo_region_num_rectangles (clip_region), n; \
128 for (n = 0; n < n_clips; n++) {\
129 if (clip) {\
130 DFBRegion reg, *cli = (clip); \
131 cairo_rectangle_int_t rect; \
132 cairo_region_get_rectangle (clip_region, n, &rect); \
133 reg.x1 = rect.x; \
134 reg.y1 = rect.y; \
135 reg.x2 = rect.x + rect.width - 1; \
136 reg.y2 = rect.y + rect.height - 1; \
137 if (reg.x2 < cli->x1 || reg.y2 < cli->y1 ||\
138 reg.x1 > cli->x2 || reg.y1 > cli->y2)\
139 continue;\
140 if (reg.x1 < cli->x1)\
141 reg.x1 = cli->x1;\
142 if (reg.y1 < cli->y1)\
143 reg.y1 = cli->y1;\
144 if (reg.x2 > cli->x2)\
145 reg.x2 = cli->x2;\
146 if (reg.y2 > cli->y2)\
147 reg.y2 = cli->y2;\
148 (surface)->dfbsurface->SetClip ((surface)->dfbsurface, ®);\
149 } else {\
150 DFBRegion reg; \
151 cairo_rectangle_int_t rect; \
152 cairo_region_get_rectangle (clip_region, n, &rect); \
153 reg.x1 = rect.x; \
154 reg.y1 = rect.y; \
155 reg.x2 = rect.x + rect.width - 1; \
156 reg.y2 = rect.y + rect.height - 1; \
157 (surface)->dfbsurface->SetClip ((surface)->dfbsurface, ®); \
158 }\
159 func;\
160 }\
161 } else {\
162 (surface)->dfbsurface->SetClip ((surface)->dfbsurface, clip);\
163 func;\
164 }\
165 }
166
167 #define TRANSFORM_POINT2X(m, x, y, ret_x, ret_y) do { \
168 double _x = (x); \
169 double _y = (y); \
170 (ret_x) = (_x * (m).xx + (m).x0); \
171 (ret_y) = (_y * (m).yy + (m).y0); \
172 } while (0)
173
174 #define TRANSFORM_POINT3X(m, x, y, ret_x, ret_y) do { \
175 double _x = (x); \
176 double _y = (y); \
177 (ret_x) = (_x * (m).xx + _y * (m).xy + (m).x0); \
178 (ret_y) = (_x * (m).yx + _y * (m).yy + (m).y0); \
179 } while (0)
180
181 /* XXX: A1 has a different bits ordering in cairo.
182 * Probably we should drop it.
183 */
184
185 static cairo_content_t
_directfb_format_to_content(DFBSurfacePixelFormat format)186 _directfb_format_to_content (DFBSurfacePixelFormat format)
187 {
188 if (DFB_PIXELFORMAT_HAS_ALPHA (format)) {
189 if (DFB_COLOR_BITS_PER_PIXEL (format))
190 return CAIRO_CONTENT_COLOR_ALPHA;
191
192 return CAIRO_CONTENT_ALPHA;
193 }
194
195 return CAIRO_CONTENT_COLOR;
196 }
197
198 static inline DFBSurfacePixelFormat
_cairo_to_directfb_format(cairo_format_t format)199 _cairo_to_directfb_format (cairo_format_t format)
200 {
201 switch (format) {
202 case CAIRO_FORMAT_RGB24:
203 return DSPF_RGB32;
204 case CAIRO_FORMAT_ARGB32:
205 return DSPF_ARGB;
206 case CAIRO_FORMAT_A8:
207 return DSPF_A8;
208 case CAIRO_FORMAT_A1:
209 return DSPF_A1;
210 default:
211 break;
212 }
213
214 return -1;
215 }
216
217 static inline pixman_format_code_t
_directfb_to_pixman_format(DFBSurfacePixelFormat format)218 _directfb_to_pixman_format (DFBSurfacePixelFormat format)
219 {
220 switch (format) {
221 case DSPF_UNKNOWN: return PIXMAN_invalid;
222 case DSPF_ARGB1555: return PIXMAN_a1r5g5b5;
223 case DSPF_RGB16: return PIXMAN_r5g6b5;
224 case DSPF_RGB24: return PIXMAN_r8g8b8;
225 case DSPF_RGB32: return PIXMAN_x8r8g8b8;
226 case DSPF_ARGB: return PIXMAN_a8r8g8b8;
227 case DSPF_A8: return PIXMAN_a8;
228 case DSPF_YUY2: return PIXMAN_yuy2;
229 case DSPF_RGB332: return PIXMAN_r3g3b2;
230 case DSPF_UYVY: return PIXMAN_invalid;
231 case DSPF_I420: return PIXMAN_invalid;
232 case DSPF_YV12: return PIXMAN_yv12;
233 case DSPF_LUT8: return PIXMAN_invalid;
234 case DSPF_ALUT44: return PIXMAN_invalid;
235 case DSPF_AiRGB: return PIXMAN_invalid;
236 case DSPF_A1: return PIXMAN_a1; /* bit reversed, oops */
237 case DSPF_NV12: return PIXMAN_invalid;
238 case DSPF_NV16: return PIXMAN_invalid;
239 case DSPF_ARGB2554: return PIXMAN_invalid;
240 case DSPF_ARGB4444: return PIXMAN_a4r4g4b4;
241 case DSPF_NV21: return PIXMAN_invalid;
242 case DSPF_AYUV: return PIXMAN_invalid;
243 case DSPF_A4: return PIXMAN_a4;
244 case DSPF_ARGB1666: return PIXMAN_invalid;
245 case DSPF_ARGB6666: return PIXMAN_invalid;
246 case DSPF_RGB18: return PIXMAN_invalid;
247 case DSPF_LUT2: return PIXMAN_invalid;
248 case DSPF_RGB444: return PIXMAN_x4r4g4b4;
249 case DSPF_RGB555: return PIXMAN_x1r5g5b5;
250 #if DFB_NUM_PIXELFORMATS >= 29
251 case DSPF_BGR555: return PIXMAN_x1b5g5r5;
252 #endif
253 }
254 return PIXMAN_invalid;
255 }
256
257 static inline DFBSurfacePixelFormat
_directfb_from_pixman_format(pixman_format_code_t format)258 _directfb_from_pixman_format (pixman_format_code_t format)
259 {
260 switch ((int) format) {
261 case PIXMAN_a1r5g5b5: return DSPF_ARGB1555;
262 case PIXMAN_r5g6b5: return DSPF_RGB16;
263 case PIXMAN_r8g8b8: return DSPF_RGB24;
264 case PIXMAN_x8r8g8b8: return DSPF_RGB32;
265 case PIXMAN_a8r8g8b8: return DSPF_ARGB;
266 case PIXMAN_a8: return DSPF_A8;
267 case PIXMAN_yuy2: return DSPF_YUY2;
268 case PIXMAN_r3g3b2: return DSPF_RGB332;
269 case PIXMAN_yv12: return DSPF_YV12;
270 case PIXMAN_a1: return DSPF_A1; /* bit reversed, oops */
271 case PIXMAN_a4r4g4b4: return DSPF_ARGB4444;
272 case PIXMAN_a4: return DSPF_A4;
273 case PIXMAN_x4r4g4b4: return DSPF_RGB444;
274 case PIXMAN_x1r5g5b5: return DSPF_RGB555;
275 #if DFB_NUM_PIXELFORMATS >= 29
276 case PIXMAN_x1b5g5r5: return DSPF_BGR555;
277 #endif
278 default: return 0;
279 }
280 }
281
282 static cairo_bool_t
_directfb_get_operator(cairo_operator_t operator,DFBSurfaceBlendFunction * ret_srcblend,DFBSurfaceBlendFunction * ret_dstblend)283 _directfb_get_operator (cairo_operator_t operator,
284 DFBSurfaceBlendFunction *ret_srcblend,
285 DFBSurfaceBlendFunction *ret_dstblend)
286 {
287 DFBSurfaceBlendFunction srcblend = DSBF_ONE;
288 DFBSurfaceBlendFunction dstblend = DSBF_ZERO;
289
290 switch (operator) {
291 case CAIRO_OPERATOR_CLEAR:
292 srcblend = DSBF_ZERO;
293 dstblend = DSBF_ZERO;
294 break;
295 case CAIRO_OPERATOR_SOURCE:
296 srcblend = DSBF_ONE;
297 dstblend = DSBF_ZERO;
298 break;
299 case CAIRO_OPERATOR_OVER:
300 srcblend = DSBF_ONE;
301 dstblend = DSBF_INVSRCALPHA;
302 break;
303 case CAIRO_OPERATOR_IN:
304 srcblend = DSBF_DESTALPHA;
305 dstblend = DSBF_ZERO;
306 break;
307 case CAIRO_OPERATOR_OUT:
308 srcblend = DSBF_INVDESTALPHA;
309 dstblend = DSBF_ZERO;
310 break;
311 case CAIRO_OPERATOR_ATOP:
312 srcblend = DSBF_DESTALPHA;
313 dstblend = DSBF_INVSRCALPHA;
314 break;
315 case CAIRO_OPERATOR_DEST:
316 srcblend = DSBF_ZERO;
317 dstblend = DSBF_ONE;
318 break;
319 case CAIRO_OPERATOR_DEST_OVER:
320 srcblend = DSBF_INVDESTALPHA;
321 dstblend = DSBF_ONE;
322 break;
323 case CAIRO_OPERATOR_DEST_IN:
324 srcblend = DSBF_ZERO;
325 dstblend = DSBF_SRCALPHA;
326 break;
327 case CAIRO_OPERATOR_DEST_OUT:
328 srcblend = DSBF_ZERO;
329 dstblend = DSBF_INVSRCALPHA;
330 break;
331 case CAIRO_OPERATOR_DEST_ATOP:
332 srcblend = DSBF_INVDESTALPHA;
333 dstblend = DSBF_SRCALPHA;
334 break;
335 case CAIRO_OPERATOR_XOR:
336 srcblend = DSBF_INVDESTALPHA;
337 dstblend = DSBF_INVSRCALPHA;
338 break;
339 case CAIRO_OPERATOR_ADD:
340 srcblend = DSBF_ONE;
341 dstblend = DSBF_ONE;
342 break;
343 case CAIRO_OPERATOR_SATURATE:
344 /* XXX This does not work. */
345 #if 0
346 srcblend = DSBF_SRCALPHASAT;
347 dstblend = DSBF_ONE;
348 break;
349 #endif
350 case CAIRO_OPERATOR_MULTIPLY:
351 case CAIRO_OPERATOR_SCREEN:
352 case CAIRO_OPERATOR_OVERLAY:
353 case CAIRO_OPERATOR_DARKEN:
354 case CAIRO_OPERATOR_LIGHTEN:
355 case CAIRO_OPERATOR_COLOR_DODGE:
356 case CAIRO_OPERATOR_COLOR_BURN:
357 case CAIRO_OPERATOR_HARD_LIGHT:
358 case CAIRO_OPERATOR_SOFT_LIGHT:
359 case CAIRO_OPERATOR_DIFFERENCE:
360 case CAIRO_OPERATOR_EXCLUSION:
361 case CAIRO_OPERATOR_HSL_HUE:
362 case CAIRO_OPERATOR_HSL_SATURATION:
363 case CAIRO_OPERATOR_HSL_COLOR:
364 case CAIRO_OPERATOR_HSL_LUMINOSITY:
365 default:
366 return FALSE;
367 }
368
369 *ret_srcblend = srcblend;
370 *ret_dstblend = dstblend;
371
372 return TRUE;
373 }
374
375 static cairo_status_t
_directfb_buffer_surface_create(IDirectFB * dfb,DFBSurfacePixelFormat format,int width,int height,IDirectFBSurface ** out)376 _directfb_buffer_surface_create (IDirectFB *dfb,
377 DFBSurfacePixelFormat format,
378 int width,
379 int height,
380 IDirectFBSurface **out)
381 {
382 IDirectFBSurface *buffer;
383 DFBSurfaceDescription dsc;
384 DFBResult ret;
385
386 dsc.flags = DSDESC_WIDTH | DSDESC_HEIGHT | DSDESC_PIXELFORMAT;
387 dsc.caps = DSCAPS_PREMULTIPLIED;
388 dsc.width = width;
389 dsc.height = height;
390 dsc.pixelformat = format;
391
392 ret = dfb->CreateSurface (dfb, &dsc, &buffer);
393 if (ret) {
394 DirectFBError ("IDirectFB::CreateSurface()", ret);
395 return _cairo_error (CAIRO_STATUS_NO_MEMORY);
396 }
397
398 *out = buffer;
399 return CAIRO_STATUS_SUCCESS;
400 }
401
402 static cairo_status_t
_directfb_acquire_surface(cairo_directfb_surface_t * surface,cairo_rectangle_int_t * intrest_rec,cairo_image_surface_t ** image_out,cairo_rectangle_int_t * image_rect_out,void ** image_extra,DFBSurfaceLockFlags lock_flags)403 _directfb_acquire_surface (cairo_directfb_surface_t *surface,
404 cairo_rectangle_int_t *intrest_rec,
405 cairo_image_surface_t **image_out,
406 cairo_rectangle_int_t *image_rect_out,
407 void **image_extra,
408 DFBSurfaceLockFlags lock_flags)
409 {
410 IDirectFBSurface *buffer = NULL;
411 DFBRectangle source_rect;
412 cairo_surface_t *image;
413 pixman_image_t *pixman_image;
414 pixman_format_code_t pixman_format;
415 cairo_status_t status;
416 void *data;
417 int pitch;
418
419 if (surface->pixman_format == PIXMAN_invalid) {
420 if (intrest_rec != NULL) {
421 source_rect.x = intrest_rec->x;
422 source_rect.y = intrest_rec->y;
423 source_rect.w = intrest_rec->width;
424 source_rect.h = intrest_rec->height;
425 } else {
426 source_rect.x = 0;
427 source_rect.y = 0;
428 surface->dfbsurface->GetSize (surface->dfbsurface,
429 &source_rect.w, &source_rect.h);
430 }
431
432 if (surface->tmpsurface != NULL) {
433 int w, h;
434
435 surface->tmpsurface->GetSize (surface->tmpsurface, &w, &h);
436 if (w < source_rect.w || h < source_rect.h) {
437 surface->tmpsurface->Release (surface->tmpsurface);
438 surface->tmpsurface = NULL;
439 surface->tmpformat = PIXMAN_invalid;
440 }
441 }
442
443 if (surface->tmpsurface == NULL) {
444 DFBSurfacePixelFormat format;
445
446 D_DEBUG_AT (CairoDFB_Acquire, "Allocating buffer for surface %p.\n", surface);
447
448 format = _cairo_to_directfb_format (_cairo_format_from_content (surface->base.content));
449 status =
450 _directfb_buffer_surface_create (surface->dfb, format,
451 source_rect.w, source_rect.h,
452 &surface->tmpsurface);
453 if (unlikely (status))
454 goto ERROR;
455
456 surface->tmpformat = _directfb_to_pixman_format (format);
457 }
458 buffer = surface->tmpsurface;
459 pixman_format = surface->tmpformat;
460
461
462 /* surface->dfbsurface->GetCapabilities (surface->dfbsurface, &caps);
463 DFBSurfaceCapabilities caps;
464 if (caps & DSCAPS_FLIPPING) {
465 DFBRegion region = { .x1 = source_rect.x, .y1 = source_rect.y,
466 .x2 = source_rect.x + source_rect.w - 1,
467 .y2 = source_rect.y + source_rect.h - 1 };
468 surface->dfbsurface->Flip (surface->dfbsurface, ®ion, DSFLIP_BLIT);
469 } */
470 buffer->Blit (buffer, surface->dfbsurface, &source_rect, 0, 0);
471 } else {
472 /*might be a subsurface get the offset*/
473 surface->dfbsurface->GetVisibleRectangle (surface->dfbsurface, &source_rect);
474 pixman_format = surface->pixman_format;
475 buffer = surface->dfbsurface;
476 }
477
478 if (buffer->Lock (buffer, lock_flags, &data, &pitch)) {
479 D_DEBUG_AT (CairoDFB_Acquire, "Couldn't lock surface!\n");
480 status = _cairo_error (CAIRO_STATUS_NO_MEMORY);
481 goto ERROR;
482 }
483
484 pixman_image = pixman_image_create_bits (pixman_format,
485 source_rect.w, source_rect.h,
486 data, pitch);
487 if (pixman_image == NULL) {
488 status = _cairo_error (CAIRO_STATUS_NO_MEMORY);
489 goto ERROR;
490 }
491
492 image = _cairo_image_surface_create_for_pixman_image (pixman_image,
493 pixman_format);
494 status = image->status;
495 if (status)
496 goto ERROR;
497
498 if (image_rect_out) {
499 image_rect_out->x = source_rect.x;
500 image_rect_out->y = source_rect.y;
501 image_rect_out->width = source_rect.w;
502 image_rect_out->height = source_rect.h;
503 } else {
504 /* lock for read */
505 /* might be a subsurface */
506 if (buffer == surface->dfbsurface) {
507 cairo_surface_set_device_offset (image,
508 source_rect.x, source_rect.y);
509 }
510 }
511
512 *image_extra = buffer;
513 *image_out = (cairo_image_surface_t *) image;
514 return CAIRO_STATUS_SUCCESS;
515
516 ERROR:
517 if (buffer) {
518 buffer->Unlock (buffer);
519 if (buffer != surface->dfbsurface)
520 buffer->Release (buffer);
521 }
522 return status;
523 }
524
525 static cairo_surface_t *
_cairo_directfb_surface_create_internal(IDirectFB * dfb,DFBSurfacePixelFormat format,cairo_content_t content,int width,int height)526 _cairo_directfb_surface_create_internal (IDirectFB *dfb,
527 DFBSurfacePixelFormat format,
528 cairo_content_t content,
529 int width,
530 int height)
531 {
532 cairo_directfb_surface_t *surface;
533 cairo_status_t status;
534
535 surface = calloc (1, sizeof (cairo_directfb_surface_t));
536 if (unlikely (surface == NULL))
537 return _cairo_surface_create_in_error (_cairo_error (CAIRO_STATUS_NO_MEMORY));
538
539 surface->dfb = dfb;
540
541 if (width < 8 || height < 8) {
542 IDirectFBSurface *tmp;
543 DFBRectangle rect = { .x=0, .y=0, .w=width, .h=height };
544
545 /* Some cards (e.g. Matrox) don't support surfaces smaller than 8x8 */
546 status = _directfb_buffer_surface_create (dfb, format,
547 MAX (width, 8), MAX (height, 8),
548 &tmp);
549 if (status) {
550 free (surface);
551 return _cairo_surface_create_in_error (status);
552 }
553
554 tmp->GetSubSurface (tmp, &rect, &surface->dfbsurface);
555 tmp->Release (tmp);
556 } else {
557 status = _directfb_buffer_surface_create (dfb, format,
558 width, height,
559 &surface->dfbsurface);
560 if (status) {
561 free (surface);
562 return _cairo_surface_create_in_error (status);
563 }
564 }
565
566 _cairo_surface_init (&surface->base,
567 &_cairo_directfb_surface_backend,
568 NULL, /* device */
569 content);
570 surface->pixman_format = _directfb_to_pixman_format (format);
571 surface->supported_destination = pixman_format_supported_destination (surface->pixman_format);
572
573 surface->width = width;
574 surface->height = height;
575 surface->local = TRUE;
576 surface->blit_premultiplied = TRUE;
577
578 return &surface->base;
579 }
580
581 static cairo_surface_t *
_cairo_directfb_surface_create_similar(void * abstract_src,cairo_content_t content,int width,int height)582 _cairo_directfb_surface_create_similar (void *abstract_src,
583 cairo_content_t content,
584 int width,
585 int height)
586 {
587 cairo_directfb_surface_t *other = abstract_src;
588 DFBSurfacePixelFormat format;
589
590 D_DEBUG_AT (CairoDFB_Surface,
591 "%s( src=%p, content=0x%x, width=%d, height=%d).\n",
592 __FUNCTION__, other, content, width, height);
593
594 width = (width <= 0) ? 1 : width;
595 height = (height<= 0) ? 1 : height;
596
597 format = _cairo_to_directfb_format (_cairo_format_from_content (content));
598 return _cairo_directfb_surface_create_internal (other->dfb, format,
599 content, width, height);
600 }
601
602 static cairo_status_t
_cairo_directfb_surface_finish(void * data)603 _cairo_directfb_surface_finish (void *data)
604 {
605 cairo_directfb_surface_t *surface = (cairo_directfb_surface_t *)data;
606
607 D_DEBUG_AT (CairoDFB_Surface, "%s( surface=%p ).\n", __FUNCTION__, surface);
608
609 if (surface->tmpsurface) {
610 surface->tmpsurface->Release (surface->tmpsurface);
611 surface->tmpsurface = NULL;
612 }
613
614 if (surface->dfbsurface) {
615 surface->dfbsurface->Release (surface->dfbsurface);
616 surface->dfbsurface = NULL;
617 }
618
619 if (surface->dfb)
620 surface->dfb = NULL;
621
622 return CAIRO_STATUS_SUCCESS;
623 }
624
625 static cairo_status_t
_cairo_directfb_surface_acquire_source_image(void * abstract_surface,cairo_image_surface_t ** image_out,void ** image_extra)626 _cairo_directfb_surface_acquire_source_image (void *abstract_surface,
627 cairo_image_surface_t **image_out,
628 void **image_extra)
629 {
630 cairo_directfb_surface_t *surface = abstract_surface;
631
632 D_DEBUG_AT (CairoDFB_Acquire,
633 "%s( surface=%p ).\n", __FUNCTION__, surface);
634
635 return _directfb_acquire_surface (surface, NULL, image_out,
636 NULL, image_extra, DSLF_READ);
637 }
638
639 static void
_cairo_directfb_surface_release_source_image(void * abstract_surface,cairo_image_surface_t * image,void * image_extra)640 _cairo_directfb_surface_release_source_image (void *abstract_surface,
641 cairo_image_surface_t *image,
642 void *image_extra)
643 {
644 IDirectFBSurface *buffer = image_extra;
645
646 D_DEBUG_AT (CairoDFB_Acquire,
647 "%s( release=%p ).\n", __FUNCTION__, abstract_surface);
648
649 buffer->Unlock (buffer);
650
651 cairo_surface_destroy (&image->base);
652 }
653
654 static cairo_status_t
_cairo_directfb_surface_acquire_dest_image(void * abstract_surface,cairo_rectangle_int_t * interest_rect,cairo_image_surface_t ** image_out,cairo_rectangle_int_t * image_rect_out,void ** image_extra)655 _cairo_directfb_surface_acquire_dest_image (void *abstract_surface,
656 cairo_rectangle_int_t *interest_rect,
657 cairo_image_surface_t **image_out,
658 cairo_rectangle_int_t *image_rect_out,
659 void **image_extra)
660 {
661 cairo_directfb_surface_t *surface = abstract_surface;
662
663 D_DEBUG_AT (CairoDFB_Acquire,
664 "%s( surface=%p (%dx%d), interest_rect={ %u %u %u %u } ).\n",
665 __FUNCTION__, surface, surface->width, surface->height,
666 interest_rect ? interest_rect->x : 0,
667 interest_rect ? interest_rect->y : 0,
668 interest_rect ? interest_rect->width : (unsigned) surface->width,
669 interest_rect ? interest_rect->height : (unsigned) surface->height);
670
671 return _directfb_acquire_surface (surface, interest_rect, image_out,
672 image_rect_out, image_extra,
673 DSLF_READ | DSLF_WRITE);
674 }
675
676 static void
_cairo_directfb_surface_release_dest_image(void * abstract_surface,cairo_rectangle_int_t * interest_rect,cairo_image_surface_t * image,cairo_rectangle_int_t * image_rect,void * image_extra)677 _cairo_directfb_surface_release_dest_image (void *abstract_surface,
678 cairo_rectangle_int_t *interest_rect,
679 cairo_image_surface_t *image,
680 cairo_rectangle_int_t *image_rect,
681 void *image_extra)
682 {
683 cairo_directfb_surface_t *surface = abstract_surface;
684 IDirectFBSurface *buffer = image_extra;
685
686 D_DEBUG_AT (CairoDFB_Acquire,
687 "%s( surface=%p ).\n", __FUNCTION__, surface);
688
689 buffer->Unlock (buffer);
690
691 if (surface->dfbsurface != buffer) {
692 DFBRegion region = {
693 .x1 = interest_rect->x,
694 .y1 = interest_rect->y,
695 .x2 = interest_rect->x + interest_rect->width - 1,
696 .y2 = interest_rect->y + interest_rect->height - 1
697 };
698 surface->dfbsurface->SetBlittingFlags (surface->dfbsurface, DSBLIT_NOFX);
699 surface->dfbsurface->SetClip (surface->dfbsurface, ®ion);
700 surface->dfbsurface->Blit (surface->dfbsurface,
701 buffer, NULL,
702 image_rect->x, image_rect->y);
703 }
704
705 cairo_surface_destroy (&image->base);
706 }
707
708 static cairo_status_t
_cairo_directfb_surface_clone_similar(void * abstract_surface,cairo_surface_t * src,int src_x,int src_y,int width,int height,int * clone_offset_x,int * clone_offset_y,cairo_surface_t ** clone_out)709 _cairo_directfb_surface_clone_similar (void *abstract_surface,
710 cairo_surface_t *src,
711 int src_x,
712 int src_y,
713 int width,
714 int height,
715 int *clone_offset_x,
716 int *clone_offset_y,
717 cairo_surface_t **clone_out)
718 {
719 cairo_directfb_surface_t *surface = abstract_surface;
720 cairo_directfb_surface_t *clone;
721
722 D_DEBUG_AT (CairoDFB_Surface,
723 "%s( surface=%p, src=%p ).\n", __FUNCTION__, surface, src);
724
725 if (src->backend == surface->base.backend) {
726 *clone_offset_x = 0;
727 *clone_offset_y = 0;
728 *clone_out = cairo_surface_reference (src);
729
730 return CAIRO_STATUS_SUCCESS;
731 } else if (_cairo_surface_is_image (src)) {
732 cairo_image_surface_t *image_src = (cairo_image_surface_t *) src;
733 DFBSurfacePixelFormat format;
734 DFBResult ret;
735 pixman_image_t *pixman_image;
736 void *data;
737 int pitch;
738
739 format = _directfb_from_pixman_format (image_src->pixman_format);
740 if (format == 0)
741 return CAIRO_INT_STATUS_UNSUPPORTED;
742
743 clone = (cairo_directfb_surface_t *)
744 _cairo_directfb_surface_create_internal (surface->dfb, format,
745 image_src->base.content,
746 width, height);
747 if (unlikely (clone->base.status))
748 return clone->base.status;
749
750 ret = clone->dfbsurface->Lock (clone->dfbsurface,
751 DSLF_WRITE, (void *)&data, &pitch);
752 if (ret) {
753 DirectFBError ("IDirectFBSurface::Lock()", ret);
754 cairo_surface_destroy (&clone->base);
755 return _cairo_error (CAIRO_STATUS_NO_MEMORY);
756 }
757
758 pixman_image = pixman_image_create_bits (clone->pixman_format,
759 width, height,
760 data, pitch);
761 if (unlikely (pixman_image == NULL)) {
762 DirectFBError ("IDirectFBSurface::Lock()", ret);
763 cairo_surface_destroy (&clone->base);
764 return _cairo_error (CAIRO_STATUS_NO_MEMORY);
765 }
766
767 pixman_image_composite32 (PIXMAN_OP_SRC,
768 image_src->pixman_image,
769 NULL,
770 pixman_image,
771 src_x, src_y,
772 0, 0,
773 0, 0,
774 width, height);
775
776 pixman_image_unref (pixman_image);
777
778 clone->dfbsurface->Unlock (clone->dfbsurface);
779
780 *clone_offset_x = src_x;
781 *clone_offset_y = src_y;
782 *clone_out = &clone->base;
783 return CAIRO_STATUS_SUCCESS;
784 }
785
786 return CAIRO_INT_STATUS_UNSUPPORTED;
787 }
788
789 #if DFB_COMPOSITE || DFB_COMPOSITE_TRAPEZOIDS
790 static cairo_int_status_t
_directfb_prepare_composite(cairo_directfb_surface_t * dst,const cairo_pattern_t * src_pattern,const cairo_pattern_t * mask_pattern,cairo_operator_t op,int * src_x,int * src_y,int * mask_x,int * mask_y,unsigned int width,unsigned int height,cairo_directfb_surface_t ** ret_src,cairo_surface_attributes_t * ret_src_attr)791 _directfb_prepare_composite (cairo_directfb_surface_t *dst,
792 const cairo_pattern_t *src_pattern,
793 const cairo_pattern_t *mask_pattern,
794 cairo_operator_t op,
795 int *src_x, int *src_y,
796 int *mask_x, int *mask_y,
797 unsigned int width,
798 unsigned int height,
799 cairo_directfb_surface_t **ret_src,
800 cairo_surface_attributes_t *ret_src_attr)
801 {
802 cairo_directfb_surface_t *src;
803 cairo_surface_attributes_t src_attr;
804 cairo_status_t status;
805 DFBSurfaceBlittingFlags flags;
806 DFBSurfaceBlendFunction sblend;
807 DFBSurfaceBlendFunction dblend;
808 const cairo_color_t *color;
809
810 /* XXX Unbounded operators are not handled correctly */
811 if (! _cairo_operator_bounded_by_source (op))
812 return CAIRO_INT_STATUS_UNSUPPORTED;
813
814 if (! _directfb_get_operator (op, &sblend, &dblend))
815 return CAIRO_INT_STATUS_UNSUPPORTED;
816
817 if (mask_pattern) {
818 return CAIRO_INT_STATUS_UNSUPPORTED;
819 if (mask_pattern->type != CAIRO_PATTERN_TYPE_SOLID) {
820 const cairo_pattern_t *tmp;
821 int tmp_x, tmp_y;
822
823 if (src_pattern->type != CAIRO_PATTERN_TYPE_SOLID ||
824 sblend == DSBF_INVDESTALPHA) /* Doesn't work correctly */
825 return CAIRO_INT_STATUS_UNSUPPORTED;
826
827 D_DEBUG_AT (CairoDFB_Render, "Replacing src pattern by mask pattern.\n");
828
829 tmp = src_pattern;
830 tmp_x = *src_x; tmp_y = *src_y;
831
832 src_pattern = mask_pattern;
833 *src_x = *mask_x; *src_y = *mask_y;
834
835 mask_pattern = tmp;
836 *mask_x = tmp_x; *mask_y = tmp_y;
837
838 if (sblend == DSBF_ONE) {
839 sblend = DSBF_SRCALPHA;
840 /*dblend = DSBF_INVSRCALPHA;*/
841 }
842 }
843
844 color = &((cairo_solid_pattern_t *) mask_pattern)->color;
845 } else {
846 color = _cairo_stock_color (CAIRO_STOCK_WHITE);
847 }
848
849 status = _cairo_pattern_acquire_surface (src_pattern, &dst->base,
850 *src_x, *src_y, width, height,
851 CAIRO_PATTERN_ACQUIRE_NO_REFLECT,
852 (cairo_surface_t **) &src,
853 &src_attr);
854 if (status)
855 return status;
856
857 if (src->base.backend != &_cairo_directfb_surface_backend ||
858 src->dfb != dst->dfb)
859 {
860 _cairo_pattern_release_surface (src_pattern, &src->base, &src_attr);
861 return CAIRO_INT_STATUS_UNSUPPORTED;
862 }
863
864 if ((src->base.content & CAIRO_CONTENT_ALPHA) == 0) {
865 if (sblend == DSBF_SRCALPHA)
866 sblend = DSBF_ONE;
867 else if (sblend == DSBF_INVSRCALPHA)
868 sblend = DSBF_ZERO;
869
870 if (dblend == DSBF_SRCALPHA)
871 dblend = DSBF_ONE;
872 else if (dblend == DSBF_INVSRCALPHA)
873 dblend = DSBF_ZERO;
874 }
875
876 if ((dst->base.content & CAIRO_CONTENT_ALPHA) == 0) {
877 if (sblend == DSBF_DESTALPHA)
878 sblend = DSBF_ONE;
879 else if (sblend == DSBF_INVDESTALPHA)
880 sblend = DSBF_ZERO;
881
882 if (dblend == DSBF_DESTALPHA)
883 dblend = DSBF_ONE;
884 else if (dblend == DSBF_INVDESTALPHA)
885 dblend = DSBF_ZERO;
886 }
887
888 flags = (sblend == DSBF_ONE && dblend == DSBF_ZERO)
889 ? DSBLIT_NOFX : DSBLIT_BLEND_ALPHACHANNEL;
890 if (! CAIRO_COLOR_IS_OPAQUE (color))
891 flags |= DSBLIT_BLEND_COLORALPHA;
892 if (! _cairo_color_equal (color, _cairo_stock_color (CAIRO_STOCK_WHITE)))
893 flags |= DSBLIT_COLORIZE;
894
895 dst->dfbsurface->SetBlittingFlags (dst->dfbsurface, flags);
896
897 if (flags & (DSBLIT_BLEND_ALPHACHANNEL | DSBLIT_BLEND_COLORALPHA)) {
898 dst->dfbsurface->SetSrcBlendFunction (dst->dfbsurface, sblend);
899 dst->dfbsurface->SetDstBlendFunction (dst->dfbsurface, dblend);
900 }
901
902 if (flags & (DSBLIT_BLEND_COLORALPHA | DSBLIT_COLORIZE)) {
903 if (dst->blit_premultiplied) {
904 dst->dfbsurface->SetColor (dst->dfbsurface,
905 color->red_short >> 8,
906 color->green_short >> 8,
907 color->blue_short >> 8,
908 color->alpha_short >> 8);
909 } else {
910 dst->dfbsurface->SetColor (dst->dfbsurface,
911 color->red * 0xff,
912 color->green * 0xff,
913 color->blue * 0xff,
914 color->alpha * 0xff);
915 }
916 }
917
918 *ret_src = src;
919 *ret_src_attr = src_attr;
920
921 return CAIRO_STATUS_SUCCESS;
922 }
923
924 static void
_directfb_finish_composite(cairo_directfb_surface_t * dst,const cairo_pattern_t * src_pattern,cairo_surface_t * src,cairo_surface_attributes_t * src_attr)925 _directfb_finish_composite (cairo_directfb_surface_t *dst,
926 const cairo_pattern_t *src_pattern,
927 cairo_surface_t *src,
928 cairo_surface_attributes_t *src_attr)
929 {
930 _cairo_pattern_release_surface (src_pattern, src, src_attr);
931 }
932 #endif /* DFB_COMPOSITE || DFB_COMPOSITE_TRAPEZOIDS */
933
934 #if DFB_COMPOSITE
935 static DFBAccelerationMask
_directfb_categorize_operation(cairo_surface_attributes_t * src_attr)936 _directfb_categorize_operation (cairo_surface_attributes_t *src_attr)
937 {
938 cairo_matrix_t *m = &src_attr->matrix;
939
940 if (m->xy != 0 || m->yx != 0 || m->xx < 0 || m->yy < 0) {
941 if (src_attr->extend != CAIRO_EXTEND_NONE)
942 return DFXL_NONE;
943
944 return DFXL_TEXTRIANGLES;
945 }
946
947 if (m->xx != 1 || m->yy != 1) {
948 if (src_attr->extend != CAIRO_EXTEND_NONE)
949 return DFXL_NONE;
950
951 return DFXL_STRETCHBLIT;
952 }
953
954 switch (src_attr->extend) {
955 case CAIRO_EXTEND_NONE:
956 case CAIRO_EXTEND_REPEAT:
957 if (_cairo_matrix_is_integer_translation (&src_attr->matrix,
958 NULL, NULL))
959 {
960 return DFXL_BLIT;
961 }
962 else
963 {
964 return DFXL_STRETCHBLIT;
965 }
966
967 default:
968 case CAIRO_EXTEND_REFLECT:
969 case CAIRO_EXTEND_PAD:
970 return DFXL_NONE;
971 }
972 }
973
974 static cairo_int_status_t
_cairo_directfb_surface_composite(cairo_operator_t op,const cairo_pattern_t * src_pattern,const cairo_pattern_t * mask_pattern,void * abstract_dst,int src_x,int src_y,int mask_x,int mask_y,int dst_x,int dst_y,unsigned int width,unsigned int height,cairo_region_t * clip_region)975 _cairo_directfb_surface_composite (cairo_operator_t op,
976 const cairo_pattern_t *src_pattern,
977 const cairo_pattern_t *mask_pattern,
978 void *abstract_dst,
979 int src_x, int src_y,
980 int mask_x, int mask_y,
981 int dst_x, int dst_y,
982 unsigned int width,
983 unsigned int height,
984 cairo_region_t *clip_region)
985 {
986 cairo_directfb_surface_t *dst = abstract_dst;
987 cairo_directfb_surface_t *src;
988 cairo_surface_attributes_t src_attr;
989 cairo_bool_t is_integer_translation;
990 DFBAccelerationMask accel, mask;
991 cairo_int_status_t status;
992 int tx, ty;
993
994 D_DEBUG_AT (CairoDFB_Render,
995 "%s( op=%d, src_pattern=%p, mask_pattern=%p, dst=%p,"
996 " src_x=%d, src_y=%d, mask_x=%d, mask_y=%d, dst_x=%d,"
997 " dst_y=%d, width=%u, height=%u ).\n",
998 __FUNCTION__, op, src_pattern, mask_pattern, dst,
999 src_x, src_y, mask_x, mask_y, dst_x, dst_y, width, height);
1000
1001 if (! dst->supported_destination)
1002 return CAIRO_INT_STATUS_UNSUPPORTED;
1003
1004 status = _directfb_prepare_composite (dst, src_pattern, mask_pattern, op,
1005 &src_x, &src_y, &mask_x, &mask_y,
1006 width, height, &src, &src_attr);
1007 if (status)
1008 return status;
1009
1010 accel = _directfb_categorize_operation (&src_attr);
1011 if (accel == DFXL_NONE) {
1012 _directfb_finish_composite (dst, src_pattern, &src->base, &src_attr);
1013 return CAIRO_INT_STATUS_UNSUPPORTED;
1014 }
1015
1016 dst->dfbsurface->GetAccelerationMask (dst->dfbsurface,
1017 src->dfbsurface,
1018 &mask);
1019 if ((mask & accel) == 0) {
1020 D_DEBUG_AT (CairoDFB_Render, "No acceleration (%08x)!\n", accel);
1021 if (accel != DFXL_BLIT) {
1022 _directfb_finish_composite (dst, src_pattern, &src->base, &src_attr);
1023 return CAIRO_INT_STATUS_UNSUPPORTED;
1024 }
1025 }
1026
1027 src_x += src_attr.x_offset;
1028 src_y += src_attr.y_offset;
1029
1030 switch ((int) accel) {
1031 case DFXL_BLIT:
1032 {
1033 DFBRectangle sr;
1034
1035 is_integer_translation =
1036 _cairo_matrix_is_integer_translation (&src_attr.matrix,
1037 &tx, &ty);
1038 assert (is_integer_translation);
1039
1040 sr.x = src_x + tx;
1041 sr.y = src_y + ty;
1042 sr.w = width;
1043 sr.h = height;
1044
1045 if (src_attr.extend == CAIRO_EXTEND_NONE) {
1046 D_DEBUG_AT (CairoDFB_Render, "Running Blit().\n");
1047
1048 RUN_CLIPPED (dst, clip_region, NULL,
1049 dst->dfbsurface->Blit (dst->dfbsurface,
1050 src->dfbsurface,
1051 &sr, dst_x, dst_y));
1052 } else if (src_attr.extend == CAIRO_EXTEND_REPEAT) {
1053 DFBRegion clip;
1054
1055 clip.x1 = dst_x;
1056 clip.y1 = dst_y;
1057 clip.x2 = dst_x + width - 1;
1058 clip.y2 = dst_y + height - 1;
1059
1060 D_DEBUG_AT (CairoDFB_Render, "Running TileBlit().\n");
1061
1062 RUN_CLIPPED (dst, clip_region, &clip,
1063 dst->dfbsurface->TileBlit (dst->dfbsurface,
1064 src->dfbsurface,
1065 &sr, dst_x, dst_y));
1066 }
1067 break;
1068 }
1069
1070 case DFXL_STRETCHBLIT:
1071 {
1072 DFBRectangle sr, dr;
1073 double x1, y1, x2, y2;
1074
1075 TRANSFORM_POINT2X (src_attr.matrix,
1076 src_x, src_y, x1, y1);
1077 TRANSFORM_POINT2X (src_attr.matrix,
1078 src_x+width, src_y+height, x2, y2);
1079
1080 sr.x = floor (x1);
1081 sr.y = floor (y1);
1082 sr.w = ceil (x2) - sr.x;
1083 sr.h = ceil (y2) - sr.y;
1084
1085 dr.x = dst_x;
1086 dr.y = dst_y;
1087 dr.w = width;
1088 dr.h = height;
1089
1090 D_DEBUG_AT (CairoDFB_Render, "Running StretchBlit().\n");
1091
1092 RUN_CLIPPED (dst, clip_region, NULL,
1093 dst->dfbsurface->StretchBlit (dst->dfbsurface,
1094 src->dfbsurface,
1095 &sr, &dr));
1096 break;
1097 }
1098
1099 case DFXL_TEXTRIANGLES:
1100 {
1101 DFBRegion clip;
1102 DFBVertex v[4];
1103 float x1, y1, x2, y2;
1104 int w, h;
1105
1106 status = cairo_matrix_invert (&src_attr.matrix);
1107 /* guaranteed by cairo_pattern_set_matrix (); */
1108 assert (status == CAIRO_STATUS_SUCCESS);
1109
1110 x1 = src_x;
1111 y1 = src_y;
1112 x2 = width + x1;
1113 y2 = height + y1;
1114
1115 src->dfbsurface->GetSize (src->dfbsurface, &w, &h);
1116
1117 TRANSFORM_POINT3X (src_attr.matrix, x1, y1, v[0].x, v[0].y);
1118 v[0].z = 0;
1119 v[0].w = 1;
1120 v[0].s = x1 / w;
1121 v[0].t = y1 / h;
1122
1123 TRANSFORM_POINT3X (src_attr.matrix, x2, y1, v[1].x, v[1].y);
1124 v[1].z = 0;
1125 v[1].w = 1;
1126 v[1].s = x2 / w;
1127 v[1].t = y1 / h;
1128
1129 TRANSFORM_POINT3X (src_attr.matrix, x2, y2, v[2].x, v[2].y);
1130 v[2].z = 0;
1131 v[2].w = 1;
1132 v[2].s = x2 / w;
1133 v[2].t = y2 / h;
1134
1135 TRANSFORM_POINT3X (src_attr.matrix, x1, y2, v[3].x, v[3].y);
1136 v[3].z = 0;
1137 v[3].w = 1;
1138 v[3].s = x1 / w;
1139 v[3].t = y2 / h;
1140
1141 clip.x1 = dst_x;
1142 clip.y1 = dst_y;
1143 clip.x2 = dst_x + width - 1;
1144 clip.y2 = dst_y + height - 1;
1145
1146 D_DEBUG_AT (CairoDFB_Render, "Running TextureTriangles().\n");
1147
1148 RUN_CLIPPED (dst, clip_region, &clip,
1149 dst->dfbsurface->TextureTriangles (dst->dfbsurface,
1150 src->dfbsurface,
1151 v, NULL,
1152 4, DTTF_FAN));
1153 break;
1154 }
1155
1156 default:
1157 D_BUG ("Unexpected operation");
1158 break;
1159 }
1160
1161 _directfb_finish_composite (dst, src_pattern, &src->base, &src_attr);
1162
1163 return CAIRO_STATUS_SUCCESS;
1164 }
1165 #endif /* DFB_COMPOSITE */
1166
1167 #if DFB_RECTANGLES
1168 static cairo_int_status_t
_cairo_directfb_surface_fill_rectangles(void * abstract_surface,cairo_operator_t op,const cairo_color_t * color,cairo_rectangle_int_t * rects,int n_rects)1169 _cairo_directfb_surface_fill_rectangles (void *abstract_surface,
1170 cairo_operator_t op,
1171 const cairo_color_t *color,
1172 cairo_rectangle_int_t *rects,
1173 int n_rects)
1174 {
1175 cairo_directfb_surface_t *dst = abstract_surface;
1176 DFBSurfaceDrawingFlags flags;
1177 DFBSurfaceBlendFunction sblend;
1178 DFBSurfaceBlendFunction dblend;
1179 DFBRectangle r[n_rects];
1180 int i;
1181
1182 D_DEBUG_AT (CairoDFB_Render,
1183 "%s( dst=%p, op=%d, color=%p, rects=%p, n_rects=%d ).\n",
1184 __FUNCTION__, dst, op, color, rects, n_rects);
1185
1186 if (! dst->supported_destination)
1187 return CAIRO_INT_STATUS_UNSUPPORTED;
1188
1189 if (! _directfb_get_operator (op, &sblend, &dblend))
1190 return CAIRO_INT_STATUS_UNSUPPORTED;
1191
1192 if (CAIRO_COLOR_IS_OPAQUE (color)) {
1193 if (sblend == DSBF_SRCALPHA)
1194 sblend = DSBF_ONE;
1195 else if (sblend == DSBF_INVSRCALPHA)
1196 sblend = DSBF_ZERO;
1197
1198 if (dblend == DSBF_SRCALPHA)
1199 dblend = DSBF_ONE;
1200 else if (dblend == DSBF_INVSRCALPHA)
1201 dblend = DSBF_ZERO;
1202 }
1203 if ((dst->base.content & CAIRO_CONTENT_ALPHA) == 0) {
1204 if (sblend == DSBF_DESTALPHA)
1205 sblend = DSBF_ONE;
1206 else if (sblend == DSBF_INVDESTALPHA)
1207 sblend = DSBF_ZERO;
1208
1209 if (dblend == DSBF_DESTALPHA)
1210 dblend = DSBF_ONE;
1211 else if (dblend == DSBF_INVDESTALPHA)
1212 dblend = DSBF_ZERO;
1213 }
1214
1215 flags = (sblend == DSBF_ONE && dblend == DSBF_ZERO) ? DSDRAW_NOFX : DSDRAW_BLEND;
1216 dst->dfbsurface->SetDrawingFlags (dst->dfbsurface, flags);
1217 if (flags & DSDRAW_BLEND) {
1218 dst->dfbsurface->SetSrcBlendFunction (dst->dfbsurface, sblend);
1219 dst->dfbsurface->SetDstBlendFunction (dst->dfbsurface, dblend);
1220 }
1221
1222 dst->dfbsurface->SetColor (dst->dfbsurface,
1223 color->red_short >> 8,
1224 color->green_short >> 8,
1225 color->blue_short >> 8,
1226 color->alpha_short >> 8);
1227
1228 for (i = 0; i < n_rects; i++) {
1229 r[i].x = rects[i].x;
1230 r[i].y = rects[i].y;
1231 r[i].w = rects[i].width;
1232 r[i].h = rects[i].height;
1233 }
1234
1235 RUN_CLIPPED (dst, NULL, NULL,
1236 dst->dfbsurface->FillRectangles (dst->dfbsurface, r, n_rects));
1237
1238 return CAIRO_STATUS_SUCCESS;
1239 }
1240 #endif
1241
1242 #if DFB_COMPOSITE_TRAPEZOIDS
1243 static cairo_int_status_t
_cairo_directfb_surface_composite_trapezoids(cairo_operator_t op,const cairo_pattern_t * pattern,void * abstract_dst,cairo_antialias_t antialias,int src_x,int src_y,int dst_x,int dst_y,unsigned int width,unsigned int height,cairo_trapezoid_t * traps,int num_traps,cairo_region_t * clip_region)1244 _cairo_directfb_surface_composite_trapezoids (cairo_operator_t op,
1245 const cairo_pattern_t *pattern,
1246 void *abstract_dst,
1247 cairo_antialias_t antialias,
1248 int src_x, int src_y,
1249 int dst_x, int dst_y,
1250 unsigned int width,
1251 unsigned int height,
1252 cairo_trapezoid_t *traps,
1253 int num_traps,
1254 cairo_region_t *clip_region)
1255 {
1256 cairo_directfb_surface_t *dst = abstract_dst;
1257 cairo_directfb_surface_t *src;
1258 cairo_surface_attributes_t src_attr;
1259 cairo_status_t status;
1260 DFBAccelerationMask accel;
1261
1262 D_DEBUG_AT (CairoDFB_Render,
1263 "%s( op=%d, pattern=%p, dst=%p, antialias=%d,"
1264 " src_x=%d, src_y=%d, dst_x=%d, dst_y=%d,"
1265 " width=%u, height=%u, traps=%p, num_traps=%d ).\n",
1266 __FUNCTION__, op, pattern, dst, antialias,
1267 src_x, src_y, dst_x, dst_y, width, height, traps, num_traps);
1268
1269 if (! dst->supported_destination)
1270 return CAIRO_INT_STATUS_UNSUPPORTED;
1271
1272 if (antialias != CAIRO_ANTIALIAS_NONE)
1273 return CAIRO_INT_STATUS_UNSUPPORTED;
1274
1275 /* Textures are not supported yet. */
1276 if (pattern->type != CAIRO_PATTERN_TYPE_SOLID)
1277 return CAIRO_INT_STATUS_UNSUPPORTED;
1278
1279 status = _directfb_prepare_composite (dst, pattern, NULL, op,
1280 &src_x, &src_y, NULL, NULL,
1281 width, height, &src, &src_attr);
1282 if (status)
1283 return status;
1284
1285 dst->dfbsurface->GetAccelerationMask (dst->dfbsurface,
1286 src->dfbsurface,
1287 &accel);
1288
1289 status = CAIRO_INT_STATUS_UNSUPPORTED;
1290
1291 if (accel & DFXL_TEXTRIANGLES) {
1292 DFBVertex vertex[6*num_traps];
1293 DFBVertex *v = &vertex[0];
1294 int n = 0;
1295
1296 #define ADD_TRI_V(V, X, Y) do { \
1297 (V)->x = (X); (V)->y = (Y); (V)->w = 1; (V)->z = (V)->s = (V)->t = 0; \
1298 } while (0)
1299 #define ADD_TRI(id, x1, y1, x2, y2, x3, y3) do {\
1300 const int p = (id)*3;\
1301 ADD_TRI_V (v+p+0, x1, y1); \
1302 ADD_TRI_V (v+p+1, x2, y2); \
1303 ADD_TRI_V (v+p+2, x3, y3); \
1304 } while (0)
1305 while (num_traps--) {
1306 double lx1, ly1, lx2, ly2;
1307 double rx1, ry1, rx2, ry2;
1308
1309 lx1 = _cairo_fixed_to_double (traps->left.p1.x);
1310 ly1 = _cairo_fixed_to_double (traps->left.p1.y);
1311 lx2 = _cairo_fixed_to_double (traps->left.p2.x);
1312 ly2 = _cairo_fixed_to_double (traps->left.p2.y);
1313 rx1 = _cairo_fixed_to_double (traps->right.p1.x);
1314 ry1 = _cairo_fixed_to_double (traps->right.p1.y);
1315 rx2 = _cairo_fixed_to_double (traps->right.p2.x);
1316 ry2 = _cairo_fixed_to_double (traps->right.p2.y);
1317
1318 if (traps->left.p1.y < traps->top) {
1319 double y = _cairo_fixed_to_double (traps->top);
1320 if (lx2 != lx1)
1321 lx1 = (y - ly1) * (lx2 - lx1) / (ly2 - ly1) + lx1;
1322 ly1 = y;
1323 }
1324 if (traps->left.p2.y > traps->bottom) {
1325 double y = _cairo_fixed_to_double (traps->bottom);
1326 if (lx2 != lx1)
1327 lx2 = (y - ly1) * (lx2 - lx1) / (ly2 - ly1) + lx1;
1328 ly2 = y;
1329 }
1330
1331 if (traps->right.p1.y < traps->top) {
1332 double y = _cairo_fixed_to_double (traps->top);
1333 if (rx2 != rx1)
1334 rx1 = (y - ry1) * (rx2 - rx1) / (ry2 - ry1) + rx1;
1335 ry1 = y;
1336 }
1337 if (traps->right.p2.y > traps->bottom) {
1338 double y = _cairo_fixed_to_double (traps->bottom);
1339 if (rx2 != rx1)
1340 rx2 = (y - ry1) * (rx2 - rx1) / (ry2 - ry1) + rx1;
1341 ry2 = y;
1342 }
1343
1344 if (lx1 == rx1 && ly1 == ry1) {
1345 ADD_TRI (0, lx2, ly2, lx1, ly1, rx2, ry2);
1346 v += 3;
1347 n += 3;
1348 } else if (lx2 == rx2 && ly2 == ry2) {
1349 ADD_TRI (0, lx1, ly1, lx2, ly2, rx1, ry1);
1350 v += 3;
1351 n += 3;
1352 } else {
1353 ADD_TRI (0, lx1, ly1, rx1, ry1, lx2, ly2);
1354 ADD_TRI (1, lx2, ly2, rx1, ry1, rx2, ry2);
1355 v += 6;
1356 n += 6;
1357 }
1358
1359 traps++;
1360 }
1361 #undef ADD_TRI
1362 #undef ADD_TRI_V
1363
1364 D_DEBUG_AT (CairoDFB_Render, "Running TextureTriangles().\n");
1365
1366 RUN_CLIPPED (dst, clip_region, NULL,
1367 dst->dfbsurface->TextureTriangles (dst->dfbsurface,
1368 src->dfbsurface,
1369 vertex, NULL, n,
1370 DTTF_LIST));
1371
1372 status = CAIRO_STATUS_SUCCESS;
1373 }
1374
1375 _directfb_finish_composite (dst, pattern, &src->base, &src_attr);
1376
1377 return status;
1378 }
1379 #endif /* DFB_COMPOSITE_TRAPEZOIDS */
1380
1381 static cairo_bool_t
_cairo_directfb_abstract_surface_get_extents(void * abstract_surface,cairo_rectangle_int_t * rectangle)1382 _cairo_directfb_abstract_surface_get_extents (void *abstract_surface,
1383 cairo_rectangle_int_t *rectangle)
1384 {
1385 cairo_directfb_surface_t *surface = abstract_surface;
1386
1387 D_DEBUG_AT (CairoDFB_Surface,
1388 "%s( surface=%p, rectangle=%p ).\n",
1389 __FUNCTION__, surface, rectangle);
1390
1391 if (!surface->local) {
1392 surface->dfbsurface->GetSize (surface->dfbsurface,
1393 &surface->width, &surface->height);
1394 }
1395
1396 rectangle->x = 0;
1397 rectangle->y = 0;
1398 rectangle->width = surface->width;
1399 rectangle->height = surface->height;
1400
1401 return TRUE;
1402 }
1403
1404 #if DFB_SHOW_GLYPHS
1405 static cairo_status_t
_directfb_allocate_font_cache(IDirectFB * dfb,int width,int height,cairo_directfb_font_cache_t ** out)1406 _directfb_allocate_font_cache (IDirectFB *dfb,
1407 int width, int height,
1408 cairo_directfb_font_cache_t **out)
1409 {
1410 cairo_directfb_font_cache_t *cache;
1411 cairo_status_t status;
1412
1413 cache = calloc (1, sizeof (cairo_directfb_font_cache_t));
1414 if (cache == NULL)
1415 return _cairo_error (CAIRO_STATUS_NO_MEMORY);
1416
1417 cache->dfb = dfb;
1418 status = _directfb_buffer_surface_create (dfb,
1419 _directfb_argb_font ? DSPF_ARGB : DSPF_A8,
1420 width, height,
1421 &cache->dfbsurface);
1422 if (status) {
1423 free (cache);
1424 return status;
1425 }
1426
1427 cache->width = width;
1428 cache->height = height;
1429 *out = cache;
1430 return CAIRO_STATUS_SUCCESS;
1431 }
1432
1433 static void
_directfb_destroy_font_cache(cairo_directfb_font_cache_t * cache)1434 _directfb_destroy_font_cache (cairo_directfb_font_cache_t *cache)
1435 {
1436 cache->dfbsurface->Release (cache->dfbsurface);
1437 free (cache);
1438 }
1439
1440 /* XXX hook into rtree font cache from drm */
1441 static cairo_status_t
_directfb_acquire_font_cache(cairo_directfb_surface_t * surface,cairo_scaled_font_t * scaled_font,const cairo_glyph_t * glyphs,int num_glyphs,cairo_directfb_font_cache_t ** ret_cache,DFBRectangle * rects,DFBPoint * points,int * ret_num)1442 _directfb_acquire_font_cache (cairo_directfb_surface_t *surface,
1443 cairo_scaled_font_t *scaled_font,
1444 const cairo_glyph_t *glyphs,
1445 int num_glyphs,
1446 cairo_directfb_font_cache_t **ret_cache,
1447 DFBRectangle *rects,
1448 DFBPoint *points,
1449 int *ret_num)
1450 {
1451 cairo_status_t status;
1452 cairo_scaled_glyph_t *chars[num_glyphs];
1453 int num_chars = 0;
1454 cairo_directfb_font_cache_t *cache = NULL;
1455 int n = 0;
1456 int x = 0;
1457 int y = 0;
1458 int w = 8;
1459 int h = 8;
1460 int i;
1461
1462 D_DEBUG_AT (CairoDFB_Font, "%s( %p [%d] )\n", __FUNCTION__, glyphs, num_glyphs );
1463
1464 _cairo_scaled_font_freeze_cache (scaled_font);
1465
1466 if (scaled_font->surface_private) {
1467 cache = scaled_font->surface_private;
1468 x = cache->x;
1469 y = cache->y;
1470 }
1471
1472 for (i = 0; i < num_glyphs; i++) {
1473 cairo_scaled_glyph_t *scaled_glyph;
1474 cairo_image_surface_t *img;
1475
1476 D_DEBUG_AT (CairoDFB_Font, " -> [%2d] = %4lu\n", i, glyphs[i].index );
1477
1478 status = _cairo_scaled_glyph_lookup (scaled_font, glyphs[i].index,
1479 CAIRO_SCALED_GLYPH_INFO_SURFACE,
1480 &scaled_glyph);
1481 if (status) {
1482 _cairo_scaled_font_thaw_cache (scaled_font);
1483 return status;
1484 }
1485
1486 img = scaled_glyph->surface;
1487 switch (img->format) {
1488 case CAIRO_FORMAT_A1:
1489 case CAIRO_FORMAT_A8:
1490 case CAIRO_FORMAT_ARGB32:
1491 break;
1492 case CAIRO_FORMAT_RGB24:
1493 default:
1494 D_DEBUG_AT (CairoDFB_Font,
1495 " -> Unsupported font format %d!\n", img->format);
1496 _cairo_scaled_font_thaw_cache (scaled_font);
1497 return CAIRO_INT_STATUS_UNSUPPORTED;
1498 }
1499
1500 points[n].x = _cairo_lround (glyphs[i].x - img->base.device_transform.x0);
1501 points[n].y = _cairo_lround (glyphs[i].y - img->base.device_transform.y0);
1502
1503 // D_DEBUG_AT (CairoDFB_Font, " (%4d,%4d) [%2d]\n", points[n].x, points[n].y, n );
1504
1505 if (points[n].x >= surface->width ||
1506 points[n].y >= surface->height ||
1507 points[n].x+img->width <= 0 ||
1508 points[n].y+img->height <= 0)
1509 {
1510 continue;
1511 }
1512
1513 if (scaled_glyph->surface_private == NULL) {
1514 DFBRectangle *rect;
1515
1516 if (x+img->width > 2048) {
1517 x = 0;
1518 y = h;
1519 h = 0;
1520 }
1521
1522 rects[n].x = x;
1523 rects[n].y = y;
1524 rects[n].w = img->width;
1525 rects[n].h = img->height;
1526
1527 x += img->width;
1528 h = MAX (h, img->height);
1529 w = MAX (w, x);
1530
1531 /* Remember glyph location */
1532 rect = malloc (sizeof (DFBRectangle));
1533 if (rect == NULL) {
1534 _cairo_scaled_font_thaw_cache (scaled_font);
1535 return _cairo_error (CAIRO_STATUS_NO_MEMORY);
1536 }
1537 *rect = rects[n];
1538
1539 scaled_glyph->surface_private = rect;
1540 chars[num_chars++] = scaled_glyph;
1541
1542 D_DEBUG_AT (CairoDFB_Font, " -> loading at %4d,%2d <- rect %p, img %p, entry %p\n",
1543 rects[n].x, rects[n].y, rect, scaled_glyph->surface, scaled_glyph);
1544 } else {
1545 rects[n] = *(DFBRectangle *) scaled_glyph->surface_private;
1546
1547 D_DEBUG_AT (CairoDFB_Font, " -> exists at %4d,%2d\n", rects[n].x, rects[n].y);
1548 }
1549
1550 n++;
1551 }
1552
1553 if (n == 0) {
1554 _cairo_scaled_font_thaw_cache (scaled_font);
1555 return CAIRO_INT_STATUS_NOTHING_TO_DO;
1556 }
1557
1558 h += y;
1559 w = MAX (w, 8);
1560 h = MAX (h, 8);
1561
1562 /* XXX query maximum surface size */
1563 if (w > 2048 || h > 2048) {
1564 _cairo_scaled_font_thaw_cache (scaled_font);
1565 return CAIRO_INT_STATUS_UNSUPPORTED;
1566 }
1567
1568 if (cache) {
1569 if (cache->width < w || cache->height < h) {
1570 cairo_directfb_font_cache_t *new_cache;
1571
1572 w = MAX (w, cache->width);
1573 h = MAX (h, cache->height);
1574
1575 D_DEBUG_AT (CairoDFB_Font, " -> Reallocating font cache (%dx%d).\n", w, h);
1576
1577 status = _directfb_allocate_font_cache (surface->dfb,
1578 w, h,
1579 &new_cache);
1580 if (status) {
1581 _cairo_scaled_font_thaw_cache (scaled_font);
1582 return status;
1583 }
1584
1585 new_cache->dfbsurface->Blit (new_cache->dfbsurface,
1586 cache->dfbsurface, NULL, 0, 0);
1587
1588 _directfb_destroy_font_cache (cache);
1589 scaled_font->surface_private = cache = new_cache;
1590 }
1591 } else {
1592 D_DEBUG_AT (CairoDFB_Font, " -> Allocating font cache (%dx%d).\n", w, h);
1593
1594 status = _directfb_allocate_font_cache (surface->dfb, w, h, &cache);
1595 if (status) {
1596 _cairo_scaled_font_thaw_cache (scaled_font);
1597 return status;
1598 }
1599
1600 scaled_font->surface_backend = &_cairo_directfb_surface_backend;
1601 scaled_font->surface_private = cache;
1602 }
1603
1604 if (num_chars) {
1605 unsigned char *data;
1606 int pitch;
1607
1608 if (cache->dfbsurface->Lock (cache->dfbsurface,
1609 DSLF_WRITE, (void *)&data, &pitch))
1610 {
1611 _cairo_scaled_font_thaw_cache (scaled_font);
1612 return _cairo_error (CAIRO_STATUS_NO_MEMORY);
1613 }
1614
1615 D_DEBUG_AT (CairoDFB_Font, " => %d chars to load, cache %dx%d\n", num_chars, cache->width, cache->height);
1616
1617 for (i = 0; i < num_chars; i++) {
1618 cairo_image_surface_t *img = chars[i]->surface;
1619 DFBRectangle *rect = chars[i]->surface_private;
1620 unsigned char *dst = data;
1621 unsigned char *src;
1622 int j;
1623
1624 D_DEBUG_AT (CairoDFB_Font, " -> loading [%2d] <- rect %p, img %p, entry %p\n", i, rect, img, chars[i]);
1625
1626 src = img->data;
1627
1628 D_DEBUG_AT (CairoDFB_Font, " from %p\n", src);
1629
1630 dst += rect->y * pitch + (_directfb_argb_font ? (rect->x<<2) : rect->x);
1631
1632 D_DEBUG_AT (CairoDFB_Font, " to %4d,%2d (%p)\n", rect->x, rect->y, dst);
1633
1634 if (img->format == CAIRO_FORMAT_A1) {
1635 for (h = rect->h; h; h--) {
1636 if (_directfb_argb_font) {
1637 for (j = 0; j < rect->w; j++)
1638 ((uint32_t *) dst)[j] = (src[j>>3] & (1 << (j&7))) ? 0xffffffff : 0;
1639 } else {
1640 for (j = 0; j < rect->w; j++)
1641 dst[j] = (src[j>>3] & (1 << (j&7))) ? 0xff : 0;
1642 }
1643
1644 dst += pitch;
1645 src += img->stride;
1646 }
1647 } else if (img->format == CAIRO_FORMAT_A8) {
1648 for (h = rect->h; h; h--) {
1649 if (_directfb_argb_font) {
1650 for (j = 0; j < rect->w; j++)
1651 ((uint32_t *) dst)[j] = src[j] * 0x01010101;
1652 } else {
1653 direct_memcpy (dst, src, rect->w);
1654 }
1655
1656 dst += pitch;
1657 src += img->stride;
1658 }
1659 } else { /* ARGB32 */
1660 for (h = rect->h; h; h--) {
1661 if (_directfb_argb_font) {
1662 direct_memcpy (dst, src, rect->w<<2);
1663 } else {
1664 for (j = 0; j < rect->w; j++)
1665 dst[j] = ((uint32_t *) src)[j] >> 24;
1666 }
1667
1668 dst += pitch;
1669 src += img->stride;
1670 }
1671 }
1672 }
1673
1674 cache->dfbsurface->Unlock (cache->dfbsurface);
1675 }
1676
1677 _cairo_scaled_font_thaw_cache (scaled_font);
1678
1679 cache->x = x;
1680 cache->y = y;
1681
1682 D_DEBUG_AT (CairoDFB_Font, " => cache %d,%d, %p [%d]\n", x, y, cache, n);
1683
1684 *ret_cache = cache;
1685 *ret_num = n;
1686
1687 return CAIRO_STATUS_SUCCESS;
1688 }
1689
1690 static void
_cairo_directfb_surface_scaled_font_fini(cairo_scaled_font_t * scaled_font)1691 _cairo_directfb_surface_scaled_font_fini (cairo_scaled_font_t *scaled_font)
1692 {
1693 cairo_directfb_font_cache_t *cache = scaled_font->surface_private;
1694
1695 D_DEBUG_AT (CairoDFB_Font,
1696 "%s( scaled_font=%p ).\n", __FUNCTION__, scaled_font);
1697
1698 if (cache != NULL) {
1699 _directfb_destroy_font_cache (cache);
1700 scaled_font->surface_private = NULL;
1701 }
1702 }
1703
1704 static void
_cairo_directfb_surface_scaled_glyph_fini(cairo_scaled_glyph_t * scaled_glyph,cairo_scaled_font_t * scaled_font)1705 _cairo_directfb_surface_scaled_glyph_fini (cairo_scaled_glyph_t *scaled_glyph,
1706 cairo_scaled_font_t *scaled_font)
1707 {
1708 D_DEBUG_AT (CairoDFB_Font,
1709 "%s( scaled_glyph=%p, scaled_font=%p ).\n",
1710 __FUNCTION__, scaled_glyph, scaled_font);
1711
1712 if (scaled_glyph->surface_private != NULL) {
1713 free (scaled_glyph->surface_private);
1714 scaled_glyph->surface_private = NULL;
1715 }
1716 }
1717
1718 static cairo_int_status_t
_cairo_directfb_surface_show_glyphs(void * abstract_dst,cairo_operator_t op,const cairo_pattern_t * pattern,cairo_glyph_t * glyphs,int num_glyphs,cairo_scaled_font_t * scaled_font,cairo_clip_t * clip,int * remaining_glyphs)1719 _cairo_directfb_surface_show_glyphs (void *abstract_dst,
1720 cairo_operator_t op,
1721 const cairo_pattern_t *pattern,
1722 cairo_glyph_t *glyphs,
1723 int num_glyphs,
1724 cairo_scaled_font_t *scaled_font,
1725 cairo_clip_t *clip,
1726 int *remaining_glyphs)
1727 {
1728 cairo_directfb_surface_t *dst = abstract_dst;
1729 cairo_directfb_font_cache_t *cache;
1730 cairo_status_t status;
1731 DFBSurfaceBlittingFlags flags;
1732 DFBSurfaceBlendFunction sblend;
1733 DFBSurfaceBlendFunction dblend;
1734 DFBRectangle rects[num_glyphs];
1735 DFBPoint points[num_glyphs];
1736 int num;
1737 const cairo_color_t *color;
1738 cairo_region_t *clip_region = NULL;
1739
1740 D_DEBUG_AT (CairoDFB_Font,
1741 "%s( dst=%p, op=%d, pattern=%p, glyphs=%p, num_glyphs=%d, scaled_font=%p ).\n",
1742 __FUNCTION__, dst, op, pattern, glyphs, num_glyphs, scaled_font);
1743
1744 if (! dst->supported_destination)
1745 return CAIRO_INT_STATUS_UNSUPPORTED;
1746
1747 if (pattern->type != CAIRO_PATTERN_TYPE_SOLID)
1748 return CAIRO_INT_STATUS_UNSUPPORTED;
1749
1750 /* Fallback if we need to emulate clip regions */
1751 if (clip != NULL) {
1752 status = _cairo_clip_get_region (clip, &clip_region);
1753 assert (status != CAIRO_INT_STATUS_NOTHING_TO_DO);
1754 if (status)
1755 return status;
1756 }
1757
1758 /* XXX Unbounded operators are not handled correctly */
1759 if (! _cairo_operator_bounded_by_mask (op))
1760 return CAIRO_INT_STATUS_UNSUPPORTED;
1761
1762 if (! _directfb_get_operator (op, &sblend, &dblend) ||
1763 sblend == DSBF_DESTALPHA || sblend == DSBF_INVDESTALPHA)
1764 {
1765 return CAIRO_INT_STATUS_UNSUPPORTED;
1766 }
1767
1768 status = _directfb_acquire_font_cache (dst, scaled_font, glyphs, num_glyphs,
1769 &cache, &rects[0], &points[0], &num);
1770 if (status) {
1771 if (status == CAIRO_INT_STATUS_NOTHING_TO_DO)
1772 status = CAIRO_STATUS_SUCCESS;
1773 return status;
1774 }
1775
1776 color = &((cairo_solid_pattern_t *) pattern)->color;
1777
1778 flags = DSBLIT_BLEND_ALPHACHANNEL | DSBLIT_COLORIZE;
1779 if (! CAIRO_COLOR_IS_OPAQUE (color))
1780 flags |= DSBLIT_BLEND_COLORALPHA;
1781
1782 if (!_directfb_argb_font) {
1783 if (sblend == DSBF_ONE) {
1784 sblend = DSBF_SRCALPHA;
1785 if (dblend == DSBF_ZERO)
1786 dblend = DSBF_INVSRCALPHA;
1787 }
1788 }
1789
1790 dst->dfbsurface->SetBlittingFlags (dst->dfbsurface, flags);
1791 dst->dfbsurface->SetSrcBlendFunction (dst->dfbsurface, sblend);
1792 dst->dfbsurface->SetDstBlendFunction (dst->dfbsurface, dblend);
1793 if (dst->blit_premultiplied) {
1794 dst->dfbsurface->SetColor (dst->dfbsurface,
1795 color->red_short >> 8,
1796 color->green_short >> 8,
1797 color->blue_short >> 8,
1798 color->alpha_short >> 8);
1799 } else {
1800 dst->dfbsurface->SetColor (dst->dfbsurface,
1801 color->red * 0xff,
1802 color->green * 0xff,
1803 color->blue * 0xff,
1804 color->alpha * 0xff);
1805 }
1806
1807 D_DEBUG_AT (CairoDFB_Font, "Running BatchBlit().\n");
1808
1809 RUN_CLIPPED (dst, clip_region, NULL,
1810 dst->dfbsurface->BatchBlit (dst->dfbsurface,
1811 cache->dfbsurface, rects, points, num));
1812
1813 return CAIRO_STATUS_SUCCESS;
1814 }
1815 #endif /* DFB_SHOW_GLYPHS */
1816
1817
1818 static cairo_bool_t
_cairo_directfb_surface_is_similar(void * surface_a,void * surface_b)1819 _cairo_directfb_surface_is_similar (void *surface_a, void *surface_b)
1820 {
1821 cairo_directfb_surface_t *a = (cairo_directfb_surface_t *) surface_a;
1822 cairo_directfb_surface_t *b = (cairo_directfb_surface_t *) surface_b;
1823
1824 return a->dfb == b->dfb;
1825 }
1826
1827 static cairo_surface_backend_t
1828 _cairo_directfb_surface_backend = {
1829 CAIRO_SURFACE_TYPE_DIRECTFB, /*type*/
1830 _cairo_directfb_surface_create_similar,/*create_similar*/
1831 _cairo_directfb_surface_finish, /*finish*/
1832 _cairo_directfb_surface_acquire_source_image,/*acquire_source_image*/
1833 _cairo_directfb_surface_release_source_image,/*release_source_image*/
1834 _cairo_directfb_surface_acquire_dest_image,/*acquire_dest_image*/
1835 _cairo_directfb_surface_release_dest_image,/*release_dest_image*/
1836 _cairo_directfb_surface_clone_similar,/*clone_similar*/
1837 #if DFB_COMPOSITE
1838 _cairo_directfb_surface_composite,/*composite*/
1839 #else
1840 NULL,/*composite*/
1841 #endif
1842 #if DFB_RECTANGLES
1843 _cairo_directfb_surface_fill_rectangles,/*fill_rectangles*/
1844 #else
1845 NULL,/*fill_rectangles*/
1846 #endif
1847 #if DFB_COMPOSITE_TRAPEZOIDS
1848 _cairo_directfb_surface_composite_trapezoids,/*composite_trapezoids*/
1849 #else
1850 NULL,/*composite_trapezoids*/
1851 #endif
1852 NULL, /* create_span_renderer */
1853 NULL, /* check_span_renderer */
1854 NULL, /* copy_page */
1855 NULL, /* show_page */
1856 _cairo_directfb_abstract_surface_get_extents,/* get_extents */
1857 NULL, /* old_show_glyphs */
1858 NULL, /* get_font_options */
1859 NULL, /* flush */
1860 NULL, /* mark_dirty_rectangle */
1861 #if DFB_SHOW_GLYPHS
1862 _cairo_directfb_surface_scaled_font_fini,/* scaled_font_fini */
1863 _cairo_directfb_surface_scaled_glyph_fini,/* scaled_glyph_fini */
1864 #else
1865 NULL,
1866 NULL,
1867 #endif
1868 NULL, /* paint */
1869 NULL, /* mask */
1870 NULL, /* stroke */
1871 NULL, /* fill */
1872 #if DFB_SHOW_GLYPHS
1873 _cairo_directfb_surface_show_glyphs,/* show_glyphs */
1874 #else
1875 NULL, /* show_glyphs */
1876 #endif
1877 NULL, /* snapshot */
1878 _cairo_directfb_surface_is_similar,
1879 };
1880
1881
1882 static void
cairo_directfb_surface_backend_init(IDirectFB * dfb)1883 cairo_directfb_surface_backend_init (IDirectFB *dfb)
1884 {
1885 static int done = 0;
1886
1887 if (done)
1888 return;
1889
1890 if (getenv ("CAIRO_DIRECTFB_NO_ACCEL")) {
1891 #if DFB_RECTANGLES
1892 _cairo_directfb_surface_backend.fill_rectangles = NULL;
1893 #endif
1894 #if DFB_COMPOSITE
1895 _cairo_directfb_surface_backend.composite = NULL;
1896 #endif
1897 #if DFB_COMPOSITE_TRAPEZOIDS
1898 _cairo_directfb_surface_backend.composite_trapezoids = NULL;
1899 #endif
1900 #if DFB_SHOW_GLYPHS
1901 _cairo_directfb_surface_backend.scaled_font_fini = NULL;
1902 _cairo_directfb_surface_backend.scaled_glyph_fini = NULL;
1903 _cairo_directfb_surface_backend.show_glyphs = NULL;
1904 #endif
1905 D_DEBUG_AT (CairoDFB_Surface, "Acceleration disabled.\n");
1906 } else {
1907 DFBGraphicsDeviceDescription dsc;
1908
1909 dfb->GetDeviceDescription (dfb, &dsc);
1910
1911 #if DFB_COMPOSITE
1912 // if (!(dsc.acceleration_mask & DFXL_BLIT))
1913 // _cairo_directfb_surface_backend.composite = NULL;
1914 #endif
1915
1916 #if DFB_COMPOSITE_TRAPEZOIDS
1917 // if (!(dsc.acceleration_mask & DFXL_TEXTRIANGLES))
1918 // _cairo_directfb_surface_backend.composite_trapezoids = NULL;
1919 #endif
1920 }
1921
1922 if (getenv ("CAIRO_DIRECTFB_ARGB_FONT")) {
1923 _directfb_argb_font = 1;
1924 D_DEBUG_AT (CairoDFB_Surface, "Using ARGB fonts.\n");
1925 }
1926
1927 done = 1;
1928 }
1929
1930 cairo_surface_t *
cairo_directfb_surface_create(IDirectFB * dfb,IDirectFBSurface * dfbsurface)1931 cairo_directfb_surface_create (IDirectFB *dfb, IDirectFBSurface *dfbsurface)
1932 {
1933 cairo_directfb_surface_t *surface;
1934 DFBSurfacePixelFormat format;
1935 DFBSurfaceCapabilities caps;
1936
1937 D_ASSERT (dfb != NULL);
1938 D_ASSERT (dfbsurface != NULL);
1939
1940 cairo_directfb_surface_backend_init (dfb);
1941
1942 surface = calloc (1, sizeof (cairo_directfb_surface_t));
1943 if (surface == NULL)
1944 return _cairo_surface_create_in_error (_cairo_error (CAIRO_STATUS_NO_MEMORY));
1945
1946 dfbsurface->AddRef (dfbsurface);
1947 dfbsurface->GetPixelFormat (dfbsurface, &format);
1948 dfbsurface->GetSize (dfbsurface, &surface->width, &surface->height);
1949 surface->dfb = dfb;
1950 surface->dfbsurface = dfbsurface;
1951 surface->pixman_format = _directfb_to_pixman_format (format);
1952 surface->supported_destination = pixman_format_supported_destination (surface->pixman_format);
1953
1954 dfbsurface->GetCapabilities (dfbsurface, &caps);
1955 if (caps & DSCAPS_PREMULTIPLIED)
1956 surface->blit_premultiplied = TRUE;
1957
1958 _cairo_surface_init (&surface->base,
1959 &_cairo_directfb_surface_backend,
1960 NULL, /* device */
1961 _directfb_format_to_content (format));
1962
1963 return &surface->base;
1964 }
1965