1 /* cairo - a vector graphics library with display and print output
3 * Copyright © 2004 David Reveman
5 * Permission to use, copy, modify, distribute, and sell this software
6 * and its documentation for any purpose is hereby granted without
7 * fee, provided that the above copyright notice appear in all copies
8 * and that both that copyright notice and this permission notice
9 * appear in supporting documentation, and that the name of David
10 * Reveman not be used in advertising or publicity pertaining to
11 * distribution of the software without specific, written prior
12 * permission. David Reveman makes no representations about the
13 * suitability of this software for any purpose. It is provided "as
14 * is" without express or implied warranty.
16 * DAVID REVEMAN DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS
17 * SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND
18 * FITNESS, IN NO EVENT SHALL DAVID REVEMAN BE LIABLE FOR ANY SPECIAL,
19 * INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER
20 * RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION
21 * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR
22 * IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
24 * Author: David Reveman <davidr@novell.com>
28 #include "cairo-glitz.h"
29 #include "cairo-glitz-private.h"
31 typedef struct _cairo_glitz_surface
{
34 glitz_surface_t
*surface
;
35 glitz_format_t
*format
;
37 cairo_bool_t has_clip
;
38 glitz_box_t
*clip_boxes
;
40 } cairo_glitz_surface_t
;
42 static const cairo_surface_backend_t
*
43 _cairo_glitz_surface_get_backend (void);
46 _cairo_glitz_surface_finish (void *abstract_surface
)
48 cairo_glitz_surface_t
*surface
= abstract_surface
;
50 if (surface
->clip_boxes
)
51 free (surface
->clip_boxes
);
53 glitz_surface_destroy (surface
->surface
);
55 return CAIRO_STATUS_SUCCESS
;
58 static glitz_format_name_t
59 _glitz_format_from_content (cairo_content_t content
)
62 case CAIRO_CONTENT_COLOR
:
63 return GLITZ_STANDARD_RGB24
;
64 case CAIRO_CONTENT_ALPHA
:
65 return GLITZ_STANDARD_A8
;
66 case CAIRO_CONTENT_COLOR_ALPHA
:
67 return GLITZ_STANDARD_ARGB32
;
71 return GLITZ_STANDARD_ARGB32
;
74 static cairo_surface_t
*
75 _cairo_glitz_surface_create_similar (void *abstract_src
,
76 cairo_content_t content
,
80 cairo_glitz_surface_t
*src
= abstract_src
;
81 cairo_surface_t
*crsurface
;
82 glitz_drawable_t
*drawable
;
83 glitz_surface_t
*surface
;
84 glitz_format_t
*gformat
;
86 drawable
= glitz_surface_get_drawable (src
->surface
);
89 glitz_find_standard_format (drawable
,
90 _glitz_format_from_content (content
));
94 surface
= glitz_surface_create (drawable
, gformat
,
95 width
<= 0 ? 1 : width
,
96 height
<= 0 ? 1 : height
,
100 return _cairo_surface_create_in_error (_cairo_error (CAIRO_STATUS_NO_MEMORY
));
102 crsurface
= cairo_glitz_surface_create (surface
);
104 glitz_surface_destroy (surface
);
109 static cairo_status_t
110 _cairo_glitz_get_boxes_from_region (cairo_region_t
*region
,
114 pixman_box32_t
*pboxes
;
115 cairo_status_t status
= CAIRO_STATUS_SUCCESS
;
120 pboxes
= pixman_region32_rectangles (®ion
->rgn
, &n
);
123 return CAIRO_STATUS_SUCCESS
;
127 *boxes
= _cairo_malloc_ab (n
, sizeof (glitz_box_t
));
128 if (*boxes
== NULL
) {
129 status
= _cairo_error (CAIRO_STATUS_NO_MEMORY
);
134 for (i
= 0; i
< n
; i
++) {
135 (*boxes
)[i
].x1
= pboxes
[i
].x1
;
136 (*boxes
)[i
].y1
= pboxes
[i
].y1
;
137 (*boxes
)[i
].x2
= pboxes
[i
].x2
;
138 (*boxes
)[i
].y2
= pboxes
[i
].y2
;
146 static cairo_status_t
147 _cairo_glitz_surface_get_image (cairo_glitz_surface_t
*surface
,
148 cairo_rectangle_int_t
*interest
,
149 cairo_image_surface_t
**image_out
,
150 cairo_rectangle_int_t
*rect_out
)
152 cairo_image_surface_t
*image
;
153 cairo_rectangle_int_t extents
;
154 cairo_format_t format
;
155 cairo_format_masks_t masks
;
156 glitz_buffer_t
*buffer
;
157 glitz_pixel_format_t pf
;
161 extents
.width
= glitz_surface_get_width (surface
->surface
);
162 extents
.height
= glitz_surface_get_height (surface
->surface
);
164 if (interest
!= NULL
) {
165 if (! _cairo_rectangle_intersect (&extents
, interest
)) {
167 return CAIRO_STATUS_SUCCESS
;
171 if (rect_out
!= NULL
)
174 if (surface
->format
->color
.fourcc
== GLITZ_FOURCC_RGB
) {
175 if (surface
->format
->color
.red_size
> 0) {
176 if (surface
->format
->color
.alpha_size
> 0)
177 format
= CAIRO_FORMAT_ARGB32
;
179 format
= CAIRO_FORMAT_RGB24
;
181 format
= CAIRO_FORMAT_A8
;
184 format
= CAIRO_FORMAT_ARGB32
;
186 image
= (cairo_image_surface_t
*)
187 cairo_image_surface_create (format
, extents
.width
, extents
.height
);
188 if (image
->base
.status
)
189 return image
->base
.status
;
191 _pixman_format_to_masks (image
->pixman_format
, &masks
);
192 pf
.fourcc
= GLITZ_FOURCC_RGB
;
193 pf
.masks
.bpp
= masks
.bpp
;
194 pf
.masks
.alpha_mask
= masks
.alpha_mask
;
195 pf
.masks
.red_mask
= masks
.red_mask
;
196 pf
.masks
.green_mask
= masks
.green_mask
;
197 pf
.masks
.blue_mask
= masks
.blue_mask
;
201 /* XXX: we should eventually return images with negative stride,
202 need to verify that libpixman have no problem with this first. */
203 pf
.bytes_per_line
= image
->stride
;
204 pf
.scanline_order
= GLITZ_PIXEL_SCANLINE_ORDER_TOP_DOWN
;
206 buffer
= glitz_buffer_create_for_data (image
->data
);
207 if (buffer
== NULL
) {
208 cairo_surface_destroy (&image
->base
);
209 return _cairo_error (CAIRO_STATUS_NO_MEMORY
);
212 /* clear out the glitz clip; the clip affects glitz_get_pixels */
213 if (surface
->has_clip
)
214 glitz_surface_set_clip_region (surface
->surface
,
217 glitz_get_pixels (surface
->surface
,
218 extents
.x
, extents
.y
,
219 extents
.width
, extents
.height
,
223 glitz_buffer_destroy (buffer
);
225 /* restore the clip, if any */
226 if (surface
->has_clip
) {
227 glitz_surface_set_clip_region (surface
->surface
,
230 surface
->num_clip_boxes
);
235 return CAIRO_STATUS_SUCCESS
;
238 static cairo_status_t
239 _cairo_glitz_surface_set_image (void *abstract_surface
,
240 cairo_image_surface_t
*image
,
248 cairo_glitz_surface_t
*surface
= abstract_surface
;
249 glitz_buffer_t
*buffer
;
250 glitz_pixel_format_t pf
;
251 cairo_format_masks_t masks
;
254 _pixman_format_to_masks (image
->pixman_format
, &masks
);
256 pf
.fourcc
= GLITZ_FOURCC_RGB
;
257 pf
.masks
.bpp
= masks
.bpp
;
258 pf
.masks
.alpha_mask
= masks
.alpha_mask
;
259 pf
.masks
.red_mask
= masks
.red_mask
;
260 pf
.masks
.green_mask
= masks
.green_mask
;
261 pf
.masks
.blue_mask
= masks
.blue_mask
;
263 pf
.skip_lines
= src_y
;
265 /* check for negative stride */
266 if (image
->stride
< 0) {
267 pf
.bytes_per_line
= -image
->stride
;
268 pf
.scanline_order
= GLITZ_PIXEL_SCANLINE_ORDER_BOTTOM_UP
;
269 data
= (char *) image
->data
+ image
->stride
* (image
->height
- 1);
271 pf
.bytes_per_line
= image
->stride
;
272 pf
.scanline_order
= GLITZ_PIXEL_SCANLINE_ORDER_TOP_DOWN
;
273 data
= (char *) image
->data
;
276 buffer
= glitz_buffer_create_for_data (data
);
278 return _cairo_error (CAIRO_STATUS_NO_MEMORY
);
280 glitz_set_pixels (surface
->surface
,
286 glitz_buffer_destroy (buffer
);
288 return CAIRO_STATUS_SUCCESS
;
291 static cairo_status_t
292 _cairo_glitz_surface_acquire_source_image (void *abstract_surface
,
293 cairo_image_surface_t
**image_out
,
296 cairo_glitz_surface_t
*surface
= abstract_surface
;
300 return _cairo_glitz_surface_get_image (surface
, NULL
, image_out
, NULL
);
303 static cairo_surface_t
*
304 _cairo_glitz_surface_snapshot (void *abstract_surface
)
306 cairo_glitz_surface_t
*surface
= abstract_surface
;
307 cairo_status_t status
;
308 cairo_image_surface_t
*image
;
310 status
= _cairo_glitz_surface_get_image (surface
, NULL
, &image
, NULL
);
311 if (unlikely (status
))
312 return _cairo_surface_create_in_error (status
);
318 _cairo_glitz_surface_release_source_image (void *abstract_surface
,
319 cairo_image_surface_t
*image
,
322 cairo_surface_destroy (&image
->base
);
325 static cairo_status_t
326 _cairo_glitz_surface_acquire_dest_image (void *abstract_surface
,
327 cairo_rectangle_int_t
*interest_rect
,
328 cairo_image_surface_t
**image_out
,
329 cairo_rectangle_int_t
*image_rect_out
,
332 cairo_glitz_surface_t
*surface
= abstract_surface
;
333 cairo_image_surface_t
*image
;
334 cairo_status_t status
;
336 status
= _cairo_glitz_surface_get_image (surface
, interest_rect
, &image
,
348 _cairo_glitz_surface_release_dest_image (void *abstract_surface
,
349 cairo_rectangle_int_t
*interest_rect
,
350 cairo_image_surface_t
*image
,
351 cairo_rectangle_int_t
*image_rect
,
354 cairo_glitz_surface_t
*surface
= abstract_surface
;
355 cairo_status_t status
;
357 status
= _cairo_glitz_surface_set_image (surface
, image
, 0, 0,
358 image
->width
, image
->height
,
359 image_rect
->x
, image_rect
->y
);
361 status
= _cairo_surface_set_error (&surface
->base
, status
);
363 cairo_surface_destroy (&image
->base
);
366 static cairo_status_t
367 _cairo_glitz_surface_clone_similar (void *abstract_surface
,
368 cairo_surface_t
*src
,
369 cairo_content_t content
,
376 cairo_surface_t
**clone_out
)
378 cairo_glitz_surface_t
*surface
= abstract_surface
;
379 cairo_glitz_surface_t
*clone
;
380 cairo_status_t status
;
382 if (surface
->base
.status
)
383 return surface
->base
.status
;
385 if (src
->backend
== surface
->base
.backend
)
389 *clone_out
= cairo_surface_reference (src
);
391 return CAIRO_STATUS_SUCCESS
;
393 else if (_cairo_surface_is_image (src
))
395 cairo_image_surface_t
*image_src
= (cairo_image_surface_t
*) src
;
397 clone
= (cairo_glitz_surface_t
*)
398 _cairo_glitz_surface_create_similar (surface
, src
->content
,
401 return CAIRO_INT_STATUS_UNSUPPORTED
;
402 if (clone
->base
.status
)
403 return clone
->base
.status
;
405 status
= _cairo_glitz_surface_set_image (clone
, image_src
,
410 cairo_surface_destroy (&clone
->base
);
414 *clone_out
= &clone
->base
;
415 *clone_offset_x
= src_x
;
416 *clone_offset_y
= src_y
;
417 return CAIRO_STATUS_SUCCESS
;
420 return CAIRO_INT_STATUS_UNSUPPORTED
;
424 _cairo_glitz_surface_set_matrix (cairo_glitz_surface_t
*surface
,
425 cairo_matrix_t
*matrix
)
427 glitz_transform_t transform
;
429 transform
.matrix
[0][0] = _cairo_fixed_16_16_from_double (matrix
->xx
);
430 transform
.matrix
[0][1] = _cairo_fixed_16_16_from_double (matrix
->xy
);
431 transform
.matrix
[0][2] = _cairo_fixed_16_16_from_double (matrix
->x0
);
433 transform
.matrix
[1][0] = _cairo_fixed_16_16_from_double (matrix
->yx
);
434 transform
.matrix
[1][1] = _cairo_fixed_16_16_from_double (matrix
->yy
);
435 transform
.matrix
[1][2] = _cairo_fixed_16_16_from_double (matrix
->y0
);
437 transform
.matrix
[2][0] = 0;
438 transform
.matrix
[2][1] = 0;
439 transform
.matrix
[2][2] = _cairo_fixed_16_16_from_double (1);
441 glitz_surface_set_transform (surface
->surface
, &transform
);
444 static glitz_operator_t
445 _glitz_operator (cairo_operator_t op
)
448 case CAIRO_OPERATOR_CLEAR
:
449 return GLITZ_OPERATOR_CLEAR
;
451 case CAIRO_OPERATOR_SOURCE
:
452 return GLITZ_OPERATOR_SRC
;
453 case CAIRO_OPERATOR_OVER
:
454 return GLITZ_OPERATOR_OVER
;
455 case CAIRO_OPERATOR_IN
:
456 return GLITZ_OPERATOR_IN
;
457 case CAIRO_OPERATOR_OUT
:
458 return GLITZ_OPERATOR_OUT
;
459 case CAIRO_OPERATOR_ATOP
:
460 return GLITZ_OPERATOR_ATOP
;
462 case CAIRO_OPERATOR_DEST
:
463 return GLITZ_OPERATOR_DST
;
464 case CAIRO_OPERATOR_DEST_OVER
:
465 return GLITZ_OPERATOR_OVER_REVERSE
;
466 case CAIRO_OPERATOR_DEST_IN
:
467 return GLITZ_OPERATOR_IN_REVERSE
;
468 case CAIRO_OPERATOR_DEST_OUT
:
469 return GLITZ_OPERATOR_OUT_REVERSE
;
470 case CAIRO_OPERATOR_DEST_ATOP
:
471 return GLITZ_OPERATOR_ATOP_REVERSE
;
473 case CAIRO_OPERATOR_XOR
:
474 return GLITZ_OPERATOR_XOR
;
475 case CAIRO_OPERATOR_ADD
:
476 return GLITZ_OPERATOR_ADD
;
477 case CAIRO_OPERATOR_SATURATE
:
478 /* XXX: This line should never be reached. Glitz backend should bail
479 out earlier if saturate operator is used. OpenGL can't do saturate
480 with pre-multiplied colors. Solid colors can still be done as we
481 can just un-pre-multiply them. However, support for that will have
482 to be added to glitz. */
490 /* Something's very broken if this line of code can be reached, so
491 we want to return something that would give a noticeably
492 incorrect result. The XOR operator seems so rearely desired
493 that it should fit the bill here. */
494 return CAIRO_OPERATOR_XOR
;
497 #define CAIRO_GLITZ_FEATURE_OK(surface, name) \
498 (glitz_drawable_get_features (glitz_surface_get_drawable (surface)) & \
499 (GLITZ_FEATURE_ ## name ## _MASK))
501 static glitz_status_t
502 _glitz_ensure_target (glitz_surface_t
*surface
)
504 if (!glitz_surface_get_attached_drawable (surface
))
506 glitz_drawable_format_t
*target_format
, templ
;
507 glitz_format_t
*format
;
508 glitz_drawable_t
*drawable
, *target
;
509 unsigned int width
, height
;
512 drawable
= glitz_surface_get_drawable (surface
);
513 format
= glitz_surface_get_format (surface
);
514 width
= glitz_surface_get_width (surface
);
515 height
= glitz_surface_get_height (surface
);
517 if (format
->color
.fourcc
!= GLITZ_FOURCC_RGB
)
518 return CAIRO_INT_STATUS_UNSUPPORTED
;
520 templ
.color
= format
->color
;
521 templ
.depth_size
= 0;
522 templ
.stencil_size
= 0;
523 templ
.doublebuffer
= 0;
527 GLITZ_FORMAT_RED_SIZE_MASK
|
528 GLITZ_FORMAT_GREEN_SIZE_MASK
|
529 GLITZ_FORMAT_BLUE_SIZE_MASK
|
530 GLITZ_FORMAT_ALPHA_SIZE_MASK
|
531 GLITZ_FORMAT_DEPTH_SIZE_MASK
|
532 GLITZ_FORMAT_STENCIL_SIZE_MASK
|
533 GLITZ_FORMAT_DOUBLEBUFFER_MASK
|
534 GLITZ_FORMAT_SAMPLES_MASK
;
536 target_format
= glitz_find_drawable_format (drawable
, mask
, &templ
, 0);
538 return CAIRO_INT_STATUS_UNSUPPORTED
;
540 target
= glitz_create_drawable (drawable
, target_format
,
543 return CAIRO_INT_STATUS_UNSUPPORTED
;
545 glitz_surface_attach (surface
, target
,
546 GLITZ_DRAWABLE_BUFFER_FRONT_COLOR
);
548 glitz_drawable_destroy (target
);
551 return CAIRO_STATUS_SUCCESS
;
554 typedef struct _cairo_glitz_surface_attributes
{
555 cairo_surface_attributes_t base
;
558 glitz_filter_t filter
;
559 glitz_fixed16_16_t
*params
;
561 cairo_bool_t acquired
;
562 } cairo_glitz_surface_attributes_t
;
564 static cairo_int_status_t
565 _cairo_glitz_pattern_acquire_surface (const cairo_pattern_t
*pattern
,
566 cairo_glitz_surface_t
*dst
,
571 cairo_glitz_surface_t
**surface_out
,
572 cairo_glitz_surface_attributes_t
*attr
)
574 cairo_glitz_surface_t
*src
= NULL
;
576 attr
->acquired
= FALSE
;
578 switch (pattern
->type
) {
579 case CAIRO_PATTERN_TYPE_LINEAR
:
580 case CAIRO_PATTERN_TYPE_RADIAL
: {
581 cairo_gradient_pattern_t
*gradient
=
582 (cairo_gradient_pattern_t
*) pattern
;
584 glitz_fixed16_16_t
*params
;
585 unsigned int n_params
;
586 unsigned int *pixels
;
587 unsigned int i
, n_base_params
;
588 glitz_buffer_t
*buffer
;
589 static const glitz_pixel_format_t format
= {
599 GLITZ_PIXEL_SCANLINE_ORDER_BOTTOM_UP
602 /* XXX: the current color gradient acceleration provided by glitz is
603 * experimental, it's been proven inappropriate in a number of ways,
604 * most importantly, it's currently implemented as filters and
605 * gradients are not filters. eventually, it will be replaced with
606 * something more appropriate.
609 if (gradient
->n_stops
< 2)
612 if (!CAIRO_GLITZ_FEATURE_OK (dst
->surface
, FRAGMENT_PROGRAM
))
615 if (pattern
->type
== CAIRO_PATTERN_TYPE_RADIAL
)
620 n_params
= gradient
->n_stops
* 3 + n_base_params
;
622 /* check for int overflow */
625 if (n_params
>= INT32_MAX
/ sizeof (glitz_fixed16_16_t
) ||
626 gradient
->n_stops
>= INT32_MAX
/ sizeof (unsigned int))
627 return _cairo_error (CAIRO_STATUS_NO_MEMORY
);
629 size1
= n_params
* sizeof (glitz_fixed16_16_t
);
630 size2
= gradient
->n_stops
* sizeof (unsigned int);
632 if (size1
>= INT32_MAX
- size2
)
633 return _cairo_error (CAIRO_STATUS_NO_MEMORY
);
635 data
= malloc (size1
+ size2
);
639 return _cairo_error (CAIRO_STATUS_NO_MEMORY
);
641 params
= (glitz_fixed16_16_t
*) data
;
642 pixels
= (unsigned int *)
643 (data
+ sizeof (glitz_fixed16_16_t
) * n_params
);
645 buffer
= glitz_buffer_create_for_data (pixels
);
648 return _cairo_error (CAIRO_STATUS_NO_MEMORY
);
651 src
= (cairo_glitz_surface_t
*)
652 _cairo_surface_create_similar_scratch (&dst
->base
,
653 CAIRO_CONTENT_COLOR_ALPHA
,
654 gradient
->n_stops
, 1);
655 if (src
->base
.status
) {
656 glitz_buffer_destroy (buffer
);
658 return src
->base
.status
;
661 for (i
= 0; i
< gradient
->n_stops
; i
++)
664 (((int) (gradient
->stops
[i
].color
.alpha_short
>> 8)) << 24) |
665 (((int) (gradient
->stops
[i
].color
.red_short
>> 8)) << 16) |
666 (((int) (gradient
->stops
[i
].color
.green_short
>> 8)) << 8) |
667 (((int) (gradient
->stops
[i
].color
.blue_short
>> 8)));
669 params
[n_base_params
+ 3 * i
+ 0] = _cairo_fixed_16_16_from_double (gradient
->stops
[i
].offset
);
670 params
[n_base_params
+ 3 * i
+ 1] = i
<< 16;
671 params
[n_base_params
+ 3 * i
+ 2] = 0;
674 glitz_set_pixels (src
->surface
, 0, 0, gradient
->n_stops
, 1,
675 (glitz_pixel_format_t
*)&format
, buffer
);
677 glitz_buffer_destroy (buffer
);
679 if (pattern
->type
== CAIRO_PATTERN_TYPE_LINEAR
)
681 cairo_linear_pattern_t
*grad
= (cairo_linear_pattern_t
*) pattern
;
683 params
[0] = _cairo_fixed_to_16_16 (grad
->p1
.x
);
684 params
[1] = _cairo_fixed_to_16_16 (grad
->p1
.y
);
685 params
[2] = _cairo_fixed_to_16_16 (grad
->p2
.x
);
686 params
[3] = _cairo_fixed_to_16_16 (grad
->p2
.y
);
687 attr
->filter
= GLITZ_FILTER_LINEAR_GRADIENT
;
691 cairo_radial_pattern_t
*grad
= (cairo_radial_pattern_t
*) pattern
;
693 params
[0] = _cairo_fixed_to_16_16 (grad
->c1
.x
);
694 params
[1] = _cairo_fixed_to_16_16 (grad
->c1
.y
);
695 params
[2] = _cairo_fixed_to_16_16 (grad
->r1
);
696 params
[3] = _cairo_fixed_to_16_16 (grad
->c2
.x
);
697 params
[4] = _cairo_fixed_to_16_16 (grad
->c2
.y
);
698 params
[5] = _cairo_fixed_to_16_16 (grad
->r2
);
699 attr
->filter
= GLITZ_FILTER_RADIAL_GRADIENT
;
702 switch (pattern
->extend
) {
703 case CAIRO_EXTEND_NONE
:
704 attr
->fill
= GLITZ_FILL_TRANSPARENT
;
706 case CAIRO_EXTEND_REPEAT
:
707 attr
->fill
= GLITZ_FILL_REPEAT
;
709 case CAIRO_EXTEND_REFLECT
:
710 attr
->fill
= GLITZ_FILL_REFLECT
;
712 case CAIRO_EXTEND_PAD
:
713 attr
->fill
= GLITZ_FILL_NEAREST
;
717 attr
->params
= params
;
718 attr
->n_params
= n_params
;
719 attr
->base
.matrix
= pattern
->matrix
;
720 attr
->base
.x_offset
= 0;
721 attr
->base
.y_offset
= 0;
723 case CAIRO_PATTERN_TYPE_SOLID
:
724 case CAIRO_PATTERN_TYPE_SURFACE
:
731 cairo_int_status_t status
;
733 status
= _cairo_pattern_acquire_surface (pattern
, &dst
->base
,
734 CAIRO_CONTENT_COLOR_ALPHA
,
736 CAIRO_PATTERN_ACQUIRE_NONE
,
737 (cairo_surface_t
**) &src
,
744 switch (attr
->base
.extend
) {
745 case CAIRO_EXTEND_NONE
:
746 attr
->fill
= GLITZ_FILL_TRANSPARENT
;
748 case CAIRO_EXTEND_REPEAT
:
749 attr
->fill
= GLITZ_FILL_REPEAT
;
751 case CAIRO_EXTEND_REFLECT
:
752 attr
->fill
= GLITZ_FILL_REFLECT
;
754 case CAIRO_EXTEND_PAD
:
756 attr
->fill
= GLITZ_FILL_NEAREST
;
760 switch (attr
->base
.filter
) {
761 case CAIRO_FILTER_FAST
:
762 case CAIRO_FILTER_NEAREST
:
763 attr
->filter
= GLITZ_FILTER_NEAREST
;
765 case CAIRO_FILTER_GOOD
:
766 case CAIRO_FILTER_BEST
:
767 case CAIRO_FILTER_BILINEAR
:
768 case CAIRO_FILTER_GAUSSIAN
:
770 attr
->filter
= GLITZ_FILTER_BILINEAR
;
776 attr
->acquired
= TRUE
;
782 return CAIRO_STATUS_SUCCESS
;
786 _cairo_glitz_pattern_release_surface (const cairo_pattern_t
*pattern
,
787 cairo_glitz_surface_t
*surface
,
788 cairo_glitz_surface_attributes_t
*attr
)
791 _cairo_pattern_release_surface (pattern
, &surface
->base
, &attr
->base
);
793 cairo_surface_destroy (&surface
->base
);
796 static cairo_int_status_t
797 _cairo_glitz_pattern_acquire_surfaces (const cairo_pattern_t
*src
,
798 const cairo_pattern_t
*mask
,
799 cairo_glitz_surface_t
*dst
,
806 cairo_glitz_surface_t
**src_out
,
807 cairo_glitz_surface_t
**mask_out
,
808 cairo_glitz_surface_attributes_t
*sattr
,
809 cairo_glitz_surface_attributes_t
*mattr
)
811 cairo_int_status_t status
;
812 cairo_solid_pattern_t tmp
;
814 /* If src and mask are both solid, then the mask alpha can be
815 * combined into src and mask can be ignored. */
817 /* XXX: This optimization assumes that there is no color
818 * information in mask, so this will need to change when we
819 * support RENDER-style 4-channel masks. */
821 if (src
->type
== CAIRO_PATTERN_TYPE_SOLID
&&
822 mask
->type
== CAIRO_PATTERN_TYPE_SOLID
)
824 cairo_color_t combined
;
825 cairo_solid_pattern_t
*src_solid
= (cairo_solid_pattern_t
*) src
;
826 cairo_solid_pattern_t
*mask_solid
= (cairo_solid_pattern_t
*) mask
;
828 combined
= src_solid
->color
;
829 _cairo_color_multiply_alpha (&combined
, mask_solid
->color
.alpha
);
831 _cairo_pattern_init_solid (&tmp
, &combined
, CAIRO_CONTENT_COLOR_ALPHA
);
837 status
= _cairo_glitz_pattern_acquire_surface (src
, dst
,
842 if (src
== &tmp
.base
)
843 _cairo_pattern_fini (&tmp
.base
);
850 status
= _cairo_glitz_pattern_acquire_surface (mask
, dst
,
856 /* XXX src == &tmp.base -> invalid (currently inconsequential) */
857 _cairo_glitz_pattern_release_surface (src
, *src_out
, sattr
);
867 return CAIRO_STATUS_SUCCESS
;
871 _cairo_glitz_surface_set_attributes (cairo_glitz_surface_t
*surface
,
872 cairo_glitz_surface_attributes_t
*a
)
874 _cairo_glitz_surface_set_matrix (surface
, &a
->base
.matrix
);
875 glitz_surface_set_fill (surface
->surface
, a
->fill
);
876 glitz_surface_set_filter (surface
->surface
, a
->filter
,
877 a
->params
, a
->n_params
);
880 static cairo_int_status_t
881 _cairo_glitz_surface_composite (cairo_operator_t op
,
882 const cairo_pattern_t
*src_pattern
,
883 const cairo_pattern_t
*mask_pattern
,
894 cairo_glitz_surface_attributes_t src_attr
, mask_attr
;
895 cairo_glitz_surface_t
*dst
= abstract_dst
;
896 cairo_glitz_surface_t
*src
;
897 cairo_glitz_surface_t
*mask
;
898 cairo_int_status_t status
;
900 if (op
== CAIRO_OPERATOR_SATURATE
)
901 return CAIRO_INT_STATUS_UNSUPPORTED
;
903 if (_glitz_ensure_target (dst
->surface
))
904 return CAIRO_INT_STATUS_UNSUPPORTED
;
906 status
= _cairo_glitz_pattern_acquire_surfaces (src_pattern
, mask_pattern
,
912 &src_attr
, &mask_attr
);
916 _cairo_glitz_surface_set_attributes (src
, &src_attr
);
919 _cairo_glitz_surface_set_attributes (mask
, &mask_attr
);
920 glitz_composite (_glitz_operator (op
),
924 src_x
+ src_attr
.base
.x_offset
,
925 src_y
+ src_attr
.base
.y_offset
,
926 mask_x
+ mask_attr
.base
.x_offset
,
927 mask_y
+ mask_attr
.base
.y_offset
,
933 glitz_composite (_glitz_operator (op
),
937 src_x
+ src_attr
.base
.x_offset
,
938 src_y
+ src_attr
.base
.y_offset
,
944 if (glitz_surface_get_status (dst
->surface
) == GLITZ_STATUS_NOT_SUPPORTED
)
945 status
= CAIRO_INT_STATUS_UNSUPPORTED
;
947 if (status
== CAIRO_STATUS_SUCCESS
&&
948 ! _cairo_operator_bounded_by_source (op
))
950 int src_width
, src_height
;
951 int mask_width
, mask_height
;
953 src_width
= glitz_surface_get_width (src
->surface
);
954 src_height
= glitz_surface_get_height (src
->surface
);
957 mask_width
= glitz_surface_get_width (mask
->surface
);
958 mask_height
= glitz_surface_get_height (mask
->surface
);
965 status
= _cairo_surface_composite_fixup_unbounded (&dst
->base
,
967 src_width
, src_height
,
968 mask
? &mask_attr
.base
: NULL
,
969 mask_width
, mask_height
,
972 dst_x
, dst_y
, width
, height
);
977 if (mask_attr
.n_params
)
978 free (mask_attr
.params
);
980 _cairo_glitz_pattern_release_surface (mask_pattern
, mask
, &mask_attr
);
983 if (src_attr
.n_params
)
984 free (src_attr
.params
);
986 _cairo_glitz_pattern_release_surface (src_pattern
, src
, &src_attr
);
988 return CAIRO_STATUS_SUCCESS
;
991 static cairo_int_status_t
992 _cairo_glitz_surface_fill_rectangles (void *abstract_dst
,
994 const cairo_color_t
*color
,
995 cairo_rectangle_int_t
*rects
,
998 cairo_glitz_surface_t
*dst
= abstract_dst
;
999 cairo_glitz_surface_t
*src
;
1000 glitz_rectangle_t stack_rects
[CAIRO_STACK_ARRAY_LENGTH (glitz_rectangle_t
)];
1001 glitz_rectangle_t
*glitz_rects
= stack_rects
;
1002 glitz_rectangle_t
*current_rect
;
1005 if (n_rects
> ARRAY_LENGTH (stack_rects
)) {
1006 glitz_rects
= _cairo_malloc_ab (n_rects
, sizeof (glitz_rectangle_t
));
1007 if (glitz_rects
== NULL
)
1008 return _cairo_error (CAIRO_STATUS_NO_MEMORY
);
1011 for (i
= 0; i
< n_rects
; i
++) {
1012 glitz_rects
[i
].x
= rects
[i
].x
;
1013 glitz_rects
[i
].y
= rects
[i
].y
;
1014 glitz_rects
[i
].width
= rects
[i
].width
;
1015 glitz_rects
[i
].height
= rects
[i
].height
;
1019 case CAIRO_OPERATOR_CLEAR
:
1020 case CAIRO_OPERATOR_SOURCE
: {
1021 glitz_color_t glitz_color
;
1022 glitz_format_t
*format
;
1024 glitz_color
.red
= color
->red_short
;
1025 glitz_color
.green
= color
->green_short
;
1026 glitz_color
.blue
= color
->blue_short
;
1027 glitz_color
.alpha
= color
->alpha_short
;
1030 * XXX even if the dst surface don't have an alpha channel, the
1031 * above alpha still effect the dst surface because the
1032 * underlying glitz drawable may have an alpha channel. So
1033 * replacing the color with an opaque one is needed.
1035 format
= glitz_surface_get_format (dst
->surface
);
1036 if (format
->color
.alpha_size
== 0)
1037 glitz_color
.alpha
= 0xffff;
1039 glitz_set_rectangles (dst
->surface
, &glitz_color
,
1040 glitz_rects
, n_rects
);
1042 case CAIRO_OPERATOR_SATURATE
:
1043 return CAIRO_INT_STATUS_UNSUPPORTED
;
1044 case CAIRO_OPERATOR_OVER
:
1045 case CAIRO_OPERATOR_IN
:
1046 case CAIRO_OPERATOR_OUT
:
1047 case CAIRO_OPERATOR_ATOP
:
1048 case CAIRO_OPERATOR_DEST
:
1049 case CAIRO_OPERATOR_DEST_OVER
:
1050 case CAIRO_OPERATOR_DEST_IN
:
1051 case CAIRO_OPERATOR_DEST_OUT
:
1052 case CAIRO_OPERATOR_DEST_ATOP
:
1053 case CAIRO_OPERATOR_XOR
:
1054 case CAIRO_OPERATOR_ADD
:
1056 if (_glitz_ensure_target (dst
->surface
))
1058 if (glitz_rects
!= stack_rects
)
1060 return CAIRO_INT_STATUS_UNSUPPORTED
;
1063 src
= (cairo_glitz_surface_t
*)
1064 _cairo_surface_create_similar_solid (&dst
->base
,
1065 CAIRO_CONTENT_COLOR_ALPHA
,
1067 (cairo_color_t
*) color
);
1068 if (src
->base
.status
)
1070 if (glitz_rects
!= stack_rects
)
1072 return src
->base
.status
;
1075 glitz_surface_set_fill (src
->surface
, GLITZ_FILL_REPEAT
);
1077 current_rect
= glitz_rects
;
1080 glitz_composite (_glitz_operator (op
),
1086 current_rect
->x
, current_rect
->y
,
1087 current_rect
->width
, current_rect
->height
);
1091 cairo_surface_destroy (&src
->base
);
1095 if (glitz_rects
!= stack_rects
)
1098 if (glitz_surface_get_status (dst
->surface
) == GLITZ_STATUS_NOT_SUPPORTED
)
1099 return CAIRO_INT_STATUS_UNSUPPORTED
;
1101 return CAIRO_STATUS_SUCCESS
;
1104 static cairo_int_status_t
1105 _cairo_glitz_surface_composite_trapezoids (cairo_operator_t op
,
1106 const cairo_pattern_t
*pattern
,
1108 cairo_antialias_t antialias
,
1114 unsigned int height
,
1115 cairo_trapezoid_t
*traps
,
1118 cairo_glitz_surface_attributes_t attributes
;
1119 cairo_glitz_surface_t
*dst
= abstract_dst
;
1120 cairo_glitz_surface_t
*src
;
1121 cairo_glitz_surface_t
*mask
= NULL
;
1122 glitz_buffer_t
*buffer
= NULL
;
1124 cairo_int_status_t status
;
1125 unsigned short alpha
;
1126 pixman_trapezoid_t stack_traps
[CAIRO_STACK_ARRAY_LENGTH (pixman_trapezoid_t
)];
1127 pixman_trapezoid_t
*pixman_traps
= stack_traps
;
1130 if (antialias
== CAIRO_ANTIALIAS_NONE
)
1132 return CAIRO_INT_STATUS_UNSUPPORTED
;
1135 if (op
== CAIRO_OPERATOR_SATURATE
)
1136 return CAIRO_INT_STATUS_UNSUPPORTED
;
1138 if (_glitz_ensure_target (dst
->surface
))
1139 return CAIRO_INT_STATUS_UNSUPPORTED
;
1141 /* Convert traps to pixman traps */
1142 if (n_traps
> ARRAY_LENGTH (stack_traps
)) {
1143 pixman_traps
= _cairo_malloc_ab (n_traps
, sizeof (pixman_trapezoid_t
));
1144 if (pixman_traps
== NULL
)
1145 return _cairo_error (CAIRO_STATUS_NO_MEMORY
);
1148 for (i
= 0; i
< n_traps
; i
++) {
1149 pixman_traps
[i
].top
= _cairo_fixed_to_16_16 (traps
[i
].top
);
1150 pixman_traps
[i
].bottom
= _cairo_fixed_to_16_16 (traps
[i
].bottom
);
1151 pixman_traps
[i
].left
.p1
.x
= _cairo_fixed_to_16_16 (traps
[i
].left
.p1
.x
);
1152 pixman_traps
[i
].left
.p1
.y
= _cairo_fixed_to_16_16 (traps
[i
].left
.p1
.y
);
1153 pixman_traps
[i
].left
.p2
.x
= _cairo_fixed_to_16_16 (traps
[i
].left
.p2
.x
);
1154 pixman_traps
[i
].left
.p2
.y
= _cairo_fixed_to_16_16 (traps
[i
].left
.p2
.y
);
1155 pixman_traps
[i
].right
.p1
.x
= _cairo_fixed_to_16_16 (traps
[i
].right
.p1
.x
);
1156 pixman_traps
[i
].right
.p1
.y
= _cairo_fixed_to_16_16 (traps
[i
].right
.p1
.y
);
1157 pixman_traps
[i
].right
.p2
.x
= _cairo_fixed_to_16_16 (traps
[i
].right
.p2
.x
);
1158 pixman_traps
[i
].right
.p2
.y
= _cairo_fixed_to_16_16 (traps
[i
].right
.p2
.y
);
1161 status
= _cairo_glitz_pattern_acquire_surface (pattern
, dst
,
1170 if (op
== CAIRO_OPERATOR_ADD
|| n_traps
<= 1) {
1171 static const glitz_color_t clear_black
= { 0, 0, 0, 0 };
1172 glitz_color_t color
;
1173 glitz_geometry_format_t format
;
1177 int size
= 30 * n_traps
; /* just a guess */
1179 format
.vertex
.primitive
= GLITZ_PRIMITIVE_QUADS
;
1180 format
.vertex
.type
= GLITZ_DATA_TYPE_FLOAT
;
1181 format
.vertex
.bytes_per_vertex
= 3 * sizeof (glitz_float_t
);
1182 format
.vertex
.attributes
= GLITZ_VERTEX_ATTRIBUTE_MASK_COORD_MASK
;
1183 format
.vertex
.mask
.type
= GLITZ_DATA_TYPE_FLOAT
;
1184 format
.vertex
.mask
.size
= GLITZ_COORDINATE_SIZE_X
;
1185 format
.vertex
.mask
.offset
= 2 * sizeof (glitz_float_t
);
1187 mask
= (cairo_glitz_surface_t
*)
1188 _cairo_glitz_surface_create_similar (&dst
->base
,
1189 CAIRO_CONTENT_ALPHA
,
1192 status
= CAIRO_INT_STATUS_UNSUPPORTED
;
1195 if (mask
->base
.status
) {
1196 status
= mask
->base
.status
;
1200 color
.red
= color
.green
= color
.blue
= color
.alpha
= 0xffff;
1202 glitz_set_rectangle (mask
->surface
, &clear_black
, 0, 0, 1, 1);
1203 glitz_set_rectangle (mask
->surface
, &color
, 1, 0, 1, 1);
1205 glitz_surface_set_fill (mask
->surface
, GLITZ_FILL_NEAREST
);
1206 glitz_surface_set_filter (mask
->surface
,
1207 GLITZ_FILTER_BILINEAR
,
1210 size
*= format
.vertex
.bytes_per_vertex
;
1213 if (data_size
< size
) {
1217 p
= realloc (data
, data_size
);
1219 status
= _cairo_error (CAIRO_STATUS_NO_MEMORY
);
1225 glitz_buffer_destroy (buffer
);
1227 buffer
= glitz_buffer_create_for_data (data
);
1228 if (buffer
== NULL
) {
1229 status
= _cairo_error (CAIRO_STATUS_NO_MEMORY
);
1236 glitz_add_trapezoids (buffer
,
1237 offset
, size
- offset
,
1238 format
.vertex
.type
, mask
->surface
,
1239 (glitz_trapezoid_t
*) pixman_traps
, n_traps
,
1242 n_traps
-= n_trap_added
;
1243 traps
+= n_trap_added
;
1247 glitz_set_geometry (dst
->surface
,
1248 GLITZ_GEOMETRY_TYPE_VERTEX
,
1250 glitz_set_array (dst
->surface
, 0, 3,
1251 offset
/ format
.vertex
.bytes_per_vertex
,
1254 cairo_image_surface_t
*image
;
1258 stride
= (width
+ 3) & -4;
1259 data
= calloc (stride
, height
);
1261 status
= _cairo_error (CAIRO_STATUS_NO_MEMORY
);
1265 /* using negative stride */
1266 ptr
= (unsigned char *) data
+ stride
* (height
- 1);
1268 image
= (cairo_image_surface_t
*)
1269 cairo_image_surface_create_for_data (ptr
,
1273 status
= image
->base
.status
;
1279 pixman_add_trapezoids (image
->pixman_image
, -dst_x
, -dst_y
,
1280 n_traps
, (pixman_trapezoid_t
*) pixman_traps
);
1282 mask
= (cairo_glitz_surface_t
*)
1283 _cairo_surface_create_similar_scratch (&dst
->base
,
1284 CAIRO_CONTENT_ALPHA
,
1286 status
= mask
->base
.status
;
1289 cairo_surface_destroy (&image
->base
);
1293 status
= _cairo_glitz_surface_set_image (mask
, image
,
1294 0, 0, width
, height
, 0, 0);
1296 cairo_surface_destroy (&image
->base
);
1302 _cairo_glitz_surface_set_attributes (src
, &attributes
);
1304 glitz_composite (_glitz_operator (op
),
1308 src_x
+ attributes
.base
.x_offset
,
1309 src_y
+ attributes
.base
.y_offset
,
1314 if (attributes
.n_params
)
1315 free (attributes
.params
);
1317 glitz_set_geometry (dst
->surface
,
1318 GLITZ_GEOMETRY_TYPE_NONE
,
1322 glitz_buffer_destroy (buffer
);
1326 if (glitz_surface_get_status (dst
->surface
) == GLITZ_STATUS_NOT_SUPPORTED
) {
1327 status
= CAIRO_INT_STATUS_UNSUPPORTED
;
1331 if (! _cairo_operator_bounded_by_mask (op
)) {
1332 status
= _cairo_surface_composite_shape_fixup_unbounded (&dst
->base
,
1334 glitz_surface_get_width (src
->surface
),
1335 glitz_surface_get_height (src
->surface
),
1344 _cairo_glitz_pattern_release_surface (pattern
, src
, &attributes
);
1347 cairo_surface_destroy (&mask
->base
);
1349 if (pixman_traps
!= stack_traps
)
1350 free (pixman_traps
);
1355 static cairo_int_status_t
1356 _cairo_glitz_surface_set_clip_region (void *abstract_surface
,
1357 cairo_region_t
*region
)
1359 cairo_glitz_surface_t
*surface
= abstract_surface
;
1361 if (region
!= NULL
) {
1362 cairo_status_t status
;
1364 status
= _cairo_glitz_get_boxes_from_region (region
,
1365 &surface
->clip_boxes
,
1366 &surface
->num_clip_boxes
);
1370 glitz_surface_set_clip_region (surface
->surface
,
1372 surface
->clip_boxes
,
1373 surface
->num_clip_boxes
);
1374 surface
->has_clip
= TRUE
;
1376 glitz_surface_set_clip_region (surface
->surface
, 0, 0, NULL
, 0);
1377 surface
->has_clip
= FALSE
;
1380 return CAIRO_STATUS_SUCCESS
;
1383 static cairo_int_status_t
1384 _cairo_glitz_surface_get_extents (void *abstract_surface
,
1385 cairo_rectangle_int_t
*rectangle
)
1387 cairo_glitz_surface_t
*surface
= abstract_surface
;
1391 rectangle
->width
= glitz_surface_get_width (surface
->surface
);
1392 rectangle
->height
= glitz_surface_get_height (surface
->surface
);
1394 return CAIRO_STATUS_SUCCESS
;
1397 #define CAIRO_GLITZ_AREA_AVAILABLE 0
1398 #define CAIRO_GLITZ_AREA_DIVIDED 1
1399 #define CAIRO_GLITZ_AREA_OCCUPIED 2
1401 typedef struct _cairo_glitz_root_area cairo_glitz_root_area_t
;
1403 typedef struct _cairo_glitz_area
{
1408 struct _cairo_glitz_area
*area
[4];
1409 cairo_glitz_root_area_t
*root
;
1411 } cairo_glitz_area_t
;
1413 static cairo_glitz_area_t _empty_area
= {
1415 { NULL
, NULL
, NULL
, NULL
},
1420 typedef struct _cairo_glitz_area_funcs
{
1421 cairo_status_t (*move_in
) (cairo_glitz_area_t
*area
,
1424 void (*move_out
) (cairo_glitz_area_t
*area
,
1427 int (*compare_score
) (cairo_glitz_area_t
*area
,
1430 } cairo_glitz_area_funcs_t
;
1432 struct _cairo_glitz_root_area
{
1435 cairo_glitz_area_t
*area
;
1436 const cairo_glitz_area_funcs_t
*funcs
;
1439 static cairo_status_t
1440 _cairo_glitz_area_move_in (cairo_glitz_area_t
*area
,
1443 area
->closure
= closure
;
1444 area
->state
= CAIRO_GLITZ_AREA_OCCUPIED
;
1446 return (*area
->root
->funcs
->move_in
) (area
, area
->closure
);
1450 _cairo_glitz_area_move_out (cairo_glitz_area_t
*area
)
1454 (*area
->root
->funcs
->move_out
) (area
, area
->closure
);
1456 area
->closure
= NULL
;
1457 area
->state
= CAIRO_GLITZ_AREA_AVAILABLE
;
1461 static cairo_glitz_area_t
*
1462 _cairo_glitz_area_create (cairo_glitz_root_area_t
*root
,
1469 cairo_glitz_area_t
*area
;
1472 area
= malloc (sizeof (cairo_glitz_area_t
));
1474 _cairo_error_throw (CAIRO_STATUS_NO_MEMORY
);
1478 area
->level
= level
;
1481 area
->width
= width
;
1482 area
->height
= height
;
1484 area
->closure
= NULL
;
1485 area
->state
= CAIRO_GLITZ_AREA_AVAILABLE
;
1488 area
->area
[n
] = NULL
;
1494 _cairo_glitz_area_destroy (cairo_glitz_area_t
*area
)
1499 if (area
->state
== CAIRO_GLITZ_AREA_OCCUPIED
)
1501 _cairo_glitz_area_move_out (area
);
1508 _cairo_glitz_area_destroy (area
->area
[n
]);
1514 static cairo_glitz_area_t
*
1515 _cairo_glitz_area_get_top_scored_sub_area (cairo_glitz_area_t
*area
)
1520 switch (area
->state
) {
1521 case CAIRO_GLITZ_AREA_OCCUPIED
:
1523 case CAIRO_GLITZ_AREA_AVAILABLE
:
1525 case CAIRO_GLITZ_AREA_DIVIDED
: {
1526 cairo_glitz_area_t
*tmp
, *top
= NULL
;
1529 for (i
= 0; i
< 4; i
++)
1531 tmp
= _cairo_glitz_area_get_top_scored_sub_area (area
->area
[i
]);
1534 if ((*area
->root
->funcs
->compare_score
) (tmp
,
1551 static cairo_int_status_t
1552 _cairo_glitz_area_find (cairo_glitz_area_t
*area
,
1555 cairo_bool_t kick_out
,
1558 cairo_status_t status
;
1560 if (area
->width
< width
|| area
->height
< height
)
1561 return CAIRO_INT_STATUS_UNSUPPORTED
;
1563 switch (area
->state
) {
1564 case CAIRO_GLITZ_AREA_OCCUPIED
:
1567 if ((*area
->root
->funcs
->compare_score
) (area
,
1570 return CAIRO_INT_STATUS_UNSUPPORTED
;
1572 _cairo_glitz_area_move_out (area
);
1574 return CAIRO_INT_STATUS_UNSUPPORTED
;
1578 case CAIRO_GLITZ_AREA_AVAILABLE
: {
1579 if (area
->level
== area
->root
->max_level
||
1580 (area
->width
== width
&& area
->height
== height
))
1582 return _cairo_glitz_area_move_in (area
, closure
);
1586 int dx
[4], dy
[4], w
[4], h
[4], i
;
1588 dx
[0] = dx
[2] = dy
[0] = dy
[1] = 0;
1590 w
[0] = w
[2] = dx
[1] = dx
[3] = width
;
1591 h
[0] = h
[1] = dy
[2] = dy
[3] = height
;
1593 w
[1] = w
[3] = area
->width
- width
;
1594 h
[2] = h
[3] = area
->height
- height
;
1596 for (i
= 0; i
< 2; i
++)
1600 _cairo_glitz_area_create (area
->root
,
1611 _cairo_glitz_area_create (area
->root
,
1618 area
->state
= CAIRO_GLITZ_AREA_DIVIDED
;
1620 status
= _cairo_glitz_area_find (area
->area
[0],
1623 if (status
== CAIRO_STATUS_SUCCESS
)
1624 return CAIRO_STATUS_SUCCESS
;
1627 case CAIRO_GLITZ_AREA_DIVIDED
: {
1628 cairo_glitz_area_t
*to_area
;
1629 int i
, rejected
= FALSE
;
1631 for (i
= 0; i
< 4; i
++)
1635 if (area
->area
[i
]->width
>= width
&&
1636 area
->area
[i
]->height
>= height
)
1638 status
= _cairo_glitz_area_find (area
->area
[i
],
1641 if (status
== CAIRO_STATUS_SUCCESS
)
1642 return CAIRO_STATUS_SUCCESS
;
1650 return CAIRO_INT_STATUS_UNSUPPORTED
;
1652 to_area
= _cairo_glitz_area_get_top_scored_sub_area (area
);
1657 if ((*area
->root
->funcs
->compare_score
) (to_area
,
1660 return CAIRO_INT_STATUS_UNSUPPORTED
;
1662 return CAIRO_INT_STATUS_UNSUPPORTED
;
1666 for (i
= 0; i
< 4; i
++)
1668 _cairo_glitz_area_destroy (area
->area
[i
]);
1669 area
->area
[i
] = NULL
;
1672 area
->closure
= NULL
;
1673 area
->state
= CAIRO_GLITZ_AREA_AVAILABLE
;
1675 status
= _cairo_glitz_area_find (area
, width
, height
,
1677 if (status
== CAIRO_STATUS_SUCCESS
)
1678 return CAIRO_STATUS_SUCCESS
;
1683 return CAIRO_INT_STATUS_UNSUPPORTED
;
1686 static cairo_status_t
1687 _cairo_glitz_root_area_init (cairo_glitz_root_area_t
*root
,
1691 const cairo_glitz_area_funcs_t
*funcs
)
1693 root
->max_level
= max_level
;
1694 root
->funcs
= funcs
;
1696 root
->area
= _cairo_glitz_area_create (root
, 0, 0, 0, width
, height
);
1698 return _cairo_error (CAIRO_STATUS_NO_MEMORY
);
1700 return CAIRO_STATUS_SUCCESS
;
1704 _cairo_glitz_root_area_fini (cairo_glitz_root_area_t
*root
)
1706 _cairo_glitz_area_destroy (root
->area
);
1709 typedef struct _cairo_glitz_surface_font_private
{
1710 cairo_glitz_root_area_t root
;
1711 glitz_surface_t
*surface
;
1712 } cairo_glitz_surface_font_private_t
;
1714 typedef struct _cairo_glitz_surface_glyph_private
{
1715 cairo_glitz_area_t
*area
;
1716 cairo_bool_t locked
;
1717 cairo_point_double_t p1
, p2
;
1718 } cairo_glitz_surface_glyph_private_t
;
1720 static cairo_status_t
1721 _cairo_glitz_glyph_move_in (cairo_glitz_area_t
*area
,
1724 cairo_glitz_surface_glyph_private_t
*glyph_private
= closure
;
1726 glyph_private
->area
= area
;
1728 return CAIRO_STATUS_SUCCESS
;
1732 _cairo_glitz_glyph_move_out (cairo_glitz_area_t
*area
,
1735 cairo_glitz_surface_glyph_private_t
*glyph_private
= closure
;
1737 glyph_private
->area
= NULL
;
1741 _cairo_glitz_glyph_compare (cairo_glitz_area_t
*area
,
1745 cairo_glitz_surface_glyph_private_t
*glyph_private
= closure1
;
1747 if (glyph_private
->locked
)
1753 static const cairo_glitz_area_funcs_t _cairo_glitz_area_funcs
= {
1754 _cairo_glitz_glyph_move_in
,
1755 _cairo_glitz_glyph_move_out
,
1756 _cairo_glitz_glyph_compare
1759 #define GLYPH_CACHE_TEXTURE_SIZE 512
1760 #define GLYPH_CACHE_MAX_LEVEL 64
1761 #define GLYPH_CACHE_MAX_HEIGHT 96
1762 #define GLYPH_CACHE_MAX_WIDTH 96
1764 #define WRITE_VEC2(ptr, _x, _y) \
1768 #define WRITE_BOX(ptr, _vx1, _vy1, _vx2, _vy2, p1, p2) \
1769 WRITE_VEC2 (ptr, _vx1, _vy1); \
1770 WRITE_VEC2 (ptr, (p1)->x, (p2)->y); \
1771 WRITE_VEC2 (ptr, _vx2, _vy1); \
1772 WRITE_VEC2 (ptr, (p2)->x, (p2)->y); \
1773 WRITE_VEC2 (ptr, _vx2, _vy2); \
1774 WRITE_VEC2 (ptr, (p2)->x, (p1)->y); \
1775 WRITE_VEC2 (ptr, _vx1, _vy2); \
1776 WRITE_VEC2 (ptr, (p1)->x, (p1)->y)
1778 static cairo_status_t
1779 _cairo_glitz_surface_font_init (cairo_glitz_surface_t
*surface
,
1780 cairo_scaled_font_t
*scaled_font
,
1781 cairo_format_t format
)
1783 cairo_glitz_surface_font_private_t
*font_private
;
1784 glitz_drawable_t
*drawable
;
1785 glitz_format_t
*surface_format
= NULL
;
1786 cairo_int_status_t status
;
1788 drawable
= glitz_surface_get_drawable (surface
->surface
);
1791 case CAIRO_FORMAT_A1
:
1792 case CAIRO_FORMAT_A8
:
1794 glitz_find_standard_format (drawable
, GLITZ_STANDARD_A8
);
1796 case CAIRO_FORMAT_RGB24
:
1799 case CAIRO_FORMAT_ARGB32
:
1801 glitz_find_standard_format (drawable
, GLITZ_STANDARD_ARGB32
);
1806 if (!surface_format
)
1807 return CAIRO_INT_STATUS_UNSUPPORTED
;
1809 font_private
= malloc (sizeof (cairo_glitz_surface_font_private_t
));
1811 return _cairo_error (CAIRO_STATUS_NO_MEMORY
);
1813 font_private
->surface
= glitz_surface_create (drawable
, surface_format
,
1814 GLYPH_CACHE_TEXTURE_SIZE
,
1815 GLYPH_CACHE_TEXTURE_SIZE
,
1817 if (font_private
->surface
== NULL
)
1819 free (font_private
);
1821 return CAIRO_INT_STATUS_UNSUPPORTED
;
1824 if (format
== CAIRO_FORMAT_ARGB32
)
1825 glitz_surface_set_component_alpha (font_private
->surface
, 1);
1827 status
= _cairo_glitz_root_area_init (&font_private
->root
,
1828 GLYPH_CACHE_MAX_LEVEL
,
1829 GLYPH_CACHE_TEXTURE_SIZE
,
1830 GLYPH_CACHE_TEXTURE_SIZE
,
1831 &_cairo_glitz_area_funcs
);
1832 if (status
!= CAIRO_STATUS_SUCCESS
)
1834 glitz_surface_destroy (font_private
->surface
);
1835 free (font_private
);
1840 scaled_font
->surface_private
= font_private
;
1841 scaled_font
->surface_backend
= _cairo_glitz_surface_get_backend ();
1843 return CAIRO_STATUS_SUCCESS
;
1847 _cairo_glitz_surface_scaled_font_fini (cairo_scaled_font_t
*scaled_font
)
1849 cairo_glitz_surface_font_private_t
*font_private
;
1851 font_private
= scaled_font
->surface_private
;
1854 _cairo_glitz_root_area_fini (&font_private
->root
);
1855 glitz_surface_destroy (font_private
->surface
);
1856 free (font_private
);
1861 _cairo_glitz_surface_scaled_glyph_fini (cairo_scaled_glyph_t
*scaled_glyph
,
1862 cairo_scaled_font_t
*scaled_font
)
1864 cairo_glitz_surface_glyph_private_t
*glyph_private
;
1866 glyph_private
= scaled_glyph
->surface_private
;
1869 if (glyph_private
->area
)
1870 _cairo_glitz_area_move_out (glyph_private
->area
);
1872 free (glyph_private
);
1876 #define FIXED_TO_FLOAT(f) (((glitz_float_t) (f)) / 65536)
1878 static cairo_status_t
1879 _cairo_glitz_surface_add_glyph (cairo_glitz_surface_t
*surface
,
1880 cairo_scaled_font_t
*scaled_font
,
1881 cairo_scaled_glyph_t
*scaled_glyph
)
1883 cairo_image_surface_t
*glyph_surface
= scaled_glyph
->surface
;
1884 cairo_glitz_surface_font_private_t
*font_private
;
1885 cairo_glitz_surface_glyph_private_t
*glyph_private
;
1886 glitz_point_fixed_t p1
, p2
;
1887 glitz_pixel_format_t pf
;
1888 glitz_buffer_t
*buffer
;
1889 cairo_format_masks_t masks
;
1890 cairo_int_status_t status
;
1892 glyph_private
= scaled_glyph
->surface_private
;
1893 if (glyph_private
== NULL
)
1895 glyph_private
= malloc (sizeof (cairo_glitz_surface_glyph_private_t
));
1897 return _cairo_error (CAIRO_STATUS_NO_MEMORY
);
1899 glyph_private
->area
= NULL
;
1900 glyph_private
->locked
= FALSE
;
1902 scaled_glyph
->surface_private
= (void *) glyph_private
;
1905 if (glyph_surface
->width
> GLYPH_CACHE_MAX_WIDTH
||
1906 glyph_surface
->height
> GLYPH_CACHE_MAX_HEIGHT
)
1907 return CAIRO_INT_STATUS_UNSUPPORTED
;
1909 if (scaled_font
->surface_private
== NULL
)
1911 status
= _cairo_glitz_surface_font_init (surface
, scaled_font
,
1912 glyph_surface
->format
);
1917 font_private
= scaled_font
->surface_private
;
1919 if (glyph_surface
->width
== 0 || glyph_surface
->height
== 0)
1921 glyph_private
->area
= &_empty_area
;
1922 return CAIRO_STATUS_SUCCESS
;
1925 if (_cairo_glitz_area_find (font_private
->root
.area
,
1926 glyph_surface
->width
,
1927 glyph_surface
->height
,
1928 FALSE
, glyph_private
))
1930 if (_cairo_glitz_area_find (font_private
->root
.area
,
1931 glyph_surface
->width
,
1932 glyph_surface
->height
,
1933 TRUE
, glyph_private
))
1934 return CAIRO_STATUS_SUCCESS
;
1937 buffer
= glitz_buffer_create_for_data (glyph_surface
->data
);
1940 _cairo_glitz_area_move_out (glyph_private
->area
);
1941 return _cairo_error (CAIRO_STATUS_NO_MEMORY
);
1944 _pixman_format_to_masks (glyph_surface
->pixman_format
, &masks
);
1946 pf
.fourcc
= GLITZ_FOURCC_RGB
;
1947 pf
.masks
.bpp
= masks
.bpp
;
1948 pf
.masks
.alpha_mask
= masks
.alpha_mask
;
1949 pf
.masks
.red_mask
= masks
.red_mask
;
1950 pf
.masks
.green_mask
= masks
.green_mask
;
1951 pf
.masks
.blue_mask
= masks
.blue_mask
;
1953 pf
.bytes_per_line
= glyph_surface
->stride
;
1954 pf
.scanline_order
= GLITZ_PIXEL_SCANLINE_ORDER_BOTTOM_UP
;
1958 glitz_set_pixels (font_private
->surface
,
1959 glyph_private
->area
->x
,
1960 glyph_private
->area
->y
,
1961 glyph_surface
->width
,
1962 glyph_surface
->height
,
1965 glitz_buffer_destroy (buffer
);
1967 p1
.x
= glyph_private
->area
->x
<< 16;
1968 p1
.y
= glyph_private
->area
->y
<< 16;
1969 p2
.x
= (glyph_private
->area
->x
+ glyph_surface
->width
) << 16;
1970 p2
.y
= (glyph_private
->area
->y
+ glyph_surface
->height
) << 16;
1972 glitz_surface_translate_point (font_private
->surface
, &p1
, &p1
);
1973 glitz_surface_translate_point (font_private
->surface
, &p2
, &p2
);
1975 glyph_private
->p1
.x
= FIXED_TO_FLOAT (p1
.x
);
1976 glyph_private
->p1
.y
= FIXED_TO_FLOAT (p1
.y
);
1977 glyph_private
->p2
.x
= FIXED_TO_FLOAT (p2
.x
);
1978 glyph_private
->p2
.y
= FIXED_TO_FLOAT (p2
.y
);
1980 return CAIRO_STATUS_SUCCESS
;
1983 #define N_STACK_BUF 256
1985 static cairo_int_status_t
1986 _cairo_glitz_surface_old_show_glyphs (cairo_scaled_font_t
*scaled_font
,
1987 cairo_operator_t op
,
1988 const cairo_pattern_t
*pattern
,
1989 void *abstract_surface
,
1995 unsigned int height
,
1996 cairo_glyph_t
*glyphs
,
1999 cairo_glitz_surface_attributes_t attributes
;
2000 cairo_glitz_surface_glyph_private_t
*glyph_private
;
2001 cairo_glitz_surface_t
*dst
= abstract_surface
;
2002 cairo_glitz_surface_t
*src
;
2003 cairo_scaled_glyph_t
*stack_scaled_glyphs
[N_STACK_BUF
];
2004 cairo_scaled_glyph_t
**scaled_glyphs
;
2005 glitz_float_t stack_vertices
[N_STACK_BUF
* 16];
2006 glitz_float_t
*vertices
;
2007 glitz_buffer_t
*buffer
;
2008 cairo_int_status_t status
;
2009 int x_offset
, y_offset
;
2010 int i
, cached_glyphs
= 0;
2011 int remaining_glyps
= num_glyphs
;
2012 glitz_float_t x1
, y1
, x2
, y2
;
2013 static const glitz_vertex_format_t format
= {
2014 GLITZ_PRIMITIVE_QUADS
,
2015 GLITZ_DATA_TYPE_FLOAT
,
2016 sizeof (glitz_float_t
) * 4,
2017 GLITZ_VERTEX_ATTRIBUTE_MASK_COORD_MASK
,
2020 GLITZ_DATA_TYPE_FLOAT
,
2021 GLITZ_COORDINATE_SIZE_XY
,
2022 sizeof (glitz_float_t
) * 2,
2026 if (scaled_font
->surface_backend
!= NULL
&&
2027 scaled_font
->surface_backend
!= _cairo_glitz_surface_get_backend ())
2028 return CAIRO_INT_STATUS_UNSUPPORTED
;
2030 if (op
== CAIRO_OPERATOR_SATURATE
)
2031 return CAIRO_INT_STATUS_UNSUPPORTED
;
2033 /* XXX Unbounded operators are not handled correctly */
2034 if (! _cairo_operator_bounded_by_mask (op
))
2035 return CAIRO_INT_STATUS_UNSUPPORTED
;
2037 if (_glitz_ensure_target (dst
->surface
))
2038 return CAIRO_INT_STATUS_UNSUPPORTED
;
2040 status
= _cairo_glitz_pattern_acquire_surface (pattern
, dst
,
2047 _cairo_glitz_surface_set_attributes (src
, &attributes
);
2049 if (num_glyphs
> N_STACK_BUF
)
2052 size_t size1
, size2
;
2054 if ((size_t)num_glyphs
>= INT32_MAX
/ sizeof(void*) ||
2055 (size_t)num_glyphs
>= INT32_MAX
/ sizeof(glitz_float_t
) ||
2056 ((size_t)num_glyphs
* sizeof(glitz_float_t
)) >= INT32_MAX
/ 16)
2059 size1
= num_glyphs
* sizeof(void *);
2060 size2
= num_glyphs
* sizeof(glitz_float_t
) * 16;
2061 if (size1
>= INT32_MAX
- size2
)
2064 data
= malloc (size1
+ size2
);
2066 _cairo_error_throw (CAIRO_STATUS_NO_MEMORY
);
2070 scaled_glyphs
= (cairo_scaled_glyph_t
**) data
;
2071 vertices
= (glitz_float_t
*) (data
+ num_glyphs
* sizeof (void *));
2075 scaled_glyphs
= stack_scaled_glyphs
;
2076 vertices
= stack_vertices
;
2079 buffer
= glitz_buffer_create_for_data (vertices
);
2083 _cairo_scaled_font_freeze_cache (scaled_font
);
2085 for (i
= 0; i
< num_glyphs
; i
++)
2087 status
= _cairo_scaled_glyph_lookup (scaled_font
,
2089 CAIRO_SCALED_GLYPH_INFO_SURFACE
,
2091 if (status
!= CAIRO_STATUS_SUCCESS
)
2097 glyph_private
= scaled_glyphs
[i
]->surface_private
;
2098 if (!glyph_private
|| !glyph_private
->area
)
2100 status
= _cairo_glitz_surface_add_glyph (dst
,
2103 if (status
!= CAIRO_STATUS_SUCCESS
) {
2108 glyph_private
= scaled_glyphs
[i
]->surface_private
;
2109 if (glyph_private
&& glyph_private
->area
)
2113 if (glyph_private
->area
->width
)
2115 x_offset
= scaled_glyphs
[i
]->surface
->base
.device_transform
.x0
;
2116 y_offset
= scaled_glyphs
[i
]->surface
->base
.device_transform
.y0
;
2118 x1
= _cairo_lround (glyphs
[i
].x
- x_offset
);
2119 y1
= _cairo_lround (glyphs
[i
].y
- y_offset
);
2120 x2
= x1
+ glyph_private
->area
->width
;
2121 y2
= y1
+ glyph_private
->area
->height
;
2123 WRITE_BOX (vertices
, x1
, y1
, x2
, y2
,
2124 &glyph_private
->p1
, &glyph_private
->p2
);
2126 glyph_private
->locked
= TRUE
;
2133 if (remaining_glyps
)
2135 cairo_surface_t
*image
;
2136 cairo_glitz_surface_t
*clone
;
2138 for (i
= 0; i
< num_glyphs
; i
++)
2140 glyph_private
= scaled_glyphs
[i
]->surface_private
;
2141 if (!glyph_private
|| !glyph_private
->area
)
2143 int glyph_width
, glyph_height
;
2144 int clone_offset_x
, clone_offset_y
;
2146 image
= &scaled_glyphs
[i
]->surface
->base
;
2147 glyph_width
= scaled_glyphs
[i
]->surface
->width
;
2148 glyph_height
= scaled_glyphs
[i
]->surface
->height
;
2150 _cairo_glitz_surface_clone_similar (abstract_surface
,
2152 CAIRO_CONTENT_COLOR_ALPHA
,
2159 (cairo_surface_t
**)
2164 assert (clone_offset_x
== 0);
2165 assert (clone_offset_y
== 0);
2167 x_offset
= scaled_glyphs
[i
]->surface
->base
.device_transform
.x0
;
2168 y_offset
= scaled_glyphs
[i
]->surface
->base
.device_transform
.y0
;
2169 x1
= _cairo_lround (glyphs
[i
].x
- x_offset
);
2170 y1
= _cairo_lround (glyphs
[i
].y
- y_offset
);
2172 glitz_composite (_glitz_operator (op
),
2176 src_x
+ attributes
.base
.x_offset
+ x1
,
2177 src_y
+ attributes
.base
.y_offset
+ y1
,
2183 cairo_surface_destroy (&clone
->base
);
2185 if (glitz_surface_get_status (dst
->surface
) ==
2186 GLITZ_STATUS_NOT_SUPPORTED
)
2188 status
= CAIRO_INT_STATUS_UNSUPPORTED
;
2197 cairo_glitz_surface_font_private_t
*font_private
;
2199 glitz_set_geometry (dst
->surface
,
2200 GLITZ_GEOMETRY_TYPE_VERTEX
,
2201 (glitz_geometry_format_t
*) &format
,
2204 glitz_set_array (dst
->surface
, 0, 4, cached_glyphs
* 4, 0, 0);
2206 font_private
= scaled_font
->surface_private
;
2208 glitz_composite (_glitz_operator (op
),
2210 font_private
->surface
,
2212 src_x
+ attributes
.base
.x_offset
,
2213 src_y
+ attributes
.base
.y_offset
,
2218 glitz_set_geometry (dst
->surface
,
2219 GLITZ_GEOMETRY_TYPE_NONE
,
2226 for (i
= 0; i
< num_glyphs
; i
++)
2228 glyph_private
= scaled_glyphs
[i
]->surface_private
;
2230 glyph_private
->locked
= FALSE
;
2234 _cairo_scaled_font_thaw_cache (scaled_font
);
2236 glitz_buffer_destroy (buffer
);
2239 if (num_glyphs
> N_STACK_BUF
)
2240 free (scaled_glyphs
);
2243 if (attributes
.n_params
)
2244 free (attributes
.params
);
2246 _cairo_glitz_pattern_release_surface (pattern
, src
, &attributes
);
2251 if (glitz_surface_get_status (dst
->surface
) == GLITZ_STATUS_NOT_SUPPORTED
)
2252 return CAIRO_INT_STATUS_UNSUPPORTED
;
2254 return CAIRO_STATUS_SUCCESS
;
2257 static cairo_status_t
2258 _cairo_glitz_surface_flush (void *abstract_surface
)
2260 cairo_glitz_surface_t
*surface
= abstract_surface
;
2262 glitz_surface_flush (surface
->surface
);
2264 return CAIRO_STATUS_SUCCESS
;
2268 _cairo_glitz_surface_is_similar (void *surface_a
,
2270 cairo_content_t content
)
2272 cairo_glitz_surface_t
*a
= (cairo_glitz_surface_t
*) surface_a
;
2273 cairo_glitz_surface_t
*b
= (cairo_glitz_surface_t
*) surface_b
;
2275 glitz_drawable_t
*drawable_a
= glitz_surface_get_drawable (a
->surface
);
2276 glitz_drawable_t
*drawable_b
= glitz_surface_get_drawable (b
->surface
);
2278 /* XXX Disable caching of glitz surfaces by the solid pattern cache.
2279 * Until glitz has a mechanism for releasing resources on connection
2280 * closure, we will attempt to access invalid pointers when evicting
2281 * old surfaces from the solid pattern cache.
2285 return drawable_a
== drawable_b
;
2288 static cairo_status_t
2289 _cairo_glitz_surface_reset (void *abstract_surface
)
2291 cairo_glitz_surface_t
*surface
= abstract_surface
;
2292 cairo_status_t status
;
2294 status
= _cairo_glitz_surface_set_clip_region (surface
, NULL
);
2298 return CAIRO_STATUS_SUCCESS
;
2301 static const cairo_surface_backend_t cairo_glitz_surface_backend
= {
2302 CAIRO_SURFACE_TYPE_GLITZ
,
2303 _cairo_glitz_surface_create_similar
,
2304 _cairo_glitz_surface_finish
,
2305 _cairo_glitz_surface_acquire_source_image
,
2306 _cairo_glitz_surface_release_source_image
,
2307 _cairo_glitz_surface_acquire_dest_image
,
2308 _cairo_glitz_surface_release_dest_image
,
2309 _cairo_glitz_surface_clone_similar
,
2310 _cairo_glitz_surface_composite
,
2311 _cairo_glitz_surface_fill_rectangles
,
2312 _cairo_glitz_surface_composite_trapezoids
,
2313 NULL
, /* create_span_renderer */
2314 NULL
, /* check_span_renderer */
2315 NULL
, /* copy_page */
2316 NULL
, /* show_page */
2317 _cairo_glitz_surface_set_clip_region
,
2318 NULL
, /* intersect_clip_path */
2319 _cairo_glitz_surface_get_extents
,
2320 _cairo_glitz_surface_old_show_glyphs
,
2321 NULL
, /* get_font_options */
2322 _cairo_glitz_surface_flush
,
2323 NULL
, /* mark_dirty_rectangle */
2324 _cairo_glitz_surface_scaled_font_fini
,
2325 _cairo_glitz_surface_scaled_glyph_fini
,
2331 NULL
, /* show_glyphs */
2333 _cairo_glitz_surface_snapshot
,
2334 _cairo_glitz_surface_is_similar
,
2336 _cairo_glitz_surface_reset
2339 static const cairo_surface_backend_t
*
2340 _cairo_glitz_surface_get_backend (void)
2342 return &cairo_glitz_surface_backend
;
2345 static cairo_content_t
2346 _glitz_format_to_content (glitz_format_t
* format
)
2348 assert (format
->color
.fourcc
== GLITZ_FOURCC_RGB
);
2350 if (format
->color
.alpha_size
!= 0) {
2351 if (format
->color
.red_size
!= 0 &&
2352 format
->color
.green_size
!= 0 &&
2353 format
->color
.blue_size
!= 0)
2354 return CAIRO_CONTENT_COLOR_ALPHA
;
2356 return CAIRO_CONTENT_ALPHA
;
2358 return CAIRO_CONTENT_COLOR
;
2362 cairo_glitz_surface_create (glitz_surface_t
*surface
)
2364 cairo_glitz_surface_t
*crsurface
;
2365 glitz_format_t
*format
;
2367 if (surface
== NULL
)
2368 return _cairo_surface_create_in_error (_cairo_error (CAIRO_STATUS_NULL_POINTER
));
2370 crsurface
= malloc (sizeof (cairo_glitz_surface_t
));
2371 if (crsurface
== NULL
)
2372 return _cairo_surface_create_in_error (_cairo_error (CAIRO_STATUS_NO_MEMORY
));
2374 format
= glitz_surface_get_format (surface
);
2375 _cairo_surface_init (&crsurface
->base
, &cairo_glitz_surface_backend
,
2376 _glitz_format_to_content (format
));
2378 glitz_surface_reference (surface
);
2380 crsurface
->surface
= surface
;
2381 crsurface
->format
= format
;
2383 crsurface
->has_clip
= FALSE
;
2384 crsurface
->clip_boxes
= NULL
;
2385 crsurface
->num_clip_boxes
= 0;
2387 return &crsurface
->base
;
2389 slim_hidden_def (cairo_glitz_surface_create
);