tizen 2.3.1 release
[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 static cairo_int_status_t
72 _draw_trap (cairo_gl_context_t          *ctx,
73             cairo_gl_composite_t        *setup,
74             cairo_trapezoid_t           *trap)
75 {
76     cairo_point_t quad[4];
77
78     if (trap->left.p1.x == trap->left.p2.x) {
79         quad[0].x = trap->left.p1.x;
80         quad[1].x = trap->left.p1.x;
81     } else {
82         cairo_fixed_t x, dy;
83         x = trap->left.p1.x;
84         dy = trap->left.p2.y - trap->left.p1.y;
85
86         if (trap->top == trap->left.p1.y)
87             quad[0].x = x;
88         else if (trap->top == trap->left.p2.y)
89             quad[0].x = trap->left.p2.x;
90         else if (dy != 0)
91             quad[0].x = x + _cairo_fixed_mul_div_floor (trap->top - trap->left.p1.y,
92                                                         trap->left.p2.x - trap->left.p1.x, dy);
93
94         if (trap->bottom == trap->left.p2.y)
95             quad[1].x = trap->left.p2.x;
96         else if (trap->bottom == trap->left.p1.y)
97             quad[1].x = x;
98         else if (dy != 0)
99             quad[1].x = x + _cairo_fixed_mul_div_floor (trap->bottom - trap->left.p1.y,
100                                                         trap->left.p2.x - trap->left.p1.x, dy);
101     }
102     quad[0].y = trap->top;
103     quad[1].y = trap->bottom;
104
105     if (trap->right.p1.x == trap->right.p2.x) {
106         quad[2].x = trap->right.p1.x;
107         quad[3].x = trap->right.p1.x;
108     } else {
109         cairo_fixed_t x, dy;
110         x = trap->right.p1.x;
111         dy = trap->right.p2.y - trap->right.p1.y;
112
113         if (trap->bottom == trap->right.p2.y)
114             quad[2].x = trap->right.p2.x;
115         else if (trap->bottom == trap->right.p1.y)
116             quad[2].x = x;
117         else if (dy != 0)
118             quad[2].x = x + _cairo_fixed_mul_div_floor (trap->bottom - trap->right.p1.y,
119                                                         trap->right.p2.x - trap->right.p1.x, dy);
120
121         if (trap->top == trap->right.p1.y)
122             quad[3].x = x;
123         else if (trap->top == trap->right.p2.y)
124             quad[3].x = trap->right.p2.x;
125         else if (dy != 0)
126             quad[3].x = x + _cairo_fixed_mul_div_floor (trap->top - trap->right.p1.y,
127                                                         trap->right.p2.x - trap->right.p1.x, dy);
128     }
129     quad[2].y = trap->bottom;
130     quad[3].y = trap->top;
131
132     return _cairo_gl_composite_emit_quad_as_tristrip (ctx, setup, quad);
133 }
134
135 static cairo_int_status_t
136 _draw_traps (cairo_gl_context_t         *ctx,
137              cairo_gl_composite_t       *setup,
138              cairo_traps_t              *traps)
139 {
140     cairo_int_status_t status = CAIRO_STATUS_SUCCESS;
141     int i;
142
143     for (i = 0; i < traps->num_traps; i++) {
144         cairo_trapezoid_t *trap = traps->traps + i;
145         if (unlikely ((status = _draw_trap (ctx, setup, trap))))
146             return status;
147     }
148
149    return status;
150 }
151
152 static cairo_int_status_t
153 _draw_int_rect (cairo_gl_context_t      *ctx,
154                 cairo_gl_composite_t    *setup,
155                 cairo_rectangle_int_t   *rect)
156 {
157     int quad[8];
158
159     quad[0] = quad[2] = rect->x;
160     quad[1] = quad[7] = rect->y;
161     quad[3] = quad[5] = rect->y + rect->height;
162     quad[4] = quad[6] = rect->x + rect->width;
163
164     return _cairo_gl_composite_emit_int_quad_as_tristrip (ctx, setup, quad);
165 }
166
167 static cairo_int_status_t
168 _draw_triangle_fan (cairo_gl_context_t          *ctx,
169                     cairo_gl_composite_t        *setup,
170                     const cairo_point_t         *midpt,
171                     const cairo_point_t         *points,
172                     int                          npoints)
173 {
174     int i;
175
176     /* Our strategy here is to not even try to build a triangle fan, but to
177        draw each triangle as if it was an unconnected member of a triangle strip. */
178     for (i = 1; i < npoints; i++) {
179         cairo_int_status_t status;
180         cairo_point_t triangle[3];
181
182         triangle[0] = *midpt;
183         triangle[1] = points[i - 1];
184         triangle[2] = points[i];
185
186         status = _cairo_gl_composite_emit_triangle_as_tristrip (ctx, setup, triangle);
187         if (unlikely (status))
188             return status;
189     }
190
191     return CAIRO_STATUS_SUCCESS;
192 }
193
194 static cairo_int_status_t
195 _clip_to_traps (cairo_clip_t *clip,
196                 cairo_traps_t *traps)
197 {
198     cairo_int_status_t status;
199     cairo_polygon_t polygon;
200     cairo_antialias_t antialias;
201     cairo_fill_rule_t fill_rule;
202
203     _cairo_traps_init (traps);
204
205     if (clip->num_boxes == 1 && clip->path == NULL) {
206         cairo_boxes_t boxes;
207         _cairo_boxes_init_for_array (&boxes, clip->boxes, clip->num_boxes);
208         return _cairo_traps_init_boxes (traps, &boxes);
209     }
210
211     status = _cairo_clip_get_polygon (clip, &polygon, &fill_rule, &antialias);
212     if (unlikely (status))
213         return status;
214
215     /* We ignore the antialias mode of the clip here, since the user requested
216      * unantialiased rendering of their path and we expect that this stencil
217      * based rendering of the clip to be a reasonable approximation to
218      * the intersection between that clip and the path.
219      *
220      * In other words, what the user expects when they try to perform
221      * a geometric intersection between an unantialiased polygon and an
222      * antialiased polygon is open to interpretation. And we choose the fast
223      * option.
224      */
225
226     _cairo_traps_init (traps);
227     status = _cairo_bentley_ottmann_tessellate_polygon (traps,
228                                                         &polygon,
229                                                         fill_rule);
230     _cairo_polygon_fini (&polygon);
231
232     return status;
233 }
234
235 cairo_int_status_t
236 _cairo_gl_msaa_compositor_draw_clip (cairo_gl_context_t *ctx,
237                                      cairo_gl_composite_t *setup,
238                                      cairo_clip_t *clip)
239 {
240     cairo_int_status_t status;
241     cairo_traps_t traps;
242
243     status = _clip_to_traps (clip, &traps);
244     if (unlikely (status))
245         return status;
246     status = _draw_traps (ctx, setup, &traps);
247
248     _cairo_traps_fini (&traps);
249     return status;
250 }
251
252 static cairo_int_status_t
253 _blit_texture_to_renderbuffer (cairo_gl_surface_t *surface)
254 {
255     cairo_gl_context_t *ctx = NULL;
256     cairo_gl_composite_t setup;
257     cairo_surface_pattern_t pattern;
258     cairo_rectangle_int_t extents;
259     cairo_int_status_t status;
260     cairo_gl_flavor_t gl_flavor = ((cairo_gl_context_t *) surface->base.device)->gl_flavor;
261
262     if (gl_flavor == CAIRO_GL_FLAVOR_DESKTOP)
263         return CAIRO_INT_STATUS_SUCCESS;
264     else if (! _cairo_gl_surface_is_texture (surface))
265         return CAIRO_INT_STATUS_SUCCESS;
266     else if (surface->msaa_active)
267         return CAIRO_INT_STATUS_SUCCESS;
268     else if (surface->content_synced) {
269         status = _cairo_gl_context_acquire (surface->base.device, &ctx);
270         if (unlikely (status))
271             return status;
272         _cairo_gl_context_set_destination (ctx, surface, TRUE);
273         return _cairo_gl_context_release (ctx, status);
274     }
275
276     memset (&setup, 0, sizeof (cairo_gl_composite_t));
277
278     status = _cairo_gl_composite_set_operator (&setup,
279                                                CAIRO_OPERATOR_SOURCE,
280                                                FALSE);
281     if (status)
282         return status;
283
284     setup.dst = surface;
285     setup.clip_region = surface->clip_region;
286
287     _cairo_pattern_init_for_surface (&pattern, &surface->base);
288
289     extents.x = extents.y = 0;
290     extents.width = surface->width;
291     extents.height = surface->height;
292
293     status = _cairo_gl_composite_set_source (&setup, &pattern.base,
294                                              NULL, &extents, FALSE, FALSE);
295     _cairo_pattern_fini (&pattern.base);
296
297     if (unlikely (status))
298         goto FAIL;
299
300     _cairo_gl_composite_set_multisample (&setup);
301
302     status = _cairo_gl_composite_begin (&setup, &ctx);
303
304     if (unlikely (status))
305         goto FAIL;
306
307     status = _draw_int_rect (ctx, &setup, &extents);
308
309     if (unlikely (status))
310         goto FAIL;
311
312     surface->content_synced = TRUE;
313 FAIL:
314     _cairo_gl_composite_fini (&setup);
315
316     if (ctx) {
317         _cairo_gl_composite_flush (ctx);
318         status = _cairo_gl_context_release (ctx, status);
319     }
320
321     return status;
322 }
323
324
325 static cairo_bool_t
326 _should_use_unbounded_surface (cairo_composite_rectangles_t *composite)
327 {
328     cairo_gl_surface_t *dst = (cairo_gl_surface_t *) composite->surface;
329     cairo_rectangle_int_t *source = &composite->source;
330
331     if (composite->is_bounded)
332         return FALSE;
333
334     /* This isn't just an optimization. It also detects when painting is used
335        to paint back the unbounded surface, preventing infinite recursion. */
336     return ! (source->x <= 0 && source->y <= 0 &&
337               source->height + source->y >= dst->height &&
338               source->width + source->x >= dst->width);
339 }
340
341 static cairo_surface_t*
342 _prepare_unbounded_surface (cairo_gl_surface_t *dst)
343 {
344
345     cairo_surface_t* surface = cairo_gl_surface_create (dst->base.device,
346                                                         dst->base.content,
347                                                         dst->width,
348                                                         dst->height);
349     if (surface == NULL)
350         return NULL;
351     if (unlikely (surface->status)) {
352         cairo_surface_destroy (surface);
353         return NULL;
354     }
355     return surface;
356 }
357
358 static cairo_int_status_t
359 _paint_back_unbounded_surface (const cairo_compositor_t         *compositor,
360                                cairo_composite_rectangles_t     *composite,
361                                cairo_surface_t                  *surface)
362 {
363     cairo_gl_surface_t *dst = (cairo_gl_surface_t *) composite->surface;
364     cairo_int_status_t status;
365
366     cairo_pattern_t *pattern = cairo_pattern_create_for_surface (surface);
367     if (unlikely (pattern->status)) {
368         status = pattern->status;
369         goto finish;
370     }
371
372     status = _cairo_compositor_paint (compositor, &dst->base,
373                                       composite->op, pattern,
374                                       composite->clip);
375
376 finish:
377     cairo_pattern_destroy (pattern);
378     cairo_surface_destroy (surface);
379     return status;
380 }
381
382 static cairo_bool_t
383 can_use_msaa_compositor (cairo_gl_surface_t *surface,
384                          cairo_antialias_t antialias)
385 {
386     cairo_gl_flavor_t flavor = ((cairo_gl_context_t *) surface->base.device)->gl_flavor;
387     cairo_bool_t has_angle_multisampling = ((cairo_gl_context_t *) surface->base.device)->has_angle_multisampling;
388
389     query_surface_capabilities (surface);
390     if (! surface->supports_stencil)
391         return FALSE;
392
393     /* Multisampling OpenGL ES surfaces only maintain one multisampling
394        framebuffer and thus must use the spans compositor to do non-antialiased
395        rendering. */
396     if (! (flavor == CAIRO_GL_FLAVOR_DESKTOP ||
397            flavor == CAIRO_GL_FLAVOR_ES3 ||
398            (flavor == CAIRO_GL_FLAVOR_ES2 &&
399             has_angle_multisampling)) &&
400         surface->supports_msaa &&
401         antialias == CAIRO_ANTIALIAS_NONE)
402         return FALSE;
403
404     /* The MSAA compositor has a single-sample mode, so we can
405        support non-antialiased rendering. */
406     if (antialias == CAIRO_ANTIALIAS_NONE)
407         return TRUE;
408
409     if ((antialias == CAIRO_ANTIALIAS_GRAY ||
410          antialias== CAIRO_ANTIALIAS_SUBPIXEL ||
411          antialias == CAIRO_ANTIALIAS_FAST ||
412          antialias == CAIRO_ANTIALIAS_DEFAULT) &&
413         surface->num_samples > 1)
414         return surface->supports_msaa;
415     return FALSE;
416 }
417
418 static void
419 _cairo_gl_msaa_compositor_set_clip (cairo_composite_rectangles_t *composite,
420                                     cairo_gl_composite_t *setup)
421 {
422     uint32_t is_bounded;
423
424     /* We don't need to check CAIRO_OPERATOR_BOUND_BY_MASK in these
425        situations. */
426     is_bounded = composite->is_bounded;
427     composite->is_bounded = CAIRO_OPERATOR_BOUND_BY_SOURCE;
428     if (_cairo_composite_rectangles_can_reduce_clip (composite, composite->clip))
429         return;
430
431     _cairo_gl_composite_set_clip (setup, composite->clip);
432
433     composite->is_bounded = is_bounded;
434 }
435
436 static cairo_bool_t
437 _pattern_is_pixel_aligned (const cairo_pattern_t *pattern)
438 {
439     long xoffset, yoffset;
440
441     if (!pattern)
442         return TRUE;
443
444     xoffset = pattern->matrix.x0;
445     yoffset = pattern->matrix.y0;
446
447     if (pattern->matrix.xx != 1.0 ||
448         pattern->matrix.xy != 0.0 ||
449         pattern->matrix.yy != 1.0 ||
450         pattern->matrix.yx != 1.0 ||
451         pattern->matrix.x0 != xoffset ||
452         pattern->matrix.y0 != yoffset)
453         return FALSE;
454     return TRUE;
455 }
456
457 static cairo_bool_t
458 _clip_is_pixel_aligned (const cairo_clip_t *clip)
459 {
460     if (!clip)
461         return TRUE;
462
463     if (clip->path || clip->num_boxes > 1)
464         return FALSE;
465
466     if (_cairo_fixed_is_integer (clip->boxes[0].p1.x) &&
467         _cairo_fixed_is_integer (clip->boxes[0].p1.y) &&
468         _cairo_fixed_is_integer (clip->boxes[0].p2.x) &&
469         _cairo_fixed_is_integer (clip->boxes[0].p2.y))
470         return TRUE;
471     return FALSE;
472 }
473
474 /* Masking with the SOURCE operator requires two passes. In the first
475  * pass we use the mask as the source to get:
476  * result = (1 - ma) * dst
477  * In the second pass we use the add operator to achieve:
478  * result = (src * ma) + dst
479  * Combined this produces:
480  * result = (src * ma) + (1 - ma) * dst
481  */
482 static cairo_int_status_t
483 _cairo_gl_msaa_compositor_mask_source_operator (const cairo_compositor_t *compositor,
484                                                 cairo_composite_rectangles_t *composite)
485 {
486     cairo_gl_composite_t setup;
487     cairo_gl_surface_t *dst = (cairo_gl_surface_t *) composite->surface;
488     cairo_gl_context_t *ctx = NULL;
489     cairo_int_status_t status;
490
491     cairo_clip_t *clip = composite->clip;
492     cairo_traps_t traps;
493     cairo_bool_t is_pixel_aligned =
494         _pattern_is_pixel_aligned (composite->original_source_pattern) &&
495         _pattern_is_pixel_aligned (composite->original_mask_pattern) &&
496         _clip_is_pixel_aligned (clip);
497
498     /* If we have a non-rectangular clip, we can avoid using the stencil buffer
499      * for clipping and just draw the clip polygon. */
500     if (clip) {
501         status = _clip_to_traps (clip, &traps);
502         if (unlikely (status)) {
503             _cairo_traps_fini (&traps);
504             return status;
505         }
506     }
507
508     if (! is_pixel_aligned) {
509         status = _blit_texture_to_renderbuffer (dst);
510         if (unlikely (status))
511             return status;
512     }
513
514     status = _cairo_gl_composite_init (&setup,
515                                        CAIRO_OPERATOR_DEST_OUT,
516                                        dst,
517                                        FALSE /* assume_component_alpha */);
518     if (unlikely (status))
519         return status;
520     status = _cairo_gl_composite_set_source (&setup,
521                                              composite->original_mask_pattern,
522                                              &composite->mask_sample_area,
523                                              &composite->bounded,
524                                              FALSE, FALSE);
525     if (unlikely (status))
526         goto finish;
527
528     if (! is_pixel_aligned || dst->msaa_active)
529         _cairo_gl_composite_set_multisample (&setup);
530
531     status = _cairo_gl_composite_begin (&setup, &ctx);
532     if (unlikely (status))
533         goto finish;
534
535     if (! clip)
536         status = _draw_int_rect (ctx, &setup, &composite->bounded);
537     else
538         status = _draw_traps (ctx, &setup, &traps);
539
540     /* Now draw the second pass. */
541     status = _cairo_gl_composite_set_operator (&setup, CAIRO_OPERATOR_ADD,
542                                       FALSE /* assume_component_alpha */);
543     if (unlikely (status))
544         goto finish;
545     status = _cairo_gl_composite_set_source (&setup,
546                                              composite->original_source_pattern,
547                                              &composite->source_sample_area,
548                                              &composite->bounded,
549                                              FALSE, FALSE);
550     if (unlikely (status))
551         goto finish;
552     status = _cairo_gl_composite_set_mask (&setup,
553                                            composite->original_mask_pattern,
554                                            &composite->source_sample_area,
555                                            &composite->bounded,
556                                            FALSE);
557     if (unlikely (status))
558         goto finish;
559
560     _cairo_gl_context_set_destination (ctx, dst, setup.multisample);
561
562     status = _cairo_gl_set_operands_and_operator (&setup, ctx);
563     if (unlikely (status))
564         goto finish;
565
566     if (! clip)
567         status = _draw_int_rect (ctx, &setup, &composite->bounded);
568     else
569         status = _draw_traps (ctx, &setup, &traps);
570
571     if (unlikely (status))
572         goto finish;
573
574     dst->content_synced = FALSE;
575
576 finish:
577     _cairo_gl_composite_fini (&setup);
578     if (ctx)
579         status = _cairo_gl_context_release (ctx, status);
580     if (clip)
581         _cairo_traps_fini (&traps);
582
583     return status;
584 }
585
586 static cairo_int_status_t
587 _cairo_gl_msaa_compositor_mask (const cairo_compositor_t        *compositor,
588                                 cairo_composite_rectangles_t    *composite)
589 {
590     cairo_gl_composite_t setup;
591     cairo_gl_surface_t *dst = (cairo_gl_surface_t *) composite->surface;
592     cairo_gl_context_t *ctx = NULL;
593     cairo_int_status_t status;
594     cairo_operator_t op = composite->op;
595     cairo_clip_t *clip = composite->clip;
596     cairo_bool_t is_pixel_aligned = FALSE;
597
598     if (! can_use_msaa_compositor (dst, CAIRO_ANTIALIAS_DEFAULT))
599         return CAIRO_INT_STATUS_UNSUPPORTED;
600
601     if (composite->op == CAIRO_OPERATOR_CLEAR &&
602         composite->original_mask_pattern != NULL)
603         return CAIRO_INT_STATUS_UNSUPPORTED;
604
605     /* GL compositing operators cannot properly represent a mask operation
606        using the SOURCE compositing operator in one pass. This only matters if
607        there actually is a mask (there isn't in a paint operation) and if the
608        mask isn't totally opaque. */
609     if (op == CAIRO_OPERATOR_SOURCE &&
610          composite->original_mask_pattern != NULL &&
611         ! _cairo_pattern_is_opaque (&composite->mask_pattern.base,
612                                     &composite->mask_sample_area)) {
613
614         if (! _cairo_pattern_is_opaque (&composite->source_pattern.base,
615                                       &composite->source_sample_area)) {
616             return _cairo_gl_msaa_compositor_mask_source_operator (compositor, composite);
617         }
618
619         /* If the source is opaque the operation reduces to OVER. */
620         op = CAIRO_OPERATOR_OVER;
621     }
622
623     if (_should_use_unbounded_surface (composite)) {
624         cairo_surface_t* surface = _prepare_unbounded_surface (dst);
625
626         if (unlikely (surface == NULL))
627             return CAIRO_INT_STATUS_UNSUPPORTED;
628
629         /* This may be a paint operation. */
630         if (composite->original_mask_pattern == NULL) {
631             status = _cairo_compositor_paint (compositor, surface,
632                                               CAIRO_OPERATOR_SOURCE,
633                                               &composite->source_pattern.base,
634                                               NULL);
635         } else {
636             status = _cairo_compositor_mask (compositor, surface,
637                                              CAIRO_OPERATOR_SOURCE,
638                                              &composite->source_pattern.base,
639                                              &composite->mask_pattern.base,
640                                              NULL);
641         }
642
643         if (unlikely (status)) {
644             cairo_surface_destroy (surface);
645             return status;
646         }
647
648         return _paint_back_unbounded_surface (compositor, composite, surface);
649     }
650
651     if (_pattern_is_pixel_aligned (composite->original_source_pattern) &&
652         _pattern_is_pixel_aligned (composite->original_mask_pattern) &&
653         _clip_is_pixel_aligned (composite->clip))
654         is_pixel_aligned = TRUE;
655
656     if (! is_pixel_aligned) {
657         status = _blit_texture_to_renderbuffer (dst);
658         if (unlikely (status))
659             return status;
660     }
661
662     status = _cairo_gl_composite_init (&setup,
663                                        op,
664                                        dst,
665                                        FALSE /* assume_component_alpha */);
666     if (unlikely (status))
667         return status;
668
669     status = _cairo_gl_composite_set_source (&setup,
670                                              composite->original_source_pattern,
671                                              &composite->source_sample_area,
672                                              &composite->bounded,
673                                              FALSE, FALSE);
674     if (unlikely (status))
675         goto finish;
676
677     if (composite->original_mask_pattern != NULL) {
678         status = _cairo_gl_composite_set_mask (&setup,
679                                                composite->original_mask_pattern,
680                                                &composite->mask_sample_area,
681                                                &composite->bounded,
682                                                FALSE);
683     }
684     if (unlikely (status))
685         goto finish;
686
687     /* if the source, mask and clip are pixel-aligned and
688        msaa is not active, we paint to texture directly */
689     if (! is_pixel_aligned || dst->msaa_active)
690         _cairo_gl_composite_set_multisample (&setup);
691
692     status = _cairo_gl_composite_begin (&setup, &ctx);
693
694     if (unlikely (status))
695         goto finish;
696
697     if (op != CAIRO_OPERATOR_OVER) {
698         if (! clip)
699             status = _draw_int_rect (ctx, &setup, &composite->bounded);
700         else
701             status = _cairo_gl_msaa_compositor_draw_clip (ctx, &setup, clip);
702     }
703     else {
704         /* fast path for CAIRO_OVER_OPERATOR */
705         cairo_rectangle_int_t rect, temp;
706
707         _cairo_surface_get_extents (&dst->base, &rect);
708         _cairo_pattern_get_extents (composite->original_source_pattern,
709                                     &temp);
710         _cairo_rectangle_intersect (&rect, &temp);
711         if (composite->original_mask_pattern) {
712             _cairo_pattern_get_extents (composite->original_mask_pattern,
713                                         &temp);
714             _cairo_rectangle_intersect (&rect, &temp);
715         }
716
717         if (clip) {
718             cairo_clip_t *clip_copy = _cairo_clip_copy (clip);
719
720             clip_copy = _cairo_clip_intersect_rectangle (clip_copy, &rect);
721             status = _cairo_gl_msaa_compositor_draw_clip (ctx, &setup,
722                                                           clip_copy);
723             _cairo_clip_destroy (clip_copy);
724         }
725         else
726             status = _draw_int_rect (ctx, &setup, &rect);
727     }
728
729     if (unlikely (status))
730         goto finish;
731
732     dst->content_synced = FALSE;
733
734 finish:
735     _cairo_gl_composite_fini (&setup);
736
737     if (ctx)
738         status = _cairo_gl_context_release (ctx, status);
739
740     return status;
741 }
742
743 static cairo_int_status_t
744 _cairo_gl_msaa_compositor_paint (const cairo_compositor_t       *compositor,
745                                  cairo_composite_rectangles_t   *composite)
746 {
747     return _cairo_gl_msaa_compositor_mask (compositor, composite);
748 }
749
750 static cairo_status_t
751 _stroke_shaper_add_triangle (void                       *closure,
752                              const cairo_point_t         triangle[3])
753 {
754     struct _tristrip_composite_info *info = closure;
755     return _cairo_gl_composite_emit_triangle_as_tristrip (info->ctx,
756                                                           &info->setup,
757                                                           triangle);
758 }
759
760 static cairo_status_t
761 _stroke_shaper_add_triangle_fan (void                   *closure,
762                                  const cairo_point_t    *midpoint,
763                                  const cairo_point_t    *points,
764                                  int                     npoints)
765 {
766     struct _tristrip_composite_info *info = closure;
767     return _draw_triangle_fan (info->ctx, &info->setup,
768                                midpoint, points, npoints);
769 }
770
771 static cairo_status_t
772 _stroke_shaper_add_quad (void                   *closure,
773                          const cairo_point_t     quad[4])
774 {
775     struct _tristrip_composite_info *info = closure;
776     return _cairo_gl_composite_emit_quad_as_tristrip (info->ctx, &info->setup,
777                                                       quad);
778 }
779
780 static cairo_bool_t
781 _is_continuous_arc (const cairo_path_fixed_t   *path,
782                     const cairo_stroke_style_t *style)
783 {
784     return (_cairo_path_fixed_is_single_arc (path) &&
785             style->dash == NULL);
786 }
787
788 static cairo_int_status_t
789 _prevent_overlapping_strokes (cairo_gl_context_t                *ctx,
790                               cairo_gl_composite_t              *setup,
791                               cairo_composite_rectangles_t      *composite,
792                               const cairo_path_fixed_t          *path,
793                               const cairo_stroke_style_t        *style,
794                               const cairo_matrix_t              *ctm)
795 {
796     cairo_rectangle_int_t stroke_extents;
797     const cairo_pattern_t *pattern = composite->original_source_pattern;
798     cairo_pattern_type_t type = cairo_pattern_get_type ((cairo_pattern_t *) pattern);
799
800     if (! _cairo_gl_ensure_stencil (ctx, setup->dst))
801         return CAIRO_INT_STATUS_UNSUPPORTED;
802
803
804     /* XXX: improve me - since we have lazy init, we cannot use sample
805        area */
806     if (type == CAIRO_PATTERN_TYPE_SOLID &&
807         _cairo_pattern_is_opaque_solid (pattern))
808         return CAIRO_INT_STATUS_SUCCESS;
809
810     if (ctx->states_cache.stencil_test_enabled == FALSE) {
811        /* In case we have pending operations we have to flush before
812           adding the stencil buffer. */
813        _cairo_gl_composite_flush (ctx);
814
815         /* Enable the stencil buffer, even if we are not using it for clipping,
816            so we can use it below to prevent overlapping shapes. We initialize
817            it all to one here which represents infinite clip. */
818         if (! ctx->states_cache.depth_mask) {
819             ctx->dispatch.DepthMask (GL_TRUE);
820             ctx->states_cache.depth_mask = TRUE;
821         }
822         ctx->dispatch.Enable (GL_STENCIL_TEST);
823         ctx->states_cache.stencil_test_enabled = TRUE;
824
825         /* We scissor here so that we don't have to clear the entire stencil
826          * buffer. If the scissor test is already enabled, it was enabled
827          * for clipping. In that case, instead of calculating an intersection,
828          * we just reuse it, and risk clearing too much. */
829         if (ctx->states_cache.scissor_test_enabled == FALSE) {
830             _cairo_path_fixed_approximate_stroke_extents (path, style, ctm,
831                                                           &stroke_extents);
832             _cairo_gl_scissor_to_rectangle (setup->dst, &stroke_extents);
833             ctx->dispatch.Enable (GL_SCISSOR_TEST);
834             ctx->states_cache.scissor_test_enabled = TRUE;
835         }
836         ctx->dispatch.ClearStencil (1);
837         ctx->dispatch.Clear (GL_STENCIL_BUFFER_BIT);
838         _disable_scissor_buffer (ctx);
839
840         ctx->dispatch.StencilFunc (GL_EQUAL, 1, 1);
841     }
842
843     /* This means that once we draw to a particular pixel nothing else can
844        be drawn there until the stencil buffer is reset or the stencil test
845        is disabled. */
846     ctx->dispatch.StencilOp (GL_ZERO, GL_ZERO, GL_ZERO);
847
848     _cairo_clip_destroy (setup->dst->clip_on_stencil_buffer);
849     setup->dst->clip_on_stencil_buffer = NULL;
850
851     /* we must let the next drawing know we have changed stencil buffer
852      * so that next drawing calls flush
853      */
854     setup->dst->needs_update = TRUE;
855
856     return CAIRO_INT_STATUS_SUCCESS;
857 }
858
859 static void
860 query_surface_capabilities (cairo_gl_surface_t *surface)
861 {
862     GLint samples, stencil_bits;
863     cairo_gl_context_t *ctx;
864     cairo_int_status_t status;
865
866     /* Texture surfaces are create in such a way that they always
867        have stencil and multisample bits if possible, so we don't
868        need to query their capabilities lazily. */
869     if (_cairo_gl_surface_is_texture (surface))
870         return;
871     if (surface->stencil_and_msaa_caps_initialized)
872         return;
873
874     surface->stencil_and_msaa_caps_initialized = TRUE;
875     surface->supports_stencil = FALSE;
876     surface->supports_msaa = FALSE;
877
878     status = _cairo_gl_context_acquire (surface->base.device, &ctx);
879     if (unlikely (status))
880         return;
881
882     _cairo_gl_context_set_destination (ctx, surface, FALSE);
883
884     //ctx->dispatch.GetIntegerv(GL_SAMPLES, &samples);
885     //ctx->dispatch.GetIntegerv(GL_STENCIL_BITS, &stencil_bits);
886     samples = 4;
887     stencil_bits = 4;
888     surface->supports_stencil = stencil_bits > 0;
889
890     surface->supports_msaa = samples > 1;
891
892     surface->num_samples = samples;
893
894     status = _cairo_gl_context_release (ctx, status);
895 }
896
897 static cairo_int_status_t
898 _cairo_gl_msaa_compositor_stroke (const cairo_compositor_t      *compositor,
899                                   cairo_composite_rectangles_t  *composite,
900                                   const cairo_path_fixed_t      *path,
901                                   const cairo_stroke_style_t    *style,
902                                   const cairo_matrix_t          *ctm,
903                                   const cairo_matrix_t          *ctm_inverse,
904                                   double                         tolerance,
905                                   cairo_antialias_t              antialias)
906 {
907     cairo_int_status_t status;
908     cairo_gl_surface_t *dst = (cairo_gl_surface_t *) composite->surface;
909     struct _tristrip_composite_info info;
910     cairo_bool_t use_color_attribute;
911     cairo_rectangle_int_t stroke_extents;
912
913     if (! can_use_msaa_compositor (dst, antialias))
914         return CAIRO_INT_STATUS_UNSUPPORTED;
915
916     if (! _cairo_path_fixed_stroke_is_rectilinear (path)) {
917         _cairo_path_fixed_approximate_fill_extents (path, &stroke_extents);
918
919         if (stroke_extents.width != 0 &&
920             stroke_extents.height != 0) {
921             if ((stroke_extents.width / stroke_extents.height > 10  &&
922                  stroke_extents.height < 10) ||
923                 (stroke_extents.height / stroke_extents.width > 10 &&
924                  stroke_extents.width < 10)) {
925                 return CAIRO_INT_STATUS_UNSUPPORTED;
926             }
927         }
928     }
929
930     if (composite->is_bounded == FALSE) {
931         cairo_surface_t* surface = _prepare_unbounded_surface (dst);
932
933         if (unlikely (surface == NULL))
934             return CAIRO_INT_STATUS_UNSUPPORTED;
935
936         status = _cairo_compositor_stroke (compositor, surface,
937                                            CAIRO_OPERATOR_SOURCE,
938                                            &composite->source_pattern.base,
939                                            path, style, ctm, ctm_inverse,
940                                            tolerance, antialias, NULL);
941         if (unlikely (status)) {
942             cairo_surface_destroy (surface);
943             return status;
944         }
945
946         return _paint_back_unbounded_surface (compositor, composite, surface);
947     }
948
949     if (antialias != CAIRO_ANTIALIAS_NONE) {
950         status = _blit_texture_to_renderbuffer (dst);
951         if (unlikely (status))
952             return status;
953     }
954
955     status = _cairo_gl_composite_init (&info.setup,
956                                        composite->op,
957                                        dst,
958                                        FALSE /* assume_component_alpha */);
959     if (unlikely (status))
960         return status;
961
962     info.ctx = NULL;
963     use_color_attribute = _cairo_gl_hairline_style_is_hairline (style, ctm);
964
965     status = _cairo_gl_composite_set_source (&info.setup,
966                                              composite->original_source_pattern,
967                                              &composite->source_sample_area,
968                                              &composite->bounded,
969                                              FALSE, use_color_attribute);
970     if (unlikely (status))
971         goto finish;
972
973     _cairo_gl_msaa_compositor_set_clip (composite, &info.setup);
974     if (antialias != CAIRO_ANTIALIAS_NONE)
975         _cairo_gl_composite_set_multisample (&info.setup);
976
977     status = _cairo_gl_composite_begin (&info.setup, &info.ctx);
978     if (unlikely (status))
979         goto finish;
980
981     if (_cairo_gl_hairline_style_is_hairline (style, ctm)) {
982         cairo_gl_hairline_closure_t closure;
983
984         if (! (_is_continuous_arc (path, style) ||
985                _is_continuous_single_line (path, style))) {
986             status = _prevent_overlapping_strokes (info.ctx, &info.setup,
987                                                    composite, path,
988                                                    style, ctm);
989             if (unlikely (status))
990                 goto finish;
991         }
992
993         closure.ctx = info.ctx;
994
995         closure.tolerance = tolerance;
996
997         status = _cairo_gl_path_fixed_stroke_to_hairline (path, &closure,
998                                                           style, ctm,
999                                                           ctm_inverse,
1000                                                           _cairo_gl_hairline_move_to,
1001                                                           style->dash ?
1002                                                           _cairo_gl_hairline_line_to_dashed :
1003                                                           _cairo_gl_hairline_line_to,
1004                                                           _cairo_gl_hairline_curve_to,
1005                                                           _cairo_gl_hairline_close_path);
1006         goto finish;
1007     }
1008
1009     if (!_is_continuous_single_line (path, style)) {
1010         status = _prevent_overlapping_strokes (info.ctx, &info.setup,
1011                                                composite, path, style, ctm);
1012         if (unlikely (status))
1013             goto finish;
1014     }
1015
1016     status =
1017         _cairo_path_fixed_stroke_to_shaper ((cairo_path_fixed_t *) path,
1018                                             style,
1019                                             ctm,
1020                                             ctm_inverse,
1021                                             tolerance,
1022                                             _stroke_shaper_add_triangle,
1023                                             _stroke_shaper_add_triangle_fan,
1024                                             _stroke_shaper_add_quad,
1025                                             &info);
1026     if (unlikely (status))
1027         goto finish;
1028
1029     dst->content_synced = FALSE;
1030
1031 finish:
1032     _cairo_gl_composite_fini (&info.setup);
1033
1034     if (info.ctx)
1035         status = _cairo_gl_context_release (info.ctx, status);
1036
1037     return status;
1038 }
1039
1040 static cairo_int_status_t
1041 _draw_simple_quad_path (cairo_gl_context_t *ctx,
1042                         cairo_gl_composite_t *setup,
1043                         const cairo_path_fixed_t *path)
1044 {
1045     cairo_point_t triangle[3];
1046     cairo_int_status_t status;
1047     const cairo_point_t *points;
1048
1049     points = cairo_path_head (path)->points;
1050
1051     triangle[0] = points[0];
1052     triangle[1] = points[1];
1053     triangle[2] = points[2];
1054     status = _cairo_gl_composite_emit_triangle_as_tristrip (ctx, setup, triangle);
1055     if (status)
1056         return status;
1057
1058     triangle[0] = points[2];
1059     triangle[1] = points[3];
1060     triangle[2] = points[0];
1061     return _cairo_gl_composite_emit_triangle_as_tristrip (ctx, setup, triangle);
1062 }
1063
1064 static cairo_int_status_t
1065 _cairo_gl_msaa_compositor_fill (const cairo_compositor_t        *compositor,
1066                                 cairo_composite_rectangles_t    *composite,
1067                                 const cairo_path_fixed_t        *path,
1068                                 cairo_fill_rule_t                fill_rule,
1069                                 double                           tolerance,
1070                                 cairo_antialias_t                antialias)
1071 {
1072     cairo_gl_composite_t setup;
1073     cairo_gl_surface_t *dst = (cairo_gl_surface_t *) composite->surface;
1074     cairo_gl_context_t *ctx = NULL;
1075     cairo_int_status_t status;
1076     cairo_traps_t traps;
1077     cairo_bool_t draw_path_with_traps;
1078     cairo_rectangle_int_t fill_extents;
1079
1080     if (! can_use_msaa_compositor (dst, antialias))
1081         return CAIRO_INT_STATUS_UNSUPPORTED;
1082
1083     if (! _cairo_path_fixed_fill_is_rectilinear (path)) {
1084         _cairo_path_fixed_approximate_fill_extents (path, &fill_extents);
1085
1086         if (fill_extents.width != 0 && fill_extents.height != 0) {
1087             if ((fill_extents.width / fill_extents.height > 10  &&
1088                  fill_extents.height < 10) ||
1089                 (fill_extents.height / fill_extents.width > 10 &&
1090                  fill_extents.width < 10)) {
1091                 return CAIRO_INT_STATUS_UNSUPPORTED;
1092             }
1093         }
1094     }
1095
1096     if (composite->is_bounded == FALSE) {
1097         cairo_surface_t* surface = _prepare_unbounded_surface (dst);
1098
1099         if (unlikely (surface == NULL))
1100             return CAIRO_INT_STATUS_UNSUPPORTED;
1101
1102
1103         status = _cairo_compositor_fill (compositor, surface,
1104                                          CAIRO_OPERATOR_SOURCE,
1105                                          &composite->source_pattern.base,
1106                                          path, fill_rule, tolerance,
1107                                          antialias, NULL);
1108
1109         if (unlikely (status)) {
1110             cairo_surface_destroy (surface);
1111             return status;
1112         }
1113
1114         return _paint_back_unbounded_surface (compositor, composite, surface);
1115     }
1116
1117     if (antialias != CAIRO_ANTIALIAS_NONE) {
1118         status = _blit_texture_to_renderbuffer (dst);
1119         if (unlikely (status))
1120             return status;
1121     }
1122
1123     draw_path_with_traps = ! _cairo_path_fixed_is_simple_quad (path);
1124
1125     if (draw_path_with_traps) {
1126         _cairo_traps_init (&traps);
1127         status = _cairo_path_fixed_fill_to_traps (path, fill_rule, tolerance, &traps);
1128         if (unlikely (status))
1129             goto cleanup_traps;
1130     }
1131
1132     status = _cairo_gl_composite_init (&setup,
1133                                        composite->op,
1134                                        dst,
1135                                        FALSE /* assume_component_alpha */);
1136     if (unlikely (status))
1137         goto cleanup_traps;
1138
1139     status = _cairo_gl_composite_set_source (&setup,
1140                                              composite->original_source_pattern,
1141                                              &composite->source_sample_area,
1142                                              &composite->bounded,
1143                                              FALSE, ! draw_path_with_traps);
1144     if (unlikely (status))
1145         goto cleanup_setup;
1146
1147     _cairo_gl_msaa_compositor_set_clip (composite, &setup);
1148     if (antialias != CAIRO_ANTIALIAS_NONE)
1149         _cairo_gl_composite_set_multisample (&setup);
1150
1151     status = _cairo_gl_composite_begin (&setup, &ctx);
1152     if (unlikely (status))
1153         goto cleanup_setup;
1154
1155     if (! draw_path_with_traps)
1156         status = _draw_simple_quad_path (ctx, &setup, path);
1157     else
1158         status = _draw_traps (ctx, &setup, &traps);
1159     if (unlikely (status))
1160         goto cleanup_setup;
1161
1162     dst->content_synced = FALSE;
1163
1164 cleanup_setup:
1165     _cairo_gl_composite_fini (&setup);
1166
1167     if (ctx)
1168         status = _cairo_gl_context_release (ctx, status);
1169
1170 cleanup_traps:
1171     if (draw_path_with_traps)
1172         _cairo_traps_fini (&traps);
1173
1174     return status;
1175 }
1176
1177 static cairo_int_status_t
1178 _cairo_gl_msaa_compositor_glyphs (const cairo_compositor_t      *compositor,
1179                                   cairo_composite_rectangles_t  *composite,
1180                                   cairo_scaled_font_t           *scaled_font,
1181                                   cairo_glyph_t                 *glyphs,
1182                                   int                            num_glyphs,
1183                                   cairo_bool_t                   overlap)
1184 {
1185     cairo_int_status_t status;
1186     cairo_surface_t *src = NULL;
1187     int src_x, src_y;
1188     cairo_composite_glyphs_info_t info;
1189
1190     cairo_gl_surface_t *dst = (cairo_gl_surface_t *) composite->surface;
1191
1192     query_surface_capabilities (dst);
1193     if (! dst->supports_stencil)
1194         return CAIRO_INT_STATUS_UNSUPPORTED;
1195
1196     if (composite->op == CAIRO_OPERATOR_CLEAR)
1197         return CAIRO_INT_STATUS_UNSUPPORTED;
1198
1199     if (composite->is_bounded == FALSE) {
1200         cairo_surface_t* surface = _prepare_unbounded_surface (dst);
1201
1202         if (unlikely (surface == NULL))
1203             return CAIRO_INT_STATUS_UNSUPPORTED;
1204
1205         status = _cairo_compositor_glyphs (compositor, surface,
1206                                            CAIRO_OPERATOR_SOURCE,
1207                                            &composite->source_pattern.base,
1208                                            glyphs, num_glyphs,
1209                                            scaled_font, composite->clip);
1210
1211         if (unlikely (status)) {
1212             cairo_surface_destroy (surface);
1213             return status;
1214         }
1215
1216         return _paint_back_unbounded_surface (compositor, composite, surface);
1217     }
1218
1219     src = _cairo_gl_pattern_to_source (&dst->base,
1220                                        composite->original_source_pattern,
1221                                        FALSE,
1222                                        &composite->bounded,
1223                                        &composite->source_sample_area,
1224                                        &src_x, &src_y);
1225     if (unlikely (src->status)) {
1226         status = src->status;
1227         goto finish;
1228     }
1229
1230     status = _cairo_gl_check_composite_glyphs (composite,
1231                                                scaled_font, glyphs,
1232                                                &num_glyphs);
1233     if (unlikely (status != CAIRO_INT_STATUS_SUCCESS))
1234         goto finish;
1235
1236     info.font = scaled_font;
1237     info.glyphs = glyphs;
1238     info.num_glyphs = num_glyphs;
1239     info.use_mask = overlap || ! composite->is_bounded ||
1240                     composite->op == CAIRO_OPERATOR_SOURCE;
1241     info.extents = composite->source;
1242
1243     _cairo_scaled_font_freeze_cache (scaled_font);
1244     status = _cairo_gl_composite_glyphs_with_clip (dst, composite->op,
1245                                                    src, src_x, src_y,
1246                                                    0, 0, &info,
1247                                                    composite->clip);
1248
1249     _cairo_scaled_font_thaw_cache (scaled_font);
1250     if (unlikely (status))
1251         goto finish;
1252
1253     dst->content_synced = FALSE;
1254
1255 finish:
1256         cairo_surface_destroy (src);
1257
1258     return status;
1259 }
1260
1261 static void
1262 _cairo_gl_msaa_compositor_init (cairo_compositor_t       *compositor,
1263                                 const cairo_compositor_t *delegate)
1264 {
1265     compositor->delegate = delegate;
1266     compositor->lazy_init = TRUE;
1267
1268     compositor->paint = _cairo_gl_msaa_compositor_paint;
1269     compositor->mask = _cairo_gl_msaa_compositor_mask;
1270     compositor->fill = _cairo_gl_msaa_compositor_fill;
1271     compositor->stroke = _cairo_gl_msaa_compositor_stroke;
1272     compositor->glyphs = _cairo_gl_msaa_compositor_glyphs;
1273 }
1274
1275 const cairo_compositor_t *
1276 _cairo_gl_msaa_compositor_get (void)
1277 {
1278     static cairo_compositor_t compositor;
1279     if (compositor.delegate == NULL)
1280         _cairo_gl_msaa_compositor_init (&compositor,
1281                                         _cairo_gl_span_compositor_get ());
1282
1283     return &compositor;
1284 }