Fix bugs
[framework/graphics/cairo.git] / src / cairo-gl-msaa-compositor.c
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
3  *
4  * Copyright © 2002 University of Southern California
5  * Copyright © 2005 Red Hat, Inc.
6  * Copyright © 2011 Intel Corporation
7  * Copyright © 2011 Samsung Electronics
8  *
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.
16  *
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
22  *
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/
27  *
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.
31  *
32  * The Original Code is the cairo graphics library.
33  *
34  * The Initial Developer of the Original Code is University of Southern
35  * California.
36  *
37  * Contributor(s):
38  *      Henry Song <hsong@sisa.samsung.com>
39  *      Martin Robinson <mrobinson@igalia.com>
40  */
41
42 #include "cairoint.h"
43
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"
50
51 static cairo_bool_t
52 can_use_msaa_compositor (cairo_gl_surface_t *surface,
53                          cairo_antialias_t antialias);
54
55 static void
56 query_surface_capabilities (cairo_gl_surface_t *surface);
57
58 struct _tristrip_composite_info {
59     cairo_gl_composite_t        setup;
60     cairo_gl_context_t          *ctx;
61 };
62
63 static cairo_bool_t
64 _is_continuous_single_line (const cairo_path_fixed_t   *path,
65                             const cairo_stroke_style_t *style)
66 {
67     return (_cairo_path_fixed_is_single_line (path) &&
68             style->dash == NULL);
69 }
70
71
72 static cairo_int_status_t
73 _draw_trap (cairo_gl_context_t          *ctx,
74             cairo_gl_composite_t        *setup,
75             cairo_trapezoid_t           *trap)
76 {
77     cairo_point_t quad[4];
78
79     if (trap->left.p1.x == trap->left.p2.x) {
80         quad[0].x = trap->left.p1.x;
81         quad[1].x = trap->left.p1.x;
82     } else {
83         cairo_fixed_t x, dy;
84         x = trap->left.p1.x;
85         dy = trap->left.p2.y - trap->left.p1.y;
86
87         if (trap->top == trap->left.p1.y)
88             quad[0].x = x;
89         else if (trap->top == trap->left.p2.y)
90             quad[0].x = trap->left.p2.x;
91         else if (dy != 0)
92             quad[0].x = x + _cairo_fixed_mul_div_floor (trap->top - trap->left.p1.y,
93                                                         trap->left.p2.x - trap->left.p1.x, dy);
94
95         if (trap->bottom == trap->left.p2.y)
96             quad[1].x = trap->left.p2.x;
97         else if (trap->bottom == trap->left.p1.y)
98             quad[1].x = x;
99         else if (dy != 0)
100             quad[1].x = x + _cairo_fixed_mul_div_floor (trap->bottom - trap->left.p1.y,
101                                                         trap->left.p2.x - trap->left.p1.x, dy);
102     }
103     quad[0].y = trap->top;
104     quad[1].y = trap->bottom;
105
106     if (trap->right.p1.x == trap->right.p2.x) {
107         quad[2].x = trap->right.p1.x;
108         quad[3].x = trap->right.p1.x;
109     } else {
110         cairo_fixed_t x, dy;
111         x = trap->right.p1.x;
112         dy = trap->right.p2.y - trap->right.p1.y;
113
114         if (trap->bottom == trap->right.p2.y)
115             quad[2].x = trap->right.p2.x;
116         else if (trap->bottom == trap->right.p1.y)
117             quad[2].x = x;
118         else if (dy != 0)
119             quad[2].x = x + _cairo_fixed_mul_div_floor (trap->bottom - trap->right.p1.y,
120                                                         trap->right.p2.x - trap->right.p1.x, dy);
121
122         if (trap->top == trap->right.p1.y)
123             quad[3].x = x;
124         else if (trap->top == trap->right.p2.y)
125             quad[3].x = trap->right.p2.x;
126         else if (dy != 0)
127             quad[3].x = x + _cairo_fixed_mul_div_floor (trap->top - trap->right.p1.y,
128                                                         trap->right.p2.x - trap->right.p1.x, dy);
129     }
130     quad[2].y = trap->bottom;
131     quad[3].y = trap->top;
132
133     return _cairo_gl_composite_emit_quad_as_tristrip (ctx, setup, quad);
134 }
135
136 static cairo_int_status_t
137 _draw_traps (cairo_gl_context_t         *ctx,
138              cairo_gl_composite_t       *setup,
139              cairo_traps_t              *traps)
140 {
141     cairo_int_status_t status = CAIRO_STATUS_SUCCESS;
142     int i;
143
144     for (i = 0; i < traps->num_traps; i++) {
145         cairo_trapezoid_t *trap = traps->traps + i;
146         if (unlikely ((status = _draw_trap (ctx, setup, trap))))
147             return status;
148     }
149
150    return status;
151 }
152
153 static cairo_int_status_t
154 _draw_int_rect (cairo_gl_context_t      *ctx,
155                 cairo_gl_composite_t    *setup,
156                 cairo_rectangle_int_t   *rect)
157 {
158     cairo_box_t box;
159     cairo_point_t quad[4];
160
161     _cairo_box_from_rectangle (&box, rect);
162     quad[0].x = box.p1.x;
163     quad[0].y = box.p1.y;
164     quad[1].x = box.p1.x;
165     quad[1].y = box.p2.y;
166     quad[2].x = box.p2.x;
167     quad[2].y = box.p2.y;
168     quad[3].x = box.p2.x;
169     quad[3].y = box.p1.y;
170
171     return _cairo_gl_composite_emit_quad_as_tristrip (ctx, setup, quad);
172 }
173
174 static cairo_int_status_t
175 _draw_triangle_fan (cairo_gl_context_t          *ctx,
176                     cairo_gl_composite_t        *setup,
177                     const cairo_point_t         *midpt,
178                     const cairo_point_t         *points,
179                     int                          npoints)
180 {
181     int i;
182
183     /* Our strategy here is to not even try to build a triangle fan, but to
184        draw each triangle as if it was an unconnected member of a triangle strip. */
185     for (i = 1; i < npoints; i++) {
186         cairo_int_status_t status;
187         cairo_point_t triangle[3];
188
189         triangle[0] = *midpt;
190         triangle[1] = points[i - 1];
191         triangle[2] = points[i];
192
193         status = _cairo_gl_composite_emit_triangle_as_tristrip (ctx, setup, triangle);
194         if (unlikely (status))
195             return status;
196     }
197
198     return CAIRO_STATUS_SUCCESS;
199 }
200
201 static cairo_int_status_t
202 _clip_to_traps (cairo_clip_t *clip,
203                 cairo_traps_t *traps)
204 {
205     cairo_int_status_t status;
206     cairo_polygon_t polygon;
207     cairo_antialias_t antialias;
208     cairo_fill_rule_t fill_rule;
209
210     _cairo_traps_init (traps);
211
212     if (clip->num_boxes == 1 && clip->path == NULL) {
213         cairo_boxes_t boxes;
214         _cairo_boxes_init_for_array (&boxes, clip->boxes, clip->num_boxes);
215         return _cairo_traps_init_boxes (traps, &boxes);
216     }
217
218     status = _cairo_clip_get_polygon (clip, &polygon, &fill_rule, &antialias);
219     if (unlikely (status))
220         return status;
221
222     /* We ignore the antialias mode of the clip here, since the user requested
223      * unantialiased rendering of their path and we expect that this stencil
224      * based rendering of the clip to be a reasonable approximation to
225      * the intersection between that clip and the path.
226      *
227      * In other words, what the user expects when they try to perform
228      * a geometric intersection between an unantialiased polygon and an
229      * antialiased polygon is open to interpretation. And we choose the fast
230      * option.
231      */
232
233     _cairo_traps_init (traps);
234     status = _cairo_bentley_ottmann_tessellate_polygon (traps,
235                                                         &polygon,
236                                                         fill_rule);
237     _cairo_polygon_fini (&polygon);
238
239     return status;
240 }
241
242 cairo_int_status_t
243 _cairo_gl_msaa_compositor_draw_clip (cairo_gl_context_t *ctx,
244                                      cairo_gl_composite_t *setup,
245                                      cairo_clip_t *clip)
246 {
247     cairo_int_status_t status;
248     cairo_traps_t traps;
249
250     status = _clip_to_traps (clip, &traps);
251     if (unlikely (status))
252         return status;
253     status = _draw_traps (ctx, setup, &traps);
254
255     _cairo_traps_fini (&traps);
256     return status;
257 }
258
259 static cairo_bool_t
260 _should_use_unbounded_surface (cairo_composite_rectangles_t *composite)
261 {
262     cairo_gl_surface_t *dst = (cairo_gl_surface_t *) composite->surface;
263     cairo_rectangle_int_t *source = &composite->source;
264
265     if (composite->is_bounded)
266         return FALSE;
267
268     /* This isn't just an optimization. It also detects when painting is used
269        to paint back the unbounded surface, preventing infinite recursion. */
270     return ! (source->x <= 0 && source->y <= 0 &&
271               source->height + source->y >= dst->height &&
272               source->width + source->x >= dst->width);
273 }
274
275 static cairo_surface_t*
276 _prepare_unbounded_surface (cairo_gl_surface_t *dst)
277 {
278
279     cairo_surface_t* surface = cairo_gl_surface_create (dst->base.device,
280                                                         dst->base.content,
281                                                         dst->width,
282                                                         dst->height);
283     if (surface == NULL)
284         return NULL;
285     if (unlikely (surface->status)) {
286         cairo_surface_destroy (surface);
287         return NULL;
288     }
289     return surface;
290 }
291
292 static cairo_int_status_t
293 _paint_back_unbounded_surface (const cairo_compositor_t         *compositor,
294                                cairo_composite_rectangles_t     *composite,
295                                cairo_surface_t                  *surface)
296 {
297     cairo_gl_surface_t *dst = (cairo_gl_surface_t *) composite->surface;
298     cairo_int_status_t status;
299
300     cairo_pattern_t *pattern = cairo_pattern_create_for_surface (surface);
301     if (unlikely (pattern->status)) {
302         status = pattern->status;
303         goto finish;
304     }
305
306     status = _cairo_compositor_paint (compositor, &dst->base,
307                                       composite->op, pattern,
308                                       composite->clip);
309
310 finish:
311     cairo_pattern_destroy (pattern);
312     cairo_surface_destroy (surface);
313     return status;
314 }
315
316 static cairo_bool_t
317 can_use_msaa_compositor (cairo_gl_surface_t *surface,
318                          cairo_antialias_t antialias)
319 {
320     query_surface_capabilities (surface);
321     if (! surface->supports_stencil)
322         return FALSE;
323
324     /* Multisampling OpenGL ES surfaces only maintain one multisampling
325        framebuffer and thus must use the spans compositor to do non-antialiased
326        rendering. */
327     if (((cairo_gl_context_t *) surface->base.device)->gl_flavor == CAIRO_GL_FLAVOR_ES
328          && surface->supports_msaa
329          && antialias == CAIRO_ANTIALIAS_NONE)
330         return FALSE;
331
332     /* The MSAA compositor has a single-sample mode, so we can
333        support non-antialiased rendering. */
334     if (antialias == CAIRO_ANTIALIAS_NONE)
335         return TRUE;
336
337     if (antialias == CAIRO_ANTIALIAS_FAST || antialias == CAIRO_ANTIALIAS_DEFAULT)
338         return surface->supports_msaa;
339     return FALSE;
340 }
341
342 static void
343 _cairo_gl_msaa_compositor_set_clip (cairo_composite_rectangles_t *composite,
344                                     cairo_gl_composite_t *setup)
345 {
346     uint32_t is_bounded;
347
348     /* We don't need to check CAIRO_OPERATOR_BOUND_BY_MASK in these
349        situations. */
350     is_bounded = composite->is_bounded;
351     composite->is_bounded = CAIRO_OPERATOR_BOUND_BY_SOURCE;
352     if (_cairo_composite_rectangles_can_reduce_clip (composite, composite->clip))
353         return;
354
355     _cairo_gl_composite_set_clip (setup, composite->clip);
356
357     composite->is_bounded = is_bounded;
358 }
359
360 /* Masking with the SOURCE operator requires two passes. In the first
361  * pass we use the mask as the source to get:
362  * result = (1 - ma) * dst
363  * In the second pass we use the add operator to achieve:
364  * result = (src * ma) + dst
365  * Combined this produces:
366  * result = (src * ma) + (1 - ma) * dst
367  */
368 static cairo_int_status_t
369 _cairo_gl_msaa_compositor_mask_source_operator (const cairo_compositor_t *compositor,
370                                                 cairo_composite_rectangles_t *composite)
371 {
372     cairo_gl_composite_t setup;
373     cairo_gl_surface_t *dst = (cairo_gl_surface_t *) composite->surface;
374     cairo_gl_context_t *ctx = NULL;
375     cairo_int_status_t status;
376
377     cairo_clip_t *clip = composite->clip;
378     cairo_traps_t traps;
379
380     /* If we have a non-rectangular clip, we can avoid using the stencil buffer
381      * for clipping and just draw the clip polygon. */
382     if (clip) {
383         status = _clip_to_traps (clip, &traps);
384         if (unlikely (status)) {
385             _cairo_traps_fini (&traps);
386             return status;
387         }
388     }
389
390     status = _cairo_gl_composite_init (&setup,
391                                        CAIRO_OPERATOR_DEST_OUT,
392                                        dst,
393                                        FALSE /* assume_component_alpha */);
394     if (unlikely (status))
395         return status;
396     status = _cairo_gl_composite_set_source (&setup,
397                                              composite->original_mask_pattern,
398                                              &composite->mask_sample_area,
399                                              &composite->bounded,
400                                              FALSE);
401     if (unlikely (status))
402         goto finish;
403     _cairo_gl_composite_set_multisample (&setup);
404     status = _cairo_gl_composite_begin (&setup, &ctx);
405     if (unlikely (status))
406         goto finish;
407
408     if (! clip)
409         status = _draw_int_rect (ctx, &setup, &composite->bounded);
410     else
411         status = _draw_traps (ctx, &setup, &traps);
412
413     /* Now draw the second pass. */
414     _cairo_gl_composite_set_operator (&setup, CAIRO_OPERATOR_ADD,
415                                       FALSE /* assume_component_alpha */);
416     if (unlikely (status))
417         goto finish;
418     status = _cairo_gl_composite_set_source (&setup,
419                                              composite->original_source_pattern,
420                                              &composite->source_sample_area,
421                                              &composite->bounded,
422                                              FALSE);
423     if (unlikely (status))
424         goto finish;
425     status = _cairo_gl_composite_set_mask (&setup,
426                                            composite->original_mask_pattern,
427                                            &composite->source_sample_area,
428                                            &composite->bounded);
429     if (unlikely (status))
430         goto finish;
431     status = _cairo_gl_set_operands_and_operator (&setup, ctx);
432     if (unlikely (status))
433         goto finish;
434
435     if (! clip)
436         status = _draw_int_rect (ctx, &setup, &composite->bounded);
437     else
438         status = _draw_traps (ctx, &setup, &traps);
439
440 finish:
441     _cairo_gl_composite_fini (&setup);
442     if (ctx)
443         status = _cairo_gl_context_release (ctx, status);
444     if (clip)
445         _cairo_traps_fini (&traps);
446
447     return status;
448 }
449
450 static cairo_int_status_t
451 _cairo_gl_msaa_compositor_mask (const cairo_compositor_t        *compositor,
452                                 cairo_composite_rectangles_t    *composite)
453 {
454     cairo_gl_composite_t setup;
455     cairo_gl_surface_t *dst = (cairo_gl_surface_t *) composite->surface;
456     cairo_gl_context_t *ctx = NULL;
457     cairo_int_status_t status;
458     cairo_operator_t op = composite->op;
459     cairo_bool_t use_color_attribute = FALSE;
460     cairo_clip_t *clip = composite->clip;
461
462     if (! can_use_msaa_compositor (dst, CAIRO_ANTIALIAS_DEFAULT))
463         return CAIRO_INT_STATUS_UNSUPPORTED;
464
465     /* GL compositing operators cannot properly represent a mask operation
466        using the SOURCE compositing operator in one pass. This only matters if
467        there actually is a mask (there isn't in a paint operation) and if the
468        mask isn't totally opaque. */
469     if (op == CAIRO_OPERATOR_SOURCE &&
470          composite->original_mask_pattern != NULL &&
471         ! _cairo_pattern_is_opaque (&composite->mask_pattern.base,
472                                     &composite->mask_sample_area)) {
473
474         if (! _cairo_pattern_is_opaque (&composite->source_pattern.base,
475                                       &composite->source_sample_area)) {
476             return _cairo_gl_msaa_compositor_mask_source_operator (compositor, composite);
477         }
478
479         /* If the source is opaque the operation reduces to OVER. */
480         op = CAIRO_OPERATOR_OVER;
481     }
482
483     if (_should_use_unbounded_surface (composite)) {
484         cairo_surface_t* surface = _prepare_unbounded_surface (dst);
485
486         if (unlikely (surface == NULL))
487             return CAIRO_INT_STATUS_UNSUPPORTED;
488
489         /* This may be a paint operation. */
490         if (composite->original_mask_pattern == NULL) {
491             status = _cairo_compositor_paint (compositor, surface,
492                                               CAIRO_OPERATOR_SOURCE,
493                                               &composite->source_pattern.base,
494                                               NULL);
495         } else {
496             status = _cairo_compositor_mask (compositor, surface,
497                                              CAIRO_OPERATOR_SOURCE,
498                                              &composite->source_pattern.base,
499                                              &composite->mask_pattern.base,
500                                              NULL);
501         }
502
503         if (unlikely (status)) {
504             cairo_surface_destroy (surface);
505             return status;
506         }
507
508         return _paint_back_unbounded_surface (compositor, composite, surface);
509     }
510
511     status = _cairo_gl_composite_init (&setup,
512                                        op,
513                                        dst,
514                                        FALSE /* assume_component_alpha */);
515     if (unlikely (status))
516         return status;
517
518     if (! composite->clip ||
519         (composite->clip->num_boxes == 1 && ! composite->clip->path))
520         use_color_attribute = TRUE;
521
522     status = _cairo_gl_composite_set_source (&setup,
523                                              composite->original_source_pattern,
524                                              &composite->source_sample_area,
525                                              &composite->bounded,
526                                              use_color_attribute);
527     if (unlikely (status))
528         goto finish;
529
530     if (composite->original_mask_pattern != NULL) {
531         status = _cairo_gl_composite_set_mask (&setup,
532                                                composite->original_mask_pattern,
533                                                &composite->mask_sample_area,
534                                                &composite->bounded);
535     }
536     if (unlikely (status))
537         goto finish;
538
539     /* We always use multisampling here, because we do not yet have the smarts
540        to calculate when the clip or the source requires it. */
541      _cairo_gl_composite_set_multisample (&setup);
542
543     status = _cairo_gl_composite_begin (&setup, &ctx);
544     if (unlikely (status))
545         goto finish;
546
547     if (! clip)
548         status = _draw_int_rect (ctx, &setup, &composite->bounded);
549     else
550         status = _cairo_gl_msaa_compositor_draw_clip (ctx, &setup, clip);
551
552 finish:
553     _cairo_gl_composite_fini (&setup);
554
555     if (ctx)
556         status = _cairo_gl_context_release (ctx, status);
557
558     return status;
559 }
560
561 static cairo_int_status_t
562 _cairo_gl_msaa_compositor_paint (const cairo_compositor_t       *compositor,
563                                  cairo_composite_rectangles_t   *composite)
564 {
565     return _cairo_gl_msaa_compositor_mask (compositor, composite);
566 }
567
568 static cairo_status_t
569 _stroke_shaper_add_triangle (void                       *closure,
570                              const cairo_point_t         triangle[3])
571 {
572     struct _tristrip_composite_info *info = closure;
573     return _cairo_gl_composite_emit_triangle_as_tristrip (info->ctx,
574                                                           &info->setup,
575                                                           triangle);
576 }
577
578 static cairo_status_t
579 _stroke_shaper_add_triangle_fan (void                   *closure,
580                                  const cairo_point_t    *midpoint,
581                                  const cairo_point_t    *points,
582                                  int                     npoints)
583 {
584     struct _tristrip_composite_info *info = closure;
585     return _draw_triangle_fan (info->ctx, &info->setup,
586                                midpoint, points, npoints);
587 }
588
589 static cairo_status_t
590 _stroke_shaper_add_quad (void                   *closure,
591                          const cairo_point_t     quad[4])
592 {
593     struct _tristrip_composite_info *info = closure;
594     return _cairo_gl_composite_emit_quad_as_tristrip (info->ctx, &info->setup,
595                                                       quad);
596 }
597
598 static cairo_bool_t
599 _is_continuous_arc (const cairo_path_fixed_t   *path,
600                     const cairo_stroke_style_t *style)
601 {
602     return (_cairo_path_fixed_is_single_arc (path) &&
603             style->dash == NULL);
604 }
605
606 static cairo_int_status_t
607 _prevent_overlapping_strokes (cairo_gl_context_t                *ctx,
608                               cairo_gl_composite_t              *setup,
609                               cairo_composite_rectangles_t      *composite,
610                               const cairo_path_fixed_t          *path,
611                               const cairo_stroke_style_t        *style,
612                               const cairo_matrix_t              *ctm)
613 {
614     cairo_rectangle_int_t stroke_extents;
615     const cairo_pattern_t *pattern = composite->original_source_pattern;
616     cairo_pattern_type_t type = cairo_pattern_get_type ((cairo_pattern_t *) pattern);
617
618     if (! _cairo_gl_ensure_stencil (ctx, setup->dst))
619         return CAIRO_INT_STATUS_UNSUPPORTED;
620
621
622     /* XXX: improve me - since we have lazy init, we cannot use sample
623        area */
624     if (type == CAIRO_PATTERN_TYPE_SOLID &&
625         _cairo_pattern_is_opaque_solid (pattern))
626         return CAIRO_INT_STATUS_SUCCESS;
627
628     if (ctx->states_cache.stencil_test_enabled == FALSE) {
629        /* In case we have pending operations we have to flush before
630           adding the stencil buffer. */
631        _cairo_gl_composite_flush (ctx);
632
633         /* Enable the stencil buffer, even if we are not using it for clipping,
634            so we can use it below to prevent overlapping shapes. We initialize
635            it all to one here which represents infinite clip. */
636         if (! ctx->states_cache.depth_mask) {
637             glDepthMask (GL_TRUE);
638             ctx->states_cache.depth_mask = TRUE;
639         }
640         glEnable (GL_STENCIL_TEST);
641         ctx->states_cache.stencil_test_enabled = TRUE;
642
643         /* We scissor here so that we don't have to clear the entire stencil
644          * buffer. If the scissor test is already enabled, it was enabled
645          * for clipping. In that case, instead of calculating an intersection,
646          * we just reuse it, and risk clearing too much. */
647         if (ctx->states_cache.scissor_test_enabled == FALSE) {
648             _cairo_path_fixed_approximate_stroke_extents (path, style, ctm,
649                                                           &stroke_extents);
650             _cairo_gl_scissor_to_rectangle (setup->dst, &stroke_extents);
651             glEnable (GL_SCISSOR_TEST);
652             ctx->states_cache.scissor_test_enabled = TRUE;
653         }
654         glClearStencil (1);
655         glClear (GL_STENCIL_BUFFER_BIT);
656         _disable_scissor_buffer (ctx);
657
658         glStencilFunc (GL_EQUAL, 1, 1);
659     }
660
661     /* This means that once we draw to a particular pixel nothing else can
662        be drawn there until the stencil buffer is reset or the stencil test
663        is disabled. */
664     glStencilOp (GL_ZERO, GL_ZERO, GL_ZERO);
665
666     _cairo_clip_destroy (setup->dst->clip_on_stencil_buffer);
667     setup->dst->clip_on_stencil_buffer = NULL;
668
669     return CAIRO_INT_STATUS_SUCCESS;
670 }
671
672 static void
673 query_surface_capabilities (cairo_gl_surface_t *surface)
674 {
675     GLint samples, stencil_bits;
676     cairo_gl_context_t *ctx;
677     cairo_int_status_t status;
678
679     /* Texture surfaces are create in such a way that they always
680        have stencil and multisample bits if possible, so we don't
681        need to query their capabilities lazily. */
682     if (_cairo_gl_surface_is_texture (surface))
683         return;
684     if (surface->stencil_and_msaa_caps_initialized)
685         return;
686
687     surface->stencil_and_msaa_caps_initialized = TRUE;
688     surface->supports_stencil = FALSE;
689     surface->supports_msaa = FALSE;
690
691     status = _cairo_gl_context_acquire (surface->base.device, &ctx);
692     if (unlikely (status))
693         return;
694
695     _cairo_gl_context_set_destination (ctx, surface, FALSE);
696
697     glGetIntegerv(GL_SAMPLES, &samples);
698     glGetIntegerv(GL_STENCIL_BITS, &stencil_bits);
699     surface->supports_stencil = stencil_bits > 0;
700     surface->supports_msaa = samples > 1;
701
702     status = _cairo_gl_context_release (ctx, status);
703 }
704
705 static cairo_int_status_t
706 _cairo_gl_msaa_compositor_stroke (const cairo_compositor_t      *compositor,
707                                   cairo_composite_rectangles_t  *composite,
708                                   const cairo_path_fixed_t      *path,
709                                   const cairo_stroke_style_t    *style,
710                                   const cairo_matrix_t          *ctm,
711                                   const cairo_matrix_t          *ctm_inverse,
712                                   double                         tolerance,
713                                   cairo_antialias_t              antialias)
714 {
715     cairo_int_status_t status;
716     cairo_gl_surface_t *dst = (cairo_gl_surface_t *) composite->surface;
717     struct _tristrip_composite_info info;
718     cairo_bool_t use_color_attribute;
719
720     if (! can_use_msaa_compositor (dst, antialias))
721         return CAIRO_INT_STATUS_UNSUPPORTED;
722
723     if (composite->is_bounded == FALSE) {
724         cairo_surface_t* surface = _prepare_unbounded_surface (dst);
725
726         if (unlikely (surface == NULL))
727             return CAIRO_INT_STATUS_UNSUPPORTED;
728
729         status = _cairo_compositor_stroke (compositor, surface,
730                                            CAIRO_OPERATOR_SOURCE,
731                                            &composite->source_pattern.base,
732                                            path, style, ctm, ctm_inverse,
733                                            tolerance, antialias, NULL);
734         if (unlikely (status)) {
735             cairo_surface_destroy (surface);
736             return status;
737         }
738
739         return _paint_back_unbounded_surface (compositor, composite, surface);
740     }
741
742     status = _cairo_gl_composite_init (&info.setup,
743                                        composite->op,
744                                        dst,
745                                        FALSE /* assume_component_alpha */);
746     if (unlikely (status))
747         return status;
748
749     info.ctx = NULL;
750     use_color_attribute = _cairo_path_fixed_stroke_is_rectilinear (path) ||
751                           _cairo_gl_hairline_style_is_hairline (style, ctm);
752
753     status = _cairo_gl_composite_set_source (&info.setup,
754                                              composite->original_source_pattern,
755                                              &composite->source_sample_area,
756                                              &composite->bounded,
757                                              use_color_attribute);
758     if (unlikely (status))
759         goto finish;
760
761     _cairo_gl_msaa_compositor_set_clip (composite, &info.setup);
762     if (antialias != CAIRO_ANTIALIAS_NONE)
763         _cairo_gl_composite_set_multisample (&info.setup);
764
765     status = _cairo_gl_composite_begin (&info.setup, &info.ctx);
766     if (unlikely (status))
767         goto finish;
768
769     if (_cairo_gl_hairline_style_is_hairline (style, ctm)) {
770         cairo_gl_hairline_closure_t closure;
771
772         if (! (_is_continuous_arc (path, style) ||
773                _is_continuous_single_line (path, style))) {
774             status = _prevent_overlapping_strokes (info.ctx, &info.setup,
775                                                    composite, path,
776                                                    style, ctm);
777             if (unlikely (status))
778                 goto finish;
779         }
780
781         closure.ctx = info.ctx;
782
783         closure.tolerance = tolerance;
784
785         status = _cairo_gl_path_fixed_stroke_to_hairline (path, &closure,
786                                                           style, ctm,
787                                                           ctm_inverse,
788                                                           _cairo_gl_hairline_move_to,
789                                                           style->dash ?
790                                                           _cairo_gl_hairline_line_to_dashed :
791                                                           _cairo_gl_hairline_line_to,
792                                                           _cairo_gl_hairline_curve_to,
793                                                           _cairo_gl_hairline_close_path);
794         goto finish;
795     }
796
797     if (use_color_attribute) {
798         cairo_traps_t traps;
799
800         _cairo_traps_init (&traps);
801
802         status = _cairo_path_fixed_stroke_polygon_to_traps (path, style,
803                                                     ctm, ctm_inverse,
804                                                     tolerance, &traps);
805         if (unlikely (status)) {
806             _cairo_traps_fini (&traps);
807             goto finish;
808         }
809
810         status = _draw_traps (info.ctx, &info.setup, &traps);
811         _cairo_traps_fini (&traps);
812     } else {
813         if (!_is_continuous_single_line (path, style)) {
814             status = _prevent_overlapping_strokes (info.ctx, &info.setup,
815                                                    composite, path, style, ctm);
816             if (unlikely (status))
817                 goto finish;
818         }
819
820         status =
821             _cairo_path_fixed_stroke_to_shaper ((cairo_path_fixed_t *) path,
822                                                 style,
823                                                 ctm,
824                                                 ctm_inverse,
825                                                 tolerance,
826                                                 _stroke_shaper_add_triangle,
827                                                 _stroke_shaper_add_triangle_fan,
828                                                 _stroke_shaper_add_quad,
829                                                 &info);
830         if (unlikely (status))
831             goto finish;
832     }
833 finish:
834     _cairo_gl_composite_fini (&info.setup);
835
836     if (info.ctx)
837         status = _cairo_gl_context_release (info.ctx, status);
838
839     return status;
840 }
841
842 static cairo_int_status_t
843 _draw_simple_quad_path (cairo_gl_context_t *ctx,
844                         cairo_gl_composite_t *setup,
845                         const cairo_path_fixed_t *path)
846 {
847     cairo_point_t triangle[3];
848     cairo_int_status_t status;
849     const cairo_point_t *points;
850
851     points = cairo_path_head (path)->points;
852     triangle[0] = points[0];
853     triangle[1] = points[1];
854     triangle[2] = points[2];
855     status = _cairo_gl_composite_emit_triangle_as_tristrip (ctx, setup, triangle);
856     if (status)
857         return status;
858
859     triangle[0] = points[2];
860     triangle[1] = points[3];
861     triangle[2] = points[0];
862     return _cairo_gl_composite_emit_triangle_as_tristrip (ctx, setup, triangle);
863 }
864
865 static cairo_int_status_t
866 _cairo_gl_msaa_compositor_fill (const cairo_compositor_t        *compositor,
867                                 cairo_composite_rectangles_t    *composite,
868                                 const cairo_path_fixed_t        *path,
869                                 cairo_fill_rule_t                fill_rule,
870                                 double                           tolerance,
871                                 cairo_antialias_t                antialias)
872 {
873     cairo_gl_composite_t setup;
874     cairo_gl_surface_t *dst = (cairo_gl_surface_t *) composite->surface;
875     cairo_gl_context_t *ctx = NULL;
876     cairo_int_status_t status;
877     cairo_traps_t traps;
878     cairo_bool_t draw_path_with_traps;
879
880     if (! can_use_msaa_compositor (dst, antialias))
881         return CAIRO_INT_STATUS_UNSUPPORTED;
882
883     if (composite->is_bounded == FALSE) {
884         cairo_surface_t* surface = _prepare_unbounded_surface (dst);
885
886         if (unlikely (surface == NULL))
887             return CAIRO_INT_STATUS_UNSUPPORTED;
888
889
890         status = _cairo_compositor_fill (compositor, surface,
891                                          CAIRO_OPERATOR_SOURCE,
892                                          &composite->source_pattern.base,
893                                          path, fill_rule, tolerance,
894                                          antialias, NULL);
895
896         if (unlikely (status)) {
897             cairo_surface_destroy (surface);
898             return status;
899         }
900
901         return _paint_back_unbounded_surface (compositor, composite, surface);
902     }
903
904     draw_path_with_traps = ! _cairo_path_fixed_is_simple_quad (path);
905
906     if (draw_path_with_traps) {
907         _cairo_traps_init (&traps);
908         status = _cairo_path_fixed_fill_to_traps (path, fill_rule, tolerance, &traps);
909         if (unlikely (status))
910             goto cleanup_traps;
911     }
912
913     status = _cairo_gl_composite_init (&setup,
914                                        composite->op,
915                                        dst,
916                                        FALSE /* assume_component_alpha */);
917     if (unlikely (status))
918         goto cleanup_traps;
919
920     status = _cairo_gl_composite_set_source (&setup,
921                                              composite->original_source_pattern,
922                                              &composite->source_sample_area,
923                                              &composite->bounded,
924                                              !draw_path_with_traps);
925     if (unlikely (status))
926         goto cleanup_setup;
927
928     _cairo_gl_msaa_compositor_set_clip (composite, &setup);
929     if (antialias != CAIRO_ANTIALIAS_NONE)
930         _cairo_gl_composite_set_multisample (&setup);
931
932     status = _cairo_gl_composite_begin (&setup, &ctx);
933     if (unlikely (status))
934         goto cleanup_setup;
935
936     if (! draw_path_with_traps)
937         status = _draw_simple_quad_path (ctx, &setup, path);
938     else
939         status = _draw_traps (ctx, &setup, &traps);
940     if (unlikely (status))
941         goto cleanup_setup;
942
943 cleanup_setup:
944     _cairo_gl_composite_fini (&setup);
945
946     if (ctx)
947         status = _cairo_gl_context_release (ctx, status);
948
949 cleanup_traps:
950     if (draw_path_with_traps)
951         _cairo_traps_fini (&traps);
952
953     return status;
954 }
955
956 static cairo_int_status_t
957 _cairo_gl_msaa_compositor_glyphs (const cairo_compositor_t      *compositor,
958                                   cairo_composite_rectangles_t  *composite,
959                                   cairo_scaled_font_t           *scaled_font,
960                                   cairo_glyph_t                 *glyphs,
961                                   int                            num_glyphs,
962                                   cairo_bool_t                   overlap)
963 {
964     cairo_int_status_t status;
965     cairo_surface_t *src = NULL;
966     int src_x, src_y;
967     cairo_composite_glyphs_info_t info;
968
969     cairo_gl_surface_t *dst = (cairo_gl_surface_t *) composite->surface;
970
971     query_surface_capabilities (dst);
972     if (! dst->supports_stencil)
973         return CAIRO_INT_STATUS_UNSUPPORTED;
974
975     if (composite->is_bounded == FALSE) {
976         cairo_surface_t* surface = _prepare_unbounded_surface (dst);
977
978         if (unlikely (surface == NULL))
979             return CAIRO_INT_STATUS_UNSUPPORTED;
980
981         status = _cairo_compositor_glyphs (compositor, surface,
982                                            CAIRO_OPERATOR_SOURCE,
983                                            &composite->source_pattern.base,
984                                            glyphs, num_glyphs,
985                                            scaled_font, composite->clip);
986
987         if (unlikely (status)) {
988             cairo_surface_destroy (surface);
989             return status;
990         }
991
992         return _paint_back_unbounded_surface (compositor, composite, surface);
993     }
994
995     src = _cairo_gl_pattern_to_source (&dst->base,
996                                        composite->original_source_pattern,
997                                        FALSE,
998                                        &composite->bounded,
999                                        &composite->source_sample_area,
1000                                        &src_x, &src_y);
1001     if (unlikely (src->status)) {
1002         status = src->status;
1003         goto finish;
1004     }
1005
1006     status = _cairo_gl_check_composite_glyphs (composite,
1007                                                scaled_font, glyphs,
1008                                                &num_glyphs);
1009     if (unlikely (status != CAIRO_INT_STATUS_SUCCESS))
1010         goto finish;
1011
1012     info.font = scaled_font;
1013     info.glyphs = glyphs;
1014     info.num_glyphs = num_glyphs;
1015     info.use_mask = overlap || ! composite->is_bounded ||
1016                     composite->op == CAIRO_OPERATOR_SOURCE;
1017     info.extents = composite->bounded;
1018
1019     _cairo_scaled_font_freeze_cache (scaled_font);
1020     status = _cairo_gl_composite_glyphs_with_clip (dst, composite->op,
1021                                                    src, src_x, src_y,
1022                                                    0, 0, &info,
1023                                                    composite->clip,
1024                                                    TRUE);
1025
1026     _cairo_scaled_font_thaw_cache (scaled_font);
1027
1028 finish:
1029     if (src)
1030         cairo_surface_destroy (src);
1031
1032     return status;
1033 }
1034
1035 static void
1036 _cairo_gl_msaa_compositor_init (cairo_compositor_t       *compositor,
1037                                 const cairo_compositor_t *delegate)
1038 {
1039     compositor->delegate = delegate;
1040     compositor->lazy_init = TRUE;
1041
1042     compositor->paint = _cairo_gl_msaa_compositor_paint;
1043     compositor->mask = _cairo_gl_msaa_compositor_mask;
1044     compositor->fill = _cairo_gl_msaa_compositor_fill;
1045     compositor->stroke = _cairo_gl_msaa_compositor_stroke;
1046     compositor->glyphs = _cairo_gl_msaa_compositor_glyphs;
1047 }
1048
1049 const cairo_compositor_t *
1050 _cairo_gl_msaa_compositor_get (void)
1051 {
1052     static cairo_compositor_t compositor;
1053     if (compositor.delegate == NULL)
1054         _cairo_gl_msaa_compositor_init (&compositor,
1055                                         _cairo_gl_span_compositor_get ());
1056
1057     return &compositor;
1058 }