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-traps-private.h"
49 #include "cairo-surface-subsurface-inline.h"
52 should_fall_back (cairo_gl_surface_t *surface,
53 cairo_antialias_t antialias);
55 struct _tristrip_composite_info {
56 cairo_gl_composite_t setup;
57 cairo_gl_context_t *ctx;
60 static cairo_int_status_t
61 _draw_trap (cairo_gl_context_t *ctx,
62 cairo_gl_composite_t *setup,
63 cairo_trapezoid_t *trap)
65 cairo_point_t quad[4];
67 quad[0].x = _cairo_edge_compute_intersection_x_for_y (&trap->left.p1,
70 quad[0].y = trap->top;
72 quad[1].x = _cairo_edge_compute_intersection_x_for_y (&trap->left.p1,
75 quad[1].y = trap->bottom;
77 quad[2].x = _cairo_edge_compute_intersection_x_for_y (&trap->right.p1,
80 quad[2].y = trap->bottom;
82 quad[3].x = _cairo_edge_compute_intersection_x_for_y (&trap->right.p1,
85 quad[3].y = trap->top;
86 return _cairo_gl_composite_emit_quad_as_tristrip (ctx, setup, quad);
89 static cairo_int_status_t
90 _draw_traps (cairo_gl_context_t *ctx,
91 cairo_gl_composite_t *setup,
94 cairo_int_status_t status = CAIRO_STATUS_SUCCESS;
97 for (i = 0; i < traps->num_traps; i++) {
98 cairo_trapezoid_t *trap = traps->traps + i;
99 if (unlikely ((status = _draw_trap (ctx, setup, trap))))
106 static cairo_int_status_t
107 _cairo_gl_msaa_compositor_draw_quad (cairo_gl_context_t *ctx,
108 cairo_gl_composite_t *setup,
111 cairo_point_t quad[4];
113 quad[0].x = box->p1.x;
114 quad[0].y = box->p1.y;
116 quad[1].x = box->p1.x;
117 quad[1].y = box->p2.y;
119 quad[2].x = box->p2.x;
120 quad[2].y = box->p2.y;
122 quad[3].x = box->p2.x;
123 quad[3].y = box->p1.y;
125 return _cairo_gl_composite_emit_quad_as_tristrip (ctx, setup, quad);
128 static cairo_int_status_t
129 _draw_int_rect (cairo_gl_context_t *ctx,
130 cairo_gl_composite_t *setup,
131 cairo_rectangle_int_t *rect)
135 _cairo_box_from_rectangle (&box, rect);
137 return _cairo_gl_msaa_compositor_draw_quad (ctx, setup, &box);
140 static cairo_int_status_t
141 _draw_triangle_fan (cairo_gl_context_t *ctx,
142 cairo_gl_composite_t *setup,
143 const cairo_point_t *midpt,
144 const cairo_point_t *points,
149 /* Our strategy here is to not even try to build a triangle fan, but to
150 draw each triangle as if it was an unconnected member of a triangle strip. */
151 for (i = 1; i < npoints; i++) {
152 cairo_int_status_t status;
153 cairo_point_t triangle[3];
155 triangle[0] = *midpt;
156 triangle[1] = points[i - 1];
157 triangle[2] = points[i];
159 status = _cairo_gl_composite_emit_triangle_as_tristrip (ctx, setup, triangle);
160 if (unlikely (status))
164 return CAIRO_STATUS_SUCCESS;
168 _cairo_gl_msaa_compositor_draw_clip (cairo_gl_context_t *ctx,
169 cairo_gl_composite_t *setup,
171 cairo_traps_t *traps)
173 cairo_int_status_t status;
175 cairo_polygon_t polygon;
176 cairo_antialias_t antialias;
177 cairo_fill_rule_t fill_rule;
180 return CAIRO_INT_STATUS_UNSUPPORTED;
182 if (clip->num_boxes == 1 && ! clip->path)
183 return _cairo_gl_msaa_compositor_draw_quad (ctx, setup,
186 if (traps->num_traps == 0) {
187 status = _cairo_clip_get_polygon (clip, &polygon, &fill_rule,
189 if (unlikely (status))
192 /* We ignore the antialias mode of the clip here, since the user requested
193 * unantialiased rendering of their path and we expect that this stencil
194 * based rendering of the clip to be a reasonable approximation to
195 * the intersection between that clip and the path.
197 * In other words, what the user expects when they try to perform
198 * a geometric intersection between an unantialiased polygon and an
199 * antialiased polygon is open to interpretation. And we choose the fast
202 status = _cairo_bentley_ottmann_tessellate_polygon (traps,
205 _cairo_polygon_fini (&polygon);
206 if (unlikely (status))
210 status = _draw_traps (ctx, setup, 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 _cairo_gl_msaa_compositor_set_clip (cairo_composite_rectangles_t *composite,
274 cairo_gl_composite_t *setup)
278 if (_cairo_clip_is_all_clipped (composite->clip))
281 /* We don't need to check CAIRO_OPERATOR_BOUND_BY_MASK in these
283 is_bounded = composite->is_bounded;
284 composite->is_bounded = CAIRO_OPERATOR_BOUND_BY_SOURCE;
285 if (_cairo_composite_rectangles_can_reduce_clip (composite, composite->clip))
288 _cairo_gl_composite_set_clip (setup, composite->clip);
290 composite->is_bounded = is_bounded;
294 _gl_pattern_fix_reference_count (const cairo_pattern_t *pattern)
296 cairo_pattern_type_t pattern_type = cairo_pattern_get_type ((cairo_pattern_t *)pattern);
298 /* We need to increase reference count on surface and gradient if
299 the original_source_pattern is a cairo_gl_source_t type. */
300 if (pattern_type == CAIRO_PATTERN_TYPE_SURFACE) {
302 cairo_surface_pattern_t *surface_pattern = (cairo_surface_pattern_t *)pattern;
303 cairo_surface_t *pattern_surface = surface_pattern->surface;
305 if (cairo_surface_get_type (pattern_surface) == CAIRO_SURFACE_TYPE_GL &&
306 ! pattern_surface->device &&
307 ! _cairo_surface_is_subsurface (pattern_surface)) {
309 cairo_gl_source_t *_source = (cairo_gl_source_t *)pattern_surface;
311 switch (_source->operand.type) {
312 case CAIRO_GL_OPERAND_TEXTURE:
313 cairo_surface_reference (&(_source->operand.texture.owns_surface)->base);
315 case CAIRO_GL_OPERAND_LINEAR_GRADIENT:
316 case CAIRO_GL_OPERAND_RADIAL_GRADIENT_A0:
317 case CAIRO_GL_OPERAND_RADIAL_GRADIENT_NONE:
318 case CAIRO_GL_OPERAND_RADIAL_GRADIENT_EXT:
319 _cairo_gl_gradient_reference (_source->operand.gradient.gradient);
322 case CAIRO_GL_OPERAND_NONE:
323 case CAIRO_GL_OPERAND_CONSTANT:
324 case CAIRO_GL_OPERAND_COUNT:
331 /* We use two passes to paint with SOURCE operator */
332 /* The first pass, we use mask as source, to get dst1 = (1 - ma) * dst) with
333 * DEST_OUT operator. In the second pass, we use ADD operator to achieve
334 * result = (src * ma) + dst1. Combining two passes, we have
335 * result = (src * ma) + (1 - ma) * dst
337 static cairo_int_status_t
338 _cairo_gl_msaa_compositor_mask_source_operator (const cairo_compositor_t *compositor,
339 cairo_composite_rectangles_t *composite)
341 cairo_gl_composite_t setup;
342 cairo_gl_surface_t *dst = (cairo_gl_surface_t *) composite->surface;
343 cairo_gl_context_t *ctx = NULL;
344 cairo_int_status_t status;
347 _cairo_traps_init (&traps);
349 status = _cairo_gl_composite_init (&setup,
350 CAIRO_OPERATOR_DEST_OUT,
352 FALSE /* assume_component_alpha */);
353 if (unlikely (status))
356 _gl_pattern_fix_reference_count (composite->original_mask_pattern);
358 status = _cairo_gl_composite_set_source (&setup,
359 &composite->mask_pattern.base,
360 &composite->mask_sample_area,
363 if (unlikely (status))
366 status = _cairo_gl_composite_begin_multisample (&setup, &ctx, TRUE);
367 if (unlikely (status))
370 if (! composite->clip)
371 status = _draw_int_rect (ctx, &setup, &composite->bounded);
373 status = _cairo_gl_msaa_compositor_draw_clip (ctx, &setup, composite->clip, &traps);
375 _cairo_gl_composite_fini (&setup);
376 status = _cairo_gl_context_release (ctx, status);
378 if (unlikely (status))
382 status = _cairo_gl_composite_init (&setup,
385 FALSE /* assume_component_alpha */);
386 if (unlikely (status))
389 _gl_pattern_fix_reference_count (composite->original_source_pattern);
391 status = _cairo_gl_composite_set_source (&setup,
392 &composite->source_pattern.base,
393 &composite->source_sample_area,
396 if (unlikely (status))
399 status = _cairo_gl_composite_set_mask (&setup,
400 &composite->mask_pattern.base,
401 &composite->source_sample_area,
402 &composite->bounded);
403 if (unlikely (status))
406 /* We always use multisampling here, because we do not yet have the smarts
407 to calculate when the clip or the source requires it. */
408 status = _cairo_gl_composite_begin_multisample (&setup, &ctx, TRUE);
409 if (unlikely (status))
412 if (! composite->clip)
413 status = _draw_int_rect (ctx, &setup, &composite->bounded);
415 status = _cairo_gl_msaa_compositor_draw_clip (ctx, &setup, composite->clip, &traps);
418 _cairo_traps_fini (&traps);
419 _cairo_gl_composite_fini (&setup);
422 status = _cairo_gl_context_release (ctx, status);
427 static cairo_int_status_t
428 _cairo_gl_msaa_compositor_mask (const cairo_compositor_t *compositor,
429 cairo_composite_rectangles_t *composite)
431 cairo_gl_composite_t setup;
432 cairo_gl_surface_t *dst = (cairo_gl_surface_t *) composite->surface;
433 cairo_gl_context_t *ctx = NULL;
434 cairo_int_status_t status;
435 cairo_operator_t op = composite->op;
437 cairo_bool_t use_color_attribute = FALSE;
439 if (should_fall_back (dst, CAIRO_ANTIALIAS_GOOD))
440 return CAIRO_INT_STATUS_UNSUPPORTED;
442 /* GL compositing operators cannot properly represent a mask operation
443 using the SOURCE compositing operator in one pass. This only matters if
444 there actually is a mask (there isn't in a paint operation) and if the
445 mask isn't totally opaque. */
446 if (op == CAIRO_OPERATOR_SOURCE &&
447 composite->original_mask_pattern != NULL &&
448 ! _cairo_pattern_is_opaque (&composite->mask_pattern.base,
449 &composite->mask_sample_area)) {
451 /* If the source is opaque the operation reduces to OVER. */
452 if (_cairo_pattern_is_opaque (&composite->source_pattern.base,
453 &composite->source_sample_area))
454 op = CAIRO_OPERATOR_OVER;
456 return _cairo_gl_msaa_compositor_mask_source_operator (compositor, composite);
459 if (_should_use_unbounded_surface (composite)) {
460 cairo_surface_t* surface = _prepare_unbounded_surface (dst);
462 if (unlikely (surface == NULL))
463 return CAIRO_INT_STATUS_UNSUPPORTED;
465 /* This may be a paint operation. */
466 if (composite->original_mask_pattern == NULL) {
467 status = _cairo_compositor_paint (compositor, surface,
468 CAIRO_OPERATOR_SOURCE,
469 &composite->source_pattern.base,
472 status = _cairo_compositor_mask (compositor, surface,
473 CAIRO_OPERATOR_SOURCE,
474 &composite->source_pattern.base,
475 &composite->mask_pattern.base,
479 if (unlikely (status)) {
480 cairo_surface_destroy (surface);
484 return _paint_back_unbounded_surface (compositor, composite, surface);
487 status = _cairo_gl_composite_init (&setup,
490 FALSE /* assume_component_alpha */);
491 if (unlikely (status))
494 _gl_pattern_fix_reference_count (composite->original_source_pattern);
496 if (! composite->clip ||
497 (composite->clip->num_boxes == 1 && ! composite->clip->path))
498 use_color_attribute = TRUE;
500 status = _cairo_gl_composite_set_source (&setup,
501 composite->original_source_pattern,
502 &composite->source_sample_area,
504 use_color_attribute);
505 if (unlikely (status))
508 if (composite->original_mask_pattern != NULL) {
509 status = _cairo_gl_composite_set_mask (&setup,
510 composite->original_mask_pattern,
511 &composite->mask_sample_area,
512 &composite->bounded);
514 if (unlikely (status))
517 /* We always use multisampling here, because we do not yet have the smarts
518 to calculate when the clip or the source requires it. */
519 status = _cairo_gl_composite_begin_multisample (&setup, &ctx, TRUE);
520 if (unlikely (status))
523 _cairo_traps_init (&traps);
525 if (! composite->clip)
526 status = _draw_int_rect (ctx, &setup, &composite->bounded);
528 status = _cairo_gl_msaa_compositor_draw_clip (ctx, &setup, composite->clip, &traps);
530 _cairo_traps_fini (&traps);
533 _cairo_gl_composite_fini (&setup);
536 status = _cairo_gl_context_release (ctx, status);
541 static cairo_int_status_t
542 _cairo_gl_msaa_compositor_paint (const cairo_compositor_t *compositor,
543 cairo_composite_rectangles_t *composite)
545 return _cairo_gl_msaa_compositor_mask (compositor, composite);
548 static cairo_status_t
549 _stroke_shaper_add_triangle (void *closure,
550 const cairo_point_t triangle[3])
552 struct _tristrip_composite_info *info = closure;
553 return _cairo_gl_composite_emit_triangle_as_tristrip (info->ctx,
558 static cairo_status_t
559 _stroke_shaper_add_triangle_fan (void *closure,
560 const cairo_point_t *midpoint,
561 const cairo_point_t *points,
564 struct _tristrip_composite_info *info = closure;
565 return _draw_triangle_fan (info->ctx, &info->setup,
566 midpoint, points, npoints);
569 static cairo_status_t
570 _stroke_shaper_add_quad (void *closure,
571 const cairo_point_t quad[4])
573 struct _tristrip_composite_info *info = closure;
574 return _cairo_gl_composite_emit_quad_as_tristrip (info->ctx, &info->setup,
578 static cairo_int_status_t
579 _prevent_overlapping_drawing (cairo_gl_context_t *ctx,
580 cairo_gl_composite_t *setup,
581 cairo_composite_rectangles_t *composite,
582 const cairo_path_fixed_t *path,
583 const cairo_stroke_style_t *style,
584 const cairo_matrix_t *ctm)
586 cairo_rectangle_int_t stroke_extents;
587 const cairo_pattern_t *pattern = composite->original_source_pattern;
588 cairo_pattern_type_t type = cairo_pattern_get_type ((cairo_pattern_t *) pattern);
590 if (! _cairo_gl_ensure_stencil (ctx, setup->dst))
591 return CAIRO_INT_STATUS_UNSUPPORTED;
593 /* XXX: improve me - since we have lazy init, we cannot use sample
595 if (type == CAIRO_PATTERN_TYPE_SOLID &&
596 _cairo_pattern_is_opaque_solid (pattern))
597 return CAIRO_INT_STATUS_SUCCESS;
599 if (glIsEnabled (GL_STENCIL_TEST) == FALSE) {
600 /* In case we have pending operations we have to flush before
601 adding the stencil buffer. */
602 _cairo_gl_composite_flush (ctx);
604 /* Enable the stencil buffer, even if we are not using it for clipping,
605 so we can use it below to prevent overlapping shapes. We initialize
606 it all to one here which represents infinite clip. */
607 glDepthMask (GL_TRUE);
608 glEnable (GL_STENCIL_TEST);
610 /* If we don't have clip, then we will setup clip extents based on
611 approximate stroke extent. */
613 _cairo_path_fixed_approximate_stroke_extents (path, style, ctm,
615 _cairo_gl_scissor_to_extents (setup->dst, &stroke_extents);
619 glClear (GL_STENCIL_BUFFER_BIT);
620 glStencilFunc (GL_EQUAL, 1, 1);
623 /* This means that once we draw to a particular pixel nothing else can
624 be drawn there until the stencil buffer is reset or the stencil test
626 glStencilOp (GL_ZERO, GL_ZERO, GL_ZERO);
628 /* we need to clean up clip cache */
629 _cairo_clip_destroy (ctx->clip);
632 return CAIRO_INT_STATUS_SUCCESS;
636 query_surface_capabilities (cairo_gl_surface_t *surface)
638 GLint samples, stencil_bits;
639 cairo_gl_context_t *ctx;
640 cairo_int_status_t status;
642 /* Texture surfaces are create in such a way that they always
643 have stencil and multisample bits if possible, so we don't
644 need to query their capabilities lazily. */
645 if (_cairo_gl_surface_is_texture (surface))
647 if (surface->stencil_and_msaa_caps_initialized)
650 surface->stencil_and_msaa_caps_initialized = TRUE;
651 surface->supports_stencil = FALSE;
652 surface->supports_msaa = FALSE;
654 status = _cairo_gl_context_acquire (surface->base.device, &ctx);
655 if (unlikely (status))
658 _cairo_gl_context_set_destination (ctx, surface, FALSE);
660 glGetIntegerv(GL_SAMPLES, &samples);
661 glGetIntegerv(GL_STENCIL_BITS, &stencil_bits);
662 surface->supports_stencil = stencil_bits > 0;
663 surface->supports_msaa = samples > 1;
665 status = _cairo_gl_context_release (ctx, status);
669 should_fall_back (cairo_gl_surface_t *surface,
670 cairo_antialias_t antialias)
672 query_surface_capabilities (surface);
673 if (! surface->supports_stencil)
676 /* Multisampling OpenGL ES surfaces only maintain one multisampling
677 framebuffer and thus must use the spans compositor to do non
679 if (((cairo_gl_context_t *) surface->base.device)->gl_flavor == CAIRO_GL_FLAVOR_ES
680 && surface->supports_msaa
681 && antialias == CAIRO_ANTIALIAS_NONE)
684 if (antialias == CAIRO_ANTIALIAS_FAST)
686 if (antialias == CAIRO_ANTIALIAS_NONE)
688 return ! surface->supports_msaa;
691 static cairo_int_status_t
692 _cairo_gl_msaa_compositor_stroke (const cairo_compositor_t *compositor,
693 cairo_composite_rectangles_t *composite,
694 const cairo_path_fixed_t *path,
695 const cairo_stroke_style_t *style,
696 const cairo_matrix_t *ctm,
697 const cairo_matrix_t *ctm_inverse,
699 cairo_antialias_t antialias)
701 cairo_int_status_t status;
702 cairo_gl_surface_t *dst = (cairo_gl_surface_t *) composite->surface;
703 struct _tristrip_composite_info info;
704 cairo_bool_t use_color_attribute;
706 if (should_fall_back (dst, antialias))
707 return CAIRO_INT_STATUS_UNSUPPORTED;
709 if (composite->is_bounded == FALSE) {
710 cairo_surface_t* surface = _prepare_unbounded_surface (dst);
712 if (unlikely (surface == NULL))
713 return CAIRO_INT_STATUS_UNSUPPORTED;
715 status = _cairo_compositor_stroke (compositor, surface,
716 CAIRO_OPERATOR_SOURCE,
717 &composite->source_pattern.base,
718 path, style, ctm, ctm_inverse,
719 tolerance, antialias, NULL);
720 if (unlikely (status)) {
721 cairo_surface_destroy (surface);
725 return _paint_back_unbounded_surface (compositor, composite, surface);
728 status = _cairo_gl_composite_init (&info.setup,
731 FALSE /* assume_component_alpha */);
732 if (unlikely (status))
736 use_color_attribute = _cairo_path_fixed_stroke_is_rectilinear (path) ||
737 _cairo_gl_hairline_style_is_hairline (style, ctm);
739 status = _cairo_gl_composite_set_source (&info.setup,
740 composite->original_source_pattern,
741 &composite->source_sample_area,
743 use_color_attribute);
744 if (unlikely (status))
747 _cairo_gl_msaa_compositor_set_clip (composite, &info.setup);
749 status = _cairo_gl_composite_begin_multisample (&info.setup, &info.ctx,
750 antialias != CAIRO_ANTIALIAS_NONE);
751 if (unlikely (status))
754 if (_cairo_gl_hairline_style_is_hairline (style, ctm)) {
755 cairo_gl_hairline_closure_t closure;
757 status = _prevent_overlapping_drawing (info.ctx, &info.setup,
758 composite, path, style, ctm);
759 if (unlikely (status))
762 closure.ctx = info.ctx;
764 closure.tolerance = tolerance;
766 status = _cairo_gl_path_fixed_stroke_to_hairline (path, &closure,
769 _cairo_gl_hairline_move_to,
771 _cairo_gl_hairline_line_to_dashed :
772 _cairo_gl_hairline_line_to,
773 _cairo_gl_hairline_curve_to,
774 _cairo_gl_hairline_close_path);
778 if (use_color_attribute || path->has_curve_to) {
781 _cairo_traps_init (&traps);
783 status = _cairo_path_fixed_stroke_to_traps (path, style,
786 if (unlikely (status)) {
787 _cairo_traps_fini (&traps);
791 status = _draw_traps (info.ctx, &info.setup, &traps);
792 _cairo_traps_fini (&traps);
794 status = _prevent_overlapping_drawing (info.ctx, &info.setup,
795 composite, path, style, ctm);
796 if (unlikely (status))
800 _cairo_path_fixed_stroke_to_shaper ((cairo_path_fixed_t *) path,
805 _stroke_shaper_add_triangle,
806 _stroke_shaper_add_triangle_fan,
807 _stroke_shaper_add_quad,
809 if (unlikely (status))
813 _cairo_gl_composite_fini (&info.setup);
816 status = _cairo_gl_context_release (info.ctx, status);
821 static cairo_int_status_t
822 _cairo_gl_msaa_compositor_fill_rectilinear (const cairo_compositor_t *compositor,
823 cairo_composite_rectangles_t *composite,
824 const cairo_path_fixed_t *path,
825 cairo_fill_rule_t fill_rule,
827 cairo_antialias_t antialias,
830 cairo_gl_composite_t setup;
831 cairo_gl_surface_t *dst = (cairo_gl_surface_t *) composite->surface;
832 cairo_gl_context_t *ctx = NULL;
833 cairo_int_status_t status;
836 status = _cairo_gl_composite_init (&setup,
839 FALSE /* assume_component_alpha */);
840 if (unlikely (status))
843 status = _cairo_gl_composite_set_source (&setup,
844 composite->original_source_pattern,
845 &composite->source_sample_area,
848 if (unlikely (status))
851 status = _cairo_gl_composite_begin_multisample (&setup, &ctx,
852 antialias != CAIRO_ANTIALIAS_NONE);
853 if (unlikely (status))
856 for (i = 0; i < clip->num_boxes; i++) {
857 status = _cairo_gl_msaa_compositor_draw_quad (ctx, &setup,
859 if (unlikely (status))
864 _cairo_gl_composite_fini (&setup);
867 status = _cairo_gl_context_release (ctx, status);
872 static cairo_int_status_t
873 _cairo_gl_msaa_compositor_fill (const cairo_compositor_t *compositor,
874 cairo_composite_rectangles_t *composite,
875 const cairo_path_fixed_t *path,
876 cairo_fill_rule_t fill_rule,
878 cairo_antialias_t antialias)
880 cairo_gl_composite_t setup;
881 cairo_gl_surface_t *dst = (cairo_gl_surface_t *) composite->surface;
882 cairo_gl_context_t *ctx = NULL;
883 cairo_int_status_t status = CAIRO_INT_STATUS_SUCCESS;
885 cairo_bool_t use_color_attr = FALSE;
887 if (should_fall_back (dst, antialias))
888 return CAIRO_INT_STATUS_UNSUPPORTED;
890 if (composite->is_bounded == FALSE) {
891 cairo_surface_t* surface = _prepare_unbounded_surface (dst);
893 if (unlikely (surface == NULL))
894 return CAIRO_INT_STATUS_UNSUPPORTED;
897 status = _cairo_compositor_fill (compositor, surface,
898 CAIRO_OPERATOR_SOURCE,
899 &composite->source_pattern.base,
900 path, fill_rule, tolerance,
903 if (unlikely (status)) {
904 cairo_surface_destroy (surface);
908 return _paint_back_unbounded_surface (compositor, composite, surface);
911 if (_cairo_path_fixed_fill_is_rectilinear (path) &&
912 composite->clip != NULL &&
913 composite->clip->num_boxes == 1 &&
914 composite->clip->path == NULL) {
915 cairo_clip_t *clip = _cairo_clip_copy (composite->clip);
916 clip = _cairo_clip_intersect_rectilinear_path (clip,
921 status = _cairo_gl_msaa_compositor_fill_rectilinear (compositor,
928 _cairo_clip_destroy (clip);
933 status = _cairo_gl_composite_init (&setup,
936 FALSE /* assume_component_alpha */);
937 if (unlikely (status)) {
938 _cairo_gl_composite_fini (&setup);
942 _cairo_traps_init (&traps);
944 if (_cairo_path_fixed_fill_is_rectilinear (path)) {
945 status = _cairo_path_fixed_fill_rectilinear_to_traps (path,
949 use_color_attr = TRUE;
951 status = _cairo_path_fixed_fill_to_traps (path, fill_rule,
953 if (unlikely (status))
956 status = _cairo_gl_composite_set_source (&setup,
957 composite->original_source_pattern,
958 &composite->source_sample_area,
961 if (unlikely (status))
964 _cairo_gl_msaa_compositor_set_clip (composite, &setup);
966 status = _cairo_gl_composite_begin_multisample (&setup, &ctx,
967 antialias != CAIRO_ANTIALIAS_NONE);
968 if (unlikely (status))
971 status = _draw_traps (ctx, &setup, &traps);
972 if (unlikely (status))
976 _cairo_gl_composite_fini (&setup);
979 status = _cairo_gl_context_release (ctx, status);
982 _cairo_traps_fini (&traps);
987 static cairo_int_status_t
988 _cairo_gl_msaa_compositor_glyphs (const cairo_compositor_t *compositor,
989 cairo_composite_rectangles_t *composite,
990 cairo_scaled_font_t *scaled_font,
991 cairo_glyph_t *glyphs,
993 cairo_bool_t overlap)
995 cairo_int_status_t status;
996 cairo_surface_t *src = NULL;
998 cairo_composite_glyphs_info_t info;
1000 cairo_gl_surface_t *dst = (cairo_gl_surface_t *) composite->surface;
1002 query_surface_capabilities (dst);
1003 if (! dst->supports_stencil)
1004 return CAIRO_INT_STATUS_UNSUPPORTED;
1006 if (composite->is_bounded == FALSE) {
1007 cairo_surface_t* surface = _prepare_unbounded_surface (dst);
1009 if (unlikely (surface == NULL))
1010 return CAIRO_INT_STATUS_UNSUPPORTED;
1012 status = _cairo_compositor_glyphs (compositor, surface,
1013 CAIRO_OPERATOR_SOURCE,
1014 &composite->source_pattern.base,
1016 scaled_font, composite->clip);
1018 if (unlikely (status)) {
1019 cairo_surface_destroy (surface);
1023 return _paint_back_unbounded_surface (compositor, composite, surface);
1026 src = _cairo_gl_pattern_to_source (&dst->base,
1027 composite->original_source_pattern,
1029 &composite->bounded,
1030 &composite->source_sample_area,
1032 if (unlikely (src->status)) {
1033 status = src->status;
1037 status = _cairo_gl_check_composite_glyphs (composite,
1038 scaled_font, glyphs,
1040 if (unlikely (status != CAIRO_INT_STATUS_SUCCESS))
1043 info.font = scaled_font;
1044 info.glyphs = glyphs;
1045 info.num_glyphs = num_glyphs;
1046 info.use_mask = overlap || ! composite->is_bounded ||
1047 composite->op == CAIRO_OPERATOR_SOURCE;
1048 info.extents = composite->bounded;
1050 _cairo_scaled_font_freeze_cache (scaled_font);
1051 status = _cairo_gl_composite_glyphs_with_clip (dst, composite->op,
1057 _cairo_scaled_font_thaw_cache (scaled_font);
1061 cairo_surface_destroy (src);
1067 _cairo_gl_msaa_compositor_init (cairo_compositor_t *compositor,
1068 const cairo_compositor_t *delegate)
1070 compositor->delegate = delegate;
1071 compositor->lazy_init = TRUE;
1073 compositor->paint = _cairo_gl_msaa_compositor_paint;
1074 compositor->mask = _cairo_gl_msaa_compositor_mask;
1075 compositor->fill = _cairo_gl_msaa_compositor_fill;
1076 compositor->stroke = _cairo_gl_msaa_compositor_stroke;
1077 compositor->glyphs = _cairo_gl_msaa_compositor_glyphs;
1080 const cairo_compositor_t *
1081 _cairo_gl_msaa_compositor_get (void)
1083 static cairo_compositor_t compositor;
1084 if (compositor.delegate == NULL)
1085 _cairo_gl_msaa_compositor_init (&compositor,
1086 _cairo_gl_span_compositor_get ());