fc7bd56bc21b12a5078d42f365c5a69a1de7bd6a
[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-traps-private.h"
49 #include "cairo-surface-subsurface-inline.h"
50
51 static cairo_bool_t
52 should_fall_back (cairo_gl_surface_t *surface,
53                   cairo_antialias_t antialias);
54
55 struct _tristrip_composite_info {
56     cairo_gl_composite_t        setup;
57     cairo_gl_context_t          *ctx;
58 };
59
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)
64 {
65     cairo_point_t quad[4];
66
67     quad[0].x = _cairo_edge_compute_intersection_x_for_y (&trap->left.p1,
68                                                           &trap->left.p2,
69                                                           trap->top);
70     quad[0].y = trap->top;
71
72     quad[1].x = _cairo_edge_compute_intersection_x_for_y (&trap->left.p1,
73                                                       &trap->left.p2,
74                                                       trap->bottom);
75     quad[1].y = trap->bottom;
76
77     quad[2].x = _cairo_edge_compute_intersection_x_for_y (&trap->right.p1,
78                                                       &trap->right.p2,
79                                                       trap->bottom);
80     quad[2].y = trap->bottom;
81
82     quad[3].x = _cairo_edge_compute_intersection_x_for_y (&trap->right.p1,
83                                                       &trap->right.p2,
84                                                       trap->top);
85     quad[3].y = trap->top;
86     return _cairo_gl_composite_emit_quad_as_tristrip (ctx, setup, quad);
87 }
88
89 static cairo_int_status_t
90 _draw_traps (cairo_gl_context_t         *ctx,
91              cairo_gl_composite_t       *setup,
92              cairo_traps_t              *traps)
93 {
94     cairo_int_status_t status = CAIRO_STATUS_SUCCESS;
95     int i;
96
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))))
100             return status;
101     }
102
103    return status;
104 }
105
106 static cairo_int_status_t
107 _cairo_gl_msaa_compositor_draw_quad (cairo_gl_context_t         *ctx,
108                                      cairo_gl_composite_t       *setup,
109                                      cairo_box_t                *box)
110 {
111     cairo_point_t quad[4];
112
113     quad[0].x = box->p1.x;
114     quad[0].y = box->p1.y;
115
116     quad[1].x = box->p1.x;
117     quad[1].y = box->p2.y;
118
119     quad[2].x = box->p2.x;
120     quad[2].y = box->p2.y;
121
122     quad[3].x = box->p2.x;
123     quad[3].y = box->p1.y;
124
125     return _cairo_gl_composite_emit_quad_as_tristrip (ctx, setup, quad);
126 }
127
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)
132 {
133     cairo_box_t box;
134
135     _cairo_box_from_rectangle (&box, rect);
136
137     return _cairo_gl_msaa_compositor_draw_quad (ctx, setup, &box);
138 }
139
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,
145                     int                          npoints)
146 {
147     int i;
148
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];
154
155         triangle[0] = *midpt;
156         triangle[1] = points[i - 1];
157         triangle[2] = points[i];
158
159         status = _cairo_gl_composite_emit_triangle_as_tristrip (ctx, setup, triangle);
160         if (unlikely (status))
161             return status;
162     }
163
164     return CAIRO_STATUS_SUCCESS;
165 }
166
167 cairo_int_status_t
168 _cairo_gl_msaa_compositor_draw_clip (cairo_gl_context_t         *ctx,
169                                      cairo_gl_composite_t       *setup,
170                                      cairo_clip_t               *clip,
171                                      cairo_traps_t              *traps)
172 {
173     cairo_int_status_t status;
174
175     cairo_polygon_t polygon;
176     cairo_antialias_t antialias;
177     cairo_fill_rule_t fill_rule;
178
179     if (! clip)
180         return CAIRO_INT_STATUS_UNSUPPORTED;
181
182     if (clip->num_boxes == 1 && ! clip->path)
183         return _cairo_gl_msaa_compositor_draw_quad (ctx, setup,
184                                                     &clip->boxes[0]);
185
186     if (traps->num_traps == 0) {
187         status = _cairo_clip_get_polygon (clip, &polygon, &fill_rule,
188                                           &antialias);
189         if (unlikely (status))
190             return status;
191
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.
196      *
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
200      * option.
201      */
202         status = _cairo_bentley_ottmann_tessellate_polygon (traps,
203                                                             &polygon,
204                                                             fill_rule);
205         _cairo_polygon_fini (&polygon);
206         if (unlikely (status))
207             return status;
208     }
209
210     status = _draw_traps (ctx, setup, traps);
211
212     return status;
213 }
214
215 static cairo_bool_t
216 _should_use_unbounded_surface (cairo_composite_rectangles_t *composite)
217 {
218     cairo_gl_surface_t *dst = (cairo_gl_surface_t *) composite->surface;
219     cairo_rectangle_int_t *source = &composite->source;
220
221     if (composite->is_bounded)
222         return FALSE;
223
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);
229 }
230
231 static cairo_surface_t*
232 _prepare_unbounded_surface (cairo_gl_surface_t *dst)
233 {
234
235     cairo_surface_t* surface = cairo_gl_surface_create (dst->base.device,
236                                                         dst->base.content,
237                                                         dst->width,
238                                                         dst->height);
239     if (surface == NULL)
240         return NULL;
241     if (unlikely (surface->status)) {
242         cairo_surface_destroy (surface);
243         return NULL;
244     }
245     return surface;
246 }
247
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)
252 {
253     cairo_gl_surface_t *dst = (cairo_gl_surface_t *) composite->surface;
254     cairo_int_status_t status;
255
256     cairo_pattern_t *pattern = cairo_pattern_create_for_surface (surface);
257     if (unlikely (pattern->status)) {
258         status = pattern->status;
259         goto finish;
260     }
261
262     status = _cairo_compositor_paint (compositor, &dst->base,
263                                       composite->op, pattern,
264                                       composite->clip);
265
266 finish:
267     cairo_pattern_destroy (pattern);
268     cairo_surface_destroy (surface);
269     return status;
270 }
271
272 static void
273 _cairo_gl_msaa_compositor_set_clip (cairo_composite_rectangles_t *composite,
274                                     cairo_gl_composite_t *setup)
275 {
276     uint32_t is_bounded;
277
278     if (_cairo_clip_is_all_clipped (composite->clip))
279         return;
280
281     /* We don't need to check CAIRO_OPERATOR_BOUND_BY_MASK in these
282        situations. */
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))
286         return;
287
288     _cairo_gl_composite_set_clip (setup, composite->clip);
289
290     composite->is_bounded = is_bounded;
291 }
292
293 static void
294 _gl_pattern_fix_reference_count (const cairo_pattern_t *pattern)
295 {
296    cairo_pattern_type_t pattern_type = cairo_pattern_get_type ((cairo_pattern_t *)pattern);
297
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) {
301
302         cairo_surface_pattern_t *surface_pattern = (cairo_surface_pattern_t *)pattern;
303         cairo_surface_t *pattern_surface = surface_pattern->surface;
304
305         if (cairo_surface_get_type (pattern_surface) == CAIRO_SURFACE_TYPE_GL &&
306             ! pattern_surface->device &&
307             ! _cairo_surface_is_subsurface (pattern_surface)) {
308
309             cairo_gl_source_t *_source = (cairo_gl_source_t *)pattern_surface;
310
311             switch (_source->operand.type) {
312             case CAIRO_GL_OPERAND_TEXTURE:
313                 cairo_surface_reference (&(_source->operand.texture.owns_surface)->base);
314                 break;
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);
320                 break;
321             default:
322             case CAIRO_GL_OPERAND_NONE:
323             case CAIRO_GL_OPERAND_CONSTANT:
324             case CAIRO_GL_OPERAND_COUNT:
325                 break;
326             }
327         }
328     }
329 }
330
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
336  */
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)
340 {
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;
345     cairo_traps_t traps;
346
347     _cairo_traps_init (&traps);
348
349     status = _cairo_gl_composite_init (&setup,
350                                        CAIRO_OPERATOR_DEST_OUT,
351                                        dst,
352                                        FALSE /* assume_component_alpha */);
353     if (unlikely (status))
354         goto finish;
355
356     _gl_pattern_fix_reference_count (composite->original_mask_pattern);
357
358     status = _cairo_gl_composite_set_source (&setup,
359                                              &composite->mask_pattern.base,
360                                              &composite->mask_sample_area,
361                                              &composite->bounded,
362                                              FALSE);
363     if (unlikely (status))
364         goto finish;
365
366     status = _cairo_gl_composite_begin_multisample (&setup, &ctx, TRUE);
367     if (unlikely (status))
368         goto finish;
369
370     if (! composite->clip)
371         status = _draw_int_rect (ctx, &setup, &composite->bounded);
372     else
373         status = _cairo_gl_msaa_compositor_draw_clip (ctx, &setup, composite->clip, &traps);
374
375     _cairo_gl_composite_fini (&setup);
376     status = _cairo_gl_context_release (ctx, status);
377     ctx = NULL;
378     if (unlikely (status))
379         return status;
380
381      /* second pass */
382     status = _cairo_gl_composite_init (&setup,
383                                        CAIRO_OPERATOR_ADD,
384                                        dst,
385                                        FALSE /* assume_component_alpha */);
386     if (unlikely (status))
387         goto finish;
388
389     _gl_pattern_fix_reference_count (composite->original_source_pattern);
390
391     status = _cairo_gl_composite_set_source (&setup,
392                                              &composite->source_pattern.base,
393                                              &composite->source_sample_area,
394                                              &composite->bounded,
395                                              FALSE);
396     if (unlikely (status))
397         goto finish;
398
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))
404         goto finish;
405
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))
410         goto finish;
411
412     if (! composite->clip)
413         status = _draw_int_rect (ctx, &setup, &composite->bounded);
414     else
415         status = _cairo_gl_msaa_compositor_draw_clip (ctx, &setup, composite->clip, &traps);
416
417 finish:
418     _cairo_traps_fini (&traps);
419     _cairo_gl_composite_fini (&setup);
420
421     if (ctx)
422         status = _cairo_gl_context_release (ctx, status);
423
424     return status;
425 }
426
427 static cairo_int_status_t
428 _cairo_gl_msaa_compositor_mask (const cairo_compositor_t        *compositor,
429                                 cairo_composite_rectangles_t    *composite)
430 {
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;
436     cairo_traps_t traps;
437     cairo_bool_t use_color_attribute = FALSE;
438
439     if (should_fall_back (dst, CAIRO_ANTIALIAS_GOOD))
440         return CAIRO_INT_STATUS_UNSUPPORTED;
441
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)) {
450
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;
455         else
456             return _cairo_gl_msaa_compositor_mask_source_operator (compositor, composite);
457     }
458
459     if (_should_use_unbounded_surface (composite)) {
460         cairo_surface_t* surface = _prepare_unbounded_surface (dst);
461
462         if (unlikely (surface == NULL))
463             return CAIRO_INT_STATUS_UNSUPPORTED;
464
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,
470                                               NULL);
471         } else {
472             status = _cairo_compositor_mask (compositor, surface,
473                                              CAIRO_OPERATOR_SOURCE,
474                                              &composite->source_pattern.base,
475                                              &composite->mask_pattern.base,
476                                              NULL);
477         }
478
479         if (unlikely (status)) {
480             cairo_surface_destroy (surface);
481             return status;
482         }
483
484         return _paint_back_unbounded_surface (compositor, composite, surface);
485     }
486
487     status = _cairo_gl_composite_init (&setup,
488                                        op,
489                                        dst,
490                                        FALSE /* assume_component_alpha */);
491     if (unlikely (status))
492         goto finish;
493
494     _gl_pattern_fix_reference_count (composite->original_source_pattern);
495
496     if (! composite->clip ||
497         (composite->clip->num_boxes == 1 && ! composite->clip->path))
498         use_color_attribute = TRUE;
499
500     status = _cairo_gl_composite_set_source (&setup,
501                                              composite->original_source_pattern,
502                                              &composite->source_sample_area,
503                                              &composite->bounded,
504                                              use_color_attribute);
505     if (unlikely (status))
506         goto finish;
507
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);
513     }
514     if (unlikely (status))
515         goto finish;
516
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))
521         goto finish;
522
523     _cairo_traps_init (&traps);
524
525     if (! composite->clip)
526         status = _draw_int_rect (ctx, &setup, &composite->bounded);
527     else
528         status = _cairo_gl_msaa_compositor_draw_clip (ctx, &setup, composite->clip, &traps);
529
530     _cairo_traps_fini (&traps);
531
532 finish:
533     _cairo_gl_composite_fini (&setup);
534
535     if (ctx)
536         status = _cairo_gl_context_release (ctx, status);
537
538     return status;
539 }
540
541 static cairo_int_status_t
542 _cairo_gl_msaa_compositor_paint (const cairo_compositor_t       *compositor,
543                                  cairo_composite_rectangles_t   *composite)
544 {
545     return _cairo_gl_msaa_compositor_mask (compositor, composite);
546 }
547
548 static cairo_status_t
549 _stroke_shaper_add_triangle (void                       *closure,
550                              const cairo_point_t         triangle[3])
551 {
552     struct _tristrip_composite_info *info = closure;
553     return _cairo_gl_composite_emit_triangle_as_tristrip (info->ctx,
554                                                           &info->setup,
555                                                           triangle);
556 }
557
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,
562                                  int                     npoints)
563 {
564     struct _tristrip_composite_info *info = closure;
565     return _draw_triangle_fan (info->ctx, &info->setup,
566                                midpoint, points, npoints);
567 }
568
569 static cairo_status_t
570 _stroke_shaper_add_quad (void                   *closure,
571                          const cairo_point_t     quad[4])
572 {
573     struct _tristrip_composite_info *info = closure;
574     return _cairo_gl_composite_emit_quad_as_tristrip (info->ctx, &info->setup,
575                                                       quad);
576 }
577
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)
585 {
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);
589
590     if (! _cairo_gl_ensure_stencil (ctx, setup->dst))
591         return CAIRO_INT_STATUS_UNSUPPORTED;
592
593     /* XXX: improve me - since we have lazy init, we cannot use sample
594        area */
595     if (type == CAIRO_PATTERN_TYPE_SOLID &&
596         _cairo_pattern_is_opaque_solid (pattern))
597         return CAIRO_INT_STATUS_SUCCESS;
598
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);
603
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);
609
610         /* If we don't have clip, then we will setup clip extents based on
611            approximate stroke extent. */
612         if (! setup->clip) {
613             _cairo_path_fixed_approximate_stroke_extents (path, style, ctm,
614                                                           &stroke_extents);
615             _cairo_gl_scissor_to_extents (setup->dst, &stroke_extents);
616         }
617
618         glClearStencil (1);
619         glClear (GL_STENCIL_BUFFER_BIT);
620         glStencilFunc (GL_EQUAL, 1, 1);
621     }
622
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
625        is disabled. */
626     glStencilOp (GL_ZERO, GL_ZERO, GL_ZERO);
627
628     /* we need to clean up clip cache */
629     _cairo_clip_destroy (ctx->clip);
630     ctx->clip = NULL;
631
632     return CAIRO_INT_STATUS_SUCCESS;
633 }
634
635 static void
636 query_surface_capabilities (cairo_gl_surface_t *surface)
637 {
638     GLint samples, stencil_bits;
639     cairo_gl_context_t *ctx;
640     cairo_int_status_t status;
641
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))
646         return;
647     if (surface->stencil_and_msaa_caps_initialized)
648         return;
649
650     surface->stencil_and_msaa_caps_initialized = TRUE;
651     surface->supports_stencil = FALSE;
652     surface->supports_msaa = FALSE;
653
654     status = _cairo_gl_context_acquire (surface->base.device, &ctx);
655     if (unlikely (status))
656         return;
657
658     _cairo_gl_context_set_destination (ctx, surface, FALSE);
659
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;
664
665     status = _cairo_gl_context_release (ctx, status);
666 }
667
668 static cairo_bool_t
669 should_fall_back (cairo_gl_surface_t *surface,
670                   cairo_antialias_t antialias)
671 {
672     query_surface_capabilities (surface);
673     if (! surface->supports_stencil)
674         return TRUE;
675
676     /* Multisampling OpenGL ES surfaces only maintain one multisampling
677        framebuffer and thus must use the spans compositor to do non
678        AA rendering */
679     if (((cairo_gl_context_t *) surface->base.device)->gl_flavor == CAIRO_GL_FLAVOR_ES
680          && surface->supports_msaa
681          && antialias == CAIRO_ANTIALIAS_NONE)
682         return TRUE;
683
684     if (antialias == CAIRO_ANTIALIAS_FAST)
685         return TRUE;
686     if (antialias == CAIRO_ANTIALIAS_NONE)
687         return FALSE;
688     return ! surface->supports_msaa;
689 }
690
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,
698                                   double                         tolerance,
699                                   cairo_antialias_t              antialias)
700 {
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;
705
706     if (should_fall_back (dst, antialias))
707         return CAIRO_INT_STATUS_UNSUPPORTED;
708
709     if (composite->is_bounded == FALSE) {
710         cairo_surface_t* surface = _prepare_unbounded_surface (dst);
711
712         if (unlikely (surface == NULL))
713             return CAIRO_INT_STATUS_UNSUPPORTED;
714
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);
722             return status;
723         }
724
725         return _paint_back_unbounded_surface (compositor, composite, surface);
726     }
727
728     status = _cairo_gl_composite_init (&info.setup,
729                                        composite->op,
730                                        dst,
731                                        FALSE /* assume_component_alpha */);
732     if (unlikely (status))
733         return status;
734
735     info.ctx = NULL;
736     use_color_attribute = _cairo_path_fixed_stroke_is_rectilinear (path) ||
737                           _cairo_gl_hairline_style_is_hairline (style, ctm);
738
739     status = _cairo_gl_composite_set_source (&info.setup,
740                                              composite->original_source_pattern,
741                                              &composite->source_sample_area,
742                                              &composite->bounded,
743                                              use_color_attribute);
744     if (unlikely (status))
745         goto finish;
746
747     _cairo_gl_msaa_compositor_set_clip (composite, &info.setup);
748
749     status = _cairo_gl_composite_begin_multisample (&info.setup, &info.ctx,
750         antialias != CAIRO_ANTIALIAS_NONE);
751     if (unlikely (status))
752         goto finish;
753
754     if (_cairo_gl_hairline_style_is_hairline (style, ctm)) {
755         cairo_gl_hairline_closure_t closure;
756
757         status = _prevent_overlapping_drawing (info.ctx, &info.setup,
758                                                composite, path, style, ctm);
759         if (unlikely (status))
760             goto finish;
761
762         closure.ctx = info.ctx;
763
764         closure.tolerance = tolerance;
765
766         status = _cairo_gl_path_fixed_stroke_to_hairline (path, &closure,
767                                                           style, ctm,
768                                                           ctm_inverse,
769                                                           _cairo_gl_hairline_move_to,
770                                                           style->dash ?
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);
775         goto finish;
776     }
777
778     if (use_color_attribute || path->has_curve_to) {
779         cairo_traps_t traps;
780
781         _cairo_traps_init (&traps);
782
783         status = _cairo_path_fixed_stroke_to_traps (path, style,
784                                                     ctm, ctm_inverse,
785                                                     tolerance, &traps);
786         if (unlikely (status)) {
787             _cairo_traps_fini (&traps);
788             goto finish;
789         }
790
791         status = _draw_traps (info.ctx, &info.setup, &traps);
792         _cairo_traps_fini (&traps);
793     } else {
794         status = _prevent_overlapping_drawing (info.ctx, &info.setup,
795                                                composite, path, style, ctm);
796         if (unlikely (status))
797             goto finish;
798
799         status =
800             _cairo_path_fixed_stroke_to_shaper ((cairo_path_fixed_t *) path,
801                                                 style,
802                                                 ctm,
803                                                 ctm_inverse,
804                                                 tolerance,
805                                                 _stroke_shaper_add_triangle,
806                                                 _stroke_shaper_add_triangle_fan,
807                                                 _stroke_shaper_add_quad,
808                                                 &info);
809         if (unlikely (status))
810             goto finish;
811     }
812 finish:
813     _cairo_gl_composite_fini (&info.setup);
814
815     if (info.ctx)
816         status = _cairo_gl_context_release (info.ctx, status);
817
818     return status;
819 }
820
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,
826                                             double tolerance,
827                                             cairo_antialias_t antialias,
828                                             cairo_clip_t *clip)
829 {
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;
834     int i;
835
836     status = _cairo_gl_composite_init (&setup,
837                                        composite->op,
838                                        dst,
839                                        FALSE /* assume_component_alpha */);
840     if (unlikely (status))
841         goto cleanup_setup;
842
843     status = _cairo_gl_composite_set_source (&setup,
844                                              composite->original_source_pattern,
845                                              &composite->source_sample_area,
846                                              &composite->bounded,
847                                              TRUE);
848     if (unlikely (status))
849         goto cleanup_setup;
850
851     status = _cairo_gl_composite_begin_multisample (&setup, &ctx,
852         antialias != CAIRO_ANTIALIAS_NONE);
853     if (unlikely (status))
854         goto cleanup_setup;
855
856     for (i = 0; i < clip->num_boxes; i++) {
857         status = _cairo_gl_msaa_compositor_draw_quad (ctx, &setup,
858                                                       &clip->boxes[i]);
859         if (unlikely (status))
860             goto cleanup_setup;
861     }
862
863 cleanup_setup:
864     _cairo_gl_composite_fini (&setup);
865
866     if (ctx)
867         status = _cairo_gl_context_release (ctx, status);
868
869     return status;
870 }
871
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,
877                                 double                           tolerance,
878                                 cairo_antialias_t                antialias)
879 {
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;
884     cairo_traps_t traps;
885     cairo_bool_t use_color_attr = FALSE;
886
887     if (should_fall_back (dst, antialias))
888         return CAIRO_INT_STATUS_UNSUPPORTED;
889
890     if (composite->is_bounded == FALSE) {
891         cairo_surface_t* surface = _prepare_unbounded_surface (dst);
892
893         if (unlikely (surface == NULL))
894             return CAIRO_INT_STATUS_UNSUPPORTED;
895
896
897         status = _cairo_compositor_fill (compositor, surface,
898                                          CAIRO_OPERATOR_SOURCE,
899                                          &composite->source_pattern.base,
900                                          path, fill_rule, tolerance,
901                                          antialias, NULL);
902
903         if (unlikely (status)) {
904             cairo_surface_destroy (surface);
905             return status;
906         }
907
908         return _paint_back_unbounded_surface (compositor, composite, surface);
909     }
910
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,
917                                                        path,
918                                                        fill_rule,
919                                                        antialias);
920         if (clip->num_boxes)
921                 status = _cairo_gl_msaa_compositor_fill_rectilinear (compositor,
922                                                                      composite,
923                                                                      path,
924                                                                      fill_rule,
925                                                                      tolerance,
926                                                                      antialias,
927                                                                      clip);
928         _cairo_clip_destroy (clip);
929
930         return status;
931     }
932
933     status = _cairo_gl_composite_init (&setup,
934                                        composite->op,
935                                        dst,
936                                        FALSE /* assume_component_alpha */);
937     if (unlikely (status)) {
938         _cairo_gl_composite_fini (&setup);
939         return status;
940     }
941
942     _cairo_traps_init (&traps);
943
944     if (_cairo_path_fixed_fill_is_rectilinear (path)) {
945         status = _cairo_path_fixed_fill_rectilinear_to_traps (path,
946                                                               fill_rule,
947                                                               antialias,
948                                                               &traps);
949         use_color_attr = TRUE;
950     } else
951         status = _cairo_path_fixed_fill_to_traps (path, fill_rule,
952                                                   tolerance, &traps);
953     if (unlikely (status))
954         goto cleanup_traps;
955
956     status = _cairo_gl_composite_set_source (&setup,
957                                              composite->original_source_pattern,
958                                              &composite->source_sample_area,
959                                              &composite->bounded,
960                                              use_color_attr);
961     if (unlikely (status))
962         goto cleanup_setup;
963
964     _cairo_gl_msaa_compositor_set_clip (composite, &setup);
965
966     status = _cairo_gl_composite_begin_multisample (&setup, &ctx,
967         antialias != CAIRO_ANTIALIAS_NONE);
968     if (unlikely (status))
969         goto cleanup_setup;
970
971     status = _draw_traps (ctx, &setup, &traps);
972     if (unlikely (status))
973         goto cleanup_setup;
974
975 cleanup_setup:
976     _cairo_gl_composite_fini (&setup);
977
978     if (ctx)
979         status = _cairo_gl_context_release (ctx, status);
980
981 cleanup_traps:
982     _cairo_traps_fini (&traps);
983
984     return status;
985 }
986
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,
992                                   int                            num_glyphs,
993                                   cairo_bool_t                   overlap)
994 {
995     cairo_int_status_t status;
996     cairo_surface_t *src = NULL;
997     int src_x, src_y;
998     cairo_composite_glyphs_info_t info;
999
1000     cairo_gl_surface_t *dst = (cairo_gl_surface_t *) composite->surface;
1001
1002     query_surface_capabilities (dst);
1003     if (! dst->supports_stencil)
1004         return CAIRO_INT_STATUS_UNSUPPORTED;
1005
1006     if (composite->is_bounded == FALSE) {
1007         cairo_surface_t* surface = _prepare_unbounded_surface (dst);
1008
1009         if (unlikely (surface == NULL))
1010             return CAIRO_INT_STATUS_UNSUPPORTED;
1011
1012         status = _cairo_compositor_glyphs (compositor, surface,
1013                                            CAIRO_OPERATOR_SOURCE,
1014                                            &composite->source_pattern.base,
1015                                            glyphs, num_glyphs,
1016                                            scaled_font, composite->clip);
1017
1018         if (unlikely (status)) {
1019             cairo_surface_destroy (surface);
1020             return status;
1021         }
1022
1023         return _paint_back_unbounded_surface (compositor, composite, surface);
1024     }
1025
1026     src = _cairo_gl_pattern_to_source (&dst->base,
1027                                        composite->original_source_pattern,
1028                                        FALSE,
1029                                        &composite->bounded,
1030                                        &composite->source_sample_area,
1031                                        &src_x, &src_y);
1032     if (unlikely (src->status)) {
1033         status = src->status;
1034         goto finish;
1035     }
1036
1037     status = _cairo_gl_check_composite_glyphs (composite,
1038                                                scaled_font, glyphs,
1039                                                &num_glyphs);
1040     if (unlikely (status != CAIRO_INT_STATUS_SUCCESS))
1041         goto finish;
1042
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;
1049
1050     _cairo_scaled_font_freeze_cache (scaled_font);
1051     status = _cairo_gl_composite_glyphs_with_clip (dst, composite->op,
1052                                                    src, src_x, src_y,
1053                                                    0, 0, &info,
1054                                                    composite->clip,
1055                                                    TRUE);
1056
1057     _cairo_scaled_font_thaw_cache (scaled_font);
1058
1059 finish:
1060     if (src)
1061         cairo_surface_destroy (src);
1062
1063     return status;
1064 }
1065
1066 static void
1067 _cairo_gl_msaa_compositor_init (cairo_compositor_t       *compositor,
1068                                 const cairo_compositor_t *delegate)
1069 {
1070     compositor->delegate = delegate;
1071     compositor->lazy_init = TRUE;
1072
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;
1078 }
1079
1080 const cairo_compositor_t *
1081 _cairo_gl_msaa_compositor_get (void)
1082 {
1083     static cairo_compositor_t compositor;
1084     if (compositor.delegate == NULL)
1085         _cairo_gl_msaa_compositor_init (&compositor,
1086                                         _cairo_gl_span_compositor_get ());
1087
1088     return &compositor;
1089 }