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