summaryrefslogtreecommitdiff
path: root/Build/source/libs/cairo/cairo-src/src/cairo-gl-composite.c
diff options
context:
space:
mode:
Diffstat (limited to 'Build/source/libs/cairo/cairo-src/src/cairo-gl-composite.c')
-rw-r--r--Build/source/libs/cairo/cairo-src/src/cairo-gl-composite.c1364
1 files changed, 0 insertions, 1364 deletions
diff --git a/Build/source/libs/cairo/cairo-src/src/cairo-gl-composite.c b/Build/source/libs/cairo/cairo-src/src/cairo-gl-composite.c
deleted file mode 100644
index 5477ef0d8ac..00000000000
--- a/Build/source/libs/cairo/cairo-src/src/cairo-gl-composite.c
+++ /dev/null
@@ -1,1364 +0,0 @@
-/* cairo - a vector graphics library with display and print output
- *
- * Copyright © 2009 Eric Anholt
- * Copyright © 2009 Chris Wilson
- * Copyright © 2005,2010 Red Hat, Inc
- * Copyright © 2011 Linaro Limited
- * Copyright © 2011 Samsung Electronics
- *
- * This library is free software; you can redistribute it and/or
- * modify it either under the terms of the GNU Lesser General Public
- * License version 2.1 as published by the Free Software Foundation
- * (the "LGPL") or, at your option, under the terms of the Mozilla
- * Public License Version 1.1 (the "MPL"). If you do not alter this
- * notice, a recipient may use your version of this file under either
- * the MPL or the LGPL.
- *
- * You should have received a copy of the LGPL along with this library
- * in the file COPYING-LGPL-2.1; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin Street, Suite 500, Boston, MA 02110-1335, USA
- * You should have received a copy of the MPL along with this library
- * in the file COPYING-MPL-1.1
- *
- * The contents of this file are subject to the Mozilla Public License
- * Version 1.1 (the "License"); you may not use this file except in
- * compliance with the License. You may obtain a copy of the License at
- * http://www.mozilla.org/MPL/
- *
- * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY
- * OF ANY KIND, either express or implied. See the LGPL or the MPL for
- * the specific language governing rights and limitations.
- *
- * The Original Code is the cairo graphics library.
- *
- * The Initial Developer of the Original Code is Red Hat, Inc.
- *
- * Contributor(s):
- * Benjamin Otte <otte@gnome.org>
- * Carl Worth <cworth@cworth.org>
- * Chris Wilson <chris@chris-wilson.co.uk>
- * Eric Anholt <eric@anholt.net>
- * Alexandros Frantzis <alexandros.frantzis@linaro.org>
- * Henry Song <hsong@sisa.samsung.com>
- * Martin Robinson <mrobinson@igalia.com>
- */
-
-#include "cairoint.h"
-
-#include "cairo-gl-private.h"
-
-#include "cairo-composite-rectangles-private.h"
-#include "cairo-clip-private.h"
-#include "cairo-error-private.h"
-#include "cairo-image-surface-private.h"
-
-/* FIXME: Copy of same routine in cairo-gl-msaa-compositor.c */
-static cairo_int_status_t
-_draw_int_rect (cairo_gl_context_t *ctx,
- cairo_gl_composite_t *setup,
- cairo_rectangle_int_t *rect)
-{
- cairo_box_t box;
- cairo_point_t quad[4];
-
- _cairo_box_from_rectangle (&box, rect);
- quad[0].x = box.p1.x;
- quad[0].y = box.p1.y;
- quad[1].x = box.p1.x;
- quad[1].y = box.p2.y;
- quad[2].x = box.p2.x;
- quad[2].y = box.p2.y;
- quad[3].x = box.p2.x;
- quad[3].y = box.p1.y;
-
- return _cairo_gl_composite_emit_quad_as_tristrip (ctx, setup, quad);
-}
-
-static cairo_int_status_t
-_blit_texture_to_renderbuffer (cairo_gl_surface_t *surface)
-{
- cairo_gl_context_t *ctx = NULL;
- cairo_gl_composite_t setup;
- cairo_surface_pattern_t pattern;
- cairo_rectangle_int_t extents;
- cairo_int_status_t status;
-
- /* FIXME: This only permits blit when glesv3 is enabled. But note that
- glesv2 with the ANGLE extension should also be able to support this feature,
- so once the ANGLE support code is in place this check can be relaxed. */
- if (((cairo_gl_context_t *)surface->base.device)->gl_flavor != CAIRO_GL_FLAVOR_ES3)
- return CAIRO_INT_STATUS_SUCCESS;
-
- if (! surface->content_in_texture)
- return CAIRO_INT_STATUS_SUCCESS;
-
- memset (&setup, 0, sizeof (cairo_gl_composite_t));
-
- status = _cairo_gl_composite_set_operator (&setup,
- CAIRO_OPERATOR_SOURCE,
- FALSE);
-
- if (status)
- return status;
-
- setup.dst = surface;
- setup.clip_region = surface->clip_region;
-
- _cairo_pattern_init_for_surface (&pattern, &surface->base);
- status = _cairo_gl_composite_set_source (&setup, &pattern.base,
- NULL, NULL, FALSE);
- _cairo_pattern_fini (&pattern.base);
-
- if (unlikely (status))
- goto FAIL;
-
- _cairo_gl_composite_set_multisample (&setup);
-
- status = _cairo_gl_composite_begin (&setup, &ctx);
-
- if (unlikely (status))
- goto FAIL;
-
- extents.x = extents.y = 0;
- extents.width = surface->width;
- extents.height = surface->height;
-
- status = _draw_int_rect (ctx, &setup, &extents);
-
- if (status == CAIRO_INT_STATUS_SUCCESS)
- surface->content_in_texture = FALSE;
-
-FAIL:
- _cairo_gl_composite_fini (&setup);
-
- if (ctx) {
- _cairo_gl_composite_flush (ctx);
- status = _cairo_gl_context_release (ctx, status);
- }
-
- return status;
-}
-
-cairo_int_status_t
-_cairo_gl_composite_set_source (cairo_gl_composite_t *setup,
- const cairo_pattern_t *pattern,
- const cairo_rectangle_int_t *sample,
- const cairo_rectangle_int_t *extents,
- cairo_bool_t use_texgen)
-{
- _cairo_gl_operand_destroy (&setup->src);
- return _cairo_gl_operand_init (&setup->src, pattern, setup->dst,
- sample, extents, use_texgen);
-}
-
-void
-_cairo_gl_composite_set_source_operand (cairo_gl_composite_t *setup,
- const cairo_gl_operand_t *source)
-{
- cairo_int_status_t status;
-
- _cairo_gl_operand_destroy (&setup->src);
- _cairo_gl_operand_copy (&setup->src, source);
-
- if (source->type == CAIRO_GL_OPERAND_TEXTURE)
- status = _cairo_gl_surface_resolve_multisampling (source->texture.surface);
-}
-
-void
-_cairo_gl_composite_set_solid_source (cairo_gl_composite_t *setup,
- const cairo_color_t *color)
-{
- _cairo_gl_operand_destroy (&setup->src);
- _cairo_gl_solid_operand_init (&setup->src, color);
-}
-
-cairo_int_status_t
-_cairo_gl_composite_set_mask (cairo_gl_composite_t *setup,
- const cairo_pattern_t *pattern,
- const cairo_rectangle_int_t *sample,
- const cairo_rectangle_int_t *extents,
- cairo_bool_t use_texgen)
-{
- _cairo_gl_operand_destroy (&setup->mask);
- if (pattern == NULL)
- return CAIRO_STATUS_SUCCESS;
-
- return _cairo_gl_operand_init (&setup->mask, pattern, setup->dst,
- sample, extents, use_texgen);
-}
-
-void
-_cairo_gl_composite_set_mask_operand (cairo_gl_composite_t *setup,
- const cairo_gl_operand_t *mask)
-{
- cairo_int_status_t status;
- _cairo_gl_operand_destroy (&setup->mask);
- if (mask) {
- _cairo_gl_operand_copy (&setup->mask, mask);
- if (mask->type == CAIRO_GL_OPERAND_TEXTURE)
- status = _cairo_gl_surface_resolve_multisampling (mask->texture.surface);
- }
-}
-
-void
-_cairo_gl_composite_set_spans (cairo_gl_composite_t *setup)
-{
- setup->spans = TRUE;
-}
-
-void
-_cairo_gl_composite_set_multisample (cairo_gl_composite_t *setup)
-{
- setup->multisample = TRUE;
-}
-
-void
-_cairo_gl_composite_set_clip_region (cairo_gl_composite_t *setup,
- cairo_region_t *clip_region)
-{
- setup->clip_region = clip_region;
-}
-
-void
-_cairo_gl_composite_set_clip (cairo_gl_composite_t *setup,
- cairo_clip_t *clip)
-{
- setup->clip = clip;
-}
-
-static void
-_cairo_gl_composite_bind_to_shader (cairo_gl_context_t *ctx,
- cairo_gl_composite_t *setup)
-{
- _cairo_gl_shader_bind_matrix4f(ctx, ctx->current_shader->mvp_location,
- ctx->modelviewprojection_matrix);
- _cairo_gl_operand_bind_to_shader (ctx, &setup->src, CAIRO_GL_TEX_SOURCE);
- _cairo_gl_operand_bind_to_shader (ctx, &setup->mask, CAIRO_GL_TEX_MASK);
-}
-
-static void
-_cairo_gl_texture_set_filter (cairo_gl_context_t *ctx,
- GLuint target,
- cairo_filter_t filter)
-{
- switch (filter) {
- case CAIRO_FILTER_FAST:
- case CAIRO_FILTER_NEAREST:
- glTexParameteri (target, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
- glTexParameteri (target, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
- break;
- case CAIRO_FILTER_GOOD:
- case CAIRO_FILTER_BEST:
- case CAIRO_FILTER_BILINEAR:
- glTexParameteri (target, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
- glTexParameteri (target, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
- break;
- default:
- case CAIRO_FILTER_GAUSSIAN:
- ASSERT_NOT_REACHED;
- }
-}
-
-static void
-_cairo_gl_texture_set_extend (cairo_gl_context_t *ctx,
- GLuint target,
- cairo_extend_t extend)
-{
- GLint wrap_mode;
- assert (! _cairo_gl_device_requires_power_of_two_textures (&ctx->base) ||
- (extend != CAIRO_EXTEND_REPEAT && extend != CAIRO_EXTEND_REFLECT));
-
- switch (extend) {
- case CAIRO_EXTEND_NONE:
- if (ctx->gl_flavor == CAIRO_GL_FLAVOR_ES3 ||
- ctx->gl_flavor == CAIRO_GL_FLAVOR_ES2)
- wrap_mode = GL_CLAMP_TO_EDGE;
- else
- wrap_mode = GL_CLAMP_TO_BORDER;
- break;
- case CAIRO_EXTEND_PAD:
- wrap_mode = GL_CLAMP_TO_EDGE;
- break;
- case CAIRO_EXTEND_REPEAT:
- if (ctx->has_npot_repeat)
- wrap_mode = GL_REPEAT;
- else
- wrap_mode = GL_CLAMP_TO_EDGE;
- break;
- case CAIRO_EXTEND_REFLECT:
- if (ctx->has_npot_repeat)
- wrap_mode = GL_MIRRORED_REPEAT;
- else
- wrap_mode = GL_CLAMP_TO_EDGE;
- break;
- default:
- wrap_mode = 0;
- }
-
- if (likely (wrap_mode)) {
- glTexParameteri (target, GL_TEXTURE_WRAP_S, wrap_mode);
- glTexParameteri (target, GL_TEXTURE_WRAP_T, wrap_mode);
- }
-}
-
-
-static void
-_cairo_gl_context_setup_operand (cairo_gl_context_t *ctx,
- cairo_gl_tex_t tex_unit,
- cairo_gl_operand_t *operand,
- unsigned int vertex_offset,
- cairo_bool_t vertex_size_changed)
-{
- cairo_gl_dispatch_t *dispatch = &ctx->dispatch;
- cairo_bool_t needs_setup;
-
- /* XXX: we need to do setup when switching from shaders
- * to no shaders (or back) */
- needs_setup = vertex_size_changed;
- needs_setup |= _cairo_gl_operand_needs_setup (&ctx->operands[tex_unit],
- operand,
- vertex_offset);
-
- if (needs_setup) {
- _cairo_gl_composite_flush (ctx);
- _cairo_gl_context_destroy_operand (ctx, tex_unit);
- }
-
- memcpy (&ctx->operands[tex_unit], operand, sizeof (cairo_gl_operand_t));
- ctx->operands[tex_unit].vertex_offset = vertex_offset;
-
- if (! needs_setup)
- return;
-
- switch (operand->type) {
- default:
- case CAIRO_GL_OPERAND_COUNT:
- ASSERT_NOT_REACHED;
- case CAIRO_GL_OPERAND_NONE:
- break;
- /* fall through */
- case CAIRO_GL_OPERAND_CONSTANT:
- break;
- case CAIRO_GL_OPERAND_TEXTURE:
- glActiveTexture (GL_TEXTURE0 + tex_unit);
- glBindTexture (ctx->tex_target, operand->texture.tex);
- _cairo_gl_texture_set_extend (ctx, ctx->tex_target,
- operand->texture.attributes.extend);
- _cairo_gl_texture_set_filter (ctx, ctx->tex_target,
- operand->texture.attributes.filter);
-
- if (! operand->texture.texgen) {
- dispatch->VertexAttribPointer (CAIRO_GL_TEXCOORD0_ATTRIB_INDEX + tex_unit, 2,
- GL_FLOAT, GL_FALSE, ctx->vertex_size,
- ctx->vb + vertex_offset);
- dispatch->EnableVertexAttribArray (CAIRO_GL_TEXCOORD0_ATTRIB_INDEX + tex_unit);
- }
- break;
- case CAIRO_GL_OPERAND_LINEAR_GRADIENT:
- case CAIRO_GL_OPERAND_RADIAL_GRADIENT_A0:
- case CAIRO_GL_OPERAND_RADIAL_GRADIENT_NONE:
- case CAIRO_GL_OPERAND_RADIAL_GRADIENT_EXT:
- glActiveTexture (GL_TEXTURE0 + tex_unit);
- glBindTexture (ctx->tex_target, operand->gradient.gradient->tex);
- _cairo_gl_texture_set_extend (ctx, ctx->tex_target, operand->gradient.extend);
- _cairo_gl_texture_set_filter (ctx, ctx->tex_target, CAIRO_FILTER_BILINEAR);
-
- if (! operand->gradient.texgen) {
- dispatch->VertexAttribPointer (CAIRO_GL_TEXCOORD0_ATTRIB_INDEX + tex_unit, 2,
- GL_FLOAT, GL_FALSE, ctx->vertex_size,
- ctx->vb + vertex_offset);
- dispatch->EnableVertexAttribArray (CAIRO_GL_TEXCOORD0_ATTRIB_INDEX + tex_unit);
- }
- break;
- }
-}
-
-static void
-_cairo_gl_context_setup_spans (cairo_gl_context_t *ctx,
- cairo_bool_t spans_enabled,
- unsigned int vertex_size,
- unsigned int vertex_offset)
-{
- cairo_gl_dispatch_t *dispatch = &ctx->dispatch;
-
- if (! spans_enabled) {
- dispatch->DisableVertexAttribArray (CAIRO_GL_COLOR_ATTRIB_INDEX);
- ctx->spans = FALSE;
- return;
- }
-
- dispatch->VertexAttribPointer (CAIRO_GL_COLOR_ATTRIB_INDEX, 4,
- GL_UNSIGNED_BYTE, GL_TRUE, vertex_size,
- ctx->vb + vertex_offset);
- dispatch->EnableVertexAttribArray (CAIRO_GL_COLOR_ATTRIB_INDEX);
- ctx->spans = TRUE;
-}
-
-void
-_cairo_gl_context_destroy_operand (cairo_gl_context_t *ctx,
- cairo_gl_tex_t tex_unit)
-{
- cairo_gl_dispatch_t *dispatch = &ctx->dispatch;
-
- if (!_cairo_gl_context_is_flushed (ctx))
- _cairo_gl_composite_flush (ctx);
-
- switch (ctx->operands[tex_unit].type) {
- default:
- case CAIRO_GL_OPERAND_COUNT:
- ASSERT_NOT_REACHED;
- case CAIRO_GL_OPERAND_NONE:
- break;
- /* fall through */
- case CAIRO_GL_OPERAND_CONSTANT:
- break;
- case CAIRO_GL_OPERAND_TEXTURE:
- dispatch->DisableVertexAttribArray (CAIRO_GL_TEXCOORD0_ATTRIB_INDEX + tex_unit);
- break;
- case CAIRO_GL_OPERAND_LINEAR_GRADIENT:
- case CAIRO_GL_OPERAND_RADIAL_GRADIENT_A0:
- case CAIRO_GL_OPERAND_RADIAL_GRADIENT_NONE:
- case CAIRO_GL_OPERAND_RADIAL_GRADIENT_EXT:
- dispatch->DisableVertexAttribArray (CAIRO_GL_TEXCOORD0_ATTRIB_INDEX + tex_unit);
- break;
- }
-
- memset (&ctx->operands[tex_unit], 0, sizeof (cairo_gl_operand_t));
-}
-
-static void
-_cairo_gl_set_operator (cairo_gl_context_t *ctx,
- cairo_operator_t op,
- cairo_bool_t component_alpha)
-{
- struct {
- GLenum src;
- GLenum dst;
- } blend_factors[] = {
- { GL_ZERO, GL_ZERO }, /* Clear */
- { GL_ONE, GL_ZERO }, /* Source */
- { GL_ONE, GL_ONE_MINUS_SRC_ALPHA }, /* Over */
- { GL_DST_ALPHA, GL_ZERO }, /* In */
- { GL_ONE_MINUS_DST_ALPHA, GL_ZERO }, /* Out */
- { GL_DST_ALPHA, GL_ONE_MINUS_SRC_ALPHA }, /* Atop */
-
- { GL_ZERO, GL_ONE }, /* Dest */
- { GL_ONE_MINUS_DST_ALPHA, GL_ONE }, /* DestOver */
- { GL_ZERO, GL_SRC_ALPHA }, /* DestIn */
- { GL_ZERO, GL_ONE_MINUS_SRC_ALPHA }, /* DestOut */
- { GL_ONE_MINUS_DST_ALPHA, GL_SRC_ALPHA }, /* DestAtop */
-
- { GL_ONE_MINUS_DST_ALPHA, GL_ONE_MINUS_SRC_ALPHA }, /* Xor */
- { GL_ONE, GL_ONE }, /* Add */
- };
- GLenum src_factor, dst_factor;
-
- assert (op < ARRAY_LENGTH (blend_factors));
- /* different dst and component_alpha changes cause flushes elsewhere */
- if (ctx->current_operator != op)
- _cairo_gl_composite_flush (ctx);
- ctx->current_operator = op;
-
- src_factor = blend_factors[op].src;
- dst_factor = blend_factors[op].dst;
-
- /* Even when the user requests CAIRO_CONTENT_COLOR, we use GL_RGBA
- * due to texture filtering of GL_CLAMP_TO_BORDER. So fix those
- * bits in that case.
- */
- if (ctx->current_target->base.content == CAIRO_CONTENT_COLOR) {
- if (src_factor == GL_ONE_MINUS_DST_ALPHA)
- src_factor = GL_ZERO;
- if (src_factor == GL_DST_ALPHA)
- src_factor = GL_ONE;
- }
-
- if (component_alpha) {
- if (dst_factor == GL_ONE_MINUS_SRC_ALPHA)
- dst_factor = GL_ONE_MINUS_SRC_COLOR;
- if (dst_factor == GL_SRC_ALPHA)
- dst_factor = GL_SRC_COLOR;
- }
-
- if (ctx->current_target->base.content == CAIRO_CONTENT_ALPHA) {
- glBlendFuncSeparate (GL_ZERO, GL_ZERO, src_factor, dst_factor);
- } else if (ctx->current_target->base.content == CAIRO_CONTENT_COLOR) {
- glBlendFuncSeparate (src_factor, dst_factor, GL_ONE, GL_ONE);
- } else {
- glBlendFunc (src_factor, dst_factor);
- }
-}
-
-static cairo_status_t
-_cairo_gl_composite_begin_component_alpha (cairo_gl_context_t *ctx,
- cairo_gl_composite_t *setup)
-{
- cairo_gl_shader_t *pre_shader = NULL;
- cairo_status_t status;
-
- /* For CLEAR, cairo's rendering equation (quoting Owen's description in:
- * https://lists.cairographics.org/archives/cairo/2005-August/004992.html)
- * is:
- * mask IN clip ? src OP dest : dest
- * or more simply:
- * mask IN CLIP ? 0 : dest
- *
- * where the ternary operator A ? B : C is (A * B) + ((1 - A) * C).
- *
- * The model we use in _cairo_gl_set_operator() is Render's:
- * src IN mask IN clip OP dest
- * which would boil down to:
- * 0 (bounded by the extents of the drawing).
- *
- * However, we can do a Render operation using an opaque source
- * and DEST_OUT to produce:
- * 1 IN mask IN clip DEST_OUT dest
- * which is
- * mask IN clip ? 0 : dest
- */
- if (setup->op == CAIRO_OPERATOR_CLEAR) {
- _cairo_gl_solid_operand_init (&setup->src, CAIRO_COLOR_WHITE);
- setup->op = CAIRO_OPERATOR_DEST_OUT;
- }
-
- /*
- * implements component-alpha %CAIRO_OPERATOR_OVER using two passes of
- * the simpler operations %CAIRO_OPERATOR_DEST_OUT and %CAIRO_OPERATOR_ADD.
- *
- * From http://anholt.livejournal.com/32058.html:
- *
- * The trouble is that component-alpha rendering requires two different sources
- * for blending: one for the source value to the blender, which is the
- * per-channel multiplication of source and mask, and one for the source alpha
- * for multiplying with the destination channels, which is the multiplication
- * of the source channels by the mask alpha. So the equation for Over is:
- *
- * dst.A = src.A * mask.A + (1 - (src.A * mask.A)) * dst.A
- * dst.R = src.R * mask.R + (1 - (src.A * mask.R)) * dst.R
- * dst.G = src.G * mask.G + (1 - (src.A * mask.G)) * dst.G
- * dst.B = src.B * mask.B + (1 - (src.A * mask.B)) * dst.B
- *
- * But we can do some simpler operations, right? How about PictOpOutReverse,
- * which has a source factor of 0 and dest factor of (1 - source alpha). We
- * can get the source alpha value (srca.X = src.A * mask.X) out of the texture
- * blenders pretty easily. So we can do a component-alpha OutReverse, which
- * gets us:
- *
- * dst.A = 0 + (1 - (src.A * mask.A)) * dst.A
- * dst.R = 0 + (1 - (src.A * mask.R)) * dst.R
- * dst.G = 0 + (1 - (src.A * mask.G)) * dst.G
- * dst.B = 0 + (1 - (src.A * mask.B)) * dst.B
- *
- * OK. And if an op doesn't use the source alpha value for the destination
- * factor, then we can do the channel multiplication in the texture blenders
- * to get the source value, and ignore the source alpha that we wouldn't use.
- * We've supported this in the Radeon driver for a long time. An example would
- * be PictOpAdd, which does:
- *
- * dst.A = src.A * mask.A + dst.A
- * dst.R = src.R * mask.R + dst.R
- * dst.G = src.G * mask.G + dst.G
- * dst.B = src.B * mask.B + dst.B
- *
- * Hey, this looks good! If we do a PictOpOutReverse and then a PictOpAdd right
- * after it, we get:
- *
- * dst.A = src.A * mask.A + ((1 - (src.A * mask.A)) * dst.A)
- * dst.R = src.R * mask.R + ((1 - (src.A * mask.R)) * dst.R)
- * dst.G = src.G * mask.G + ((1 - (src.A * mask.G)) * dst.G)
- * dst.B = src.B * mask.B + ((1 - (src.A * mask.B)) * dst.B)
- *
- * This two-pass trickery could be avoided using a new GL extension that
- * lets two values come out of the shader and into the blend unit.
- */
- if (setup->op == CAIRO_OPERATOR_OVER) {
- setup->op = CAIRO_OPERATOR_ADD;
- status = _cairo_gl_get_shader_by_type (ctx,
- &setup->src,
- &setup->mask,
- setup->spans,
- CAIRO_GL_SHADER_IN_CA_SOURCE_ALPHA,
- &pre_shader);
- if (unlikely (status))
- return status;
- }
-
- if (ctx->pre_shader != pre_shader)
- _cairo_gl_composite_flush (ctx);
- ctx->pre_shader = pre_shader;
-
- return CAIRO_STATUS_SUCCESS;
-}
-
-static void
-_scissor_to_doubles (cairo_gl_surface_t *surface,
- double x1, double y1,
- double x2, double y2)
-{
- double height;
-
- height = y2 - y1;
- if (_cairo_gl_surface_is_texture (surface) == FALSE)
- y1 = surface->height - (y1 + height);
- glScissor (x1, y1, x2 - x1, height);
- glEnable (GL_SCISSOR_TEST);
-}
-
-void
-_cairo_gl_scissor_to_rectangle (cairo_gl_surface_t *surface,
- const cairo_rectangle_int_t *r)
-{
- _scissor_to_doubles (surface, r->x, r->y, r->x+r->width, r->y+r->height);
-}
-
-static void
-_scissor_to_box (cairo_gl_surface_t *surface,
- const cairo_box_t *box)
-{
- double x1, y1, x2, y2;
- _cairo_box_to_doubles (box, &x1, &y1, &x2, &y2);
- _scissor_to_doubles (surface, x1, y1, x2, y2);
-}
-
-static cairo_bool_t
-_cairo_gl_composite_setup_vbo (cairo_gl_context_t *ctx,
- unsigned int size_per_vertex)
-{
- cairo_bool_t vertex_size_changed = ctx->vertex_size != size_per_vertex;
- if (vertex_size_changed) {
- ctx->vertex_size = size_per_vertex;
- _cairo_gl_composite_flush (ctx);
- }
-
- if (_cairo_gl_context_is_flushed (ctx)) {
- ctx->dispatch.VertexAttribPointer (CAIRO_GL_VERTEX_ATTRIB_INDEX, 2,
- GL_FLOAT, GL_FALSE, size_per_vertex,
- ctx->vb);
- ctx->dispatch.EnableVertexAttribArray (CAIRO_GL_VERTEX_ATTRIB_INDEX);
- }
-
- return vertex_size_changed;
-}
-
-static void
-_disable_stencil_buffer (void)
-{
- glDisable (GL_STENCIL_TEST);
- glDepthMask (GL_FALSE);
-}
-
-static cairo_int_status_t
-_cairo_gl_composite_setup_painted_clipping (cairo_gl_composite_t *setup,
- cairo_gl_context_t *ctx,
- int vertex_size)
-{
- cairo_int_status_t status = CAIRO_INT_STATUS_SUCCESS;
-
- cairo_gl_surface_t *dst = setup->dst;
- cairo_clip_t *clip = setup->clip;
-
- if (clip->num_boxes == 1 && clip->path == NULL) {
- _scissor_to_box (dst, &clip->boxes[0]);
- goto disable_stencil_buffer_and_return;
- }
-
- if (! _cairo_gl_ensure_stencil (ctx, setup->dst)) {
- status = CAIRO_INT_STATUS_UNSUPPORTED;
- goto disable_stencil_buffer_and_return;
- }
-
- /* We only want to clear the part of the stencil buffer
- * that we are about to use. It also does not hurt to
- * scissor around the painted clip. */
- _cairo_gl_scissor_to_rectangle (dst, _cairo_clip_get_extents (clip));
-
- /* The clip is not rectangular, so use the stencil buffer. */
- glDepthMask (GL_TRUE);
- glEnable (GL_STENCIL_TEST);
-
- /* Texture surfaces have private depth/stencil buffers, so we can
- * rely on any previous clip being cached there. */
- if (_cairo_gl_surface_is_texture (setup->dst)) {
- cairo_clip_t *old_clip = setup->dst->clip_on_stencil_buffer;
- if (_cairo_clip_equal (old_clip, setup->clip))
- goto activate_stencil_buffer_and_return;
-
- if (old_clip) {
- _cairo_clip_destroy (setup->dst->clip_on_stencil_buffer);
- }
-
- setup->dst->clip_on_stencil_buffer = _cairo_clip_copy (setup->clip);
- }
-
- glClearStencil (0);
- glClear (GL_STENCIL_BUFFER_BIT);
-
- glStencilOp (GL_REPLACE, GL_REPLACE, GL_REPLACE);
- glStencilFunc (GL_EQUAL, 1, 0xffffffff);
- glColorMask (0, 0, 0, 0);
-
- status = _cairo_gl_msaa_compositor_draw_clip (ctx, setup, clip);
-
- if (unlikely (status)) {
- glColorMask (1, 1, 1, 1);
- goto disable_stencil_buffer_and_return;
- }
-
- /* We want to only render to the stencil buffer, so draw everything now.
- Flushing also unbinds the VBO, which we want to rebind for regular
- drawing. */
- _cairo_gl_composite_flush (ctx);
- _cairo_gl_composite_setup_vbo (ctx, vertex_size);
-
-activate_stencil_buffer_and_return:
- glColorMask (1, 1, 1, 1);
- glStencilOp (GL_KEEP, GL_KEEP, GL_KEEP);
- glStencilFunc (GL_EQUAL, 1, 0xffffffff);
- return CAIRO_INT_STATUS_SUCCESS;
-
-disable_stencil_buffer_and_return:
- _disable_stencil_buffer ();
- return status;
-}
-
-static cairo_int_status_t
-_cairo_gl_composite_setup_clipping (cairo_gl_composite_t *setup,
- cairo_gl_context_t *ctx,
- int vertex_size)
-{
- cairo_bool_t clip_changing = TRUE;
- cairo_bool_t clip_region_changing = TRUE;
-
- if (! ctx->clip && ! setup->clip && ! setup->clip_region && ! ctx->clip_region)
- goto disable_all_clipping;
-
- clip_changing = ! _cairo_clip_equal (ctx->clip, setup->clip);
- clip_region_changing = ! cairo_region_equal (ctx->clip_region, setup->clip_region);
- if (! _cairo_gl_context_is_flushed (ctx) &&
- (clip_region_changing || clip_changing))
- _cairo_gl_composite_flush (ctx);
-
- assert (!setup->clip_region || !setup->clip);
-
- /* setup->clip is only used by the msaa compositor and setup->clip_region
- * only by the other compositors, so it's safe to wait to clean up obsolete
- * clips. */
- if (clip_region_changing) {
- cairo_region_destroy (ctx->clip_region);
- ctx->clip_region = cairo_region_reference (setup->clip_region);
- }
- if (clip_changing) {
- _cairo_clip_destroy (ctx->clip);
- ctx->clip = _cairo_clip_copy (setup->clip);
- }
-
- /* For clip regions, we scissor right before drawing. */
- if (setup->clip_region)
- goto disable_all_clipping;
-
- if (setup->clip)
- return _cairo_gl_composite_setup_painted_clipping (setup, ctx,
- vertex_size);
-disable_all_clipping:
- _disable_stencil_buffer ();
- glDisable (GL_SCISSOR_TEST);
- return CAIRO_INT_STATUS_SUCCESS;
-}
-
-cairo_status_t
-_cairo_gl_set_operands_and_operator (cairo_gl_composite_t *setup,
- cairo_gl_context_t *ctx)
-{
- unsigned int dst_size, src_size, mask_size, vertex_size;
- cairo_status_t status;
- cairo_gl_shader_t *shader;
- cairo_bool_t component_alpha;
- cairo_bool_t vertex_size_changed;
-
- component_alpha =
- setup->mask.type == CAIRO_GL_OPERAND_TEXTURE &&
- setup->mask.texture.attributes.has_component_alpha;
-
- /* Do various magic for component alpha */
- if (component_alpha) {
- status = _cairo_gl_composite_begin_component_alpha (ctx, setup);
- if (unlikely (status))
- return status;
- } else {
- if (ctx->pre_shader) {
- _cairo_gl_composite_flush (ctx);
- ctx->pre_shader = NULL;
- }
- }
-
- status = _cairo_gl_get_shader_by_type (ctx,
- &setup->src,
- &setup->mask,
- setup->spans,
- component_alpha ?
- CAIRO_GL_SHADER_IN_CA_SOURCE :
- CAIRO_GL_SHADER_IN_NORMAL,
- &shader);
- if (unlikely (status)) {
- ctx->pre_shader = NULL;
- return status;
- }
- if (ctx->current_shader != shader)
- _cairo_gl_composite_flush (ctx);
-
- status = CAIRO_STATUS_SUCCESS;
-
- dst_size = 2 * sizeof (GLfloat);
- src_size = _cairo_gl_operand_get_vertex_size (&setup->src);
- mask_size = _cairo_gl_operand_get_vertex_size (&setup->mask);
- vertex_size = dst_size + src_size + mask_size;
-
- if (setup->spans)
- vertex_size += sizeof (GLfloat);
-
- vertex_size_changed = _cairo_gl_composite_setup_vbo (ctx, vertex_size);
-
- _cairo_gl_context_setup_operand (ctx, CAIRO_GL_TEX_SOURCE, &setup->src, dst_size, vertex_size_changed);
- _cairo_gl_context_setup_operand (ctx, CAIRO_GL_TEX_MASK, &setup->mask, dst_size + src_size, vertex_size_changed);
-
- _cairo_gl_context_setup_spans (ctx, setup->spans, vertex_size,
- dst_size + src_size + mask_size);
-
- _cairo_gl_set_operator (ctx, setup->op, component_alpha);
-
- if (_cairo_gl_context_is_flushed (ctx)) {
- if (ctx->pre_shader) {
- _cairo_gl_set_shader (ctx, ctx->pre_shader);
- _cairo_gl_composite_bind_to_shader (ctx, setup);
- }
- _cairo_gl_set_shader (ctx, shader);
- _cairo_gl_composite_bind_to_shader (ctx, setup);
- }
-
- return status;
-}
-
-cairo_status_t
-_cairo_gl_composite_begin (cairo_gl_composite_t *setup,
- cairo_gl_context_t **ctx_out)
-{
- cairo_gl_context_t *ctx;
- cairo_status_t status;
-
- assert (setup->dst);
-
- status = _cairo_gl_context_acquire (setup->dst->base.device, &ctx);
- if (unlikely (status))
- return status;
-
- _cairo_gl_context_set_destination (ctx, setup->dst, setup->multisample);
- glEnable (GL_BLEND);
-
- status = _cairo_gl_set_operands_and_operator (setup, ctx);
- if (unlikely (status))
- goto FAIL;
-
- status = _cairo_gl_composite_setup_clipping (setup, ctx, ctx->vertex_size);
- if (unlikely (status))
- goto FAIL;
-
- *ctx_out = ctx;
-
-FAIL:
- if (unlikely (status))
- status = _cairo_gl_context_release (ctx, status);
-
- return status;
-}
-
-static inline void
-_cairo_gl_composite_draw_tristrip (cairo_gl_context_t *ctx)
-{
- cairo_array_t* indices = &ctx->tristrip_indices;
- const unsigned short *indices_array = _cairo_array_index_const (indices, 0);
-
- if (ctx->pre_shader) {
- cairo_gl_shader_t *prev_shader = ctx->current_shader;
-
- _cairo_gl_set_shader (ctx, ctx->pre_shader);
- _cairo_gl_set_operator (ctx, CAIRO_OPERATOR_DEST_OUT, TRUE);
- glDrawElements (GL_TRIANGLE_STRIP, _cairo_array_num_elements (indices), GL_UNSIGNED_SHORT, indices_array);
-
- _cairo_gl_set_shader (ctx, prev_shader);
- _cairo_gl_set_operator (ctx, CAIRO_OPERATOR_ADD, TRUE);
- }
-
- glDrawElements (GL_TRIANGLE_STRIP, _cairo_array_num_elements (indices), GL_UNSIGNED_SHORT, indices_array);
- _cairo_array_truncate (indices, 0);
-}
-
-static inline void
-_cairo_gl_composite_draw_triangles (cairo_gl_context_t *ctx,
- unsigned int count)
-{
- if (! ctx->pre_shader) {
- glDrawArrays (GL_TRIANGLES, 0, count);
- } else {
- cairo_gl_shader_t *prev_shader = ctx->current_shader;
-
- _cairo_gl_set_shader (ctx, ctx->pre_shader);
- _cairo_gl_set_operator (ctx, CAIRO_OPERATOR_DEST_OUT, TRUE);
- glDrawArrays (GL_TRIANGLES, 0, count);
-
- _cairo_gl_set_shader (ctx, prev_shader);
- _cairo_gl_set_operator (ctx, CAIRO_OPERATOR_ADD, TRUE);
- glDrawArrays (GL_TRIANGLES, 0, count);
- }
-}
-
-static void
-_cairo_gl_composite_draw_triangles_with_clip_region (cairo_gl_context_t *ctx,
- unsigned int count)
-{
- int i, num_rectangles;
-
- if (!ctx->clip_region) {
- _cairo_gl_composite_draw_triangles (ctx, count);
- return;
- }
-
- num_rectangles = cairo_region_num_rectangles (ctx->clip_region);
- for (i = 0; i < num_rectangles; i++) {
- cairo_rectangle_int_t rect;
-
- cairo_region_get_rectangle (ctx->clip_region, i, &rect);
-
- _cairo_gl_scissor_to_rectangle (ctx->current_target, &rect);
- _cairo_gl_composite_draw_triangles (ctx, count);
- }
-}
-
-static void
-_cairo_gl_composite_unmap_vertex_buffer (cairo_gl_context_t *ctx)
-{
- ctx->vb_offset = 0;
-}
-
-void
-_cairo_gl_composite_flush (cairo_gl_context_t *ctx)
-{
- unsigned int count;
- int i;
-
- if (_cairo_gl_context_is_flushed (ctx))
- return;
-
- count = ctx->vb_offset / ctx->vertex_size;
- _cairo_gl_composite_unmap_vertex_buffer (ctx);
-
- if (ctx->primitive_type == CAIRO_GL_PRIMITIVE_TYPE_TRISTRIPS) {
- _cairo_gl_composite_draw_tristrip (ctx);
- } else {
- assert (ctx->primitive_type == CAIRO_GL_PRIMITIVE_TYPE_TRIANGLES);
- _cairo_gl_composite_draw_triangles_with_clip_region (ctx, count);
- }
-
- for (i = 0; i < ARRAY_LENGTH (ctx->glyph_cache); i++)
- _cairo_gl_glyph_cache_unlock (&ctx->glyph_cache[i]);
-}
-
-static void
-_cairo_gl_composite_prepare_buffer (cairo_gl_context_t *ctx,
- unsigned int n_vertices,
- cairo_gl_primitive_type_t primitive_type)
-{
- if (ctx->primitive_type != primitive_type) {
- _cairo_gl_composite_flush (ctx);
- ctx->primitive_type = primitive_type;
- }
-
- assert(ctx->vbo_size > 0);
- if (ctx->vb_offset + n_vertices * ctx->vertex_size > ctx->vbo_size)
- _cairo_gl_composite_flush (ctx);
-}
-
-static inline void
-_cairo_gl_composite_emit_vertex (cairo_gl_context_t *ctx,
- GLfloat x, GLfloat y)
-{
- GLfloat *vb = (GLfloat *) (void *) &ctx->vb[ctx->vb_offset];
-
- *vb++ = x;
- *vb++ = y;
-
- _cairo_gl_operand_emit (&ctx->operands[CAIRO_GL_TEX_SOURCE], &vb, x, y);
- _cairo_gl_operand_emit (&ctx->operands[CAIRO_GL_TEX_MASK ], &vb, x, y);
-
- ctx->vb_offset += ctx->vertex_size;
-}
-
-static inline void
-_cairo_gl_composite_emit_alpha_vertex (cairo_gl_context_t *ctx,
- GLfloat x, GLfloat y, uint8_t alpha)
-{
- GLfloat *vb = (GLfloat *) (void *) &ctx->vb[ctx->vb_offset];
- union fi {
- float f;
- GLbyte bytes[4];
- } fi;
-
- *vb++ = x;
- *vb++ = y;
-
- _cairo_gl_operand_emit (&ctx->operands[CAIRO_GL_TEX_SOURCE], &vb, x, y);
- _cairo_gl_operand_emit (&ctx->operands[CAIRO_GL_TEX_MASK ], &vb, x, y);
-
- fi.bytes[0] = 0;
- fi.bytes[1] = 0;
- fi.bytes[2] = 0;
- fi.bytes[3] = alpha;
- *vb++ = fi.f;
-
- ctx->vb_offset += ctx->vertex_size;
-}
-
-static void
-_cairo_gl_composite_emit_point (cairo_gl_context_t *ctx,
- const cairo_point_t *point)
-{
- _cairo_gl_composite_emit_vertex (ctx,
- _cairo_fixed_to_double (point->x),
- _cairo_fixed_to_double (point->y));
-}
-
-static void
-_cairo_gl_composite_emit_rect (cairo_gl_context_t *ctx,
- GLfloat x1, GLfloat y1,
- GLfloat x2, GLfloat y2)
-{
- _cairo_gl_composite_prepare_buffer (ctx, 6,
- CAIRO_GL_PRIMITIVE_TYPE_TRIANGLES);
-
- _cairo_gl_composite_emit_vertex (ctx, x1, y1);
- _cairo_gl_composite_emit_vertex (ctx, x2, y1);
- _cairo_gl_composite_emit_vertex (ctx, x1, y2);
-
- _cairo_gl_composite_emit_vertex (ctx, x2, y1);
- _cairo_gl_composite_emit_vertex (ctx, x2, y2);
- _cairo_gl_composite_emit_vertex (ctx, x1, y2);
-}
-
-cairo_gl_emit_rect_t
-_cairo_gl_context_choose_emit_rect (cairo_gl_context_t *ctx)
-{
- return _cairo_gl_composite_emit_rect;
-}
-
-void
-_cairo_gl_context_emit_rect (cairo_gl_context_t *ctx,
- GLfloat x1, GLfloat y1,
- GLfloat x2, GLfloat y2)
-{
- _cairo_gl_composite_emit_rect (ctx, x1, y1, x2, y2);
-}
-
-static void
-_cairo_gl_composite_emit_span (cairo_gl_context_t *ctx,
- GLfloat x1, GLfloat y1,
- GLfloat x2, GLfloat y2,
- uint8_t alpha)
-{
- _cairo_gl_composite_prepare_buffer (ctx, 6,
- CAIRO_GL_PRIMITIVE_TYPE_TRIANGLES);
-
- _cairo_gl_composite_emit_alpha_vertex (ctx, x1, y1, alpha);
- _cairo_gl_composite_emit_alpha_vertex (ctx, x2, y1, alpha);
- _cairo_gl_composite_emit_alpha_vertex (ctx, x1, y2, alpha);
-
- _cairo_gl_composite_emit_alpha_vertex (ctx, x2, y1, alpha);
- _cairo_gl_composite_emit_alpha_vertex (ctx, x2, y2, alpha);
- _cairo_gl_composite_emit_alpha_vertex (ctx, x1, y2, alpha);
-}
-
-static void
-_cairo_gl_composite_emit_solid_span (cairo_gl_context_t *ctx,
- GLfloat x1, GLfloat y1,
- GLfloat x2, GLfloat y2,
- uint8_t alpha)
-{
- GLfloat *v;
- union fi {
- float f;
- GLbyte bytes[4];
- } fi;
-
- _cairo_gl_composite_prepare_buffer (ctx, 6,
- CAIRO_GL_PRIMITIVE_TYPE_TRIANGLES);
- v = (GLfloat *) (void *) &ctx->vb[ctx->vb_offset];
-
- v[15] = v[ 6] = v[0] = x1;
- v[10] = v[ 4] = v[1] = y1;
- v[12] = v[ 9] = v[3] = x2;
- v[16] = v[13] = v[7] = y2;
-
- fi.bytes[0] = 0;
- fi.bytes[1] = 0;
- fi.bytes[2] = 0;
- fi.bytes[3] = alpha;
- v[17] =v[14] = v[11] = v[8] = v[5] = v[2] = fi.f;
-
- ctx->vb_offset += 6*3 * sizeof(GLfloat);
-}
-
-cairo_gl_emit_span_t
-_cairo_gl_context_choose_emit_span (cairo_gl_context_t *ctx)
-{
- if (ctx->operands[CAIRO_GL_TEX_MASK].type != CAIRO_GL_OPERAND_NONE) {
- switch (ctx->operands[CAIRO_GL_TEX_MASK].type) {
- default:
- case CAIRO_GL_OPERAND_COUNT:
- ASSERT_NOT_REACHED;
- case CAIRO_GL_OPERAND_NONE:
- case CAIRO_GL_OPERAND_CONSTANT:
- break;
-
- case CAIRO_GL_OPERAND_LINEAR_GRADIENT:
- case CAIRO_GL_OPERAND_RADIAL_GRADIENT_A0:
- case CAIRO_GL_OPERAND_RADIAL_GRADIENT_NONE:
- case CAIRO_GL_OPERAND_RADIAL_GRADIENT_EXT:
- if (!ctx->operands[CAIRO_GL_TEX_MASK].gradient.texgen)
- return _cairo_gl_composite_emit_span;
- break;
-
- case CAIRO_GL_OPERAND_TEXTURE:
- if (!ctx->operands[CAIRO_GL_TEX_MASK].texture.texgen)
- return _cairo_gl_composite_emit_span;
- break;
- }
- }
-
- switch (ctx->operands[CAIRO_GL_TEX_SOURCE].type) {
- default:
- case CAIRO_GL_OPERAND_COUNT:
- ASSERT_NOT_REACHED;
- case CAIRO_GL_OPERAND_NONE:
- case CAIRO_GL_OPERAND_CONSTANT:
- break;
-
- case CAIRO_GL_OPERAND_LINEAR_GRADIENT:
- case CAIRO_GL_OPERAND_RADIAL_GRADIENT_A0:
- case CAIRO_GL_OPERAND_RADIAL_GRADIENT_NONE:
- case CAIRO_GL_OPERAND_RADIAL_GRADIENT_EXT:
- if (!ctx->operands[CAIRO_GL_TEX_SOURCE].gradient.texgen)
- return _cairo_gl_composite_emit_span;
- break;
-
- case CAIRO_GL_OPERAND_TEXTURE:
- if (!ctx->operands[CAIRO_GL_TEX_SOURCE].texture.texgen)
- return _cairo_gl_composite_emit_span;
- }
-
- return _cairo_gl_composite_emit_solid_span;
-}
-
-static inline void
-_cairo_gl_composite_emit_glyph_vertex (cairo_gl_context_t *ctx,
- GLfloat x, GLfloat y,
- GLfloat glyph_x, GLfloat glyph_y)
-{
- GLfloat *vb = (GLfloat *) (void *) &ctx->vb[ctx->vb_offset];
-
- *vb++ = x;
- *vb++ = y;
-
- _cairo_gl_operand_emit (&ctx->operands[CAIRO_GL_TEX_SOURCE], &vb, x, y);
-
- *vb++ = glyph_x;
- *vb++ = glyph_y;
-
- ctx->vb_offset += ctx->vertex_size;
-}
-
-static void
-_cairo_gl_composite_emit_glyph (cairo_gl_context_t *ctx,
- GLfloat x1, GLfloat y1,
- GLfloat x2, GLfloat y2,
- GLfloat glyph_x1, GLfloat glyph_y1,
- GLfloat glyph_x2, GLfloat glyph_y2)
-{
- _cairo_gl_composite_prepare_buffer (ctx, 6,
- CAIRO_GL_PRIMITIVE_TYPE_TRIANGLES);
-
- _cairo_gl_composite_emit_glyph_vertex (ctx, x1, y1, glyph_x1, glyph_y1);
- _cairo_gl_composite_emit_glyph_vertex (ctx, x2, y1, glyph_x2, glyph_y1);
- _cairo_gl_composite_emit_glyph_vertex (ctx, x1, y2, glyph_x1, glyph_y2);
-
- _cairo_gl_composite_emit_glyph_vertex (ctx, x2, y1, glyph_x2, glyph_y1);
- _cairo_gl_composite_emit_glyph_vertex (ctx, x2, y2, glyph_x2, glyph_y2);
- _cairo_gl_composite_emit_glyph_vertex (ctx, x1, y2, glyph_x1, glyph_y2);
-}
-
-static void
-_cairo_gl_composite_emit_solid_glyph (cairo_gl_context_t *ctx,
- GLfloat x1, GLfloat y1,
- GLfloat x2, GLfloat y2,
- GLfloat glyph_x1, GLfloat glyph_y1,
- GLfloat glyph_x2, GLfloat glyph_y2)
-{
- GLfloat *v;
-
- _cairo_gl_composite_prepare_buffer (ctx, 6,
- CAIRO_GL_PRIMITIVE_TYPE_TRIANGLES);
-
- v = (GLfloat *) (void *) &ctx->vb[ctx->vb_offset];
-
- v[20] = v[ 8] = v[0] = x1;
- v[13] = v[ 5] = v[1] = y1;
- v[22] = v[10] = v[2] = glyph_x1;
- v[15] = v[ 7] = v[3] = glyph_y1;
-
- v[16] = v[12] = v[4] = x2;
- v[18] = v[14] = v[6] = glyph_x2;
-
- v[21] = v[17] = v[ 9] = y2;
- v[23] = v[19] = v[11] = glyph_y2;
-
- ctx->vb_offset += 4 * 6 * sizeof (GLfloat);
-}
-
-cairo_gl_emit_glyph_t
-_cairo_gl_context_choose_emit_glyph (cairo_gl_context_t *ctx)
-{
- switch (ctx->operands[CAIRO_GL_TEX_SOURCE].type) {
- default:
- case CAIRO_GL_OPERAND_COUNT:
- ASSERT_NOT_REACHED;
- case CAIRO_GL_OPERAND_NONE:
- case CAIRO_GL_OPERAND_CONSTANT:
- return _cairo_gl_composite_emit_solid_glyph;
-
- case CAIRO_GL_OPERAND_LINEAR_GRADIENT:
- case CAIRO_GL_OPERAND_RADIAL_GRADIENT_A0:
- case CAIRO_GL_OPERAND_RADIAL_GRADIENT_NONE:
- case CAIRO_GL_OPERAND_RADIAL_GRADIENT_EXT:
- case CAIRO_GL_OPERAND_TEXTURE:
- return _cairo_gl_composite_emit_glyph;
- }
-}
-
-void
-_cairo_gl_composite_fini (cairo_gl_composite_t *setup)
-{
- _cairo_gl_operand_destroy (&setup->src);
- _cairo_gl_operand_destroy (&setup->mask);
-}
-
-cairo_status_t
-_cairo_gl_composite_set_operator (cairo_gl_composite_t *setup,
- cairo_operator_t op,
- cairo_bool_t assume_component_alpha)
-{
- if (assume_component_alpha) {
- if (op != CAIRO_OPERATOR_CLEAR &&
- op != CAIRO_OPERATOR_OVER &&
- op != CAIRO_OPERATOR_ADD)
- return UNSUPPORTED ("unsupported component alpha operator");
- } else {
- if (! _cairo_gl_operator_is_supported (op))
- return UNSUPPORTED ("unsupported operator");
- }
-
- setup->op = op;
- return CAIRO_STATUS_SUCCESS;
-}
-
-cairo_status_t
-_cairo_gl_composite_init (cairo_gl_composite_t *setup,
- cairo_operator_t op,
- cairo_gl_surface_t *dst,
- cairo_bool_t assume_component_alpha)
-{
- cairo_status_t status;
-
- status = _blit_texture_to_renderbuffer (dst);
-
- memset (setup, 0, sizeof (cairo_gl_composite_t));
-
- status = _cairo_gl_composite_set_operator (setup, op,
- assume_component_alpha);
- if (status)
- return status;
-
- setup->dst = dst;
- setup->clip_region = dst->clip_region;
-
- return CAIRO_STATUS_SUCCESS;
-}
-
-static cairo_int_status_t
-_cairo_gl_composite_append_vertex_indices (cairo_gl_context_t *ctx,
- int number_of_new_indices)
-{
- cairo_int_status_t status = CAIRO_INT_STATUS_SUCCESS;
- cairo_array_t *indices = &ctx->tristrip_indices;
- int number_of_indices = _cairo_array_num_elements (indices);
- unsigned short current_vertex_index = 0;
- int i;
-
- assert (number_of_new_indices > 0);
-
- /* If any preexisting triangle triangle strip indices exist on this
- context, we insert a set of degenerate triangles from the last
- preexisting vertex to our first one. */
- if (number_of_indices > 0) {
- const unsigned short *indices_array = _cairo_array_index_const (indices, 0);
- current_vertex_index = indices_array[number_of_indices - 1];
-
- status = _cairo_array_append (indices, &current_vertex_index);
- if (unlikely (status))
- return status;
-
- current_vertex_index++;
- status =_cairo_array_append (indices, &current_vertex_index);
- if (unlikely (status))
- return status;
- }
-
- for (i = 0; i < number_of_new_indices; i++) {
- status = _cairo_array_append (indices, &current_vertex_index);
- current_vertex_index++;
- if (unlikely (status))
- return status;
- }
-
- return CAIRO_STATUS_SUCCESS;
-}
-
-cairo_int_status_t
-_cairo_gl_composite_emit_quad_as_tristrip (cairo_gl_context_t *ctx,
- cairo_gl_composite_t *setup,
- const cairo_point_t quad[4])
-{
- _cairo_gl_composite_prepare_buffer (ctx, 4,
- CAIRO_GL_PRIMITIVE_TYPE_TRISTRIPS);
-
- _cairo_gl_composite_emit_point (ctx, &quad[0]);
- _cairo_gl_composite_emit_point (ctx, &quad[1]);
-
- /* Cairo stores quad vertices in counter-clockwise order, but we need to
- emit them from top to bottom in the triangle strip, so we need to reverse
- the order of the last two vertices. */
- _cairo_gl_composite_emit_point (ctx, &quad[3]);
- _cairo_gl_composite_emit_point (ctx, &quad[2]);
-
- return _cairo_gl_composite_append_vertex_indices (ctx, 4);
-}
-
-cairo_int_status_t
-_cairo_gl_composite_emit_triangle_as_tristrip (cairo_gl_context_t *ctx,
- cairo_gl_composite_t *setup,
- const cairo_point_t triangle[3])
-{
- _cairo_gl_composite_prepare_buffer (ctx, 3,
- CAIRO_GL_PRIMITIVE_TYPE_TRISTRIPS);
-
- _cairo_gl_composite_emit_point (ctx, &triangle[0]);
- _cairo_gl_composite_emit_point (ctx, &triangle[1]);
- _cairo_gl_composite_emit_point (ctx, &triangle[2]);
- return _cairo_gl_composite_append_vertex_indices (ctx, 3);
-}