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"
51 can_use_msaa_compositor (cairo_gl_surface_t *surface,
52 cairo_antialias_t antialias);
55 query_surface_capabilities (cairo_gl_surface_t *surface);
57 struct _tristrip_composite_info {
58 cairo_gl_composite_t setup;
59 cairo_gl_context_t *ctx;
63 _is_continuous_single_line (const cairo_path_fixed_t *path,
64 const cairo_stroke_style_t *style)
66 return (_cairo_path_fixed_is_single_line (path) &&
71 static cairo_int_status_t
72 _draw_trap (cairo_gl_context_t *ctx,
73 cairo_gl_composite_t *setup,
74 cairo_trapezoid_t *trap)
76 cairo_point_t quad[4];
78 quad[0].x = _cairo_edge_compute_intersection_x_for_y (&trap->left.p1,
81 quad[0].y = trap->top;
83 quad[1].x = _cairo_edge_compute_intersection_x_for_y (&trap->left.p1,
86 quad[1].y = trap->bottom;
88 quad[2].x = _cairo_edge_compute_intersection_x_for_y (&trap->right.p1,
91 quad[2].y = trap->bottom;
93 quad[3].x = _cairo_edge_compute_intersection_x_for_y (&trap->right.p1,
96 quad[3].y = trap->top;
97 return _cairo_gl_composite_emit_quad_as_tristrip (ctx, setup, quad);
100 static cairo_int_status_t
101 _draw_traps (cairo_gl_context_t *ctx,
102 cairo_gl_composite_t *setup,
103 cairo_traps_t *traps)
105 cairo_int_status_t status = CAIRO_STATUS_SUCCESS;
108 for (i = 0; i < traps->num_traps; i++) {
109 cairo_trapezoid_t *trap = traps->traps + i;
110 if (unlikely ((status = _draw_trap (ctx, setup, trap))))
117 static cairo_int_status_t
118 _draw_box (cairo_gl_context_t *ctx,
119 cairo_gl_composite_t *setup,
122 cairo_point_t quad[4];
124 quad[0].x = box->p1.x;
125 quad[0].y = box->p1.y;
126 quad[1].x = box->p1.x;
127 quad[1].y = box->p2.y;
128 quad[2].x = box->p2.x;
129 quad[2].y = box->p2.y;
130 quad[3].x = box->p2.x;
131 quad[3].y = box->p1.y;
133 return _cairo_gl_composite_emit_quad_as_tristrip (ctx, setup, quad);
136 static cairo_int_status_t
137 _draw_int_rect (cairo_gl_context_t *ctx,
138 cairo_gl_composite_t *setup,
139 cairo_rectangle_int_t *rect)
142 _cairo_box_from_rectangle (&box, rect);
143 return _draw_box (ctx, setup, &box);
146 static cairo_int_status_t
147 _draw_triangle_fan (cairo_gl_context_t *ctx,
148 cairo_gl_composite_t *setup,
149 const cairo_point_t *midpt,
150 const cairo_point_t *points,
155 /* Our strategy here is to not even try to build a triangle fan, but to
156 draw each triangle as if it was an unconnected member of a triangle strip. */
157 for (i = 1; i < npoints; i++) {
158 cairo_int_status_t status;
159 cairo_point_t triangle[3];
161 triangle[0] = *midpt;
162 triangle[1] = points[i - 1];
163 triangle[2] = points[i];
165 status = _cairo_gl_composite_emit_triangle_as_tristrip (ctx, setup, triangle);
166 if (unlikely (status))
170 return CAIRO_STATUS_SUCCESS;
173 static cairo_int_status_t
174 _clip_to_traps (cairo_clip_t *clip,
175 cairo_traps_t *traps)
177 cairo_int_status_t status;
178 cairo_polygon_t polygon;
179 cairo_antialias_t antialias;
180 cairo_fill_rule_t fill_rule;
182 _cairo_traps_init (traps);
184 if (clip->num_boxes == 1 && clip->path == NULL) {
186 _cairo_boxes_init_for_array (&boxes, clip->boxes, clip->num_boxes);
187 return _cairo_traps_init_boxes (traps, &boxes);
190 status = _cairo_clip_get_polygon (clip, &polygon, &fill_rule, &antialias);
191 if (unlikely (status))
194 /* We ignore the antialias mode of the clip here, since the user requested
195 * unantialiased rendering of their path and we expect that this stencil
196 * based rendering of the clip to be a reasonable approximation to
197 * the intersection between that clip and the path.
199 * In other words, what the user expects when they try to perform
200 * a geometric intersection between an unantialiased polygon and an
201 * antialiased polygon is open to interpretation. And we choose the fast
205 _cairo_traps_init (traps);
206 status = _cairo_bentley_ottmann_tessellate_polygon (traps,
213 _cairo_gl_msaa_compositor_draw_clip (cairo_gl_context_t *ctx,
214 cairo_gl_composite_t *setup,
217 cairo_int_status_t status;
220 status = _clip_to_traps (clip, &traps);
221 if (unlikely (status))
223 status = _draw_traps (ctx, setup, &traps);
225 _cairo_traps_fini (&traps);
230 _should_use_unbounded_surface (cairo_composite_rectangles_t *composite)
232 cairo_gl_surface_t *dst = (cairo_gl_surface_t *) composite->surface;
233 cairo_rectangle_int_t *source = &composite->source;
235 if (composite->is_bounded)
238 /* This isn't just an optimization. It also detects when painting is used
239 to paint back the unbounded surface, preventing infinite recursion. */
240 return ! (source->x <= 0 && source->y <= 0 &&
241 source->height + source->y >= dst->height &&
242 source->width + source->x >= dst->width);
245 static cairo_surface_t*
246 _prepare_unbounded_surface (cairo_gl_surface_t *dst)
249 cairo_surface_t* surface = cairo_gl_surface_create (dst->base.device,
255 if (unlikely (surface->status)) {
256 cairo_surface_destroy (surface);
262 static cairo_int_status_t
263 _paint_back_unbounded_surface (const cairo_compositor_t *compositor,
264 cairo_composite_rectangles_t *composite,
265 cairo_surface_t *surface)
267 cairo_gl_surface_t *dst = (cairo_gl_surface_t *) composite->surface;
268 cairo_int_status_t status;
270 cairo_pattern_t *pattern = cairo_pattern_create_for_surface (surface);
271 if (unlikely (pattern->status)) {
272 status = pattern->status;
276 status = _cairo_compositor_paint (compositor, &dst->base,
277 composite->op, pattern,
281 cairo_pattern_destroy (pattern);
282 cairo_surface_destroy (surface);
287 can_use_msaa_compositor (cairo_gl_surface_t *surface,
288 cairo_antialias_t antialias)
290 query_surface_capabilities (surface);
291 if (! surface->supports_stencil)
294 /* Multisampling OpenGL ES surfaces only maintain one multisampling
295 framebuffer and thus must use the spans compositor to do non-antialiased
297 if (((cairo_gl_context_t *) surface->base.device)->gl_flavor == CAIRO_GL_FLAVOR_ES
298 && surface->supports_msaa
299 && antialias == CAIRO_ANTIALIAS_NONE)
302 /* The MSAA compositor has a single-sample mode, so we can
303 support non-antialiased rendering. */
304 if (antialias == CAIRO_ANTIALIAS_NONE)
307 if (antialias == CAIRO_ANTIALIAS_FAST || antialias == CAIRO_ANTIALIAS_DEFAULT)
308 return surface->supports_msaa;
313 _cairo_gl_msaa_compositor_set_clip (cairo_composite_rectangles_t *composite,
314 cairo_gl_composite_t *setup)
318 if (_cairo_clip_is_all_clipped (composite->clip))
321 /* We don't need to check CAIRO_OPERATOR_BOUND_BY_MASK in these
323 is_bounded = composite->is_bounded;
324 composite->is_bounded = CAIRO_OPERATOR_BOUND_BY_SOURCE;
325 if (_cairo_composite_rectangles_can_reduce_clip (composite, composite->clip))
328 _cairo_gl_composite_set_clip (setup, composite->clip);
330 composite->is_bounded = is_bounded;
333 /* Masking with the SOURCE operator requires two passes. In the first
334 * pass we use the mask as the source to get:
335 * result = (1 - ma) * dst
336 * In the second pass we use the add operator to achieve:
337 * result = (src * ma) + dst
338 * Combined this produces:
339 * result = (src * ma) + (1 - ma) * dst
341 static cairo_int_status_t
342 _cairo_gl_msaa_compositor_mask_source_operator (const cairo_compositor_t *compositor,
343 cairo_composite_rectangles_t *composite)
345 cairo_gl_composite_t setup;
346 cairo_gl_surface_t *dst = (cairo_gl_surface_t *) composite->surface;
347 cairo_gl_context_t *ctx = NULL;
348 cairo_int_status_t status;
350 cairo_clip_t *clip = composite->clip;
353 /* If we have a non-rectangular clip, we can avoid using the stencil buffer
354 * for clipping and just draw the clip polygon. */
356 status = _clip_to_traps (clip, &traps);
357 if (unlikely (status)) {
358 _cairo_traps_fini (&traps);
363 status = _cairo_gl_composite_init (&setup,
364 CAIRO_OPERATOR_DEST_OUT,
366 FALSE /* assume_component_alpha */);
367 if (unlikely (status))
369 status = _cairo_gl_composite_set_source (&setup,
370 composite->original_mask_pattern,
371 &composite->mask_sample_area,
374 if (unlikely (status))
377 status = _cairo_gl_composite_begin_multisample (&setup, &ctx, TRUE);
378 if (unlikely (status))
382 status = _draw_int_rect (ctx, &setup, &composite->bounded);
384 status = _draw_traps (ctx, &setup, &traps);
386 /* Now draw the second pass. */
387 _cairo_gl_composite_set_operator (&setup, CAIRO_OPERATOR_ADD,
388 FALSE /* assume_component_alpha */);
389 if (unlikely (status))
391 status = _cairo_gl_composite_set_source (&setup,
392 composite->original_source_pattern,
393 &composite->source_sample_area,
396 if (unlikely (status))
398 status = _cairo_gl_composite_set_mask (&setup,
399 composite->original_mask_pattern,
400 &composite->source_sample_area,
401 &composite->bounded);
402 if (unlikely (status))
404 status = _cairo_gl_set_operands_and_operator (&setup, ctx, TRUE);
405 if (unlikely (status))
409 status = _draw_int_rect (ctx, &setup, &composite->bounded);
411 status = _draw_traps (ctx, &setup, &traps);
414 _cairo_gl_composite_fini (&setup);
416 status = _cairo_gl_context_release (ctx, status);
418 _cairo_traps_fini (&traps);
423 static cairo_int_status_t
424 _cairo_gl_msaa_compositor_mask (const cairo_compositor_t *compositor,
425 cairo_composite_rectangles_t *composite)
427 cairo_gl_composite_t setup;
428 cairo_gl_surface_t *dst = (cairo_gl_surface_t *) composite->surface;
429 cairo_gl_context_t *ctx = NULL;
430 cairo_int_status_t status;
431 cairo_operator_t op = composite->op;
432 cairo_bool_t use_color_attribute = FALSE;
433 cairo_clip_t *clip = composite->clip;
435 if (! can_use_msaa_compositor (dst, CAIRO_ANTIALIAS_DEFAULT))
436 return CAIRO_INT_STATUS_UNSUPPORTED;
438 /* GL compositing operators cannot properly represent a mask operation
439 using the SOURCE compositing operator in one pass. This only matters if
440 there actually is a mask (there isn't in a paint operation) and if the
441 mask isn't totally opaque. */
442 if (op == CAIRO_OPERATOR_SOURCE &&
443 composite->original_mask_pattern != NULL &&
444 ! _cairo_pattern_is_opaque (&composite->mask_pattern.base,
445 &composite->mask_sample_area)) {
447 if (! _cairo_pattern_is_opaque (&composite->source_pattern.base,
448 &composite->source_sample_area)) {
449 return _cairo_gl_msaa_compositor_mask_source_operator (compositor, composite);
452 /* If the source is opaque the operation reduces to OVER. */
453 op = CAIRO_OPERATOR_OVER;
456 if (_should_use_unbounded_surface (composite)) {
457 cairo_surface_t* surface = _prepare_unbounded_surface (dst);
459 if (unlikely (surface == NULL))
460 return CAIRO_INT_STATUS_UNSUPPORTED;
462 /* This may be a paint operation. */
463 if (composite->original_mask_pattern == NULL) {
464 status = _cairo_compositor_paint (compositor, surface,
465 CAIRO_OPERATOR_SOURCE,
466 &composite->source_pattern.base,
469 status = _cairo_compositor_mask (compositor, surface,
470 CAIRO_OPERATOR_SOURCE,
471 &composite->source_pattern.base,
472 &composite->mask_pattern.base,
476 if (unlikely (status)) {
477 cairo_surface_destroy (surface);
481 return _paint_back_unbounded_surface (compositor, composite, surface);
484 status = _cairo_gl_composite_init (&setup,
487 FALSE /* assume_component_alpha */);
488 if (unlikely (status))
491 if (! composite->clip ||
492 (composite->clip->num_boxes == 1 && ! composite->clip->path))
493 use_color_attribute = TRUE;
495 status = _cairo_gl_composite_set_source (&setup,
496 composite->original_source_pattern,
497 &composite->source_sample_area,
499 use_color_attribute);
500 if (unlikely (status))
503 if (composite->original_mask_pattern != NULL) {
504 status = _cairo_gl_composite_set_mask (&setup,
505 composite->original_mask_pattern,
506 &composite->mask_sample_area,
507 &composite->bounded);
509 if (unlikely (status))
512 /* We always use multisampling here, because we do not yet have the smarts
513 to calculate when the clip or the source requires it. */
514 status = _cairo_gl_composite_begin_multisample (&setup, &ctx, TRUE);
515 if (unlikely (status))
519 status = _draw_int_rect (ctx, &setup, &composite->bounded);
521 status = _cairo_gl_msaa_compositor_draw_clip (ctx, &setup, clip);
524 _cairo_gl_composite_fini (&setup);
527 status = _cairo_gl_context_release (ctx, status);
532 static cairo_int_status_t
533 _cairo_gl_msaa_compositor_paint (const cairo_compositor_t *compositor,
534 cairo_composite_rectangles_t *composite)
536 return _cairo_gl_msaa_compositor_mask (compositor, composite);
539 static cairo_status_t
540 _stroke_shaper_add_triangle (void *closure,
541 const cairo_point_t triangle[3])
543 struct _tristrip_composite_info *info = closure;
544 return _cairo_gl_composite_emit_triangle_as_tristrip (info->ctx,
549 static cairo_status_t
550 _stroke_shaper_add_triangle_fan (void *closure,
551 const cairo_point_t *midpoint,
552 const cairo_point_t *points,
555 struct _tristrip_composite_info *info = closure;
556 return _draw_triangle_fan (info->ctx, &info->setup,
557 midpoint, points, npoints);
560 static cairo_status_t
561 _stroke_shaper_add_quad (void *closure,
562 const cairo_point_t quad[4])
564 struct _tristrip_composite_info *info = closure;
565 return _cairo_gl_composite_emit_quad_as_tristrip (info->ctx, &info->setup,
570 _is_continuous_arc (const cairo_path_fixed_t *path,
571 const cairo_stroke_style_t *style)
573 return (_cairo_path_fixed_is_single_arc (path) &&
574 style->dash == NULL);
577 static cairo_int_status_t
578 _prevent_overlapping_strokes (cairo_gl_context_t *ctx,
579 cairo_gl_composite_t *setup,
580 cairo_composite_rectangles_t *composite,
581 const cairo_path_fixed_t *path,
582 const cairo_stroke_style_t *style,
583 const cairo_matrix_t *ctm)
585 cairo_rectangle_int_t stroke_extents;
586 const cairo_pattern_t *pattern = composite->original_source_pattern;
587 cairo_pattern_type_t type = cairo_pattern_get_type ((cairo_pattern_t *) pattern);
589 if (! _cairo_gl_ensure_stencil (ctx, setup->dst))
590 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 cairo_bool_t scissor_was_enabled;
602 /* In case we have pending operations we have to flush before
603 adding the stencil buffer. */
604 _cairo_gl_composite_flush (ctx);
606 /* Enable the stencil buffer, even if we are not using it for clipping,
607 so we can use it below to prevent overlapping shapes. We initialize
608 it all to one here which represents infinite clip. */
609 if (! ctx->states_cache.depth_mask) {
610 glDepthMask (GL_TRUE);
611 ctx->states_cache.depth_mask = TRUE;
613 glEnable (GL_STENCIL_TEST);
615 /* We scissor here so that we don't have to clear the entire stencil
616 * buffer. If the scissor test is already enabled, it was enabled
617 * for clipping. In that case, instead of calculating an intersection,
618 * we just reuse it, and risk clearing too much. */
619 scissor_was_enabled = glIsEnabled (GL_SCISSOR_TEST);
620 if (! scissor_was_enabled) {
621 _cairo_path_fixed_approximate_stroke_extents (path, style, ctm,
623 _cairo_gl_scissor_to_rectangle (setup->dst, &stroke_extents);
626 glClear (GL_STENCIL_BUFFER_BIT);
627 if (! scissor_was_enabled)
628 glDisable (GL_SCISSOR_TEST);
630 glStencilFunc (GL_EQUAL, 1, 1);
633 /* This means that once we draw to a particular pixel nothing else can
634 be drawn there until the stencil buffer is reset or the stencil test
636 glStencilOp (GL_ZERO, GL_ZERO, GL_ZERO);
638 return CAIRO_INT_STATUS_SUCCESS;
642 query_surface_capabilities (cairo_gl_surface_t *surface)
644 GLint samples, stencil_bits;
645 cairo_gl_context_t *ctx;
646 cairo_int_status_t status;
648 /* Texture surfaces are create in such a way that they always
649 have stencil and multisample bits if possible, so we don't
650 need to query their capabilities lazily. */
651 if (_cairo_gl_surface_is_texture (surface))
653 if (surface->stencil_and_msaa_caps_initialized)
656 surface->stencil_and_msaa_caps_initialized = TRUE;
657 surface->supports_stencil = FALSE;
658 surface->supports_msaa = FALSE;
660 status = _cairo_gl_context_acquire (surface->base.device, &ctx);
661 if (unlikely (status))
664 _cairo_gl_context_set_destination (ctx, surface, FALSE);
666 glGetIntegerv(GL_SAMPLES, &samples);
667 glGetIntegerv(GL_STENCIL_BITS, &stencil_bits);
668 surface->supports_stencil = stencil_bits > 0;
669 surface->supports_msaa = samples > 1;
671 status = _cairo_gl_context_release (ctx, status);
674 static cairo_int_status_t
675 _cairo_gl_msaa_compositor_stroke (const cairo_compositor_t *compositor,
676 cairo_composite_rectangles_t *composite,
677 const cairo_path_fixed_t *path,
678 const cairo_stroke_style_t *style,
679 const cairo_matrix_t *ctm,
680 const cairo_matrix_t *ctm_inverse,
682 cairo_antialias_t antialias)
684 cairo_int_status_t status;
685 cairo_gl_surface_t *dst = (cairo_gl_surface_t *) composite->surface;
686 struct _tristrip_composite_info info;
687 cairo_bool_t use_color_attribute;
689 if (! can_use_msaa_compositor (dst, antialias))
690 return CAIRO_INT_STATUS_UNSUPPORTED;
692 if (composite->is_bounded == FALSE) {
693 cairo_surface_t* surface = _prepare_unbounded_surface (dst);
695 if (unlikely (surface == NULL))
696 return CAIRO_INT_STATUS_UNSUPPORTED;
698 status = _cairo_compositor_stroke (compositor, surface,
699 CAIRO_OPERATOR_SOURCE,
700 &composite->source_pattern.base,
701 path, style, ctm, ctm_inverse,
702 tolerance, antialias, NULL);
703 if (unlikely (status)) {
704 cairo_surface_destroy (surface);
708 return _paint_back_unbounded_surface (compositor, composite, surface);
711 status = _cairo_gl_composite_init (&info.setup,
714 FALSE /* assume_component_alpha */);
715 if (unlikely (status))
719 use_color_attribute = _cairo_path_fixed_stroke_is_rectilinear (path) ||
720 _cairo_gl_hairline_style_is_hairline (style, ctm);
722 status = _cairo_gl_composite_set_source (&info.setup,
723 composite->original_source_pattern,
724 &composite->source_sample_area,
726 use_color_attribute);
727 if (unlikely (status))
730 _cairo_gl_msaa_compositor_set_clip (composite, &info.setup);
732 status = _cairo_gl_composite_begin_multisample (&info.setup, &info.ctx,
733 antialias != CAIRO_ANTIALIAS_NONE);
734 if (unlikely (status))
737 if (_cairo_gl_hairline_style_is_hairline (style, ctm)) {
738 cairo_gl_hairline_closure_t closure;
740 if (! (_is_continuous_arc (path, style) ||
741 _is_continuous_single_line (path, style))) {
742 status = _prevent_overlapping_strokes (info.ctx, &info.setup,
745 if (unlikely (status))
749 closure.ctx = info.ctx;
751 closure.tolerance = tolerance;
753 status = _cairo_gl_path_fixed_stroke_to_hairline (path, &closure,
756 _cairo_gl_hairline_move_to,
758 _cairo_gl_hairline_line_to_dashed :
759 _cairo_gl_hairline_line_to,
760 _cairo_gl_hairline_curve_to,
761 _cairo_gl_hairline_close_path);
765 if (use_color_attribute) {
768 _cairo_traps_init (&traps);
770 status = _cairo_path_fixed_stroke_to_traps (path, style,
773 if (unlikely (status)) {
774 _cairo_traps_fini (&traps);
778 status = _draw_traps (info.ctx, &info.setup, &traps);
779 _cairo_traps_fini (&traps);
781 if (!_is_continuous_single_line (path, style)) {
782 status = _prevent_overlapping_strokes (info.ctx, &info.setup,
783 composite, path, style, ctm);
784 if (unlikely (status))
789 _cairo_path_fixed_stroke_to_shaper ((cairo_path_fixed_t *) path,
794 _stroke_shaper_add_triangle,
795 _stroke_shaper_add_triangle_fan,
796 _stroke_shaper_add_quad,
798 if (unlikely (status))
802 _cairo_gl_composite_fini (&info.setup);
805 status = _cairo_gl_context_release (info.ctx, status);
810 static cairo_int_status_t
811 _cairo_gl_msaa_compositor_fill_rectilinear (const cairo_compositor_t *compositor,
812 cairo_composite_rectangles_t *composite,
813 const cairo_path_fixed_t *path,
814 cairo_fill_rule_t fill_rule,
816 cairo_antialias_t antialias,
819 cairo_gl_composite_t setup;
820 cairo_gl_surface_t *dst = (cairo_gl_surface_t *) composite->surface;
821 cairo_gl_context_t *ctx = NULL;
822 cairo_int_status_t status;
825 status = _cairo_gl_composite_init (&setup,
828 FALSE /* assume_component_alpha */);
829 if (unlikely (status))
832 status = _cairo_gl_composite_set_source (&setup,
833 composite->original_source_pattern,
834 &composite->source_sample_area,
837 if (unlikely (status))
840 status = _cairo_gl_composite_begin_multisample (&setup, &ctx,
841 antialias != CAIRO_ANTIALIAS_NONE);
842 if (unlikely (status))
845 for (i = 0; i < clip->num_boxes; i++) {
846 status = _draw_box (ctx, &setup, &clip->boxes[i]);
847 if (unlikely (status))
852 _cairo_gl_composite_fini (&setup);
855 status = _cairo_gl_context_release (ctx, status);
860 static cairo_int_status_t
861 _cairo_gl_msaa_compositor_fill (const cairo_compositor_t *compositor,
862 cairo_composite_rectangles_t *composite,
863 const cairo_path_fixed_t *path,
864 cairo_fill_rule_t fill_rule,
866 cairo_antialias_t antialias)
868 cairo_gl_composite_t setup;
869 cairo_gl_surface_t *dst = (cairo_gl_surface_t *) composite->surface;
870 cairo_gl_context_t *ctx = NULL;
871 cairo_int_status_t status = CAIRO_INT_STATUS_SUCCESS;
873 cairo_bool_t use_color_attr = FALSE;
875 if (! can_use_msaa_compositor (dst, antialias))
876 return CAIRO_INT_STATUS_UNSUPPORTED;
878 if (composite->is_bounded == FALSE) {
879 cairo_surface_t* surface = _prepare_unbounded_surface (dst);
881 if (unlikely (surface == NULL))
882 return CAIRO_INT_STATUS_UNSUPPORTED;
885 status = _cairo_compositor_fill (compositor, surface,
886 CAIRO_OPERATOR_SOURCE,
887 &composite->source_pattern.base,
888 path, fill_rule, tolerance,
891 if (unlikely (status)) {
892 cairo_surface_destroy (surface);
896 return _paint_back_unbounded_surface (compositor, composite, surface);
899 if (_cairo_path_fixed_fill_is_rectilinear (path) &&
900 composite->clip != NULL &&
901 composite->clip->num_boxes == 1 &&
902 composite->clip->path == NULL) {
903 cairo_clip_t *clip = _cairo_clip_copy (composite->clip);
904 clip = _cairo_clip_intersect_rectilinear_path (clip,
909 status = _cairo_gl_msaa_compositor_fill_rectilinear (compositor,
916 _cairo_clip_destroy (clip);
921 _cairo_traps_init (&traps);
922 if (_cairo_path_fixed_fill_is_rectilinear (path)) {
923 status = _cairo_path_fixed_fill_rectilinear_to_traps (path,
927 use_color_attr = TRUE;
929 status = _cairo_path_fixed_fill_to_traps (path, fill_rule,
933 status = _cairo_gl_composite_init (&setup,
936 FALSE /* assume_component_alpha */);
937 if (unlikely (status))
940 status = _cairo_gl_composite_set_source (&setup,
941 composite->original_source_pattern,
942 &composite->source_sample_area,
945 if (unlikely (status))
948 _cairo_gl_msaa_compositor_set_clip (composite, &setup);
950 status = _cairo_gl_composite_begin_multisample (&setup, &ctx,
951 antialias != CAIRO_ANTIALIAS_NONE);
952 if (unlikely (status))
955 status = _draw_traps (ctx, &setup, &traps);
956 if (unlikely (status))
960 _cairo_gl_composite_fini (&setup);
963 status = _cairo_gl_context_release (ctx, status);
966 _cairo_traps_fini (&traps);
971 static cairo_int_status_t
972 _cairo_gl_msaa_compositor_glyphs (const cairo_compositor_t *compositor,
973 cairo_composite_rectangles_t *composite,
974 cairo_scaled_font_t *scaled_font,
975 cairo_glyph_t *glyphs,
977 cairo_bool_t overlap)
979 cairo_int_status_t status;
980 cairo_surface_t *src = NULL;
982 cairo_composite_glyphs_info_t info;
984 cairo_gl_surface_t *dst = (cairo_gl_surface_t *) composite->surface;
986 query_surface_capabilities (dst);
987 if (! dst->supports_stencil)
988 return CAIRO_INT_STATUS_UNSUPPORTED;
990 if (composite->is_bounded == FALSE) {
991 cairo_surface_t* surface = _prepare_unbounded_surface (dst);
993 if (unlikely (surface == NULL))
994 return CAIRO_INT_STATUS_UNSUPPORTED;
996 status = _cairo_compositor_glyphs (compositor, surface,
997 CAIRO_OPERATOR_SOURCE,
998 &composite->source_pattern.base,
1000 scaled_font, composite->clip);
1002 if (unlikely (status)) {
1003 cairo_surface_destroy (surface);
1007 return _paint_back_unbounded_surface (compositor, composite, surface);
1010 src = _cairo_gl_pattern_to_source (&dst->base,
1011 composite->original_source_pattern,
1013 &composite->bounded,
1014 &composite->source_sample_area,
1016 if (unlikely (src->status)) {
1017 status = src->status;
1021 status = _cairo_gl_check_composite_glyphs (composite,
1022 scaled_font, glyphs,
1024 if (unlikely (status != CAIRO_INT_STATUS_SUCCESS))
1027 info.font = scaled_font;
1028 info.glyphs = glyphs;
1029 info.num_glyphs = num_glyphs;
1030 info.use_mask = overlap || ! composite->is_bounded ||
1031 composite->op == CAIRO_OPERATOR_SOURCE;
1032 info.extents = composite->bounded;
1034 _cairo_scaled_font_freeze_cache (scaled_font);
1035 status = _cairo_gl_composite_glyphs_with_clip (dst, composite->op,
1041 _cairo_scaled_font_thaw_cache (scaled_font);
1045 cairo_surface_destroy (src);
1051 _cairo_gl_msaa_compositor_init (cairo_compositor_t *compositor,
1052 const cairo_compositor_t *delegate)
1054 compositor->delegate = delegate;
1055 compositor->lazy_init = TRUE;
1057 compositor->paint = _cairo_gl_msaa_compositor_paint;
1058 compositor->mask = _cairo_gl_msaa_compositor_mask;
1059 compositor->fill = _cairo_gl_msaa_compositor_fill;
1060 compositor->stroke = _cairo_gl_msaa_compositor_stroke;
1061 compositor->glyphs = _cairo_gl_msaa_compositor_glyphs;
1064 const cairo_compositor_t *
1065 _cairo_gl_msaa_compositor_get (void)
1067 static cairo_compositor_t compositor;
1068 if (compositor.delegate == NULL)
1069 _cairo_gl_msaa_compositor_init (&compositor,
1070 _cairo_gl_span_compositor_get ());