tizen 2.3.1 release
[framework/graphics/cairo.git] / src / cairo-gl-composite.c
1 /* cairo - a vector graphics library with display and print output
2  *
3  * Copyright © 2009 Eric Anholt
4  * Copyright © 2009 Chris Wilson
5  * Copyright © 2005,2010 Red Hat, Inc
6  * Copyright © 2011 Linaro Limited
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 Red Hat, Inc.
35  *
36  * Contributor(s):
37  *      Benjamin Otte <otte@gnome.org>
38  *      Carl Worth <cworth@cworth.org>
39  *      Chris Wilson <chris@chris-wilson.co.uk>
40  *      Eric Anholt <eric@anholt.net>
41  *      Alexandros Frantzis <alexandros.frantzis@linaro.org>
42  *      Henry Song <hsong@sisa.samsung.com>
43  *      Martin Robinson <mrobinson@igalia.com>
44  */
45
46 #include "cairoint.h"
47
48 #include "cairo-gl-private.h"
49
50 #include "cairo-composite-rectangles-private.h"
51 #include "cairo-clip-private.h"
52 #include "cairo-error-private.h"
53 #include "cairo-image-surface-private.h"
54
55 cairo_int_status_t
56 _cairo_gl_composite_set_source (cairo_gl_composite_t *setup,
57                                 const cairo_pattern_t *pattern,
58                                 const cairo_rectangle_int_t *sample,
59                                 const cairo_rectangle_int_t *extents,
60                                 cairo_bool_t use_texgen,
61                                 cairo_bool_t encode_color_as_attribute)
62 {
63     _cairo_gl_operand_destroy (&setup->src);
64     return _cairo_gl_operand_init (&setup->src, pattern, setup->dst,
65                                    sample, extents, use_texgen,
66                                    encode_color_as_attribute);
67 }
68
69 void
70 _cairo_gl_composite_set_source_operand (cairo_gl_composite_t *setup,
71                                         const cairo_gl_operand_t *source)
72 {
73     cairo_int_status_t status;
74
75     _cairo_gl_operand_destroy (&setup->src);
76     _cairo_gl_operand_copy (&setup->src, source);
77     if (source->type == CAIRO_GL_OPERAND_TEXTURE ||
78         source->type == CAIRO_GL_OPERAND_GAUSSIAN)
79         status = _cairo_gl_surface_resolve_multisampling (source->texture.surface);
80 }
81
82 void
83 _cairo_gl_composite_set_solid_source (cairo_gl_composite_t *setup,
84                                       const cairo_color_t *color)
85 {
86     _cairo_gl_operand_destroy (&setup->src);
87     _cairo_gl_solid_operand_init (&setup->src, color);
88 }
89
90 cairo_int_status_t
91 _cairo_gl_composite_set_mask (cairo_gl_composite_t *setup,
92                               const cairo_pattern_t *pattern,
93                               const cairo_rectangle_int_t *sample,
94                               const cairo_rectangle_int_t *extents,
95                               cairo_bool_t use_texgen)
96 {
97     _cairo_gl_operand_destroy (&setup->mask);
98     if (pattern == NULL)
99         return CAIRO_STATUS_SUCCESS;
100
101     return _cairo_gl_operand_init (&setup->mask, pattern, setup->dst,
102                                    sample, extents, use_texgen, FALSE);
103 }
104
105 void
106 _cairo_gl_composite_set_mask_operand (cairo_gl_composite_t *setup,
107                                       const cairo_gl_operand_t *mask)
108 {
109     cairo_int_status_t status;
110     _cairo_gl_operand_destroy (&setup->mask);
111     if (mask) {
112         _cairo_gl_operand_copy (&setup->mask, mask);
113         if (mask->type == CAIRO_GL_OPERAND_TEXTURE ||
114             mask->type == CAIRO_GL_OPERAND_GAUSSIAN)
115             status = _cairo_gl_surface_resolve_multisampling (mask->texture.surface);
116     }
117 }
118
119 void
120 _cairo_gl_composite_set_spans (cairo_gl_composite_t *setup)
121 {
122     setup->spans = TRUE;
123 }
124
125 void
126 _cairo_gl_composite_set_multisample (cairo_gl_composite_t *setup)
127 {
128     setup->multisample = TRUE;
129 }
130
131 void
132 _cairo_gl_composite_set_clip_region (cairo_gl_composite_t *setup,
133                                      cairo_region_t *clip_region)
134 {
135     setup->clip_region = clip_region;
136 }
137
138 void
139 _cairo_gl_composite_set_clip (cairo_gl_composite_t *setup,
140                               cairo_clip_t *clip)
141 {
142     setup->clip = clip;
143 }
144
145 static void
146 _cairo_gl_composite_bind_to_shader (cairo_gl_context_t   *ctx,
147                                     cairo_gl_composite_t *setup)
148 {
149     _cairo_gl_shader_bind_matrix4f(ctx, CAIRO_GL_UNIFORM_PROJECTION_MATRIX,
150                                    ctx->modelviewprojection_matrix);
151     _cairo_gl_operand_bind_to_shader (ctx, &setup->src,  CAIRO_GL_TEX_SOURCE);
152     _cairo_gl_operand_bind_to_shader (ctx, &setup->mask, CAIRO_GL_TEX_MASK);
153 }
154
155 static void
156 _cairo_gl_texture_set_filter (cairo_gl_context_t *ctx,
157                               GLuint              target,
158                               cairo_filter_t      filter)
159 {
160     switch (filter) {
161     case CAIRO_FILTER_FAST:
162     case CAIRO_FILTER_NEAREST:
163         ctx->dispatch.TexParameteri (target, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
164         ctx->dispatch.TexParameteri (target, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
165         break;
166     case CAIRO_FILTER_GOOD:
167     case CAIRO_FILTER_BEST:
168     case CAIRO_FILTER_BILINEAR:
169     case CAIRO_FILTER_GAUSSIAN:
170         ctx->dispatch.TexParameteri (target, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
171         ctx->dispatch.TexParameteri (target, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
172         break;
173     default:
174         ASSERT_NOT_REACHED;
175     }
176 }
177
178 static void
179 _cairo_gl_texture_set_extend (cairo_gl_context_t *ctx,
180                               GLuint              target,
181                               cairo_extend_t      extend,
182                               cairo_bool_t            use_atlas)
183 {
184     GLint wrap_mode;
185     assert (! _cairo_gl_device_requires_power_of_two_textures (&ctx->base) ||
186             (extend != CAIRO_EXTEND_REPEAT && extend != CAIRO_EXTEND_REFLECT));
187
188     switch (extend) {
189     case CAIRO_EXTEND_NONE:
190         if (ctx->gl_flavor == CAIRO_GL_FLAVOR_ES2 ||
191             ctx->gl_flavor == CAIRO_GL_FLAVOR_ES3)
192             wrap_mode = GL_CLAMP_TO_EDGE;
193         else
194             wrap_mode = GL_CLAMP_TO_BORDER;
195         break;
196     case CAIRO_EXTEND_PAD:
197         wrap_mode = GL_CLAMP_TO_EDGE;
198         break;
199     case CAIRO_EXTEND_REPEAT:
200         if (ctx->has_npot_repeat)
201             wrap_mode = GL_REPEAT;
202         else
203             wrap_mode = GL_CLAMP_TO_EDGE;
204         break;
205     case CAIRO_EXTEND_REFLECT:
206         if (ctx->has_npot_repeat)
207             wrap_mode = GL_MIRRORED_REPEAT;
208         else
209             wrap_mode = GL_CLAMP_TO_EDGE;
210         break;
211     default:
212         wrap_mode = 0;
213     }
214
215     if (likely (wrap_mode)) {
216         ctx->dispatch.TexParameteri (target, GL_TEXTURE_WRAP_S, wrap_mode);
217         ctx->dispatch.TexParameteri (target, GL_TEXTURE_WRAP_T, wrap_mode);
218     }
219 }
220
221
222 static void
223 _cairo_gl_context_setup_operand (cairo_gl_context_t *ctx,
224                                  cairo_gl_tex_t      tex_unit,
225                                  cairo_gl_operand_t *operand,
226                                  unsigned int        vertex_offset,
227                                  cairo_bool_t        vertex_size_changed)
228 {
229     cairo_gl_dispatch_t *dispatch = &ctx->dispatch;
230     cairo_bool_t needs_setup;
231     unsigned int offset = vertex_offset;
232
233     /* XXX: we need to do setup when switching from shaders
234      * to no shaders (or back) */
235     needs_setup = vertex_size_changed;
236     needs_setup |= _cairo_gl_operand_needs_setup (&ctx->operands[tex_unit],
237                                                  operand,
238                                                  vertex_offset);
239
240     if (needs_setup) {
241         _cairo_gl_composite_flush (ctx);
242         _cairo_gl_context_destroy_operand (ctx, tex_unit);
243     }
244
245     memcpy (&ctx->operands[tex_unit], operand, sizeof (cairo_gl_operand_t));
246     ctx->operands[tex_unit].vertex_offset = vertex_offset;
247
248     if (! needs_setup)
249         return;
250
251     switch (operand->type) {
252     default:
253     case CAIRO_GL_OPERAND_COUNT:
254         ASSERT_NOT_REACHED;
255     case CAIRO_GL_OPERAND_NONE:
256         break;
257         /* fall through */
258     case CAIRO_GL_OPERAND_CONSTANT:
259         if (operand->constant.encode_as_attribute) {
260             dispatch->VertexAttribPointer (CAIRO_GL_COLOR_ATTRIB_INDEX, 4,
261                                            GL_FLOAT, GL_FALSE, ctx->vertex_size,
262                                            ctx->vb + vertex_offset);
263             dispatch->EnableVertexAttribArray (CAIRO_GL_COLOR_ATTRIB_INDEX);
264         }
265         break;
266     case CAIRO_GL_OPERAND_TEXTURE:
267     case CAIRO_GL_OPERAND_GAUSSIAN:
268         if (ctx->states_cache.active_texture != GL_TEXTURE0 + tex_unit) {
269             dispatch->ActiveTexture (GL_TEXTURE0 + tex_unit);
270             ctx->states_cache.active_texture = GL_TEXTURE0 + tex_unit;
271         }
272         dispatch->BindTexture (ctx->tex_target, operand->texture.tex);
273         _cairo_gl_texture_set_extend (ctx, ctx->tex_target,
274                                       operand->texture.attributes.extend,
275                                       operand->texture.use_atlas);
276         _cairo_gl_texture_set_filter (ctx, ctx->tex_target,
277                                       operand->texture.attributes.filter);
278         if (! operand->texture.texgen) {
279             dispatch->VertexAttribPointer (CAIRO_GL_TEXCOORD0_ATTRIB_INDEX + tex_unit, 2,
280                                            GL_FLOAT, GL_FALSE, ctx->vertex_size,
281                                            ctx->vb + offset);
282             dispatch->EnableVertexAttribArray (CAIRO_GL_TEXCOORD0_ATTRIB_INDEX + tex_unit);
283             offset += 2 * sizeof (GLfloat);
284         }
285
286         if (operand->texture.use_atlas) {
287             dispatch->VertexAttribPointer (CAIRO_GL_START_COORD0_ATTRIB_INDEX + tex_unit,
288                                            2, GL_FLOAT, GL_FALSE,
289                                            ctx->vertex_size,
290                                            ctx->vb + offset);
291             dispatch->EnableVertexAttribArray (CAIRO_GL_START_COORD0_ATTRIB_INDEX + tex_unit);
292             dispatch->VertexAttribPointer (CAIRO_GL_STOP_COORD0_ATTRIB_INDEX + tex_unit,
293                                            2, GL_FLOAT, GL_FALSE,
294                                            ctx->vertex_size,
295                                            ctx->vb + offset + 2 * sizeof (float));
296             dispatch->EnableVertexAttribArray (CAIRO_GL_STOP_COORD0_ATTRIB_INDEX + tex_unit);
297         }
298         break;
299     case CAIRO_GL_OPERAND_LINEAR_GRADIENT:
300     case CAIRO_GL_OPERAND_RADIAL_GRADIENT_A0:
301     case CAIRO_GL_OPERAND_RADIAL_GRADIENT_NONE:
302     case CAIRO_GL_OPERAND_RADIAL_GRADIENT_EXT:
303         if(ctx->states_cache.active_texture != GL_TEXTURE0 + tex_unit) {
304             dispatch->ActiveTexture (GL_TEXTURE0 + tex_unit);
305             ctx->states_cache.active_texture = GL_TEXTURE0 + tex_unit;
306         }
307         dispatch->BindTexture (ctx->tex_target, operand->gradient.gradient->tex);
308         _cairo_gl_texture_set_extend (ctx, ctx->tex_target,
309                                       operand->gradient.extend, FALSE);
310         _cairo_gl_texture_set_filter (ctx, ctx->tex_target, CAIRO_FILTER_BILINEAR);
311
312         if (! operand->gradient.texgen) {
313             dispatch->VertexAttribPointer (CAIRO_GL_TEXCOORD0_ATTRIB_INDEX + tex_unit, 2,
314                                            GL_FLOAT, GL_FALSE, ctx->vertex_size,
315                                            ctx->vb + vertex_offset);
316             dispatch->EnableVertexAttribArray (CAIRO_GL_TEXCOORD0_ATTRIB_INDEX + tex_unit);
317         }
318         break;
319     }
320 }
321
322 static void
323 _cairo_gl_context_setup_spans (cairo_gl_context_t *ctx,
324                                cairo_bool_t        encode_src_as_attribute,
325                                cairo_bool_t        spans_enabled,
326                                unsigned int        vertex_size,
327                                unsigned int        vertex_offset)
328 {
329     cairo_gl_dispatch_t *dispatch = &ctx->dispatch;
330
331     if (! spans_enabled) {
332         ctx->spans = FALSE;
333
334         /* If we are going to encode the source as an attribute, we don't want
335         * to disable the attribute array here only to enable it again later. */
336         if (! encode_src_as_attribute)
337             dispatch->DisableVertexAttribArray (CAIRO_GL_COLOR_ATTRIB_INDEX);
338
339         return;
340     }
341
342     dispatch->VertexAttribPointer (CAIRO_GL_COLOR_ATTRIB_INDEX, 4,
343                                    GL_UNSIGNED_BYTE, GL_TRUE, vertex_size,
344                                    ctx->vb + vertex_offset);
345     dispatch->EnableVertexAttribArray (CAIRO_GL_COLOR_ATTRIB_INDEX);
346     ctx->spans = TRUE;
347 }
348
349 void
350 _cairo_gl_context_destroy_operand (cairo_gl_context_t *ctx,
351                                    cairo_gl_tex_t tex_unit)
352 {
353     cairo_gl_dispatch_t *dispatch = &ctx->dispatch;
354
355     if  (!_cairo_gl_context_is_flushed (ctx))
356         _cairo_gl_composite_flush (ctx);
357
358     switch (ctx->operands[tex_unit].type) {
359     default:
360     case CAIRO_GL_OPERAND_COUNT:
361         ASSERT_NOT_REACHED;
362     case CAIRO_GL_OPERAND_NONE:
363         break;
364         /* fall through */
365     case CAIRO_GL_OPERAND_CONSTANT:
366         if (ctx->operands[tex_unit].constant.encode_as_attribute)
367             dispatch->DisableVertexAttribArray (CAIRO_GL_COLOR_ATTRIB_INDEX);
368         break;
369     case CAIRO_GL_OPERAND_TEXTURE:
370     case CAIRO_GL_OPERAND_GAUSSIAN:
371         dispatch->DisableVertexAttribArray (CAIRO_GL_TEXCOORD0_ATTRIB_INDEX + tex_unit);
372         if (ctx->operands[tex_unit].texture.use_atlas) {
373             dispatch->DisableVertexAttribArray (CAIRO_GL_START_COORD0_ATTRIB_INDEX + tex_unit);
374             dispatch->DisableVertexAttribArray (CAIRO_GL_STOP_COORD0_ATTRIB_INDEX + tex_unit);
375         }
376         break;
377     case CAIRO_GL_OPERAND_LINEAR_GRADIENT:
378     case CAIRO_GL_OPERAND_RADIAL_GRADIENT_A0:
379     case CAIRO_GL_OPERAND_RADIAL_GRADIENT_NONE:
380     case CAIRO_GL_OPERAND_RADIAL_GRADIENT_EXT:
381         dispatch->DisableVertexAttribArray (CAIRO_GL_TEXCOORD0_ATTRIB_INDEX + tex_unit);
382         break;
383     }
384
385     memset (&ctx->operands[tex_unit], 0, sizeof (cairo_gl_operand_t));
386 }
387
388 static void
389 _cairo_gl_set_operator (cairo_gl_context_t *ctx,
390                         cairo_operator_t    op,
391                         cairo_bool_t        component_alpha)
392 {
393     struct {
394         GLenum src;
395         GLenum dst;
396     } blend_factors[] = {
397         { GL_ZERO, GL_ZERO }, /* Clear */
398         { GL_ONE, GL_ZERO }, /* Source */
399         { GL_ONE, GL_ONE_MINUS_SRC_ALPHA }, /* Over */
400         { GL_DST_ALPHA, GL_ZERO }, /* In */
401         { GL_ONE_MINUS_DST_ALPHA, GL_ZERO }, /* Out */
402         { GL_DST_ALPHA, GL_ONE_MINUS_SRC_ALPHA }, /* Atop */
403
404         { GL_ZERO, GL_ONE }, /* Dest */
405         { GL_ONE_MINUS_DST_ALPHA, GL_ONE }, /* DestOver */
406         { GL_ZERO, GL_SRC_ALPHA }, /* DestIn */
407         { GL_ZERO, GL_ONE_MINUS_SRC_ALPHA }, /* DestOut */
408         { GL_ONE_MINUS_DST_ALPHA, GL_SRC_ALPHA }, /* DestAtop */
409
410         { GL_ONE_MINUS_DST_ALPHA, GL_ONE_MINUS_SRC_ALPHA }, /* Xor */
411         { GL_ONE, GL_ONE }, /* Add */
412     };
413     GLenum src_factor, dst_factor;
414
415     assert (op < ARRAY_LENGTH (blend_factors));
416     /* different dst and component_alpha changes cause flushes elsewhere */
417     if (ctx->current_operator != op)
418         _cairo_gl_composite_flush (ctx);
419     ctx->current_operator = op;
420
421     src_factor = blend_factors[op].src;
422     dst_factor = blend_factors[op].dst;
423
424     /* Even when the user requests CAIRO_CONTENT_COLOR, we use GL_RGBA
425      * due to texture filtering of GL_CLAMP_TO_BORDER.  So fix those
426      * bits in that case.
427      */
428     if (ctx->current_target->base.content == CAIRO_CONTENT_COLOR) {
429         if (src_factor == GL_ONE_MINUS_DST_ALPHA)
430             src_factor = GL_ZERO;
431         if (src_factor == GL_DST_ALPHA)
432             src_factor = GL_ONE;
433     }
434
435     if (component_alpha) {
436         if (dst_factor == GL_ONE_MINUS_SRC_ALPHA)
437             dst_factor = GL_ONE_MINUS_SRC_COLOR;
438         if (dst_factor == GL_SRC_ALPHA)
439             dst_factor = GL_SRC_COLOR;
440     }
441
442     if (ctx->current_target->base.content == CAIRO_CONTENT_ALPHA) {
443         /* cache BlendFunc, src factor and dst factor, alpha factor */
444         if (ctx->states_cache.src_color_factor != GL_ZERO ||
445            ctx->states_cache.dst_color_factor != GL_ZERO ||
446            ctx->states_cache.src_alpha_factor != src_factor ||
447            ctx->states_cache.dst_alpha_factor != dst_factor) {
448             ctx->dispatch.BlendFuncSeparate (GL_ZERO, GL_ZERO, src_factor, dst_factor);
449             ctx->states_cache.src_color_factor = GL_ZERO;
450             ctx->states_cache.dst_color_factor = GL_ZERO;
451             ctx->states_cache.src_alpha_factor = src_factor;
452             ctx->states_cache.dst_alpha_factor = dst_factor;
453         }
454     } else if (ctx->current_target->base.content == CAIRO_CONTENT_COLOR) {
455         if (ctx->states_cache.src_color_factor != src_factor ||
456             ctx->states_cache.dst_color_factor != dst_factor ||
457             ctx->states_cache.src_alpha_factor != GL_ONE ||
458             ctx->states_cache.dst_alpha_factor != GL_ONE) {
459             ctx->dispatch.BlendFuncSeparate (src_factor, dst_factor, GL_ONE, GL_ONE);
460             ctx->states_cache.src_color_factor = src_factor;
461             ctx->states_cache.dst_color_factor = dst_factor;
462             ctx->states_cache.src_alpha_factor = GL_ONE;
463             ctx->states_cache.dst_alpha_factor = GL_ONE;
464         }
465     } else {
466         if (ctx->states_cache.src_color_factor != src_factor ||
467             ctx->states_cache.dst_color_factor != dst_factor) {
468             ctx->dispatch.BlendFunc (src_factor, dst_factor);
469             ctx->states_cache.src_color_factor = src_factor;
470             ctx->states_cache.dst_color_factor = dst_factor;
471         }
472     }
473 }
474
475 static cairo_status_t
476 _cairo_gl_composite_begin_component_alpha  (cairo_gl_context_t *ctx,
477                                             cairo_gl_composite_t *setup)
478 {
479     cairo_gl_shader_t *pre_shader = NULL;
480     cairo_status_t status;
481
482     /* For CLEAR, cairo's rendering equation (quoting Owen's description in:
483      * http://lists.cairographics.org/archives/cairo/2005-August/004992.html)
484      * is:
485      *     mask IN clip ? src OP dest : dest
486      * or more simply:
487      *     mask IN CLIP ? 0 : dest
488      *
489      * where the ternary operator A ? B : C is (A * B) + ((1 - A) * C).
490      *
491      * The model we use in _cairo_gl_set_operator() is Render's:
492      *     src IN mask IN clip OP dest
493      * which would boil down to:
494      *     0 (bounded by the extents of the drawing).
495      *
496      * However, we can do a Render operation using an opaque source
497      * and DEST_OUT to produce:
498      *    1 IN mask IN clip DEST_OUT dest
499      * which is
500      *    mask IN clip ? 0 : dest
501      */
502     if (setup->op == CAIRO_OPERATOR_CLEAR) {
503         _cairo_gl_solid_operand_init (&setup->src, CAIRO_COLOR_WHITE);
504         setup->op = CAIRO_OPERATOR_DEST_OUT;
505     }
506
507     /*
508      * implements component-alpha %CAIRO_OPERATOR_OVER using two passes of
509      * the simpler operations %CAIRO_OPERATOR_DEST_OUT and %CAIRO_OPERATOR_ADD.
510      *
511      * From http://anholt.livejournal.com/32058.html:
512      *
513      * The trouble is that component-alpha rendering requires two different sources
514      * for blending: one for the source value to the blender, which is the
515      * per-channel multiplication of source and mask, and one for the source alpha
516      * for multiplying with the destination channels, which is the multiplication
517      * of the source channels by the mask alpha. So the equation for Over is:
518      *
519      * dst.A = src.A * mask.A + (1 - (src.A * mask.A)) * dst.A
520      * dst.R = src.R * mask.R + (1 - (src.A * mask.R)) * dst.R
521      * dst.G = src.G * mask.G + (1 - (src.A * mask.G)) * dst.G
522      * dst.B = src.B * mask.B + (1 - (src.A * mask.B)) * dst.B
523      *
524      * But we can do some simpler operations, right? How about PictOpOutReverse,
525      * which has a source factor of 0 and dest factor of (1 - source alpha). We
526      * can get the source alpha value (srca.X = src.A * mask.X) out of the texture
527      * blenders pretty easily. So we can do a component-alpha OutReverse, which
528      * gets us:
529      *
530      * dst.A = 0 + (1 - (src.A * mask.A)) * dst.A
531      * dst.R = 0 + (1 - (src.A * mask.R)) * dst.R
532      * dst.G = 0 + (1 - (src.A * mask.G)) * dst.G
533      * dst.B = 0 + (1 - (src.A * mask.B)) * dst.B
534      *
535      * OK. And if an op doesn't use the source alpha value for the destination
536      * factor, then we can do the channel multiplication in the texture blenders
537      * to get the source value, and ignore the source alpha that we wouldn't use.
538      * We've supported this in the Radeon driver for a long time. An example would
539      * be PictOpAdd, which does:
540      *
541      * dst.A = src.A * mask.A + dst.A
542      * dst.R = src.R * mask.R + dst.R
543      * dst.G = src.G * mask.G + dst.G
544      * dst.B = src.B * mask.B + dst.B
545      *
546      * Hey, this looks good! If we do a PictOpOutReverse and then a PictOpAdd right
547      * after it, we get:
548      *
549      * dst.A = src.A * mask.A + ((1 - (src.A * mask.A)) * dst.A)
550      * dst.R = src.R * mask.R + ((1 - (src.A * mask.R)) * dst.R)
551      * dst.G = src.G * mask.G + ((1 - (src.A * mask.G)) * dst.G)
552      * dst.B = src.B * mask.B + ((1 - (src.A * mask.B)) * dst.B)
553      *
554      * This two-pass trickery could be avoided using a new GL extension that
555      * lets two values come out of the shader and into the blend unit.
556      */
557     if (setup->op == CAIRO_OPERATOR_OVER) {
558         setup->op = CAIRO_OPERATOR_ADD;
559         status = _cairo_gl_get_shader_by_type (ctx,
560                                                &setup->src,
561                                                &setup->mask,
562                                                setup->spans,
563                                                CAIRO_GL_SHADER_IN_CA_SOURCE_ALPHA,
564                                                &pre_shader);
565         if (unlikely (status))
566             return status;
567     }
568
569     if (ctx->pre_shader != pre_shader)
570         _cairo_gl_composite_flush (ctx);
571     ctx->pre_shader = pre_shader;
572
573     return CAIRO_STATUS_SUCCESS;
574 }
575
576 static void
577 _scissor_to_doubles (cairo_gl_surface_t *surface,
578                      double x1, double y1,
579                      double x2, double y2)
580 {
581     double height;
582
583     cairo_gl_context_t *ctx = (cairo_gl_context_t *) cairo_surface_get_device ((cairo_surface_t *) surface);
584
585     height = y2 - y1;
586     if (_cairo_gl_surface_is_texture (surface) == FALSE)
587         y1 = surface->height - (y1 + height);
588     ctx->dispatch.Scissor (x1, y1, x2 - x1, height);
589 }
590
591 void
592 _cairo_gl_scissor_to_rectangle (cairo_gl_surface_t *surface,
593                        const cairo_rectangle_int_t *r)
594 {
595     _scissor_to_doubles (surface, r->x, r->y, r->x+r->width, r->y+r->height);
596 }
597
598 static void
599 _scissor_to_box (cairo_gl_surface_t     *surface,
600                  const cairo_box_t      *box)
601 {
602     double x1, y1, x2, y2;
603     _cairo_box_to_doubles (box, &x1, &y1, &x2, &y2);
604     _scissor_to_doubles (surface, x1, y1, x2, y2);
605 }
606
607 static cairo_bool_t
608 _cairo_gl_composite_setup_vbo (cairo_gl_context_t *ctx,
609                                unsigned int size_per_vertex)
610 {
611     cairo_bool_t vertex_size_changed = ctx->vertex_size != size_per_vertex;
612     if (vertex_size_changed) {
613         ctx->vertex_size = size_per_vertex;
614         _cairo_gl_composite_flush (ctx);
615     }
616
617     if (_cairo_gl_context_is_flushed (ctx)) {
618         ctx->dispatch.VertexAttribPointer (CAIRO_GL_VERTEX_ATTRIB_INDEX, 2,
619                                            GL_FLOAT, GL_FALSE, size_per_vertex,
620                                            ctx->vb);
621         ctx->dispatch.EnableVertexAttribArray (CAIRO_GL_VERTEX_ATTRIB_INDEX);
622     }
623
624     return vertex_size_changed;
625 }
626
627 static cairo_int_status_t
628 _cairo_gl_composite_setup_painted_clipping (cairo_gl_composite_t *setup,
629                                             cairo_gl_context_t *ctx,
630                                             int vertex_size,
631                                             cairo_bool_t clip_is_equal)
632 {
633     cairo_int_status_t status = CAIRO_INT_STATUS_SUCCESS;
634
635     cairo_gl_surface_t *dst = setup->dst;
636     cairo_clip_t *clip = setup->clip;
637     cairo_clip_t *old_clip = setup->dst->clip_on_stencil_buffer;
638
639     if (clip->num_boxes == 1 && clip->path == NULL) {
640         _scissor_to_box (dst, &clip->boxes[0]);
641         _enable_scissor_buffer (ctx);
642         goto disable_stencil_buffer_and_return;
643     }
644
645     if (! _cairo_gl_ensure_stencil (ctx, setup->dst)) {
646         status = CAIRO_INT_STATUS_UNSUPPORTED;
647         goto disable_stencil_buffer_and_return;
648     }
649
650     /* The clip is not rectangular, so use the stencil buffer. */
651     if (! ctx->states_cache.depth_mask ) {
652         ctx->dispatch.DepthMask (GL_TRUE);
653         ctx->states_cache.depth_mask = TRUE;
654     }
655
656     _enable_stencil_buffer (ctx);
657     _enable_scissor_buffer (ctx);
658     _cairo_gl_scissor_to_rectangle (dst, _cairo_clip_get_extents (clip));
659
660     if (clip_is_equal)
661         goto activate_stencil_buffer_and_return;
662
663       /* Clear the stencil buffer, but only the areas that we are
664        * going to be drawing to. */
665     if (old_clip) {
666         _cairo_clip_destroy (setup->dst->clip_on_stencil_buffer);
667     }
668
669     setup->dst->clip_on_stencil_buffer = _cairo_clip_copy (setup->clip);
670
671     ctx->dispatch.ClearStencil (0);
672     ctx->dispatch.Clear (GL_STENCIL_BUFFER_BIT);
673
674     ctx->dispatch.StencilOp (GL_REPLACE, GL_REPLACE, GL_REPLACE);
675     ctx->dispatch.StencilFunc (GL_EQUAL, 1, 0xffffffff);
676     ctx->dispatch.ColorMask (0, 0, 0, 0);
677
678     status = _cairo_gl_msaa_compositor_draw_clip (ctx, setup, clip);
679
680     if (unlikely (status)) {
681         ctx->dispatch.ColorMask (1, 1, 1, 1);
682         goto disable_stencil_buffer_and_return;
683     }
684
685     /* We want to only render to the stencil buffer, so draw everything now.
686        Flushing also unbinds the VBO, which we want to rebind for regular
687        drawing. */
688     _cairo_gl_composite_flush (ctx);
689     _cairo_gl_composite_setup_vbo (ctx, vertex_size);
690
691 activate_stencil_buffer_and_return:
692     ctx->dispatch.ColorMask (1, 1, 1, 1);
693
694     ctx->dispatch.StencilOp (GL_KEEP, GL_KEEP, GL_KEEP);
695     ctx->dispatch.StencilFunc (GL_EQUAL, 1, 0xffffffff);
696     return CAIRO_INT_STATUS_SUCCESS;
697
698 disable_stencil_buffer_and_return:
699     _disable_stencil_buffer (ctx);
700     return status;
701 }
702
703 static cairo_int_status_t
704 _cairo_gl_composite_setup_clipping (cairo_gl_composite_t *setup,
705                                     cairo_gl_context_t *ctx,
706                                     int vertex_size)
707 {
708     cairo_bool_t clip_region_changing = TRUE;
709     cairo_bool_t clip_is_equal = TRUE;
710
711     if (! _cairo_clip_equal (setup->dst->clip_on_stencil_buffer, setup->clip)) {
712         _cairo_gl_composite_flush (ctx);
713         clip_is_equal = FALSE;
714     }
715
716     if (! setup->clip && ! setup->clip_region && ! ctx->clip_region)
717         goto disable_all_clipping;
718
719     clip_region_changing = ! cairo_region_equal (ctx->clip_region, setup->clip_region);
720     if (! _cairo_gl_context_is_flushed (ctx) &&
721         clip_region_changing)
722         _cairo_gl_composite_flush (ctx);
723
724     assert (!setup->clip_region || !setup->clip);
725
726     /* setup->clip is only used by the msaa compositor and setup->clip_region
727      * only by the other compositors, so it's safe to wait to clean up obsolete
728      * clips. */
729     if (clip_region_changing) {
730         cairo_region_destroy (ctx->clip_region);
731         ctx->clip_region = cairo_region_reference (setup->clip_region);
732     }
733
734     /* For clip regions, we scissor right before drawing. */
735     if (setup->clip_region)
736         goto disable_all_clipping;
737
738     if (setup->clip)
739         return _cairo_gl_composite_setup_painted_clipping (setup, ctx,
740                                                            vertex_size,
741                                                            clip_is_equal);
742 disable_all_clipping:
743     _disable_stencil_buffer (ctx);
744     _disable_scissor_buffer (ctx);
745     return CAIRO_INT_STATUS_SUCCESS;
746 }
747
748 cairo_status_t
749 _cairo_gl_set_operands_and_operator (cairo_gl_composite_t *setup,
750                                      cairo_gl_context_t *ctx)
751 {
752     unsigned int dst_size, src_size, mask_size, vertex_size;
753     cairo_status_t status;
754     cairo_gl_shader_t *shader;
755     cairo_bool_t component_alpha;
756     cairo_bool_t vertex_size_changed;
757
758     component_alpha =
759         setup->mask.type == CAIRO_GL_OPERAND_TEXTURE &&
760         setup->mask.texture.attributes.has_component_alpha;
761
762     /* Do various magic for component alpha */
763     if (component_alpha) {
764         status = _cairo_gl_composite_begin_component_alpha (ctx, setup);
765         if (unlikely (status))
766             return status;
767      } else {
768         if (ctx->pre_shader) {
769             _cairo_gl_composite_flush (ctx);
770             ctx->pre_shader = NULL;
771         }
772     }
773
774     status = _cairo_gl_get_shader_by_type (ctx,
775                                            &setup->src,
776                                            &setup->mask,
777                                            setup->spans,
778                                            component_alpha ?
779                                            CAIRO_GL_SHADER_IN_CA_SOURCE :
780                                            CAIRO_GL_SHADER_IN_NORMAL,
781                                            &shader);
782     if (unlikely (status)) {
783         ctx->pre_shader = NULL;
784         return status;
785     }
786     if (ctx->current_shader != shader)
787         _cairo_gl_composite_flush (ctx);
788
789     status = CAIRO_STATUS_SUCCESS;
790
791     dst_size = 2 * sizeof (GLfloat);
792     src_size = _cairo_gl_operand_get_vertex_size (&setup->src);
793     mask_size = _cairo_gl_operand_get_vertex_size (&setup->mask);
794     vertex_size = dst_size + src_size + mask_size;
795
796     if (setup->spans)
797         vertex_size += sizeof (GLfloat);
798
799     if (setup->src.type != CAIRO_GL_OPERAND_CONSTANT ||
800         ! setup->src.constant.encode_as_attribute)
801         _cairo_gl_context_setup_spans (ctx,
802                                        setup->spans,
803                                        setup->src.type == CAIRO_GL_OPERAND_CONSTANT ||
804                                        ! setup->src.constant.encode_as_attribute,
805                                        vertex_size,
806                                        dst_size + src_size + mask_size);
807
808     vertex_size_changed = _cairo_gl_composite_setup_vbo (ctx, vertex_size);
809
810     _cairo_gl_context_setup_operand (ctx, CAIRO_GL_TEX_SOURCE, &setup->src,
811                                      dst_size, vertex_size_changed);
812     _cairo_gl_context_setup_operand (ctx, CAIRO_GL_TEX_MASK, &setup->mask,
813                                      dst_size + src_size, vertex_size_changed);
814
815     _cairo_gl_set_operator (ctx, setup->op, component_alpha);
816
817     if (_cairo_gl_context_is_flushed (ctx)) {
818         if (ctx->pre_shader) {
819             _cairo_gl_set_shader (ctx, ctx->pre_shader);
820             _cairo_gl_composite_bind_to_shader (ctx, setup);
821         }
822         _cairo_gl_set_shader (ctx, shader);
823         _cairo_gl_composite_bind_to_shader (ctx, setup);
824     }
825
826     return status;
827 }
828
829 cairo_status_t
830 _cairo_gl_composite_begin (cairo_gl_composite_t *setup,
831                            cairo_gl_context_t **ctx_out)
832 {
833     cairo_gl_context_t *ctx;
834     cairo_status_t status;
835
836     assert (setup->dst);
837
838     status = _cairo_gl_context_acquire (setup->dst->base.device, &ctx);
839     if (unlikely (status))
840         return status;
841
842     setup->dst->content_cleared = FALSE;
843
844     _cairo_gl_context_set_destination (ctx, setup->dst, setup->multisample);
845     if (ctx->states_cache.blend_enabled == FALSE) {
846         ctx->dispatch.Enable (GL_BLEND);
847         ctx->states_cache.blend_enabled = TRUE;
848     }
849     status = _cairo_gl_set_operands_and_operator (setup, ctx);
850     if (unlikely (status))
851         goto FAIL;
852
853     status = _cairo_gl_composite_setup_clipping (setup, ctx, ctx->vertex_size);
854     if (unlikely (status))
855         goto FAIL;
856
857     *ctx_out = ctx;
858
859 FAIL:
860     if (unlikely (status))
861         status = _cairo_gl_context_release (ctx, status);
862
863     return status;
864 }
865
866 static inline void
867 _cairo_gl_composite_draw_tristrip (cairo_gl_context_t *ctx)
868 {
869     cairo_array_t* indices = &ctx->tristrip_indices;
870     const unsigned short *indices_array = _cairo_array_index_const (indices, 0);
871
872     if (ctx->pre_shader) {
873         cairo_gl_shader_t *prev_shader = ctx->current_shader;
874
875         _cairo_gl_set_shader (ctx, ctx->pre_shader);
876         _cairo_gl_set_operator (ctx, CAIRO_OPERATOR_DEST_OUT, TRUE);
877         ctx->dispatch.DrawElements (GL_TRIANGLE_STRIP, _cairo_array_num_elements (indices), GL_UNSIGNED_SHORT, indices_array);
878
879         _cairo_gl_set_shader (ctx, prev_shader);
880         _cairo_gl_set_operator (ctx, CAIRO_OPERATOR_ADD, TRUE);
881     }
882
883     ctx->dispatch.DrawElements (GL_TRIANGLE_STRIP, _cairo_array_num_elements (indices), GL_UNSIGNED_SHORT, indices_array);
884     _cairo_array_truncate (indices, 0);
885 }
886
887 static inline void
888 _cairo_gl_composite_draw_line (cairo_gl_context_t *ctx)
889 {
890     GLenum type = GL_LINE_STRIP;
891     cairo_array_t* indices = &ctx->tristrip_indices;
892     const unsigned short *indices_array = _cairo_array_index_const (indices, 0);
893
894     if (ctx->draw_mode == CAIRO_GL_LINES)
895         type = GL_LINES;
896
897     if (ctx->pre_shader) {
898         cairo_gl_shader_t *prev_shader = ctx->current_shader;
899
900         _cairo_gl_set_shader (ctx, ctx->pre_shader);
901         _cairo_gl_set_operator (ctx, CAIRO_OPERATOR_DEST_OUT, TRUE);
902         ctx->dispatch.DrawElements (type, _cairo_array_num_elements (indices), GL_UNSIGNED_SHORT, indices_array);
903
904         _cairo_gl_set_shader (ctx, prev_shader);
905         _cairo_gl_set_operator (ctx, CAIRO_OPERATOR_ADD, TRUE);
906     }
907
908     ctx->dispatch.DrawElements (type, _cairo_array_num_elements (indices), GL_UNSIGNED_SHORT, indices_array);
909     _cairo_array_truncate (indices, 0);
910 }
911
912 static inline void
913 _cairo_gl_composite_draw_triangles (cairo_gl_context_t *ctx,
914                                     unsigned int count)
915 {
916     if (! ctx->pre_shader) {
917         ctx->dispatch.DrawArrays (GL_TRIANGLES, 0, count);
918     } else {
919         cairo_gl_shader_t *prev_shader = ctx->current_shader;
920
921         _cairo_gl_set_shader (ctx, ctx->pre_shader);
922         _cairo_gl_set_operator (ctx, CAIRO_OPERATOR_DEST_OUT, TRUE);
923         ctx->dispatch.DrawArrays (GL_TRIANGLES, 0, count);
924
925         _cairo_gl_set_shader (ctx, prev_shader);
926         _cairo_gl_set_operator (ctx, CAIRO_OPERATOR_ADD, TRUE);
927         ctx->dispatch.DrawArrays (GL_TRIANGLES, 0, count);
928     }
929 }
930
931 static void
932 _cairo_gl_composite_draw_triangles_with_clip_region (cairo_gl_context_t *ctx,
933                                                      unsigned int count)
934 {
935     int i, num_rectangles;
936
937     if (!ctx->clip_region) {
938         _cairo_gl_composite_draw_triangles (ctx, count);
939         return;
940     }
941
942     num_rectangles = cairo_region_num_rectangles (ctx->clip_region);
943     for (i = 0; i < num_rectangles; i++) {
944         cairo_rectangle_int_t rect;
945
946         cairo_region_get_rectangle (ctx->clip_region, i, &rect);
947
948         _cairo_gl_scissor_to_rectangle (ctx->current_target, &rect);
949         _enable_scissor_buffer (ctx);
950         _cairo_gl_composite_draw_triangles (ctx, count);
951     }
952 }
953
954 static void
955 _cairo_gl_composite_unmap_vertex_buffer (cairo_gl_context_t *ctx)
956 {
957     ctx->vb_offset = 0;
958 }
959
960 void
961 _cairo_gl_composite_flush (cairo_gl_context_t *ctx)
962 {
963     unsigned int count;
964     int i;
965
966     if (_cairo_gl_context_is_flushed (ctx))
967         return;
968
969     count = ctx->vb_offset / ctx->vertex_size;
970     _cairo_gl_composite_unmap_vertex_buffer (ctx);
971
972     if (ctx->primitive_type == CAIRO_GL_PRIMITIVE_TYPE_TRISTRIPS) {
973         if (ctx->draw_mode == CAIRO_GL_LINE_STRIP ||
974             ctx->draw_mode == CAIRO_GL_LINES)
975             _cairo_gl_composite_draw_line (ctx);
976         else
977             _cairo_gl_composite_draw_tristrip (ctx);
978     } else {
979         assert (ctx->primitive_type == CAIRO_GL_PRIMITIVE_TYPE_TRIANGLES);
980         _cairo_gl_composite_draw_triangles_with_clip_region (ctx, count);
981     }
982
983     for (i = 0; i < ARRAY_LENGTH (ctx->glyph_cache); i++)
984         _cairo_gl_glyph_cache_unlock (&ctx->glyph_cache[i]);
985
986     _cairo_gl_image_cache_unlock (ctx);
987 }
988
989 static void
990 _cairo_gl_composite_prepare_buffer (cairo_gl_context_t *ctx,
991                                     unsigned int n_vertices,
992                                     cairo_gl_primitive_type_t primitive_type)
993 {
994     if (ctx->primitive_type != primitive_type) {
995         _cairo_gl_composite_flush (ctx);
996         ctx->primitive_type = primitive_type;
997     }
998
999     if (ctx->vb_offset + n_vertices * ctx->vertex_size > CAIRO_GL_VBO_SIZE)
1000         _cairo_gl_composite_flush (ctx);
1001 }
1002
1003 static inline void
1004 _cairo_gl_composite_emit_vertex (cairo_gl_context_t *ctx,
1005                                  GLfloat x, GLfloat y)
1006 {
1007     GLfloat *vb = (GLfloat *) (void *) &ctx->vb[ctx->vb_offset];
1008
1009     *vb++ = x;
1010     *vb++ = y;
1011
1012     _cairo_gl_operand_emit (&ctx->operands[CAIRO_GL_TEX_SOURCE], &vb, x, y);
1013     _cairo_gl_operand_emit (&ctx->operands[CAIRO_GL_TEX_MASK  ], &vb, x, y);
1014
1015     ctx->vb_offset += ctx->vertex_size;
1016 }
1017
1018 static inline void
1019 _cairo_gl_composite_emit_alpha_vertex (cairo_gl_context_t *ctx,
1020                                        GLfloat x, GLfloat y, uint8_t alpha)
1021 {
1022     GLfloat *vb = (GLfloat *) (void *) &ctx->vb[ctx->vb_offset];
1023     union fi {
1024         float f;
1025         GLbyte bytes[4];
1026     } fi;
1027
1028     *vb++ = x;
1029     *vb++ = y;
1030
1031     _cairo_gl_operand_emit (&ctx->operands[CAIRO_GL_TEX_SOURCE], &vb, x, y);
1032     _cairo_gl_operand_emit (&ctx->operands[CAIRO_GL_TEX_MASK  ], &vb, x, y);
1033
1034     fi.bytes[0] = 0;
1035     fi.bytes[1] = 0;
1036     fi.bytes[2] = 0;
1037     fi.bytes[3] = alpha;
1038     *vb++ = fi.f;
1039
1040     ctx->vb_offset += ctx->vertex_size;
1041 }
1042
1043 static void
1044 _cairo_gl_composite_emit_point (cairo_gl_context_t      *ctx,
1045                                 const cairo_point_t     *point)
1046 {
1047     _cairo_gl_composite_emit_vertex (ctx,
1048                                      _cairo_fixed_to_double (point->x),
1049                                      _cairo_fixed_to_double (point->y));
1050 }
1051
1052 static void
1053 _cairo_gl_composite_emit_int (cairo_gl_context_t *ctx,
1054                               int x, int y)
1055 {
1056     float fx = x;
1057     float fy = y;
1058
1059     _cairo_gl_composite_emit_vertex (ctx, fx, fy);
1060 }
1061
1062 static void
1063 _cairo_gl_composite_emit_rect (cairo_gl_context_t *ctx,
1064                                GLfloat x1, GLfloat y1,
1065                                GLfloat x2, GLfloat y2)
1066 {
1067     _cairo_gl_composite_prepare_buffer (ctx, 6,
1068                                         CAIRO_GL_PRIMITIVE_TYPE_TRIANGLES);
1069
1070     _cairo_gl_composite_emit_vertex (ctx, x1, y1);
1071     _cairo_gl_composite_emit_vertex (ctx, x2, y1);
1072     _cairo_gl_composite_emit_vertex (ctx, x1, y2);
1073
1074     _cairo_gl_composite_emit_vertex (ctx, x2, y1);
1075     _cairo_gl_composite_emit_vertex (ctx, x2, y2);
1076     _cairo_gl_composite_emit_vertex (ctx, x1, y2);
1077 }
1078
1079 cairo_gl_emit_rect_t
1080 _cairo_gl_context_choose_emit_rect (cairo_gl_context_t *ctx)
1081 {
1082     return _cairo_gl_composite_emit_rect;
1083 }
1084
1085 void
1086 _cairo_gl_context_emit_rect (cairo_gl_context_t *ctx,
1087                              GLfloat x1, GLfloat y1,
1088                              GLfloat x2, GLfloat y2)
1089 {
1090     _cairo_gl_composite_emit_rect (ctx, x1, y1, x2, y2);
1091 }
1092
1093 static void
1094 _cairo_gl_composite_emit_span (cairo_gl_context_t *ctx,
1095                                GLfloat x1, GLfloat y1,
1096                                GLfloat x2, GLfloat y2,
1097                                uint8_t alpha)
1098 {
1099     if (ctx->draw_mode != CAIRO_GL_VERTEX) {
1100         _cairo_gl_composite_flush (ctx);
1101         ctx->draw_mode = CAIRO_GL_VERTEX;
1102     }
1103
1104     _cairo_gl_composite_prepare_buffer (ctx, 6,
1105                                         CAIRO_GL_PRIMITIVE_TYPE_TRIANGLES);
1106
1107     _cairo_gl_composite_emit_alpha_vertex (ctx, x1, y1, alpha);
1108     _cairo_gl_composite_emit_alpha_vertex (ctx, x2, y1, alpha);
1109     _cairo_gl_composite_emit_alpha_vertex (ctx, x1, y2, alpha);
1110
1111     _cairo_gl_composite_emit_alpha_vertex (ctx, x2, y1, alpha);
1112     _cairo_gl_composite_emit_alpha_vertex (ctx, x2, y2, alpha);
1113     _cairo_gl_composite_emit_alpha_vertex (ctx, x1, y2, alpha);
1114 }
1115
1116 static void
1117 _cairo_gl_composite_emit_solid_span (cairo_gl_context_t *ctx,
1118                                      GLfloat x1, GLfloat y1,
1119                                      GLfloat x2, GLfloat y2,
1120                                      uint8_t alpha)
1121 {
1122     GLfloat *v;
1123     int src_use_atlas = 0;
1124     int mask_use_atlas = 0;
1125     union fi {
1126         float f;
1127         GLbyte bytes[4];
1128     } fi;
1129
1130     _cairo_gl_composite_prepare_buffer (ctx, 6,
1131                                         CAIRO_GL_PRIMITIVE_TYPE_TRIANGLES);
1132
1133     if ((ctx->operands[CAIRO_GL_TEX_SOURCE].type == CAIRO_GL_OPERAND_TEXTURE ||
1134         ctx->operands[CAIRO_GL_TEX_SOURCE].type == CAIRO_GL_OPERAND_GAUSSIAN) &&
1135         ctx->operands[CAIRO_GL_TEX_SOURCE].texture.use_atlas)
1136         src_use_atlas = TRUE;
1137     if ((ctx->operands[CAIRO_GL_TEX_MASK].type == CAIRO_GL_OPERAND_TEXTURE ||
1138         ctx->operands[CAIRO_GL_TEX_MASK].type == CAIRO_GL_OPERAND_GAUSSIAN) &&
1139         ctx->operands[CAIRO_GL_TEX_MASK].texture.use_atlas)
1140         mask_use_atlas = TRUE;
1141
1142     v = (GLfloat *) (void *) &ctx->vb[ctx->vb_offset];
1143
1144     v[15 + 20*src_use_atlas + 20*mask_use_atlas] =
1145     v[ 6 +  8*src_use_atlas +  8*mask_use_atlas] =
1146     v[ 0                                       ] = x1;
1147     v[10 + 12*src_use_atlas + 12*mask_use_atlas] =
1148     v[ 4 +  4*src_use_atlas +  4*mask_use_atlas] =
1149     v[ 1                                       ] = y1;
1150     v[12 + 16*src_use_atlas + 16*mask_use_atlas] =
1151     v[ 9 + 12*src_use_atlas + 12*mask_use_atlas] =
1152     v[ 3 +  4*src_use_atlas +  4*mask_use_atlas] = x2;
1153     v[16 + 20*src_use_atlas + 20*mask_use_atlas] =
1154     v[13 + 16*src_use_atlas + 16*mask_use_atlas] =
1155     v[ 7 +  8*src_use_atlas +  8*mask_use_atlas] = y2;
1156
1157     fi.bytes[0] = 0;
1158     fi.bytes[1] = 0;
1159     fi.bytes[2] = 0;
1160     fi.bytes[3] = alpha;
1161     v[17 + 24*src_use_atlas + 24*mask_use_atlas] =
1162     v[14 + 20*src_use_atlas + 20*mask_use_atlas] =
1163     v[11 + 16*src_use_atlas + 16*mask_use_atlas] =
1164     v[ 8 + 12*src_use_atlas + 12*mask_use_atlas] =
1165     v[ 5 +  8*src_use_atlas +  8*mask_use_atlas] =
1166     v[ 2 +  4*src_use_atlas +  4*mask_use_atlas ] = fi.f;
1167
1168     if (src_use_atlas) {
1169         v[ 2                                       ] =
1170         v[ 5 +  4*src_use_atlas +  4*mask_use_atlas] =
1171         v[ 8 +  8*src_use_atlas +  8*mask_use_atlas] =
1172         v[11 + 12*src_use_atlas + 12*mask_use_atlas] =
1173         v[14 + 16*src_use_atlas + 16*mask_use_atlas] =
1174         v[17 + 20*src_use_atlas + 20*mask_use_atlas] =
1175         ctx->operands[CAIRO_GL_TEX_SOURCE].texture.p1.x;
1176
1177         v[ 3                                       ] =
1178         v[ 6 +  4*src_use_atlas +  4*mask_use_atlas] =
1179         v[ 9 +  8*src_use_atlas +  8*mask_use_atlas] =
1180         v[12 + 12*src_use_atlas + 12*mask_use_atlas] =
1181         v[15 + 16*src_use_atlas + 16*mask_use_atlas] =
1182         v[18 + 20*src_use_atlas + 20*mask_use_atlas] =
1183         ctx->operands[CAIRO_GL_TEX_SOURCE].texture.p1.y;
1184
1185         v[ 4                                       ] =
1186         v[ 7 +  4*src_use_atlas +  4*mask_use_atlas] =
1187         v[10 +  8*src_use_atlas +  8*mask_use_atlas] =
1188         v[13 + 12*src_use_atlas + 12*mask_use_atlas] =
1189         v[16 + 16*src_use_atlas + 16*mask_use_atlas] =
1190         v[19 + 20*src_use_atlas + 20*mask_use_atlas] =
1191         ctx->operands[CAIRO_GL_TEX_SOURCE].texture.p2.x;
1192
1193         v[ 5                                       ] =
1194         v[ 8 +  4*src_use_atlas +  4*mask_use_atlas] =
1195         v[11 +  8*src_use_atlas +  8*mask_use_atlas] =
1196         v[14 + 12*src_use_atlas + 12*mask_use_atlas] =
1197         v[17 + 16*src_use_atlas + 16*mask_use_atlas] =
1198         v[20 + 20*src_use_atlas + 20*mask_use_atlas] =
1199         ctx->operands[CAIRO_GL_TEX_SOURCE].texture.p2.y;
1200     }
1201
1202     if (mask_use_atlas) {
1203         v[ 2 +  4*src_use_atlas                    ] =
1204         v[ 5 +  8*src_use_atlas +  4*mask_use_atlas] =
1205         v[ 8 + 12*src_use_atlas +  8*mask_use_atlas] =
1206         v[11 + 16*src_use_atlas + 12*mask_use_atlas] =
1207         v[14 + 20*src_use_atlas + 16*mask_use_atlas] =
1208         v[17 + 24*src_use_atlas + 20*mask_use_atlas] =
1209         ctx->operands[CAIRO_GL_TEX_MASK].texture.p1.x;
1210
1211         v[ 3 +  4*src_use_atlas                    ] =
1212         v[ 6 +  4*src_use_atlas +  4*mask_use_atlas] =
1213         v[ 9 +  8*src_use_atlas +  8*mask_use_atlas] =
1214         v[12 + 12*src_use_atlas + 12*mask_use_atlas] =
1215         v[15 + 16*src_use_atlas + 16*mask_use_atlas] =
1216         v[18 + 20*src_use_atlas + 20*mask_use_atlas] =
1217         ctx->operands[CAIRO_GL_TEX_MASK].texture.p1.y;
1218
1219         v[ 4 +  4*src_use_atlas                    ] =
1220         v[ 7 +  4*src_use_atlas +  4*mask_use_atlas] =
1221         v[10 +  8*src_use_atlas +  8*mask_use_atlas] =
1222         v[13 + 12*src_use_atlas + 12*mask_use_atlas] =
1223         v[16 + 16*src_use_atlas + 16*mask_use_atlas] =
1224         v[19 + 20*src_use_atlas + 20*mask_use_atlas] =
1225         ctx->operands[CAIRO_GL_TEX_MASK].texture.p2.x;
1226
1227         v[ 5 +  4*src_use_atlas                    ] =
1228         v[ 8 +  4*src_use_atlas +  4*mask_use_atlas] =
1229         v[11 +  8*src_use_atlas +  8*mask_use_atlas] =
1230         v[14 + 12*src_use_atlas + 12*mask_use_atlas] =
1231         v[17 + 16*src_use_atlas + 16*mask_use_atlas] =
1232         v[20 + 20*src_use_atlas + 20*mask_use_atlas] =
1233         ctx->operands[CAIRO_GL_TEX_MASK].texture.p2.y;
1234     }
1235
1236     ctx->vb_offset += 6*(3 + 4*src_use_atlas + 4*mask_use_atlas) * sizeof(GLfloat);
1237 }
1238
1239 cairo_gl_emit_span_t
1240 _cairo_gl_context_choose_emit_span (cairo_gl_context_t *ctx)
1241 {
1242     if (ctx->operands[CAIRO_GL_TEX_MASK].type != CAIRO_GL_OPERAND_NONE) {
1243             switch (ctx->operands[CAIRO_GL_TEX_MASK].type) {
1244             default:
1245             case CAIRO_GL_OPERAND_COUNT:
1246                     ASSERT_NOT_REACHED;
1247             case CAIRO_GL_OPERAND_NONE:
1248             case CAIRO_GL_OPERAND_CONSTANT:
1249                     break;
1250
1251             case CAIRO_GL_OPERAND_LINEAR_GRADIENT:
1252             case CAIRO_GL_OPERAND_RADIAL_GRADIENT_A0:
1253             case CAIRO_GL_OPERAND_RADIAL_GRADIENT_NONE:
1254             case CAIRO_GL_OPERAND_RADIAL_GRADIENT_EXT:
1255                     if (!ctx->operands[CAIRO_GL_TEX_MASK].gradient.texgen)
1256                             return _cairo_gl_composite_emit_span;
1257                     break;
1258
1259             case CAIRO_GL_OPERAND_TEXTURE:
1260             case CAIRO_GL_OPERAND_GAUSSIAN:
1261                     if (!ctx->operands[CAIRO_GL_TEX_MASK].texture.texgen)
1262                             return _cairo_gl_composite_emit_span;
1263                     break;
1264             }
1265     }
1266
1267     switch (ctx->operands[CAIRO_GL_TEX_SOURCE].type) {
1268     default:
1269     case CAIRO_GL_OPERAND_COUNT:
1270         ASSERT_NOT_REACHED;
1271     case CAIRO_GL_OPERAND_NONE:
1272     case CAIRO_GL_OPERAND_CONSTANT:
1273         break;
1274
1275     case CAIRO_GL_OPERAND_LINEAR_GRADIENT:
1276     case CAIRO_GL_OPERAND_RADIAL_GRADIENT_A0:
1277     case CAIRO_GL_OPERAND_RADIAL_GRADIENT_NONE:
1278     case CAIRO_GL_OPERAND_RADIAL_GRADIENT_EXT:
1279         if (!ctx->operands[CAIRO_GL_TEX_SOURCE].gradient.texgen)
1280                 return _cairo_gl_composite_emit_span;
1281         break;
1282
1283     case CAIRO_GL_OPERAND_TEXTURE:
1284     case CAIRO_GL_OPERAND_GAUSSIAN:
1285         if (!ctx->operands[CAIRO_GL_TEX_SOURCE].texture.texgen)
1286                 return _cairo_gl_composite_emit_span;
1287     }
1288
1289     return _cairo_gl_composite_emit_solid_span;
1290 }
1291
1292 static inline void
1293 _cairo_gl_composite_emit_glyph_vertex (cairo_gl_context_t *ctx,
1294                                        GLfloat x, GLfloat y,
1295                                        GLfloat glyph_x, GLfloat glyph_y)
1296 {
1297     GLfloat *vb = (GLfloat *) (void *) &ctx->vb[ctx->vb_offset];
1298
1299     *vb++ = x;
1300     *vb++ = y;
1301
1302     _cairo_gl_operand_emit (&ctx->operands[CAIRO_GL_TEX_SOURCE], &vb, x, y);
1303
1304     *vb++ = glyph_x;
1305     *vb++ = glyph_y;
1306
1307     ctx->vb_offset += ctx->vertex_size;
1308 }
1309
1310 static inline void
1311 _cairo_gl_composite_emit_color_glyph_vertex (cairo_gl_context_t *ctx,
1312                                                                                         GLfloat x, GLfloat y,
1313                                                                                         GLfloat glyph_x, GLfloat glyph_y)
1314 {
1315         GLfloat *vb = (GLfloat *) (void *) &ctx->vb[ctx->vb_offset];
1316
1317         *vb++ = x;
1318         *vb++ = y;
1319         *vb++ = glyph_x;
1320         *vb++ = glyph_y;
1321
1322         ctx->vb_offset += ctx->vertex_size;
1323 }
1324
1325 static void
1326 _cairo_gl_composite_emit_glyph (cairo_gl_context_t *ctx,
1327                                 GLfloat x1, GLfloat y1,
1328                                 GLfloat x2, GLfloat y2,
1329                                 GLfloat glyph_x1, GLfloat glyph_y1,
1330                                 GLfloat glyph_x2, GLfloat glyph_y2)
1331 {
1332     if (ctx->draw_mode != CAIRO_GL_VERTEX) {
1333         _cairo_gl_composite_flush (ctx);
1334         ctx->draw_mode = CAIRO_GL_VERTEX;
1335     }
1336
1337     _cairo_gl_composite_prepare_buffer (ctx, 6,
1338                                         CAIRO_GL_PRIMITIVE_TYPE_TRIANGLES);
1339
1340     _cairo_gl_composite_emit_glyph_vertex (ctx, x1, y1, glyph_x1, glyph_y1);
1341     _cairo_gl_composite_emit_glyph_vertex (ctx, x2, y1, glyph_x2, glyph_y1);
1342     _cairo_gl_composite_emit_glyph_vertex (ctx, x1, y2, glyph_x1, glyph_y2);
1343
1344     _cairo_gl_composite_emit_glyph_vertex (ctx, x2, y1, glyph_x2, glyph_y1);
1345     _cairo_gl_composite_emit_glyph_vertex (ctx, x2, y2, glyph_x2, glyph_y2);
1346     _cairo_gl_composite_emit_glyph_vertex (ctx, x1, y2, glyph_x1, glyph_y2);
1347 }
1348
1349 static void
1350 _cairo_gl_composite_emit_color_glyph (cairo_gl_context_t *ctx,
1351                                                                 GLfloat x1, GLfloat y1,
1352                                                                 GLfloat x2, GLfloat y2,
1353                                                                 GLfloat glyph_x1, GLfloat glyph_y1,
1354                                                                 GLfloat glyph_x2, GLfloat glyph_y2)
1355 {
1356         if (ctx->draw_mode != CAIRO_GL_VERTEX) {
1357         _cairo_gl_composite_flush (ctx);
1358         ctx->draw_mode = CAIRO_GL_VERTEX;
1359         }
1360
1361         _cairo_gl_composite_prepare_buffer (ctx, 6,
1362                                                                                 CAIRO_GL_PRIMITIVE_TYPE_TRIANGLES);
1363
1364         _cairo_gl_composite_emit_color_glyph_vertex (ctx, x1, y1, glyph_x1, glyph_y1);
1365         _cairo_gl_composite_emit_color_glyph_vertex (ctx, x2, y1, glyph_x2, glyph_y1);
1366         _cairo_gl_composite_emit_color_glyph_vertex (ctx, x1, y2, glyph_x1, glyph_y2);
1367
1368         _cairo_gl_composite_emit_color_glyph_vertex (ctx, x2, y1, glyph_x2, glyph_y1);
1369         _cairo_gl_composite_emit_color_glyph_vertex (ctx, x2, y2, glyph_x2, glyph_y2);
1370         _cairo_gl_composite_emit_color_glyph_vertex (ctx, x1, y2, glyph_x1, glyph_y2);
1371 }
1372
1373 static void
1374 _cairo_gl_composite_emit_solid_glyph (cairo_gl_context_t *ctx,
1375                                       GLfloat x1, GLfloat y1,
1376                                       GLfloat x2, GLfloat y2,
1377                                       GLfloat glyph_x1, GLfloat glyph_y1,
1378                                       GLfloat glyph_x2, GLfloat glyph_y2)
1379 {
1380     GLfloat *v;
1381
1382     _cairo_gl_composite_prepare_buffer (ctx, 6,
1383                                         CAIRO_GL_PRIMITIVE_TYPE_TRIANGLES);
1384
1385     v = (GLfloat *) (void *) &ctx->vb[ctx->vb_offset];
1386
1387     v[20] = v[ 8] = v[0] = x1;
1388     v[13] = v[ 5] = v[1] = y1;
1389     v[22] = v[10] = v[2] = glyph_x1;
1390     v[15] = v[ 7] = v[3] = glyph_y1;
1391
1392     v[16] = v[12] = v[4] = x2;
1393     v[18] = v[14] = v[6] = glyph_x2;
1394
1395     v[21] = v[17] = v[ 9] = y2;
1396     v[23] = v[19] = v[11] = glyph_y2;
1397
1398     ctx->vb_offset += 4 * 6 * sizeof (GLfloat);
1399 }
1400
1401 cairo_gl_emit_glyph_t
1402 _cairo_gl_context_choose_emit_glyph (cairo_gl_context_t *ctx,
1403                                                                         const cairo_bool_t is_color_glyph)
1404 {
1405
1406         if ( is_color_glyph) {
1407         /* color glyph ignore all source and mask */
1408         return _cairo_gl_composite_emit_color_glyph;
1409         }
1410
1411     switch (ctx->operands[CAIRO_GL_TEX_SOURCE].type) {
1412     default:
1413     case CAIRO_GL_OPERAND_COUNT:
1414         ASSERT_NOT_REACHED;
1415     case CAIRO_GL_OPERAND_NONE:
1416     case CAIRO_GL_OPERAND_CONSTANT:
1417         if (! ctx->operands[CAIRO_GL_TEX_SOURCE].constant.encode_as_attribute)
1418             return _cairo_gl_composite_emit_solid_glyph;
1419
1420     case CAIRO_GL_OPERAND_LINEAR_GRADIENT:
1421     case CAIRO_GL_OPERAND_RADIAL_GRADIENT_A0:
1422     case CAIRO_GL_OPERAND_RADIAL_GRADIENT_NONE:
1423     case CAIRO_GL_OPERAND_RADIAL_GRADIENT_EXT:
1424     case CAIRO_GL_OPERAND_TEXTURE:
1425     case CAIRO_GL_OPERAND_GAUSSIAN:
1426         return _cairo_gl_composite_emit_glyph;
1427     }
1428 }
1429
1430 void
1431 _cairo_gl_composite_fini (cairo_gl_composite_t *setup)
1432 {
1433     _cairo_gl_operand_destroy (&setup->src);
1434     _cairo_gl_operand_destroy (&setup->mask);
1435 }
1436
1437 cairo_status_t
1438 _cairo_gl_composite_set_operator (cairo_gl_composite_t *setup,
1439                                   cairo_operator_t op,
1440                                   cairo_bool_t assume_component_alpha)
1441 {
1442     if (assume_component_alpha) {
1443         if (op != CAIRO_OPERATOR_CLEAR &&
1444             op != CAIRO_OPERATOR_OVER &&
1445             op != CAIRO_OPERATOR_ADD)
1446             return UNSUPPORTED ("unsupported component alpha operator");
1447     } else {
1448         if (! _cairo_gl_operator_is_supported (op))
1449             return UNSUPPORTED ("unsupported operator");
1450     }
1451
1452     setup->op = op;
1453     return CAIRO_STATUS_SUCCESS;
1454 }
1455
1456 cairo_status_t
1457 _cairo_gl_composite_init (cairo_gl_composite_t *setup,
1458                           cairo_operator_t op,
1459                           cairo_gl_surface_t *dst,
1460                           cairo_bool_t assume_component_alpha)
1461 {
1462     cairo_status_t status;
1463
1464     memset (setup, 0, sizeof (cairo_gl_composite_t));
1465
1466     status = _cairo_gl_composite_set_operator (setup, op,
1467                                                assume_component_alpha);
1468     if (status)
1469         return status;
1470
1471     setup->dst = dst;
1472     setup->clip_region = dst->clip_region;
1473
1474     return CAIRO_STATUS_SUCCESS;
1475 }
1476
1477 static cairo_int_status_t
1478 _cairo_gl_composite_append_vertex_indices (cairo_gl_context_t   *ctx,
1479                                            int                   number_of_new_indices,
1480                                            cairo_bool_t          is_connected)
1481 {
1482     cairo_int_status_t status = CAIRO_INT_STATUS_SUCCESS;
1483     cairo_array_t *indices = &ctx->tristrip_indices;
1484     int number_of_indices = _cairo_array_num_elements (indices);
1485     unsigned short current_vertex_index = 0;
1486     int i;
1487
1488     assert (number_of_new_indices > 0);
1489
1490     /* If any preexisting triangle triangle strip indices exist on this
1491        context, we insert a set of degenerate triangles from the last
1492        preexisting vertex to our first one. */
1493     if (number_of_indices > 0 && is_connected) {
1494         const unsigned short *indices_array = _cairo_array_index_const (indices, 0);
1495         if (indices_array == NULL)
1496             return CAIRO_STATUS_NULL_POINTER;
1497         current_vertex_index = indices_array[number_of_indices - 1];
1498
1499         status = _cairo_array_append (indices, &current_vertex_index);
1500         if (unlikely (status))
1501             return status;
1502
1503         current_vertex_index++;
1504         status =_cairo_array_append (indices, &current_vertex_index);
1505         if (unlikely (status))
1506             return status;
1507     } else
1508         current_vertex_index = (unsigned short) number_of_indices;
1509
1510     for (i = 0; i < number_of_new_indices; i++) {
1511         status = _cairo_array_append (indices, &current_vertex_index);
1512         current_vertex_index++;
1513         if (unlikely (status))
1514             return status;
1515     }
1516
1517     return CAIRO_STATUS_SUCCESS;
1518 }
1519
1520 cairo_int_status_t
1521 _cairo_gl_composite_emit_int_quad_as_tristrip (cairo_gl_context_t *ctx,
1522                                                cairo_gl_composite_t *setup,
1523                                                const int            quad[8])
1524 {
1525     if (ctx->draw_mode != CAIRO_GL_VERTEX) {
1526         _cairo_gl_composite_flush (ctx);
1527         ctx->draw_mode = CAIRO_GL_VERTEX;
1528     }
1529
1530     _cairo_gl_composite_prepare_buffer (ctx, 4,
1531                                         CAIRO_GL_PRIMITIVE_TYPE_TRISTRIPS);
1532
1533     _cairo_gl_composite_emit_int (ctx, quad[0], quad[1]);
1534     _cairo_gl_composite_emit_int (ctx, quad[2], quad[3]);
1535
1536     /* Cairo stores quad vertices in counter-clockwise order, but we need to
1537        emit them from top to bottom in the triangle strip, so we need to reverse
1538        the order of the last two vertices. */
1539     _cairo_gl_composite_emit_int (ctx, quad[6], quad[7]);
1540     _cairo_gl_composite_emit_int (ctx, quad[4], quad[5]);
1541
1542     return _cairo_gl_composite_append_vertex_indices (ctx, 4, TRUE);
1543 }
1544
1545 cairo_int_status_t
1546 _cairo_gl_composite_emit_quad_as_tristrip (cairo_gl_context_t   *ctx,
1547                                            cairo_gl_composite_t *setup,
1548                                            const cairo_point_t  quad[4])
1549 {
1550     if (ctx->draw_mode != CAIRO_GL_VERTEX) {
1551         _cairo_gl_composite_flush (ctx);
1552         ctx->draw_mode = CAIRO_GL_VERTEX;
1553     }
1554
1555     _cairo_gl_composite_prepare_buffer (ctx, 4,
1556                                         CAIRO_GL_PRIMITIVE_TYPE_TRISTRIPS);
1557
1558     _cairo_gl_composite_emit_point (ctx, &quad[0]);
1559     _cairo_gl_composite_emit_point (ctx, &quad[1]);
1560
1561     /* Cairo stores quad vertices in counter-clockwise order, but we need to
1562        emit them from top to bottom in the triangle strip, so we need to reverse
1563        the order of the last two vertices. */
1564     _cairo_gl_composite_emit_point (ctx, &quad[3]);
1565     _cairo_gl_composite_emit_point (ctx, &quad[2]);
1566
1567     return _cairo_gl_composite_append_vertex_indices (ctx, 4, TRUE);
1568 }
1569
1570 cairo_int_status_t
1571 _cairo_gl_composite_emit_triangle_as_tristrip (cairo_gl_context_t       *ctx,
1572                                                cairo_gl_composite_t     *setup,
1573                                                const cairo_point_t       triangle[3])
1574 {
1575     if (ctx->draw_mode != CAIRO_GL_VERTEX) {
1576         _cairo_gl_composite_flush (ctx);
1577         ctx->draw_mode = CAIRO_GL_VERTEX;
1578     }
1579
1580     _cairo_gl_composite_prepare_buffer (ctx, 3,
1581                                         CAIRO_GL_PRIMITIVE_TYPE_TRISTRIPS);
1582
1583     _cairo_gl_composite_emit_point (ctx, &triangle[0]);
1584     _cairo_gl_composite_emit_point (ctx, &triangle[1]);
1585     _cairo_gl_composite_emit_point (ctx, &triangle[2]);
1586     return _cairo_gl_composite_append_vertex_indices (ctx, 3, TRUE);
1587 }
1588
1589 cairo_int_status_t
1590 _cairo_gl_composite_emit_point_as_single_line (cairo_gl_context_t  *ctx,
1591                                                const cairo_point_t point[2])
1592 {
1593     int num_indices = 2;
1594     if (ctx->draw_mode != CAIRO_GL_LINES)
1595         _cairo_gl_composite_flush (ctx);
1596
1597     ctx->draw_mode = CAIRO_GL_LINES;
1598
1599     _cairo_gl_composite_prepare_buffer (ctx, 2,
1600                                         CAIRO_GL_PRIMITIVE_TYPE_TRISTRIPS);
1601
1602     _cairo_gl_composite_emit_point (ctx, &point[0]);
1603     _cairo_gl_composite_emit_point (ctx, &point[1]);
1604     return _cairo_gl_composite_append_vertex_indices (ctx, num_indices, FALSE);
1605 }