diff options
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.c | 281 |
1 files changed, 190 insertions, 91 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 index 5b1411472d0..5477ef0d8ac 100644 --- a/Build/source/libs/cairo/cairo-src/src/cairo-gl-composite.c +++ b/Build/source/libs/cairo/cairo-src/src/cairo-gl-composite.c @@ -52,9 +52,96 @@ #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_pattern_t *pattern, const cairo_rectangle_int_t *sample, const cairo_rectangle_int_t *extents, cairo_bool_t use_texgen) @@ -68,8 +155,13 @@ 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 @@ -89,7 +181,7 @@ _cairo_gl_composite_set_mask (cairo_gl_composite_t *setup, { _cairo_gl_operand_destroy (&setup->mask); if (pattern == NULL) - return CAIRO_STATUS_SUCCESS; + return CAIRO_STATUS_SUCCESS; return _cairo_gl_operand_init (&setup->mask, pattern, setup->dst, sample, extents, use_texgen); @@ -99,9 +191,13 @@ 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) + 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 @@ -118,7 +214,7 @@ _cairo_gl_composite_set_multisample (cairo_gl_composite_t *setup) void _cairo_gl_composite_set_clip_region (cairo_gl_composite_t *setup, - cairo_region_t *clip_region) + cairo_region_t *clip_region) { setup->clip_region = clip_region; } @@ -142,8 +238,8 @@ _cairo_gl_composite_bind_to_shader (cairo_gl_context_t *ctx, static void _cairo_gl_texture_set_filter (cairo_gl_context_t *ctx, - GLuint target, - cairo_filter_t filter) + GLuint target, + cairo_filter_t filter) { switch (filter) { case CAIRO_FILTER_FAST: @@ -165,16 +261,17 @@ _cairo_gl_texture_set_filter (cairo_gl_context_t *ctx, static void _cairo_gl_texture_set_extend (cairo_gl_context_t *ctx, - GLuint target, - cairo_extend_t extend) + 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)); + (extend != CAIRO_EXTEND_REPEAT && extend != CAIRO_EXTEND_REFLECT)); switch (extend) { case CAIRO_EXTEND_NONE: - if (ctx->gl_flavor == CAIRO_GL_FLAVOR_ES) + 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; @@ -207,10 +304,10 @@ _cairo_gl_texture_set_extend (cairo_gl_context_t *ctx, 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_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; @@ -219,36 +316,36 @@ _cairo_gl_context_setup_operand (cairo_gl_context_t *ctx, * to no shaders (or back) */ needs_setup = vertex_size_changed; needs_setup |= _cairo_gl_operand_needs_setup (&ctx->operands[tex_unit], - operand, - vertex_offset); + operand, + vertex_offset); if (needs_setup) { - _cairo_gl_composite_flush (ctx); - _cairo_gl_context_destroy_operand (ctx, tex_unit); + _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; + return; switch (operand->type) { default: case CAIRO_GL_OPERAND_COUNT: - ASSERT_NOT_REACHED; + ASSERT_NOT_REACHED; case CAIRO_GL_OPERAND_NONE: - break; - /* fall through */ + break; + /* fall through */ case CAIRO_GL_OPERAND_CONSTANT: - break; + 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); + 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, @@ -256,15 +353,15 @@ _cairo_gl_context_setup_operand (cairo_gl_context_t *ctx, ctx->vb + vertex_offset); dispatch->EnableVertexAttribArray (CAIRO_GL_TEXCOORD0_ATTRIB_INDEX + tex_unit); } - break; + 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); + 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, @@ -299,7 +396,7 @@ _cairo_gl_context_setup_spans (cairo_gl_context_t *ctx, void _cairo_gl_context_destroy_operand (cairo_gl_context_t *ctx, - cairo_gl_tex_t tex_unit) + cairo_gl_tex_t tex_unit) { cairo_gl_dispatch_t *dispatch = &ctx->dispatch; @@ -309,21 +406,21 @@ _cairo_gl_context_destroy_operand (cairo_gl_context_t *ctx, switch (ctx->operands[tex_unit].type) { default: case CAIRO_GL_OPERAND_COUNT: - ASSERT_NOT_REACHED; + ASSERT_NOT_REACHED; case CAIRO_GL_OPERAND_NONE: - break; - /* fall through */ + break; + /* fall through */ case CAIRO_GL_OPERAND_CONSTANT: - break; + break; case CAIRO_GL_OPERAND_TEXTURE: - dispatch->DisableVertexAttribArray (CAIRO_GL_TEXCOORD0_ATTRIB_INDEX + tex_unit); - break; + 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; + dispatch->DisableVertexAttribArray (CAIRO_GL_TEXCOORD0_ATTRIB_INDEX + tex_unit); + break; } memset (&ctx->operands[tex_unit], 0, sizeof (cairo_gl_operand_t)); @@ -331,7 +428,7 @@ _cairo_gl_context_destroy_operand (cairo_gl_context_t *ctx, static void _cairo_gl_set_operator (cairo_gl_context_t *ctx, - cairo_operator_t op, + cairo_operator_t op, cairo_bool_t component_alpha) { struct { @@ -359,7 +456,7 @@ _cairo_gl_set_operator (cairo_gl_context_t *ctx, 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); + _cairo_gl_composite_flush (ctx); ctx->current_operator = op; src_factor = blend_factors[op].src; @@ -384,23 +481,23 @@ _cairo_gl_set_operator (cairo_gl_context_t *ctx, } if (ctx->current_target->base.content == CAIRO_CONTENT_ALPHA) { - glBlendFuncSeparate (GL_ZERO, GL_ZERO, src_factor, dst_factor); + 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); + glBlendFuncSeparate (src_factor, dst_factor, GL_ONE, GL_ONE); } else { - glBlendFunc (src_factor, dst_factor); + 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_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: - * http://lists.cairographics.org/archives/cairo/2005-August/004992.html) + * https://lists.cairographics.org/archives/cairo/2005-August/004992.html) * is: * mask IN clip ? src OP dest : dest * or more simply: @@ -420,7 +517,7 @@ _cairo_gl_composite_begin_component_alpha (cairo_gl_context_t *ctx, * mask IN clip ? 0 : dest */ if (setup->op == CAIRO_OPERATOR_CLEAR) { - _cairo_gl_solid_operand_init (&setup->src, CAIRO_COLOR_WHITE); + _cairo_gl_solid_operand_init (&setup->src, CAIRO_COLOR_WHITE); setup->op = CAIRO_OPERATOR_DEST_OUT; } @@ -477,17 +574,17 @@ _cairo_gl_composite_begin_component_alpha (cairo_gl_context_t *ctx, if (setup->op == CAIRO_OPERATOR_OVER) { setup->op = CAIRO_OPERATOR_ADD; status = _cairo_gl_get_shader_by_type (ctx, - &setup->src, - &setup->mask, + &setup->src, + &setup->mask, setup->spans, - CAIRO_GL_SHADER_IN_CA_SOURCE_ALPHA, - &pre_shader); - if (unlikely (status)) - return status; + 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); + _cairo_gl_composite_flush (ctx); ctx->pre_shader = pre_shader; return CAIRO_STATUS_SUCCESS; @@ -661,7 +758,7 @@ _cairo_gl_composite_setup_clipping (cairo_gl_composite_t *setup, if (setup->clip) return _cairo_gl_composite_setup_painted_clipping (setup, ctx, - vertex_size); + vertex_size); disable_all_clipping: _disable_stencil_buffer (); glDisable (GL_SCISSOR_TEST); @@ -701,13 +798,13 @@ _cairo_gl_set_operands_and_operator (cairo_gl_composite_t *setup, component_alpha ? CAIRO_GL_SHADER_IN_CA_SOURCE : CAIRO_GL_SHADER_IN_NORMAL, - &shader); + &shader); if (unlikely (status)) { ctx->pre_shader = NULL; return status; } if (ctx->current_shader != shader) - _cairo_gl_composite_flush (ctx); + _cairo_gl_composite_flush (ctx); status = CAIRO_STATUS_SUCCESS; @@ -769,7 +866,7 @@ _cairo_gl_composite_begin (cairo_gl_composite_t *setup, FAIL: if (unlikely (status)) - status = _cairo_gl_context_release (ctx, status); + status = _cairo_gl_context_release (ctx, status); return status; } @@ -800,17 +897,17 @@ _cairo_gl_composite_draw_triangles (cairo_gl_context_t *ctx, unsigned int count) { if (! ctx->pre_shader) { - glDrawArrays (GL_TRIANGLES, 0, count); + glDrawArrays (GL_TRIANGLES, 0, count); } else { - cairo_gl_shader_t *prev_shader = ctx->current_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); - glDrawArrays (GL_TRIANGLES, 0, count); + _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); + _cairo_gl_set_shader (ctx, prev_shader); + _cairo_gl_set_operator (ctx, CAIRO_OPERATOR_ADD, TRUE); + glDrawArrays (GL_TRIANGLES, 0, count); } } @@ -849,7 +946,7 @@ _cairo_gl_composite_flush (cairo_gl_context_t *ctx) int i; if (_cairo_gl_context_is_flushed (ctx)) - return; + return; count = ctx->vb_offset / ctx->vertex_size; _cairo_gl_composite_unmap_vertex_buffer (ctx); @@ -931,8 +1028,8 @@ _cairo_gl_composite_emit_point (cairo_gl_context_t *ctx, static void _cairo_gl_composite_emit_rect (cairo_gl_context_t *ctx, - GLfloat x1, GLfloat y1, - GLfloat x2, GLfloat y2) + GLfloat x1, GLfloat y1, + GLfloat x2, GLfloat y2) { _cairo_gl_composite_prepare_buffer (ctx, 6, CAIRO_GL_PRIMITIVE_TYPE_TRIANGLES); @@ -962,9 +1059,9 @@ _cairo_gl_context_emit_rect (cairo_gl_context_t *ctx, static void _cairo_gl_composite_emit_span (cairo_gl_context_t *ctx, - GLfloat x1, GLfloat y1, - GLfloat x2, GLfloat y2, - uint8_t alpha) + GLfloat x1, GLfloat y1, + GLfloat x2, GLfloat y2, + uint8_t alpha) { _cairo_gl_composite_prepare_buffer (ctx, 6, CAIRO_GL_PRIMITIVE_TYPE_TRIANGLES); @@ -1038,7 +1135,7 @@ _cairo_gl_context_choose_emit_span (cairo_gl_context_t *ctx) switch (ctx->operands[CAIRO_GL_TEX_SOURCE].type) { default: case CAIRO_GL_OPERAND_COUNT: - ASSERT_NOT_REACHED; + ASSERT_NOT_REACHED; case CAIRO_GL_OPERAND_NONE: case CAIRO_GL_OPERAND_CONSTANT: break; @@ -1079,10 +1176,10 @@ _cairo_gl_composite_emit_glyph_vertex (cairo_gl_context_t *ctx, 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) + 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); @@ -1130,7 +1227,7 @@ _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; + ASSERT_NOT_REACHED; case CAIRO_GL_OPERAND_NONE: case CAIRO_GL_OPERAND_CONSTANT: return _cairo_gl_composite_emit_solid_glyph; @@ -1157,13 +1254,13 @@ _cairo_gl_composite_set_operator (cairo_gl_composite_t *setup, 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"); + 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"); + if (! _cairo_gl_operator_is_supported (op)) + return UNSUPPORTED ("unsupported operator"); } setup->op = op; @@ -1172,12 +1269,14 @@ _cairo_gl_composite_set_operator (cairo_gl_composite_t *setup, 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_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, |