1 /* -*- Mode: c; tab-width: 8; c-basic-offset: 4; indent-tabs-mode: t; -*- */
2 /* cairo - a vector graphics library with display and print output
4 * Copyright © 2002 University of Southern California
5 * Copyright © 2005 Red Hat, Inc.
6 * Copyright © 2011 Intel Corporation
7 * Copyright © 2011 Samsung Electronics
9 * This library is free software; you can redistribute it and/or
10 * modify it either under the terms of the GNU Lesser General Public
11 * License version 2.1 as published by the Free Software Foundation
12 * (the "LGPL") or, at your option, under the terms of the Mozilla
13 * Public License Version 1.1 (the "MPL"). If you do not alter this
14 * notice, a recipient may use your version of this file under either
15 * the MPL or the LGPL.
17 * You should have received a copy of the LGPL along with this library
18 * in the file COPYING-LGPL-2.1; if not, write to the Free Software
19 * Foundation, Inc., 51 Franklin Street, Suite 500, Boston, MA 02110-1335, USA
20 * You should have received a copy of the MPL along with this library
21 * in the file COPYING-MPL-1.1
23 * The contents of this file are subject to the Mozilla Public License
24 * Version 1.1 (the "License"); you may not use this file except in
25 * compliance with the License. You may obtain a copy of the License at
26 * http://www.mozilla.org/MPL/
28 * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY
29 * OF ANY KIND, either express or implied. See the LGPL or the MPL for
30 * the specific language governing rights and limitations.
32 * The Original Code is the cairo graphics library.
34 * The Initial Developer of the Original Code is University of Southern
38 * Henry Song <hsong@sisa.samsung.com>
39 * Martin Robinson <mrobinson@igalia.com>
44 #include "cairo-clip-inline.h"
45 #include "cairo-composite-rectangles-private.h"
46 #include "cairo-compositor-private.h"
47 #include "cairo-gl-private.h"
48 #include "cairo-path-private.h"
49 #include "cairo-traps-private.h"
52 can_use_msaa_compositor (cairo_gl_surface_t
*surface
,
53 cairo_antialias_t antialias
);
56 query_surface_capabilities (cairo_gl_surface_t
*surface
);
58 struct _tristrip_composite_info
{
59 cairo_gl_composite_t setup
;
60 cairo_gl_context_t
*ctx
;
63 static cairo_int_status_t
64 _draw_trap (cairo_gl_context_t
*ctx
,
65 cairo_gl_composite_t
*setup
,
66 cairo_trapezoid_t
*trap
)
68 cairo_point_t quad
[4];
70 quad
[0].x
= _cairo_edge_compute_intersection_x_for_y (&trap
->left
.p1
,
73 quad
[0].y
= trap
->top
;
75 quad
[1].x
= _cairo_edge_compute_intersection_x_for_y (&trap
->left
.p1
,
78 quad
[1].y
= trap
->bottom
;
80 quad
[2].x
= _cairo_edge_compute_intersection_x_for_y (&trap
->right
.p1
,
83 quad
[2].y
= trap
->bottom
;
85 quad
[3].x
= _cairo_edge_compute_intersection_x_for_y (&trap
->right
.p1
,
88 quad
[3].y
= trap
->top
;
89 return _cairo_gl_composite_emit_quad_as_tristrip (ctx
, setup
, quad
);
92 static cairo_int_status_t
93 _draw_traps (cairo_gl_context_t
*ctx
,
94 cairo_gl_composite_t
*setup
,
97 cairo_int_status_t status
= CAIRO_STATUS_SUCCESS
;
100 for (i
= 0; i
< traps
->num_traps
; i
++) {
101 cairo_trapezoid_t
*trap
= traps
->traps
+ i
;
102 if (unlikely ((status
= _draw_trap (ctx
, setup
, trap
))))
109 static cairo_int_status_t
110 _draw_int_rect (cairo_gl_context_t
*ctx
,
111 cairo_gl_composite_t
*setup
,
112 cairo_rectangle_int_t
*rect
)
115 cairo_point_t quad
[4];
117 _cairo_box_from_rectangle (&box
, rect
);
118 quad
[0].x
= box
.p1
.x
;
119 quad
[0].y
= box
.p1
.y
;
120 quad
[1].x
= box
.p1
.x
;
121 quad
[1].y
= box
.p2
.y
;
122 quad
[2].x
= box
.p2
.x
;
123 quad
[2].y
= box
.p2
.y
;
124 quad
[3].x
= box
.p2
.x
;
125 quad
[3].y
= box
.p1
.y
;
127 return _cairo_gl_composite_emit_quad_as_tristrip (ctx
, setup
, quad
);
130 static cairo_int_status_t
131 _draw_triangle_fan (cairo_gl_context_t
*ctx
,
132 cairo_gl_composite_t
*setup
,
133 const cairo_point_t
*midpt
,
134 const cairo_point_t
*points
,
139 /* Our strategy here is to not even try to build a triangle fan, but to
140 draw each triangle as if it was an unconnected member of a triangle strip. */
141 for (i
= 1; i
< npoints
; i
++) {
142 cairo_int_status_t status
;
143 cairo_point_t triangle
[3];
145 triangle
[0] = *midpt
;
146 triangle
[1] = points
[i
- 1];
147 triangle
[2] = points
[i
];
149 status
= _cairo_gl_composite_emit_triangle_as_tristrip (ctx
, setup
, triangle
);
150 if (unlikely (status
))
154 return CAIRO_STATUS_SUCCESS
;
157 static cairo_int_status_t
158 _clip_to_traps (cairo_clip_t
*clip
,
159 cairo_traps_t
*traps
)
161 cairo_int_status_t status
;
162 cairo_polygon_t polygon
;
163 cairo_antialias_t antialias
;
164 cairo_fill_rule_t fill_rule
;
166 _cairo_traps_init (traps
);
168 if (clip
->num_boxes
== 1 && clip
->path
== NULL
) {
170 _cairo_boxes_init_for_array (&boxes
, clip
->boxes
, clip
->num_boxes
);
171 return _cairo_traps_init_boxes (traps
, &boxes
);
174 status
= _cairo_clip_get_polygon (clip
, &polygon
, &fill_rule
, &antialias
);
175 if (unlikely (status
))
178 /* We ignore the antialias mode of the clip here, since the user requested
179 * unantialiased rendering of their path and we expect that this stencil
180 * based rendering of the clip to be a reasonable approximation to
181 * the intersection between that clip and the path.
183 * In other words, what the user expects when they try to perform
184 * a geometric intersection between an unantialiased polygon and an
185 * antialiased polygon is open to interpretation. And we choose the fast
189 _cairo_traps_init (traps
);
190 status
= _cairo_bentley_ottmann_tessellate_polygon (traps
,
193 _cairo_polygon_fini (&polygon
);
199 _cairo_gl_msaa_compositor_draw_clip (cairo_gl_context_t
*ctx
,
200 cairo_gl_composite_t
*setup
,
203 cairo_int_status_t status
;
206 status
= _clip_to_traps (clip
, &traps
);
207 if (unlikely (status
))
209 status
= _draw_traps (ctx
, setup
, &traps
);
211 _cairo_traps_fini (&traps
);
216 _should_use_unbounded_surface (cairo_composite_rectangles_t
*composite
)
218 cairo_gl_surface_t
*dst
= (cairo_gl_surface_t
*) composite
->surface
;
219 cairo_rectangle_int_t
*source
= &composite
->source
;
221 if (composite
->is_bounded
)
224 /* This isn't just an optimization. It also detects when painting is used
225 to paint back the unbounded surface, preventing infinite recursion. */
226 return ! (source
->x
<= 0 && source
->y
<= 0 &&
227 source
->height
+ source
->y
>= dst
->height
&&
228 source
->width
+ source
->x
>= dst
->width
);
231 static cairo_surface_t
*
232 _prepare_unbounded_surface (cairo_gl_surface_t
*dst
)
235 cairo_surface_t
* surface
= cairo_gl_surface_create (dst
->base
.device
,
241 if (unlikely (surface
->status
)) {
242 cairo_surface_destroy (surface
);
248 static cairo_int_status_t
249 _paint_back_unbounded_surface (const cairo_compositor_t
*compositor
,
250 cairo_composite_rectangles_t
*composite
,
251 cairo_surface_t
*surface
)
253 cairo_gl_surface_t
*dst
= (cairo_gl_surface_t
*) composite
->surface
;
254 cairo_int_status_t status
;
256 cairo_pattern_t
*pattern
= cairo_pattern_create_for_surface (surface
);
257 if (unlikely (pattern
->status
)) {
258 status
= pattern
->status
;
262 status
= _cairo_compositor_paint (compositor
, &dst
->base
,
263 composite
->op
, pattern
,
267 cairo_pattern_destroy (pattern
);
268 cairo_surface_destroy (surface
);
273 can_use_msaa_compositor (cairo_gl_surface_t
*surface
,
274 cairo_antialias_t antialias
)
276 query_surface_capabilities (surface
);
277 if (! surface
->supports_stencil
)
280 /* Multisampling OpenGL ES surfaces only maintain one multisampling
281 framebuffer and thus must use the spans compositor to do non-antialiased
283 if (((cairo_gl_context_t
*) surface
->base
.device
)->gl_flavor
== CAIRO_GL_FLAVOR_ES
284 && surface
->supports_msaa
285 && antialias
== CAIRO_ANTIALIAS_NONE
)
288 /* The MSAA compositor has a single-sample mode, so we can
289 support non-antialiased rendering. */
290 if (antialias
== CAIRO_ANTIALIAS_NONE
)
293 if (antialias
== CAIRO_ANTIALIAS_FAST
|| antialias
== CAIRO_ANTIALIAS_DEFAULT
)
294 return surface
->supports_msaa
;
299 _cairo_gl_msaa_compositor_set_clip (cairo_composite_rectangles_t
*composite
,
300 cairo_gl_composite_t
*setup
)
302 if (_cairo_composite_rectangles_can_reduce_clip (composite
, composite
->clip
))
304 _cairo_gl_composite_set_clip (setup
, composite
->clip
);
307 /* Masking with the SOURCE operator requires two passes. In the first
308 * pass we use the mask as the source to get:
309 * result = (1 - ma) * dst
310 * In the second pass we use the add operator to achieve:
311 * result = (src * ma) + dst
312 * Combined this produces:
313 * result = (src * ma) + (1 - ma) * dst
315 static cairo_int_status_t
316 _cairo_gl_msaa_compositor_mask_source_operator (const cairo_compositor_t
*compositor
,
317 cairo_composite_rectangles_t
*composite
)
319 cairo_gl_composite_t setup
;
320 cairo_gl_surface_t
*dst
= (cairo_gl_surface_t
*) composite
->surface
;
321 cairo_gl_context_t
*ctx
= NULL
;
322 cairo_int_status_t status
;
324 cairo_clip_t
*clip
= composite
->clip
;
327 /* If we have a non-rectangular clip, we can avoid using the stencil buffer
328 * for clipping and just draw the clip polygon. */
330 status
= _clip_to_traps (clip
, &traps
);
331 if (unlikely (status
)) {
332 _cairo_traps_fini (&traps
);
337 status
= _cairo_gl_composite_init (&setup
,
338 CAIRO_OPERATOR_DEST_OUT
,
340 FALSE
/* assume_component_alpha */);
341 if (unlikely (status
))
343 status
= _cairo_gl_composite_set_source (&setup
,
344 &composite
->mask_pattern
.base
,
345 &composite
->mask_sample_area
,
348 if (unlikely (status
))
350 _cairo_gl_composite_set_multisample (&setup
);
351 status
= _cairo_gl_composite_begin (&setup
, &ctx
);
352 if (unlikely (status
))
356 status
= _draw_int_rect (ctx
, &setup
, &composite
->bounded
);
358 status
= _draw_traps (ctx
, &setup
, &traps
);
359 if (unlikely (status
))
362 /* Now draw the second pass. */
363 status
= _cairo_gl_composite_set_operator (&setup
, CAIRO_OPERATOR_ADD
,
364 FALSE
/* assume_component_alpha */);
365 if (unlikely (status
))
367 status
= _cairo_gl_composite_set_source (&setup
,
368 &composite
->source_pattern
.base
,
369 &composite
->source_sample_area
,
372 if (unlikely (status
))
374 status
= _cairo_gl_composite_set_mask (&setup
,
375 &composite
->mask_pattern
.base
,
376 &composite
->source_sample_area
,
379 if (unlikely (status
))
381 status
= _cairo_gl_set_operands_and_operator (&setup
, ctx
);
382 if (unlikely (status
))
386 status
= _draw_int_rect (ctx
, &setup
, &composite
->bounded
);
388 status
= _draw_traps (ctx
, &setup
, &traps
);
391 _cairo_gl_composite_fini (&setup
);
393 status
= _cairo_gl_context_release (ctx
, status
);
395 _cairo_traps_fini (&traps
);
400 static cairo_int_status_t
401 _cairo_gl_msaa_compositor_mask (const cairo_compositor_t
*compositor
,
402 cairo_composite_rectangles_t
*composite
)
404 cairo_gl_composite_t setup
;
405 cairo_gl_surface_t
*dst
= (cairo_gl_surface_t
*) composite
->surface
;
406 cairo_gl_context_t
*ctx
= NULL
;
407 cairo_int_status_t status
;
408 cairo_operator_t op
= composite
->op
;
409 cairo_clip_t
*clip
= composite
->clip
;
411 if (! can_use_msaa_compositor (dst
, CAIRO_ANTIALIAS_DEFAULT
))
412 return CAIRO_INT_STATUS_UNSUPPORTED
;
414 if (composite
->op
== CAIRO_OPERATOR_CLEAR
&&
415 composite
->original_mask_pattern
!= NULL
)
416 return CAIRO_INT_STATUS_UNSUPPORTED
;
418 /* GL compositing operators cannot properly represent a mask operation
419 using the SOURCE compositing operator in one pass. This only matters if
420 there actually is a mask (there isn't in a paint operation) and if the
421 mask isn't totally opaque. */
422 if (op
== CAIRO_OPERATOR_SOURCE
&&
423 composite
->original_mask_pattern
!= NULL
&&
424 ! _cairo_pattern_is_opaque (&composite
->mask_pattern
.base
,
425 &composite
->mask_sample_area
)) {
427 if (! _cairo_pattern_is_opaque (&composite
->source_pattern
.base
,
428 &composite
->source_sample_area
)) {
429 return _cairo_gl_msaa_compositor_mask_source_operator (compositor
, composite
);
432 /* If the source is opaque the operation reduces to OVER. */
433 op
= CAIRO_OPERATOR_OVER
;
436 if (_should_use_unbounded_surface (composite
)) {
437 cairo_surface_t
* surface
= _prepare_unbounded_surface (dst
);
439 if (unlikely (surface
== NULL
))
440 return CAIRO_INT_STATUS_UNSUPPORTED
;
442 /* This may be a paint operation. */
443 if (composite
->original_mask_pattern
== NULL
) {
444 status
= _cairo_compositor_paint (compositor
, surface
,
445 CAIRO_OPERATOR_SOURCE
,
446 &composite
->source_pattern
.base
,
449 status
= _cairo_compositor_mask (compositor
, surface
,
450 CAIRO_OPERATOR_SOURCE
,
451 &composite
->source_pattern
.base
,
452 &composite
->mask_pattern
.base
,
456 if (unlikely (status
)) {
457 cairo_surface_destroy (surface
);
461 return _paint_back_unbounded_surface (compositor
, composite
, surface
);
464 status
= _cairo_gl_composite_init (&setup
,
467 FALSE
/* assume_component_alpha */);
468 if (unlikely (status
))
471 status
= _cairo_gl_composite_set_source (&setup
,
472 &composite
->source_pattern
.base
,
473 &composite
->source_sample_area
,
476 if (unlikely (status
))
479 if (composite
->original_mask_pattern
!= NULL
) {
480 status
= _cairo_gl_composite_set_mask (&setup
,
481 &composite
->mask_pattern
.base
,
482 &composite
->mask_sample_area
,
486 if (unlikely (status
))
489 /* We always use multisampling here, because we do not yet have the smarts
490 to calculate when the clip or the source requires it. */
491 _cairo_gl_composite_set_multisample (&setup
);
493 status
= _cairo_gl_composite_begin (&setup
, &ctx
);
494 if (unlikely (status
))
498 status
= _draw_int_rect (ctx
, &setup
, &composite
->bounded
);
500 status
= _cairo_gl_msaa_compositor_draw_clip (ctx
, &setup
, clip
);
503 _cairo_gl_composite_fini (&setup
);
506 status
= _cairo_gl_context_release (ctx
, status
);
511 static cairo_int_status_t
512 _cairo_gl_msaa_compositor_paint (const cairo_compositor_t
*compositor
,
513 cairo_composite_rectangles_t
*composite
)
515 return _cairo_gl_msaa_compositor_mask (compositor
, composite
);
518 static cairo_status_t
519 _stroke_shaper_add_triangle (void *closure
,
520 const cairo_point_t triangle
[3])
522 struct _tristrip_composite_info
*info
= closure
;
523 return _cairo_gl_composite_emit_triangle_as_tristrip (info
->ctx
,
528 static cairo_status_t
529 _stroke_shaper_add_triangle_fan (void *closure
,
530 const cairo_point_t
*midpoint
,
531 const cairo_point_t
*points
,
534 struct _tristrip_composite_info
*info
= closure
;
535 return _draw_triangle_fan (info
->ctx
, &info
->setup
,
536 midpoint
, points
, npoints
);
539 static cairo_status_t
540 _stroke_shaper_add_quad (void *closure
,
541 const cairo_point_t quad
[4])
543 struct _tristrip_composite_info
*info
= closure
;
544 return _cairo_gl_composite_emit_quad_as_tristrip (info
->ctx
, &info
->setup
,
548 static cairo_int_status_t
549 _prevent_overlapping_strokes (cairo_gl_context_t
*ctx
,
550 cairo_gl_composite_t
*setup
,
551 cairo_composite_rectangles_t
*composite
,
552 const cairo_path_fixed_t
*path
,
553 const cairo_stroke_style_t
*style
,
554 const cairo_matrix_t
*ctm
)
556 cairo_rectangle_int_t stroke_extents
;
558 if (! _cairo_gl_ensure_stencil (ctx
, setup
->dst
))
559 return CAIRO_INT_STATUS_UNSUPPORTED
;
561 if (_cairo_pattern_is_opaque (&composite
->source_pattern
.base
,
562 &composite
->source_sample_area
))
563 return CAIRO_INT_STATUS_SUCCESS
;
565 if (glIsEnabled (GL_STENCIL_TEST
) == FALSE
) {
566 cairo_bool_t scissor_was_enabled
;
568 /* In case we have pending operations we have to flush before
569 adding the stencil buffer. */
570 _cairo_gl_composite_flush (ctx
);
572 /* Enable the stencil buffer, even if we are not using it for clipping,
573 so we can use it below to prevent overlapping shapes. We initialize
574 it all to one here which represents infinite clip. */
575 glDepthMask (GL_TRUE
);
576 glEnable (GL_STENCIL_TEST
);
578 /* We scissor here so that we don't have to clear the entire stencil
579 * buffer. If the scissor test is already enabled, it was enabled
580 * for clipping. In that case, instead of calculating an intersection,
581 * we just reuse it, and risk clearing too much. */
582 scissor_was_enabled
= glIsEnabled (GL_SCISSOR_TEST
);
583 if (! scissor_was_enabled
) {
584 _cairo_path_fixed_approximate_stroke_extents (path
, style
, ctm
,
586 _cairo_gl_scissor_to_rectangle (setup
->dst
, &stroke_extents
);
589 glClear (GL_STENCIL_BUFFER_BIT
);
590 if (! scissor_was_enabled
)
591 glDisable (GL_SCISSOR_TEST
);
593 glStencilFunc (GL_EQUAL
, 1, 1);
596 /* This means that once we draw to a particular pixel nothing else can
597 be drawn there until the stencil buffer is reset or the stencil test
599 glStencilOp (GL_ZERO
, GL_ZERO
, GL_ZERO
);
601 _cairo_clip_destroy (setup
->dst
->clip_on_stencil_buffer
);
602 setup
->dst
->clip_on_stencil_buffer
= NULL
;
604 return CAIRO_INT_STATUS_SUCCESS
;
608 query_surface_capabilities (cairo_gl_surface_t
*surface
)
610 GLint samples
, stencil_bits
;
611 cairo_gl_context_t
*ctx
;
612 cairo_int_status_t status
;
614 /* Texture surfaces are create in such a way that they always
615 have stencil and multisample bits if possible, so we don't
616 need to query their capabilities lazily. */
617 if (_cairo_gl_surface_is_texture (surface
))
619 if (surface
->stencil_and_msaa_caps_initialized
)
622 surface
->stencil_and_msaa_caps_initialized
= TRUE
;
623 surface
->supports_stencil
= FALSE
;
624 surface
->supports_msaa
= FALSE
;
626 status
= _cairo_gl_context_acquire (surface
->base
.device
, &ctx
);
627 if (unlikely (status
))
630 _cairo_gl_context_set_destination (ctx
, surface
, FALSE
);
632 glGetIntegerv(GL_SAMPLES
, &samples
);
633 glGetIntegerv(GL_STENCIL_BITS
, &stencil_bits
);
634 surface
->supports_stencil
= stencil_bits
> 0;
635 surface
->supports_msaa
= samples
> 1;
637 status
= _cairo_gl_context_release (ctx
, status
);
640 static cairo_int_status_t
641 _cairo_gl_msaa_compositor_stroke (const cairo_compositor_t
*compositor
,
642 cairo_composite_rectangles_t
*composite
,
643 const cairo_path_fixed_t
*path
,
644 const cairo_stroke_style_t
*style
,
645 const cairo_matrix_t
*ctm
,
646 const cairo_matrix_t
*ctm_inverse
,
648 cairo_antialias_t antialias
)
650 cairo_int_status_t status
;
651 cairo_gl_surface_t
*dst
= (cairo_gl_surface_t
*) composite
->surface
;
652 struct _tristrip_composite_info info
;
654 if (! can_use_msaa_compositor (dst
, antialias
))
655 return CAIRO_INT_STATUS_UNSUPPORTED
;
657 if (composite
->is_bounded
== FALSE
) {
658 cairo_surface_t
* surface
= _prepare_unbounded_surface (dst
);
660 if (unlikely (surface
== NULL
))
661 return CAIRO_INT_STATUS_UNSUPPORTED
;
663 status
= _cairo_compositor_stroke (compositor
, surface
,
664 CAIRO_OPERATOR_SOURCE
,
665 &composite
->source_pattern
.base
,
666 path
, style
, ctm
, ctm_inverse
,
667 tolerance
, antialias
, NULL
);
668 if (unlikely (status
)) {
669 cairo_surface_destroy (surface
);
673 return _paint_back_unbounded_surface (compositor
, composite
, surface
);
676 status
= _cairo_gl_composite_init (&info
.setup
,
679 FALSE
/* assume_component_alpha */);
680 if (unlikely (status
))
685 status
= _cairo_gl_composite_set_source (&info
.setup
,
686 &composite
->source_pattern
.base
,
687 &composite
->source_sample_area
,
690 if (unlikely (status
))
693 _cairo_gl_msaa_compositor_set_clip (composite
, &info
.setup
);
694 if (antialias
!= CAIRO_ANTIALIAS_NONE
)
695 _cairo_gl_composite_set_multisample (&info
.setup
);
697 status
= _cairo_gl_composite_begin (&info
.setup
, &info
.ctx
);
698 if (unlikely (status
))
701 status
= _prevent_overlapping_strokes (info
.ctx
, &info
.setup
,
702 composite
, path
, style
, ctm
);
703 if (unlikely (status
))
706 status
= _cairo_path_fixed_stroke_to_shaper ((cairo_path_fixed_t
*) path
,
711 _stroke_shaper_add_triangle
,
712 _stroke_shaper_add_triangle_fan
,
713 _stroke_shaper_add_quad
,
715 if (unlikely (status
))
719 _cairo_gl_composite_fini (&info
.setup
);
722 status
= _cairo_gl_context_release (info
.ctx
, status
);
727 static cairo_int_status_t
728 _draw_simple_quad_path (cairo_gl_context_t
*ctx
,
729 cairo_gl_composite_t
*setup
,
730 const cairo_path_fixed_t
*path
)
732 cairo_point_t triangle
[3];
733 cairo_int_status_t status
;
734 const cairo_point_t
*points
;
736 points
= cairo_path_head (path
)->points
;
737 triangle
[0] = points
[0];
738 triangle
[1] = points
[1];
739 triangle
[2] = points
[2];
740 status
= _cairo_gl_composite_emit_triangle_as_tristrip (ctx
, setup
, triangle
);
744 triangle
[0] = points
[2];
745 triangle
[1] = points
[3];
746 triangle
[2] = points
[0];
747 return _cairo_gl_composite_emit_triangle_as_tristrip (ctx
, setup
, triangle
);
750 static cairo_int_status_t
751 _cairo_gl_msaa_compositor_fill (const cairo_compositor_t
*compositor
,
752 cairo_composite_rectangles_t
*composite
,
753 const cairo_path_fixed_t
*path
,
754 cairo_fill_rule_t fill_rule
,
756 cairo_antialias_t antialias
)
758 cairo_gl_composite_t setup
;
759 cairo_gl_surface_t
*dst
= (cairo_gl_surface_t
*) composite
->surface
;
760 cairo_gl_context_t
*ctx
= NULL
;
761 cairo_int_status_t status
;
763 cairo_bool_t draw_path_with_traps
;
765 if (! can_use_msaa_compositor (dst
, antialias
))
766 return CAIRO_INT_STATUS_UNSUPPORTED
;
768 if (composite
->is_bounded
== FALSE
) {
769 cairo_surface_t
* surface
= _prepare_unbounded_surface (dst
);
771 if (unlikely (surface
== NULL
))
772 return CAIRO_INT_STATUS_UNSUPPORTED
;
775 status
= _cairo_compositor_fill (compositor
, surface
,
776 CAIRO_OPERATOR_SOURCE
,
777 &composite
->source_pattern
.base
,
778 path
, fill_rule
, tolerance
,
781 if (unlikely (status
)) {
782 cairo_surface_destroy (surface
);
786 return _paint_back_unbounded_surface (compositor
, composite
, surface
);
789 draw_path_with_traps
= ! _cairo_path_fixed_is_simple_quad (path
);
791 if (draw_path_with_traps
) {
792 _cairo_traps_init (&traps
);
793 status
= _cairo_path_fixed_fill_to_traps (path
, fill_rule
, tolerance
, &traps
);
794 if (unlikely (status
))
798 status
= _cairo_gl_composite_init (&setup
,
801 FALSE
/* assume_component_alpha */);
802 if (unlikely (status
))
805 status
= _cairo_gl_composite_set_source (&setup
,
806 &composite
->source_pattern
.base
,
807 &composite
->source_sample_area
,
810 if (unlikely (status
))
813 _cairo_gl_msaa_compositor_set_clip (composite
, &setup
);
814 if (antialias
!= CAIRO_ANTIALIAS_NONE
)
815 _cairo_gl_composite_set_multisample (&setup
);
817 status
= _cairo_gl_composite_begin (&setup
, &ctx
);
818 if (unlikely (status
))
821 if (! draw_path_with_traps
)
822 status
= _draw_simple_quad_path (ctx
, &setup
, path
);
824 status
= _draw_traps (ctx
, &setup
, &traps
);
825 if (unlikely (status
))
829 _cairo_gl_composite_fini (&setup
);
832 status
= _cairo_gl_context_release (ctx
, status
);
835 if (draw_path_with_traps
)
836 _cairo_traps_fini (&traps
);
841 static cairo_int_status_t
842 _cairo_gl_msaa_compositor_glyphs (const cairo_compositor_t
*compositor
,
843 cairo_composite_rectangles_t
*composite
,
844 cairo_scaled_font_t
*scaled_font
,
845 cairo_glyph_t
*glyphs
,
847 cairo_bool_t overlap
)
849 cairo_int_status_t status
;
850 cairo_surface_t
*src
= NULL
;
852 cairo_composite_glyphs_info_t info
;
854 cairo_gl_surface_t
*dst
= (cairo_gl_surface_t
*) composite
->surface
;
856 query_surface_capabilities (dst
);
857 if (! dst
->supports_stencil
)
858 return CAIRO_INT_STATUS_UNSUPPORTED
;
860 if (composite
->op
== CAIRO_OPERATOR_CLEAR
)
861 return CAIRO_INT_STATUS_UNSUPPORTED
;
863 if (composite
->is_bounded
== FALSE
) {
864 cairo_surface_t
* surface
= _prepare_unbounded_surface (dst
);
866 if (unlikely (surface
== NULL
))
867 return CAIRO_INT_STATUS_UNSUPPORTED
;
869 status
= _cairo_compositor_glyphs (compositor
, surface
,
870 CAIRO_OPERATOR_SOURCE
,
871 &composite
->source_pattern
.base
,
873 scaled_font
, composite
->clip
);
875 if (unlikely (status
)) {
876 cairo_surface_destroy (surface
);
880 return _paint_back_unbounded_surface (compositor
, composite
, surface
);
883 src
= _cairo_gl_pattern_to_source (&dst
->base
,
884 &composite
->source_pattern
.base
,
887 &composite
->source_sample_area
,
889 if (unlikely (src
->status
)) {
890 status
= src
->status
;
894 status
= _cairo_gl_check_composite_glyphs (composite
,
897 if (unlikely (status
!= CAIRO_INT_STATUS_SUCCESS
))
900 info
.font
= scaled_font
;
901 info
.glyphs
= glyphs
;
902 info
.num_glyphs
= num_glyphs
;
903 info
.use_mask
= overlap
|| ! composite
->is_bounded
||
904 composite
->op
== CAIRO_OPERATOR_SOURCE
;
905 info
.extents
= composite
->bounded
;
907 _cairo_scaled_font_freeze_cache (scaled_font
);
908 status
= _cairo_gl_composite_glyphs_with_clip (dst
, composite
->op
,
913 _cairo_scaled_font_thaw_cache (scaled_font
);
917 cairo_surface_destroy (src
);
923 _cairo_gl_msaa_compositor_init (cairo_compositor_t
*compositor
,
924 const cairo_compositor_t
*delegate
)
926 compositor
->delegate
= delegate
;
928 compositor
->paint
= _cairo_gl_msaa_compositor_paint
;
929 compositor
->mask
= _cairo_gl_msaa_compositor_mask
;
930 compositor
->fill
= _cairo_gl_msaa_compositor_fill
;
931 compositor
->stroke
= _cairo_gl_msaa_compositor_stroke
;
932 compositor
->glyphs
= _cairo_gl_msaa_compositor_glyphs
;
935 const cairo_compositor_t
*
936 _cairo_gl_msaa_compositor_get (void)
938 static cairo_compositor_t compositor
;
939 if (compositor
.delegate
== NULL
)
940 _cairo_gl_msaa_compositor_init (&compositor
,
941 _cairo_gl_span_compositor_get ());