1 /* cairo - a vector graphics library with display and print output
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
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.
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
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/
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.
32 * The Original Code is the cairo graphics library.
34 * The Initial Developer of the Original Code is Red Hat, Inc.
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>
48 #include "cairo-gl-private.h"
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"
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
)
62 _cairo_gl_operand_destroy (&setup
->src
);
63 return _cairo_gl_operand_init (&setup
->src
, pattern
, setup
->dst
,
64 sample
, extents
, use_texgen
);
68 _cairo_gl_composite_set_source_operand (cairo_gl_composite_t
*setup
,
69 const cairo_gl_operand_t
*source
)
71 _cairo_gl_operand_destroy (&setup
->src
);
72 _cairo_gl_operand_copy (&setup
->src
, source
);
76 _cairo_gl_composite_set_solid_source (cairo_gl_composite_t
*setup
,
77 const cairo_color_t
*color
)
79 _cairo_gl_operand_destroy (&setup
->src
);
80 _cairo_gl_solid_operand_init (&setup
->src
, color
);
84 _cairo_gl_composite_set_mask (cairo_gl_composite_t
*setup
,
85 const cairo_pattern_t
*pattern
,
86 const cairo_rectangle_int_t
*sample
,
87 const cairo_rectangle_int_t
*extents
,
88 cairo_bool_t use_texgen
)
90 _cairo_gl_operand_destroy (&setup
->mask
);
92 return CAIRO_STATUS_SUCCESS
;
94 return _cairo_gl_operand_init (&setup
->mask
, pattern
, setup
->dst
,
95 sample
, extents
, use_texgen
);
99 _cairo_gl_composite_set_mask_operand (cairo_gl_composite_t
*setup
,
100 const cairo_gl_operand_t
*mask
)
102 _cairo_gl_operand_destroy (&setup
->mask
);
104 _cairo_gl_operand_copy (&setup
->mask
, mask
);
108 _cairo_gl_composite_set_spans (cairo_gl_composite_t
*setup
)
114 _cairo_gl_composite_set_multisample (cairo_gl_composite_t
*setup
)
116 setup
->multisample
= TRUE
;
120 _cairo_gl_composite_set_clip_region (cairo_gl_composite_t
*setup
,
121 cairo_region_t
*clip_region
)
123 setup
->clip_region
= clip_region
;
127 _cairo_gl_composite_set_clip (cairo_gl_composite_t
*setup
,
134 _cairo_gl_composite_bind_to_shader (cairo_gl_context_t
*ctx
,
135 cairo_gl_composite_t
*setup
)
137 _cairo_gl_shader_bind_matrix4f(ctx
, ctx
->current_shader
->mvp_location
,
138 ctx
->modelviewprojection_matrix
);
139 _cairo_gl_operand_bind_to_shader (ctx
, &setup
->src
, CAIRO_GL_TEX_SOURCE
);
140 _cairo_gl_operand_bind_to_shader (ctx
, &setup
->mask
, CAIRO_GL_TEX_MASK
);
144 _cairo_gl_texture_set_filter (cairo_gl_context_t
*ctx
,
146 cairo_filter_t filter
)
149 case CAIRO_FILTER_FAST
:
150 case CAIRO_FILTER_NEAREST
:
151 glTexParameteri (target
, GL_TEXTURE_MIN_FILTER
, GL_NEAREST
);
152 glTexParameteri (target
, GL_TEXTURE_MAG_FILTER
, GL_NEAREST
);
154 case CAIRO_FILTER_GOOD
:
155 case CAIRO_FILTER_BEST
:
156 case CAIRO_FILTER_BILINEAR
:
157 glTexParameteri (target
, GL_TEXTURE_MIN_FILTER
, GL_LINEAR
);
158 glTexParameteri (target
, GL_TEXTURE_MAG_FILTER
, GL_LINEAR
);
161 case CAIRO_FILTER_GAUSSIAN
:
167 _cairo_gl_texture_set_extend (cairo_gl_context_t
*ctx
,
169 cairo_extend_t extend
)
172 assert (! _cairo_gl_device_requires_power_of_two_textures (&ctx
->base
) ||
173 (extend
!= CAIRO_EXTEND_REPEAT
&& extend
!= CAIRO_EXTEND_REFLECT
));
176 case CAIRO_EXTEND_NONE
:
177 if (ctx
->gl_flavor
== CAIRO_GL_FLAVOR_ES
)
178 wrap_mode
= GL_CLAMP_TO_EDGE
;
180 wrap_mode
= GL_CLAMP_TO_BORDER
;
182 case CAIRO_EXTEND_PAD
:
183 wrap_mode
= GL_CLAMP_TO_EDGE
;
185 case CAIRO_EXTEND_REPEAT
:
186 if (ctx
->has_npot_repeat
)
187 wrap_mode
= GL_REPEAT
;
189 wrap_mode
= GL_CLAMP_TO_EDGE
;
191 case CAIRO_EXTEND_REFLECT
:
192 if (ctx
->has_npot_repeat
)
193 wrap_mode
= GL_MIRRORED_REPEAT
;
195 wrap_mode
= GL_CLAMP_TO_EDGE
;
201 if (likely (wrap_mode
)) {
202 glTexParameteri (target
, GL_TEXTURE_WRAP_S
, wrap_mode
);
203 glTexParameteri (target
, GL_TEXTURE_WRAP_T
, wrap_mode
);
209 _cairo_gl_context_setup_operand (cairo_gl_context_t
*ctx
,
210 cairo_gl_tex_t tex_unit
,
211 cairo_gl_operand_t
*operand
,
212 unsigned int vertex_offset
,
213 cairo_bool_t vertex_size_changed
)
215 cairo_gl_dispatch_t
*dispatch
= &ctx
->dispatch
;
216 cairo_bool_t needs_setup
;
218 /* XXX: we need to do setup when switching from shaders
219 * to no shaders (or back) */
220 needs_setup
= vertex_size_changed
;
221 needs_setup
|= _cairo_gl_operand_needs_setup (&ctx
->operands
[tex_unit
],
226 _cairo_gl_composite_flush (ctx
);
227 _cairo_gl_context_destroy_operand (ctx
, tex_unit
);
230 memcpy (&ctx
->operands
[tex_unit
], operand
, sizeof (cairo_gl_operand_t
));
231 ctx
->operands
[tex_unit
].vertex_offset
= vertex_offset
;
236 switch (operand
->type
) {
238 case CAIRO_GL_OPERAND_COUNT
:
240 case CAIRO_GL_OPERAND_NONE
:
243 case CAIRO_GL_OPERAND_CONSTANT
:
245 case CAIRO_GL_OPERAND_TEXTURE
:
246 glActiveTexture (GL_TEXTURE0
+ tex_unit
);
247 glBindTexture (ctx
->tex_target
, operand
->texture
.tex
);
248 _cairo_gl_texture_set_extend (ctx
, ctx
->tex_target
,
249 operand
->texture
.attributes
.extend
);
250 _cairo_gl_texture_set_filter (ctx
, ctx
->tex_target
,
251 operand
->texture
.attributes
.filter
);
253 if (! operand
->texture
.texgen
) {
254 dispatch
->VertexAttribPointer (CAIRO_GL_TEXCOORD0_ATTRIB_INDEX
+ tex_unit
, 2,
255 GL_FLOAT
, GL_FALSE
, ctx
->vertex_size
,
256 ctx
->vb
+ vertex_offset
);
257 dispatch
->EnableVertexAttribArray (CAIRO_GL_TEXCOORD0_ATTRIB_INDEX
+ tex_unit
);
260 case CAIRO_GL_OPERAND_LINEAR_GRADIENT
:
261 case CAIRO_GL_OPERAND_RADIAL_GRADIENT_A0
:
262 case CAIRO_GL_OPERAND_RADIAL_GRADIENT_NONE
:
263 case CAIRO_GL_OPERAND_RADIAL_GRADIENT_EXT
:
264 glActiveTexture (GL_TEXTURE0
+ tex_unit
);
265 glBindTexture (ctx
->tex_target
, operand
->gradient
.gradient
->tex
);
266 _cairo_gl_texture_set_extend (ctx
, ctx
->tex_target
, operand
->gradient
.extend
);
267 _cairo_gl_texture_set_filter (ctx
, ctx
->tex_target
, CAIRO_FILTER_BILINEAR
);
269 if (! operand
->gradient
.texgen
) {
270 dispatch
->VertexAttribPointer (CAIRO_GL_TEXCOORD0_ATTRIB_INDEX
+ tex_unit
, 2,
271 GL_FLOAT
, GL_FALSE
, ctx
->vertex_size
,
272 ctx
->vb
+ vertex_offset
);
273 dispatch
->EnableVertexAttribArray (CAIRO_GL_TEXCOORD0_ATTRIB_INDEX
+ tex_unit
);
280 _cairo_gl_context_setup_spans (cairo_gl_context_t
*ctx
,
281 cairo_bool_t spans_enabled
,
282 unsigned int vertex_size
,
283 unsigned int vertex_offset
)
285 cairo_gl_dispatch_t
*dispatch
= &ctx
->dispatch
;
287 if (! spans_enabled
) {
288 dispatch
->DisableVertexAttribArray (CAIRO_GL_COLOR_ATTRIB_INDEX
);
293 dispatch
->VertexAttribPointer (CAIRO_GL_COLOR_ATTRIB_INDEX
, 4,
294 GL_UNSIGNED_BYTE
, GL_TRUE
, vertex_size
,
295 ctx
->vb
+ vertex_offset
);
296 dispatch
->EnableVertexAttribArray (CAIRO_GL_COLOR_ATTRIB_INDEX
);
301 _cairo_gl_context_destroy_operand (cairo_gl_context_t
*ctx
,
302 cairo_gl_tex_t tex_unit
)
304 cairo_gl_dispatch_t
*dispatch
= &ctx
->dispatch
;
306 if (!_cairo_gl_context_is_flushed (ctx
))
307 _cairo_gl_composite_flush (ctx
);
309 switch (ctx
->operands
[tex_unit
].type
) {
311 case CAIRO_GL_OPERAND_COUNT
:
313 case CAIRO_GL_OPERAND_NONE
:
316 case CAIRO_GL_OPERAND_CONSTANT
:
318 case CAIRO_GL_OPERAND_TEXTURE
:
319 dispatch
->DisableVertexAttribArray (CAIRO_GL_TEXCOORD0_ATTRIB_INDEX
+ tex_unit
);
321 case CAIRO_GL_OPERAND_LINEAR_GRADIENT
:
322 case CAIRO_GL_OPERAND_RADIAL_GRADIENT_A0
:
323 case CAIRO_GL_OPERAND_RADIAL_GRADIENT_NONE
:
324 case CAIRO_GL_OPERAND_RADIAL_GRADIENT_EXT
:
325 dispatch
->DisableVertexAttribArray (CAIRO_GL_TEXCOORD0_ATTRIB_INDEX
+ tex_unit
);
329 memset (&ctx
->operands
[tex_unit
], 0, sizeof (cairo_gl_operand_t
));
333 _cairo_gl_set_operator (cairo_gl_context_t
*ctx
,
335 cairo_bool_t component_alpha
)
340 } blend_factors
[] = {
341 { GL_ZERO
, GL_ZERO
}, /* Clear */
342 { GL_ONE
, GL_ZERO
}, /* Source */
343 { GL_ONE
, GL_ONE_MINUS_SRC_ALPHA
}, /* Over */
344 { GL_DST_ALPHA
, GL_ZERO
}, /* In */
345 { GL_ONE_MINUS_DST_ALPHA
, GL_ZERO
}, /* Out */
346 { GL_DST_ALPHA
, GL_ONE_MINUS_SRC_ALPHA
}, /* Atop */
348 { GL_ZERO
, GL_ONE
}, /* Dest */
349 { GL_ONE_MINUS_DST_ALPHA
, GL_ONE
}, /* DestOver */
350 { GL_ZERO
, GL_SRC_ALPHA
}, /* DestIn */
351 { GL_ZERO
, GL_ONE_MINUS_SRC_ALPHA
}, /* DestOut */
352 { GL_ONE_MINUS_DST_ALPHA
, GL_SRC_ALPHA
}, /* DestAtop */
354 { GL_ONE_MINUS_DST_ALPHA
, GL_ONE_MINUS_SRC_ALPHA
}, /* Xor */
355 { GL_ONE
, GL_ONE
}, /* Add */
357 GLenum src_factor
, dst_factor
;
359 assert (op
< ARRAY_LENGTH (blend_factors
));
360 /* different dst and component_alpha changes cause flushes elsewhere */
361 if (ctx
->current_operator
!= op
)
362 _cairo_gl_composite_flush (ctx
);
363 ctx
->current_operator
= op
;
365 src_factor
= blend_factors
[op
].src
;
366 dst_factor
= blend_factors
[op
].dst
;
368 /* Even when the user requests CAIRO_CONTENT_COLOR, we use GL_RGBA
369 * due to texture filtering of GL_CLAMP_TO_BORDER. So fix those
372 if (ctx
->current_target
->base
.content
== CAIRO_CONTENT_COLOR
) {
373 if (src_factor
== GL_ONE_MINUS_DST_ALPHA
)
374 src_factor
= GL_ZERO
;
375 if (src_factor
== GL_DST_ALPHA
)
379 if (component_alpha
) {
380 if (dst_factor
== GL_ONE_MINUS_SRC_ALPHA
)
381 dst_factor
= GL_ONE_MINUS_SRC_COLOR
;
382 if (dst_factor
== GL_SRC_ALPHA
)
383 dst_factor
= GL_SRC_COLOR
;
386 if (ctx
->current_target
->base
.content
== CAIRO_CONTENT_ALPHA
) {
387 glBlendFuncSeparate (GL_ZERO
, GL_ZERO
, src_factor
, dst_factor
);
388 } else if (ctx
->current_target
->base
.content
== CAIRO_CONTENT_COLOR
) {
389 glBlendFuncSeparate (src_factor
, dst_factor
, GL_ONE
, GL_ONE
);
391 glBlendFunc (src_factor
, dst_factor
);
395 static cairo_status_t
396 _cairo_gl_composite_begin_component_alpha (cairo_gl_context_t
*ctx
,
397 cairo_gl_composite_t
*setup
)
399 cairo_gl_shader_t
*pre_shader
= NULL
;
400 cairo_status_t status
;
402 /* For CLEAR, cairo's rendering equation (quoting Owen's description in:
403 * http://lists.cairographics.org/archives/cairo/2005-August/004992.html)
405 * mask IN clip ? src OP dest : dest
407 * mask IN CLIP ? 0 : dest
409 * where the ternary operator A ? B : C is (A * B) + ((1 - A) * C).
411 * The model we use in _cairo_gl_set_operator() is Render's:
412 * src IN mask IN clip OP dest
413 * which would boil down to:
414 * 0 (bounded by the extents of the drawing).
416 * However, we can do a Render operation using an opaque source
417 * and DEST_OUT to produce:
418 * 1 IN mask IN clip DEST_OUT dest
420 * mask IN clip ? 0 : dest
422 if (setup
->op
== CAIRO_OPERATOR_CLEAR
) {
423 _cairo_gl_solid_operand_init (&setup
->src
, CAIRO_COLOR_WHITE
);
424 setup
->op
= CAIRO_OPERATOR_DEST_OUT
;
428 * implements component-alpha %CAIRO_OPERATOR_OVER using two passes of
429 * the simpler operations %CAIRO_OPERATOR_DEST_OUT and %CAIRO_OPERATOR_ADD.
431 * From http://anholt.livejournal.com/32058.html:
433 * The trouble is that component-alpha rendering requires two different sources
434 * for blending: one for the source value to the blender, which is the
435 * per-channel multiplication of source and mask, and one for the source alpha
436 * for multiplying with the destination channels, which is the multiplication
437 * of the source channels by the mask alpha. So the equation for Over is:
439 * dst.A = src.A * mask.A + (1 - (src.A * mask.A)) * dst.A
440 * dst.R = src.R * mask.R + (1 - (src.A * mask.R)) * dst.R
441 * dst.G = src.G * mask.G + (1 - (src.A * mask.G)) * dst.G
442 * dst.B = src.B * mask.B + (1 - (src.A * mask.B)) * dst.B
444 * But we can do some simpler operations, right? How about PictOpOutReverse,
445 * which has a source factor of 0 and dest factor of (1 - source alpha). We
446 * can get the source alpha value (srca.X = src.A * mask.X) out of the texture
447 * blenders pretty easily. So we can do a component-alpha OutReverse, which
450 * dst.A = 0 + (1 - (src.A * mask.A)) * dst.A
451 * dst.R = 0 + (1 - (src.A * mask.R)) * dst.R
452 * dst.G = 0 + (1 - (src.A * mask.G)) * dst.G
453 * dst.B = 0 + (1 - (src.A * mask.B)) * dst.B
455 * OK. And if an op doesn't use the source alpha value for the destination
456 * factor, then we can do the channel multiplication in the texture blenders
457 * to get the source value, and ignore the source alpha that we wouldn't use.
458 * We've supported this in the Radeon driver for a long time. An example would
459 * be PictOpAdd, which does:
461 * dst.A = src.A * mask.A + dst.A
462 * dst.R = src.R * mask.R + dst.R
463 * dst.G = src.G * mask.G + dst.G
464 * dst.B = src.B * mask.B + dst.B
466 * Hey, this looks good! If we do a PictOpOutReverse and then a PictOpAdd right
469 * dst.A = src.A * mask.A + ((1 - (src.A * mask.A)) * dst.A)
470 * dst.R = src.R * mask.R + ((1 - (src.A * mask.R)) * dst.R)
471 * dst.G = src.G * mask.G + ((1 - (src.A * mask.G)) * dst.G)
472 * dst.B = src.B * mask.B + ((1 - (src.A * mask.B)) * dst.B)
474 * This two-pass trickery could be avoided using a new GL extension that
475 * lets two values come out of the shader and into the blend unit.
477 if (setup
->op
== CAIRO_OPERATOR_OVER
) {
478 setup
->op
= CAIRO_OPERATOR_ADD
;
479 status
= _cairo_gl_get_shader_by_type (ctx
,
483 CAIRO_GL_SHADER_IN_CA_SOURCE_ALPHA
,
485 if (unlikely (status
))
489 if (ctx
->pre_shader
!= pre_shader
)
490 _cairo_gl_composite_flush (ctx
);
491 ctx
->pre_shader
= pre_shader
;
493 return CAIRO_STATUS_SUCCESS
;
497 _scissor_to_doubles (cairo_gl_surface_t
*surface
,
498 double x1
, double y1
,
499 double x2
, double y2
)
504 if (_cairo_gl_surface_is_texture (surface
) == FALSE
)
505 y1
= surface
->height
- (y1
+ height
);
506 glScissor (x1
, y1
, x2
- x1
, height
);
507 glEnable (GL_SCISSOR_TEST
);
511 _cairo_gl_scissor_to_rectangle (cairo_gl_surface_t
*surface
,
512 const cairo_rectangle_int_t
*r
)
514 _scissor_to_doubles (surface
, r
->x
, r
->y
, r
->x
+r
->width
, r
->y
+r
->height
);
518 _scissor_to_box (cairo_gl_surface_t
*surface
,
519 const cairo_box_t
*box
)
521 double x1
, y1
, x2
, y2
;
522 _cairo_box_to_doubles (box
, &x1
, &y1
, &x2
, &y2
);
523 _scissor_to_doubles (surface
, x1
, y1
, x2
, y2
);
527 _cairo_gl_composite_setup_vbo (cairo_gl_context_t
*ctx
,
528 unsigned int size_per_vertex
)
530 cairo_bool_t vertex_size_changed
= ctx
->vertex_size
!= size_per_vertex
;
531 if (vertex_size_changed
) {
532 ctx
->vertex_size
= size_per_vertex
;
533 _cairo_gl_composite_flush (ctx
);
536 if (_cairo_gl_context_is_flushed (ctx
)) {
537 ctx
->dispatch
.VertexAttribPointer (CAIRO_GL_VERTEX_ATTRIB_INDEX
, 2,
538 GL_FLOAT
, GL_FALSE
, size_per_vertex
,
540 ctx
->dispatch
.EnableVertexAttribArray (CAIRO_GL_VERTEX_ATTRIB_INDEX
);
543 return vertex_size_changed
;
547 _disable_stencil_buffer (void)
549 glDisable (GL_STENCIL_TEST
);
550 glDepthMask (GL_FALSE
);
553 static cairo_int_status_t
554 _cairo_gl_composite_setup_painted_clipping (cairo_gl_composite_t
*setup
,
555 cairo_gl_context_t
*ctx
,
558 cairo_int_status_t status
= CAIRO_INT_STATUS_SUCCESS
;
560 cairo_gl_surface_t
*dst
= setup
->dst
;
561 cairo_clip_t
*clip
= setup
->clip
;
563 if (clip
->num_boxes
== 1 && clip
->path
== NULL
) {
564 _scissor_to_box (dst
, &clip
->boxes
[0]);
565 goto disable_stencil_buffer_and_return
;
568 if (! _cairo_gl_ensure_stencil (ctx
, setup
->dst
)) {
569 status
= CAIRO_INT_STATUS_UNSUPPORTED
;
570 goto disable_stencil_buffer_and_return
;
573 /* We only want to clear the part of the stencil buffer
574 * that we are about to use. It also does not hurt to
575 * scissor around the painted clip. */
576 _cairo_gl_scissor_to_rectangle (dst
, _cairo_clip_get_extents (clip
));
578 /* The clip is not rectangular, so use the stencil buffer. */
579 glDepthMask (GL_TRUE
);
580 glEnable (GL_STENCIL_TEST
);
582 /* Texture surfaces have private depth/stencil buffers, so we can
583 * rely on any previous clip being cached there. */
584 if (_cairo_gl_surface_is_texture (setup
->dst
)) {
585 cairo_clip_t
*old_clip
= setup
->dst
->clip_on_stencil_buffer
;
586 if (_cairo_clip_equal (old_clip
, setup
->clip
))
587 goto activate_stencil_buffer_and_return
;
590 _cairo_clip_destroy (setup
->dst
->clip_on_stencil_buffer
);
593 setup
->dst
->clip_on_stencil_buffer
= _cairo_clip_copy (setup
->clip
);
597 glClear (GL_STENCIL_BUFFER_BIT
);
599 glStencilOp (GL_REPLACE
, GL_REPLACE
, GL_REPLACE
);
600 glStencilFunc (GL_EQUAL
, 1, 0xffffffff);
601 glColorMask (0, 0, 0, 0);
603 status
= _cairo_gl_msaa_compositor_draw_clip (ctx
, setup
, clip
);
605 if (unlikely (status
)) {
606 glColorMask (1, 1, 1, 1);
607 goto disable_stencil_buffer_and_return
;
610 /* We want to only render to the stencil buffer, so draw everything now.
611 Flushing also unbinds the VBO, which we want to rebind for regular
613 _cairo_gl_composite_flush (ctx
);
614 _cairo_gl_composite_setup_vbo (ctx
, vertex_size
);
616 activate_stencil_buffer_and_return
:
617 glColorMask (1, 1, 1, 1);
618 glStencilOp (GL_KEEP
, GL_KEEP
, GL_KEEP
);
619 glStencilFunc (GL_EQUAL
, 1, 0xffffffff);
620 return CAIRO_INT_STATUS_SUCCESS
;
622 disable_stencil_buffer_and_return
:
623 _disable_stencil_buffer ();
627 static cairo_int_status_t
628 _cairo_gl_composite_setup_clipping (cairo_gl_composite_t
*setup
,
629 cairo_gl_context_t
*ctx
,
632 cairo_bool_t clip_changing
= TRUE
;
633 cairo_bool_t clip_region_changing
= TRUE
;
635 if (! ctx
->clip
&& ! setup
->clip
&& ! setup
->clip_region
&& ! ctx
->clip_region
)
636 goto disable_all_clipping
;
638 clip_changing
= ! _cairo_clip_equal (ctx
->clip
, setup
->clip
);
639 clip_region_changing
= ! cairo_region_equal (ctx
->clip_region
, setup
->clip_region
);
640 if (! _cairo_gl_context_is_flushed (ctx
) &&
641 (clip_region_changing
|| clip_changing
))
642 _cairo_gl_composite_flush (ctx
);
644 assert (!setup
->clip_region
|| !setup
->clip
);
646 /* setup->clip is only used by the msaa compositor and setup->clip_region
647 * only by the other compositors, so it's safe to wait to clean up obsolete
649 if (clip_region_changing
) {
650 cairo_region_destroy (ctx
->clip_region
);
651 ctx
->clip_region
= cairo_region_reference (setup
->clip_region
);
654 _cairo_clip_destroy (ctx
->clip
);
655 ctx
->clip
= _cairo_clip_copy (setup
->clip
);
658 /* For clip regions, we scissor right before drawing. */
659 if (setup
->clip_region
)
660 goto disable_all_clipping
;
663 return _cairo_gl_composite_setup_painted_clipping (setup
, ctx
,
665 disable_all_clipping
:
666 _disable_stencil_buffer ();
667 glDisable (GL_SCISSOR_TEST
);
668 return CAIRO_INT_STATUS_SUCCESS
;
672 _cairo_gl_set_operands_and_operator (cairo_gl_composite_t
*setup
,
673 cairo_gl_context_t
*ctx
)
675 unsigned int dst_size
, src_size
, mask_size
, vertex_size
;
676 cairo_status_t status
;
677 cairo_gl_shader_t
*shader
;
678 cairo_bool_t component_alpha
;
679 cairo_bool_t vertex_size_changed
;
682 setup
->mask
.type
== CAIRO_GL_OPERAND_TEXTURE
&&
683 setup
->mask
.texture
.attributes
.has_component_alpha
;
685 /* Do various magic for component alpha */
686 if (component_alpha
) {
687 status
= _cairo_gl_composite_begin_component_alpha (ctx
, setup
);
688 if (unlikely (status
))
691 if (ctx
->pre_shader
) {
692 _cairo_gl_composite_flush (ctx
);
693 ctx
->pre_shader
= NULL
;
697 status
= _cairo_gl_get_shader_by_type (ctx
,
702 CAIRO_GL_SHADER_IN_CA_SOURCE
:
703 CAIRO_GL_SHADER_IN_NORMAL
,
705 if (unlikely (status
)) {
706 ctx
->pre_shader
= NULL
;
709 if (ctx
->current_shader
!= shader
)
710 _cairo_gl_composite_flush (ctx
);
712 status
= CAIRO_STATUS_SUCCESS
;
714 dst_size
= 2 * sizeof (GLfloat
);
715 src_size
= _cairo_gl_operand_get_vertex_size (&setup
->src
);
716 mask_size
= _cairo_gl_operand_get_vertex_size (&setup
->mask
);
717 vertex_size
= dst_size
+ src_size
+ mask_size
;
720 vertex_size
+= sizeof (GLfloat
);
722 vertex_size_changed
= _cairo_gl_composite_setup_vbo (ctx
, vertex_size
);
724 _cairo_gl_context_setup_operand (ctx
, CAIRO_GL_TEX_SOURCE
, &setup
->src
, dst_size
, vertex_size_changed
);
725 _cairo_gl_context_setup_operand (ctx
, CAIRO_GL_TEX_MASK
, &setup
->mask
, dst_size
+ src_size
, vertex_size_changed
);
727 _cairo_gl_context_setup_spans (ctx
, setup
->spans
, vertex_size
,
728 dst_size
+ src_size
+ mask_size
);
730 _cairo_gl_set_operator (ctx
, setup
->op
, component_alpha
);
732 if (_cairo_gl_context_is_flushed (ctx
)) {
733 if (ctx
->pre_shader
) {
734 _cairo_gl_set_shader (ctx
, ctx
->pre_shader
);
735 _cairo_gl_composite_bind_to_shader (ctx
, setup
);
737 _cairo_gl_set_shader (ctx
, shader
);
738 _cairo_gl_composite_bind_to_shader (ctx
, setup
);
745 _cairo_gl_composite_begin (cairo_gl_composite_t
*setup
,
746 cairo_gl_context_t
**ctx_out
)
748 cairo_gl_context_t
*ctx
;
749 cairo_status_t status
;
753 status
= _cairo_gl_context_acquire (setup
->dst
->base
.device
, &ctx
);
754 if (unlikely (status
))
757 _cairo_gl_context_set_destination (ctx
, setup
->dst
, setup
->multisample
);
760 status
= _cairo_gl_set_operands_and_operator (setup
, ctx
);
761 if (unlikely (status
))
764 status
= _cairo_gl_composite_setup_clipping (setup
, ctx
, ctx
->vertex_size
);
765 if (unlikely (status
))
771 if (unlikely (status
))
772 status
= _cairo_gl_context_release (ctx
, status
);
778 _cairo_gl_composite_draw_tristrip (cairo_gl_context_t
*ctx
)
780 cairo_array_t
* indices
= &ctx
->tristrip_indices
;
781 const unsigned short *indices_array
= _cairo_array_index_const (indices
, 0);
783 if (ctx
->pre_shader
) {
784 cairo_gl_shader_t
*prev_shader
= ctx
->current_shader
;
786 _cairo_gl_set_shader (ctx
, ctx
->pre_shader
);
787 _cairo_gl_set_operator (ctx
, CAIRO_OPERATOR_DEST_OUT
, TRUE
);
788 glDrawElements (GL_TRIANGLE_STRIP
, _cairo_array_num_elements (indices
), GL_UNSIGNED_SHORT
, indices_array
);
790 _cairo_gl_set_shader (ctx
, prev_shader
);
791 _cairo_gl_set_operator (ctx
, CAIRO_OPERATOR_ADD
, TRUE
);
794 glDrawElements (GL_TRIANGLE_STRIP
, _cairo_array_num_elements (indices
), GL_UNSIGNED_SHORT
, indices_array
);
795 _cairo_array_truncate (indices
, 0);
799 _cairo_gl_composite_draw_triangles (cairo_gl_context_t
*ctx
,
802 if (! ctx
->pre_shader
) {
803 glDrawArrays (GL_TRIANGLES
, 0, count
);
805 cairo_gl_shader_t
*prev_shader
= ctx
->current_shader
;
807 _cairo_gl_set_shader (ctx
, ctx
->pre_shader
);
808 _cairo_gl_set_operator (ctx
, CAIRO_OPERATOR_DEST_OUT
, TRUE
);
809 glDrawArrays (GL_TRIANGLES
, 0, count
);
811 _cairo_gl_set_shader (ctx
, prev_shader
);
812 _cairo_gl_set_operator (ctx
, CAIRO_OPERATOR_ADD
, TRUE
);
813 glDrawArrays (GL_TRIANGLES
, 0, count
);
818 _cairo_gl_composite_draw_triangles_with_clip_region (cairo_gl_context_t
*ctx
,
821 int i
, num_rectangles
;
823 if (!ctx
->clip_region
) {
824 _cairo_gl_composite_draw_triangles (ctx
, count
);
828 num_rectangles
= cairo_region_num_rectangles (ctx
->clip_region
);
829 for (i
= 0; i
< num_rectangles
; i
++) {
830 cairo_rectangle_int_t rect
;
832 cairo_region_get_rectangle (ctx
->clip_region
, i
, &rect
);
834 _cairo_gl_scissor_to_rectangle (ctx
->current_target
, &rect
);
835 _cairo_gl_composite_draw_triangles (ctx
, count
);
840 _cairo_gl_composite_unmap_vertex_buffer (cairo_gl_context_t
*ctx
)
846 _cairo_gl_composite_flush (cairo_gl_context_t
*ctx
)
851 if (_cairo_gl_context_is_flushed (ctx
))
854 count
= ctx
->vb_offset
/ ctx
->vertex_size
;
855 _cairo_gl_composite_unmap_vertex_buffer (ctx
);
857 if (ctx
->primitive_type
== CAIRO_GL_PRIMITIVE_TYPE_TRISTRIPS
) {
858 _cairo_gl_composite_draw_tristrip (ctx
);
860 assert (ctx
->primitive_type
== CAIRO_GL_PRIMITIVE_TYPE_TRIANGLES
);
861 _cairo_gl_composite_draw_triangles_with_clip_region (ctx
, count
);
864 for (i
= 0; i
< ARRAY_LENGTH (ctx
->glyph_cache
); i
++)
865 _cairo_gl_glyph_cache_unlock (&ctx
->glyph_cache
[i
]);
869 _cairo_gl_composite_prepare_buffer (cairo_gl_context_t
*ctx
,
870 unsigned int n_vertices
,
871 cairo_gl_primitive_type_t primitive_type
)
873 if (ctx
->primitive_type
!= primitive_type
) {
874 _cairo_gl_composite_flush (ctx
);
875 ctx
->primitive_type
= primitive_type
;
878 assert(ctx
->vbo_size
> 0);
879 if (ctx
->vb_offset
+ n_vertices
* ctx
->vertex_size
> ctx
->vbo_size
)
880 _cairo_gl_composite_flush (ctx
);
884 _cairo_gl_composite_emit_vertex (cairo_gl_context_t
*ctx
,
885 GLfloat x
, GLfloat y
)
887 GLfloat
*vb
= (GLfloat
*) (void *) &ctx
->vb
[ctx
->vb_offset
];
892 _cairo_gl_operand_emit (&ctx
->operands
[CAIRO_GL_TEX_SOURCE
], &vb
, x
, y
);
893 _cairo_gl_operand_emit (&ctx
->operands
[CAIRO_GL_TEX_MASK
], &vb
, x
, y
);
895 ctx
->vb_offset
+= ctx
->vertex_size
;
899 _cairo_gl_composite_emit_alpha_vertex (cairo_gl_context_t
*ctx
,
900 GLfloat x
, GLfloat y
, uint8_t alpha
)
902 GLfloat
*vb
= (GLfloat
*) (void *) &ctx
->vb
[ctx
->vb_offset
];
911 _cairo_gl_operand_emit (&ctx
->operands
[CAIRO_GL_TEX_SOURCE
], &vb
, x
, y
);
912 _cairo_gl_operand_emit (&ctx
->operands
[CAIRO_GL_TEX_MASK
], &vb
, x
, y
);
920 ctx
->vb_offset
+= ctx
->vertex_size
;
924 _cairo_gl_composite_emit_point (cairo_gl_context_t
*ctx
,
925 const cairo_point_t
*point
)
927 _cairo_gl_composite_emit_vertex (ctx
,
928 _cairo_fixed_to_double (point
->x
),
929 _cairo_fixed_to_double (point
->y
));
933 _cairo_gl_composite_emit_rect (cairo_gl_context_t
*ctx
,
934 GLfloat x1
, GLfloat y1
,
935 GLfloat x2
, GLfloat y2
)
937 _cairo_gl_composite_prepare_buffer (ctx
, 6,
938 CAIRO_GL_PRIMITIVE_TYPE_TRIANGLES
);
940 _cairo_gl_composite_emit_vertex (ctx
, x1
, y1
);
941 _cairo_gl_composite_emit_vertex (ctx
, x2
, y1
);
942 _cairo_gl_composite_emit_vertex (ctx
, x1
, y2
);
944 _cairo_gl_composite_emit_vertex (ctx
, x2
, y1
);
945 _cairo_gl_composite_emit_vertex (ctx
, x2
, y2
);
946 _cairo_gl_composite_emit_vertex (ctx
, x1
, y2
);
950 _cairo_gl_context_choose_emit_rect (cairo_gl_context_t
*ctx
)
952 return _cairo_gl_composite_emit_rect
;
956 _cairo_gl_context_emit_rect (cairo_gl_context_t
*ctx
,
957 GLfloat x1
, GLfloat y1
,
958 GLfloat x2
, GLfloat y2
)
960 _cairo_gl_composite_emit_rect (ctx
, x1
, y1
, x2
, y2
);
964 _cairo_gl_composite_emit_span (cairo_gl_context_t
*ctx
,
965 GLfloat x1
, GLfloat y1
,
966 GLfloat x2
, GLfloat y2
,
969 _cairo_gl_composite_prepare_buffer (ctx
, 6,
970 CAIRO_GL_PRIMITIVE_TYPE_TRIANGLES
);
972 _cairo_gl_composite_emit_alpha_vertex (ctx
, x1
, y1
, alpha
);
973 _cairo_gl_composite_emit_alpha_vertex (ctx
, x2
, y1
, alpha
);
974 _cairo_gl_composite_emit_alpha_vertex (ctx
, x1
, y2
, alpha
);
976 _cairo_gl_composite_emit_alpha_vertex (ctx
, x2
, y1
, alpha
);
977 _cairo_gl_composite_emit_alpha_vertex (ctx
, x2
, y2
, alpha
);
978 _cairo_gl_composite_emit_alpha_vertex (ctx
, x1
, y2
, alpha
);
982 _cairo_gl_composite_emit_solid_span (cairo_gl_context_t
*ctx
,
983 GLfloat x1
, GLfloat y1
,
984 GLfloat x2
, GLfloat y2
,
993 _cairo_gl_composite_prepare_buffer (ctx
, 6,
994 CAIRO_GL_PRIMITIVE_TYPE_TRIANGLES
);
995 v
= (GLfloat
*) (void *) &ctx
->vb
[ctx
->vb_offset
];
997 v
[15] = v
[ 6] = v
[0] = x1
;
998 v
[10] = v
[ 4] = v
[1] = y1
;
999 v
[12] = v
[ 9] = v
[3] = x2
;
1000 v
[16] = v
[13] = v
[7] = y2
;
1005 fi
.bytes
[3] = alpha
;
1006 v
[17] =v
[14] = v
[11] = v
[8] = v
[5] = v
[2] = fi
.f
;
1008 ctx
->vb_offset
+= 6*3 * sizeof(GLfloat
);
1011 cairo_gl_emit_span_t
1012 _cairo_gl_context_choose_emit_span (cairo_gl_context_t
*ctx
)
1014 if (ctx
->operands
[CAIRO_GL_TEX_MASK
].type
!= CAIRO_GL_OPERAND_NONE
) {
1015 switch (ctx
->operands
[CAIRO_GL_TEX_MASK
].type
) {
1017 case CAIRO_GL_OPERAND_COUNT
:
1019 case CAIRO_GL_OPERAND_NONE
:
1020 case CAIRO_GL_OPERAND_CONSTANT
:
1023 case CAIRO_GL_OPERAND_LINEAR_GRADIENT
:
1024 case CAIRO_GL_OPERAND_RADIAL_GRADIENT_A0
:
1025 case CAIRO_GL_OPERAND_RADIAL_GRADIENT_NONE
:
1026 case CAIRO_GL_OPERAND_RADIAL_GRADIENT_EXT
:
1027 if (!ctx
->operands
[CAIRO_GL_TEX_MASK
].gradient
.texgen
)
1028 return _cairo_gl_composite_emit_span
;
1031 case CAIRO_GL_OPERAND_TEXTURE
:
1032 if (!ctx
->operands
[CAIRO_GL_TEX_MASK
].texture
.texgen
)
1033 return _cairo_gl_composite_emit_span
;
1038 switch (ctx
->operands
[CAIRO_GL_TEX_SOURCE
].type
) {
1040 case CAIRO_GL_OPERAND_COUNT
:
1042 case CAIRO_GL_OPERAND_NONE
:
1043 case CAIRO_GL_OPERAND_CONSTANT
:
1046 case CAIRO_GL_OPERAND_LINEAR_GRADIENT
:
1047 case CAIRO_GL_OPERAND_RADIAL_GRADIENT_A0
:
1048 case CAIRO_GL_OPERAND_RADIAL_GRADIENT_NONE
:
1049 case CAIRO_GL_OPERAND_RADIAL_GRADIENT_EXT
:
1050 if (!ctx
->operands
[CAIRO_GL_TEX_SOURCE
].gradient
.texgen
)
1051 return _cairo_gl_composite_emit_span
;
1054 case CAIRO_GL_OPERAND_TEXTURE
:
1055 if (!ctx
->operands
[CAIRO_GL_TEX_SOURCE
].texture
.texgen
)
1056 return _cairo_gl_composite_emit_span
;
1059 return _cairo_gl_composite_emit_solid_span
;
1063 _cairo_gl_composite_emit_glyph_vertex (cairo_gl_context_t
*ctx
,
1064 GLfloat x
, GLfloat y
,
1065 GLfloat glyph_x
, GLfloat glyph_y
)
1067 GLfloat
*vb
= (GLfloat
*) (void *) &ctx
->vb
[ctx
->vb_offset
];
1072 _cairo_gl_operand_emit (&ctx
->operands
[CAIRO_GL_TEX_SOURCE
], &vb
, x
, y
);
1077 ctx
->vb_offset
+= ctx
->vertex_size
;
1081 _cairo_gl_composite_emit_glyph (cairo_gl_context_t
*ctx
,
1082 GLfloat x1
, GLfloat y1
,
1083 GLfloat x2
, GLfloat y2
,
1084 GLfloat glyph_x1
, GLfloat glyph_y1
,
1085 GLfloat glyph_x2
, GLfloat glyph_y2
)
1087 _cairo_gl_composite_prepare_buffer (ctx
, 6,
1088 CAIRO_GL_PRIMITIVE_TYPE_TRIANGLES
);
1090 _cairo_gl_composite_emit_glyph_vertex (ctx
, x1
, y1
, glyph_x1
, glyph_y1
);
1091 _cairo_gl_composite_emit_glyph_vertex (ctx
, x2
, y1
, glyph_x2
, glyph_y1
);
1092 _cairo_gl_composite_emit_glyph_vertex (ctx
, x1
, y2
, glyph_x1
, glyph_y2
);
1094 _cairo_gl_composite_emit_glyph_vertex (ctx
, x2
, y1
, glyph_x2
, glyph_y1
);
1095 _cairo_gl_composite_emit_glyph_vertex (ctx
, x2
, y2
, glyph_x2
, glyph_y2
);
1096 _cairo_gl_composite_emit_glyph_vertex (ctx
, x1
, y2
, glyph_x1
, glyph_y2
);
1100 _cairo_gl_composite_emit_solid_glyph (cairo_gl_context_t
*ctx
,
1101 GLfloat x1
, GLfloat y1
,
1102 GLfloat x2
, GLfloat y2
,
1103 GLfloat glyph_x1
, GLfloat glyph_y1
,
1104 GLfloat glyph_x2
, GLfloat glyph_y2
)
1108 _cairo_gl_composite_prepare_buffer (ctx
, 6,
1109 CAIRO_GL_PRIMITIVE_TYPE_TRIANGLES
);
1111 v
= (GLfloat
*) (void *) &ctx
->vb
[ctx
->vb_offset
];
1113 v
[20] = v
[ 8] = v
[0] = x1
;
1114 v
[13] = v
[ 5] = v
[1] = y1
;
1115 v
[22] = v
[10] = v
[2] = glyph_x1
;
1116 v
[15] = v
[ 7] = v
[3] = glyph_y1
;
1118 v
[16] = v
[12] = v
[4] = x2
;
1119 v
[18] = v
[14] = v
[6] = glyph_x2
;
1121 v
[21] = v
[17] = v
[ 9] = y2
;
1122 v
[23] = v
[19] = v
[11] = glyph_y2
;
1124 ctx
->vb_offset
+= 4 * 6 * sizeof (GLfloat
);
1127 cairo_gl_emit_glyph_t
1128 _cairo_gl_context_choose_emit_glyph (cairo_gl_context_t
*ctx
)
1130 switch (ctx
->operands
[CAIRO_GL_TEX_SOURCE
].type
) {
1132 case CAIRO_GL_OPERAND_COUNT
:
1134 case CAIRO_GL_OPERAND_NONE
:
1135 case CAIRO_GL_OPERAND_CONSTANT
:
1136 return _cairo_gl_composite_emit_solid_glyph
;
1138 case CAIRO_GL_OPERAND_LINEAR_GRADIENT
:
1139 case CAIRO_GL_OPERAND_RADIAL_GRADIENT_A0
:
1140 case CAIRO_GL_OPERAND_RADIAL_GRADIENT_NONE
:
1141 case CAIRO_GL_OPERAND_RADIAL_GRADIENT_EXT
:
1142 case CAIRO_GL_OPERAND_TEXTURE
:
1143 return _cairo_gl_composite_emit_glyph
;
1148 _cairo_gl_composite_fini (cairo_gl_composite_t
*setup
)
1150 _cairo_gl_operand_destroy (&setup
->src
);
1151 _cairo_gl_operand_destroy (&setup
->mask
);
1155 _cairo_gl_composite_set_operator (cairo_gl_composite_t
*setup
,
1156 cairo_operator_t op
,
1157 cairo_bool_t assume_component_alpha
)
1159 if (assume_component_alpha
) {
1160 if (op
!= CAIRO_OPERATOR_CLEAR
&&
1161 op
!= CAIRO_OPERATOR_OVER
&&
1162 op
!= CAIRO_OPERATOR_ADD
)
1163 return UNSUPPORTED ("unsupported component alpha operator");
1165 if (! _cairo_gl_operator_is_supported (op
))
1166 return UNSUPPORTED ("unsupported operator");
1170 return CAIRO_STATUS_SUCCESS
;
1174 _cairo_gl_composite_init (cairo_gl_composite_t
*setup
,
1175 cairo_operator_t op
,
1176 cairo_gl_surface_t
*dst
,
1177 cairo_bool_t assume_component_alpha
)
1179 cairo_status_t status
;
1181 memset (setup
, 0, sizeof (cairo_gl_composite_t
));
1183 status
= _cairo_gl_composite_set_operator (setup
, op
,
1184 assume_component_alpha
);
1189 setup
->clip_region
= dst
->clip_region
;
1191 return CAIRO_STATUS_SUCCESS
;
1194 static cairo_int_status_t
1195 _cairo_gl_composite_append_vertex_indices (cairo_gl_context_t
*ctx
,
1196 int number_of_new_indices
)
1198 cairo_int_status_t status
= CAIRO_INT_STATUS_SUCCESS
;
1199 cairo_array_t
*indices
= &ctx
->tristrip_indices
;
1200 int number_of_indices
= _cairo_array_num_elements (indices
);
1201 unsigned short current_vertex_index
= 0;
1204 assert (number_of_new_indices
> 0);
1206 /* If any preexisting triangle triangle strip indices exist on this
1207 context, we insert a set of degenerate triangles from the last
1208 preexisting vertex to our first one. */
1209 if (number_of_indices
> 0) {
1210 const unsigned short *indices_array
= _cairo_array_index_const (indices
, 0);
1211 current_vertex_index
= indices_array
[number_of_indices
- 1];
1213 status
= _cairo_array_append (indices
, ¤t_vertex_index
);
1214 if (unlikely (status
))
1217 current_vertex_index
++;
1218 status
=_cairo_array_append (indices
, ¤t_vertex_index
);
1219 if (unlikely (status
))
1223 for (i
= 0; i
< number_of_new_indices
; i
++) {
1224 status
= _cairo_array_append (indices
, ¤t_vertex_index
);
1225 current_vertex_index
++;
1226 if (unlikely (status
))
1230 return CAIRO_STATUS_SUCCESS
;
1234 _cairo_gl_composite_emit_quad_as_tristrip (cairo_gl_context_t
*ctx
,
1235 cairo_gl_composite_t
*setup
,
1236 const cairo_point_t quad
[4])
1238 _cairo_gl_composite_prepare_buffer (ctx
, 4,
1239 CAIRO_GL_PRIMITIVE_TYPE_TRISTRIPS
);
1241 _cairo_gl_composite_emit_point (ctx
, &quad
[0]);
1242 _cairo_gl_composite_emit_point (ctx
, &quad
[1]);
1244 /* Cairo stores quad vertices in counter-clockwise order, but we need to
1245 emit them from top to bottom in the triangle strip, so we need to reverse
1246 the order of the last two vertices. */
1247 _cairo_gl_composite_emit_point (ctx
, &quad
[3]);
1248 _cairo_gl_composite_emit_point (ctx
, &quad
[2]);
1250 return _cairo_gl_composite_append_vertex_indices (ctx
, 4);
1254 _cairo_gl_composite_emit_triangle_as_tristrip (cairo_gl_context_t
*ctx
,
1255 cairo_gl_composite_t
*setup
,
1256 const cairo_point_t triangle
[3])
1258 _cairo_gl_composite_prepare_buffer (ctx
, 3,
1259 CAIRO_GL_PRIMITIVE_TYPE_TRISTRIPS
);
1261 _cairo_gl_composite_emit_point (ctx
, &triangle
[0]);
1262 _cairo_gl_composite_emit_point (ctx
, &triangle
[1]);
1263 _cairo_gl_composite_emit_point (ctx
, &triangle
[2]);
1264 return _cairo_gl_composite_append_vertex_indices (ctx
, 3);