diff options
Diffstat (limited to 'src')
-rw-r--r-- | src/cairo-gl-device.c | 15 | ||||
-rw-r--r-- | src/cairo-gl-gradient.c | 58 | ||||
-rw-r--r-- | src/cairo-gl-operand.c | 29 | ||||
-rw-r--r-- | src/cairo-gl-private.h | 12 | ||||
-rw-r--r-- | src/cairo-gl-shaders.c | 453 |
5 files changed, 530 insertions, 37 deletions
diff --git a/src/cairo-gl-device.c b/src/cairo-gl-device.c index 7069c8312..5dce9fb91 100644 --- a/src/cairo-gl-device.c +++ b/src/cairo-gl-device.c @@ -1100,11 +1100,24 @@ void cairo_gl_device_set_thread_aware (cairo_device_t *device, cairo_bool_t thread_aware) { + if ((! device)||(cairo_device_status(device)!= CAIRO_STATUS_SUCCESS)) { + fprintf (stderr, "cairo_gl_device_set_thread_aware(): cairo_device is NULL or not available\n"); + _cairo_error_throw (CAIRO_STATUS_DEVICE_ERROR); + return; + } if (device->backend->type != CAIRO_DEVICE_TYPE_GL) { _cairo_error_throw (CAIRO_STATUS_DEVICE_TYPE_MISMATCH); return; } - ((cairo_gl_context_t *) device)->thread_aware = thread_aware; + if(thread_aware == 0 || thread_aware == 1) + { + ((cairo_gl_context_t *) device)->thread_aware = thread_aware; + } + else + { + _cairo_device_set_error (device, CAIRO_STATUS_INVALID_STATUS); + return; + } } void _cairo_gl_context_reset (cairo_gl_context_t *ctx) diff --git a/src/cairo-gl-gradient.c b/src/cairo-gl-gradient.c index b204b0ba4..325612b0f 100644 --- a/src/cairo-gl-gradient.c +++ b/src/cairo-gl-gradient.c @@ -269,36 +269,38 @@ _cairo_gl_gradient_create (cairo_gl_context_t *ctx, gradient->stops = gradient->stops_embedded; memcpy (gradient->stops_embedded, stops, n_stops * sizeof (cairo_gradient_stop_t)); - ctx->dispatch.GenTextures (1, &gradient->tex); - _cairo_gl_context_activate (ctx, CAIRO_GL_TEX_TEMP); - ctx->dispatch.BindTexture (ctx->tex_target, gradient->tex); - - data = _cairo_malloc_ab (tex_width, sizeof (uint32_t)); - if (unlikely (data == NULL)) { - status = _cairo_error (CAIRO_STATUS_NO_MEMORY); - goto cleanup_gradient; + if (n_stops != 2) { + ctx->dispatch.GenTextures (1, &gradient->tex); + _cairo_gl_context_activate (ctx, CAIRO_GL_TEX_TEMP); + ctx->dispatch.BindTexture (ctx->tex_target, gradient->tex); + + data = _cairo_malloc_ab (tex_width, sizeof (uint32_t)); + if (unlikely (data == NULL)) { + status = _cairo_error (CAIRO_STATUS_NO_MEMORY); + goto cleanup_gradient; + } + + status = _cairo_gl_gradient_render (ctx, n_stops, stops, data, tex_width); + if (unlikely (status)) + goto cleanup_data; + + /* + * In OpenGL ES 2.0 no format conversion is allowed i.e. 'internalFormat' + * must match 'format' in glTexImage2D. + */ + if (_cairo_gl_get_flavor (&ctx->dispatch) == CAIRO_GL_FLAVOR_ES2 || + _cairo_gl_get_flavor (&ctx->dispatch) == CAIRO_GL_FLAVOR_ES3) + internal_format = GL_BGRA; + else + internal_format = GL_RGBA; + + ctx->dispatch.TexImage2D (ctx->tex_target, 0, internal_format, + tex_width, 1, 0, + GL_BGRA, GL_UNSIGNED_BYTE, data); + + free (data); } - status = _cairo_gl_gradient_render (ctx, n_stops, stops, data, tex_width); - if (unlikely (status)) - goto cleanup_data; - - /* - * In OpenGL ES 2.0 no format conversion is allowed i.e. 'internalFormat' - * must match 'format' in glTexImage2D. - */ - if (_cairo_gl_get_flavor (&ctx->dispatch) == CAIRO_GL_FLAVOR_ES2 || - _cairo_gl_get_flavor (&ctx->dispatch) == CAIRO_GL_FLAVOR_ES3) - internal_format = GL_BGRA; - else - internal_format = GL_RGBA; - - ctx->dispatch.TexImage2D (ctx->tex_target, 0, internal_format, - tex_width, 1, 0, - GL_BGRA, GL_UNSIGNED_BYTE, data); - - free (data); - /* we ignore errors here and just return an uncached gradient */ if (unlikely (_cairo_cache_insert (&ctx->gradients, &gradient->cache_entry))) CAIRO_REFERENCE_COUNT_INIT (&gradient->ref_count, 1); diff --git a/src/cairo-gl-operand.c b/src/cairo-gl-operand.c index 2bbd99b74..575096a84 100644 --- a/src/cairo-gl-operand.c +++ b/src/cairo-gl-operand.c @@ -1206,6 +1206,7 @@ _cairo_gl_operand_bind_to_shader (cairo_gl_context_t *ctx, case CAIRO_GL_OPERAND_RADIAL_GRADIENT_NONE: case CAIRO_GL_OPERAND_RADIAL_GRADIENT_EXT: + _cairo_gl_shader_bind_float (ctx, ctx->current_shader->a_location[tex_unit], operand->gradient.a); @@ -1221,6 +1222,29 @@ _cairo_gl_operand_bind_to_shader (cairo_gl_context_t *ctx, operand->gradient.radius_0); /* fall through */ case CAIRO_GL_OPERAND_LINEAR_GRADIENT: + if (operand->gradient.gradient->n_stops == 2) { + _cairo_gl_shader_bind_vec4 (ctx, + ctx->current_shader->color_1_location[tex_unit], + operand->gradient.gradient->stops[0].color.red, + operand->gradient.gradient->stops[0].color.green, + operand->gradient.gradient->stops[0].color.blue, + operand->gradient.gradient->stops[0].color.alpha); + + _cairo_gl_shader_bind_vec4 (ctx, + ctx->current_shader->color_2_location[tex_unit], + operand->gradient.gradient->stops[1].color.red, + operand->gradient.gradient->stops[1].color.green, + operand->gradient.gradient->stops[1].color.blue, + operand->gradient.gradient->stops[1].color.alpha); + + _cairo_gl_shader_bind_float (ctx, + ctx->current_shader->offset_1_location[tex_unit], + operand->gradient.gradient->stops[0].offset); + _cairo_gl_shader_bind_float (ctx, + ctx->current_shader->offset_2_location[tex_unit], + operand->gradient.gradient->stops[1].offset); + } + /* fall through */ case CAIRO_GL_OPERAND_TEXTURE: case CAIRO_GL_OPERAND_GAUSSIAN: /* @@ -1311,10 +1335,10 @@ _cairo_gl_operand_bind_to_shader (cairo_gl_context_t *ctx, if (operand->type == CAIRO_GL_OPERAND_TEXTURE || operand->type == CAIRO_GL_OPERAND_GAUSSIAN) { if (operand->texture.texgen) - texgen = &operand->texture.attributes.matrix; + texgen = &operand->texture.attributes.matrix; } else { if (operand->gradient.texgen) - texgen = &operand->gradient.m; + texgen = &operand->gradient.m; } if (texgen) { _cairo_gl_shader_bind_matrix(ctx, @@ -1427,7 +1451,6 @@ _cairo_gl_operand_emit (cairo_gl_operand_t *operand, double t = y; cairo_matrix_transform_point (&operand->gradient.m, &s, &t); - *(*vb)++ = s; *(*vb)++ = t; } diff --git a/src/cairo-gl-private.h b/src/cairo-gl-private.h index e5a709e97..2c534fc39 100644 --- a/src/cairo-gl-private.h +++ b/src/cairo-gl-private.h @@ -165,6 +165,10 @@ typedef enum cairo_gl_uniform_t { CAIRO_GL_UNIFORM_BLUR_X_AXIS, /* "source_blur_x_axis" */ CAIRO_GL_UNIFORM_BLUR_Y_AXIS, /* "source_blur_y_axis" */ CAIRO_GL_UNIFORM_ALPHA, /* "source_alpha */ + CAIRO_GL_UNIFORM_COLOR_1, /* "source_color_1 */ + CAIRO_GL_UNIFORM_COLOR_2, /* "source_color_2 */ + CAIRO_GL_UNIFORM_OFFSET_1, /* "source_offset_1 */ + CAIRO_GL_UNIFORM_OFFSET_2, /* "source_offset_2 */ CAIRO_GL_UNIFORM_MASK_TEXDIMS, /* "mask_texdims" */ CAIRO_GL_UNIFORM_MASK_TEXGEN, /* "mask_texgen" */ @@ -179,6 +183,10 @@ typedef enum cairo_gl_uniform_t { CAIRO_GL_UNIFORM_MASK_BLUR_X_AXIS, /* "mask_blur_x_axis" */ CAIRO_GL_UNIFORM_MASK_BLUR_Y_AXIS, /* "mask_blur_y_axis" */ CAIRO_GL_UNIFORM_MASK_ALPHA, /* "mask_alpha" */ + CAIRO_GL_UNIFORM_MASK_COLOR_1, /* "mask_color_1" */ + CAIRO_GL_UNIFORM_MASK_COLOR_2, /* "mask_color_2" */ + CAIRO_GL_UNIFORM_MASK_OFFSET_1, /* "mask_offset_1 */ + CAIRO_GL_UNIFORM_MASK_OFFSET_2, /* "mask_offset_2 */ CAIRO_GL_UNIFORM_PROJECTION_MATRIX, /* "ModelViewProjectionMatrix" */ @@ -330,6 +338,10 @@ typedef struct cairo_gl_shader { GLint blur_x_axis_location[2]; GLint blur_y_axis_location[2]; GLint alpha_location[2]; + GLint color_1_location[2]; + GLint color_2_location[2]; + GLint offset_1_location[2]; + GLint offset_2_location[2]; } cairo_gl_shader_t; typedef struct _cairo_gl_image_cache { diff --git a/src/cairo-gl-shaders.c b/src/cairo-gl-shaders.c index 7d7b669a8..b5796f79d 100644 --- a/src/cairo-gl-shaders.c +++ b/src/cairo-gl-shaders.c @@ -125,6 +125,9 @@ typedef struct _cairo_shader_cache_entry { cairo_bool_t src_use_atlas; cairo_bool_t mask_use_atlas; + cairo_bool_t src_n_stops_is_two; + cairo_bool_t mask_n_stops_is_two; + cairo_gl_context_t *ctx; /* XXX: needed to destroy the program */ cairo_gl_shader_t shader; } cairo_shader_cache_entry_t; @@ -144,7 +147,9 @@ _cairo_gl_shader_cache_equal_desktop (const void *key_a, const void *key_b) a->use_coverage == b->use_coverage && a->in == b->in && (both_have_npot_repeat || a->src_extend == b->src_extend) && - (both_have_npot_repeat || a->mask_extend == b->mask_extend)); + (both_have_npot_repeat || a->mask_extend == b->mask_extend) && + a->src_n_stops_is_two == b->src_n_stops_is_two && + a->mask_n_stops_is_two == b->mask_n_stops_is_two); } /* @@ -171,13 +176,17 @@ _cairo_gl_shader_cache_equal_gles2 (const void *key_a, const void *key_b) (both_have_npot_repeat || a->src_extend == b->src_extend) && a->mask_gl_filter == b->mask_gl_filter && a->mask_border_fade == b->mask_border_fade && - (both_have_npot_repeat || a->mask_extend == b->mask_extend)); + (both_have_npot_repeat || a->mask_extend == b->mask_extend) && + a->src_n_stops_is_two == b->src_n_stops_is_two && + a->mask_n_stops_is_two == b->mask_n_stops_is_two); } static unsigned long _cairo_gl_shader_cache_hash (const cairo_shader_cache_entry_t *entry) { - return ((entry->src << 15) | + return ((entry->src_n_stops_is_two << 19) | + (entry->mask_n_stops_is_two << 18) | + (entry->src << 15) | (entry->mask << 12) | (entry->dest << 9) | (entry->in << 7) | @@ -551,7 +560,6 @@ cairo_gl_shader_get_vertex_source (cairo_gl_var_type_t src, status = _cairo_memory_stream_destroy (stream, &source, &length); if (unlikely (status)) return status; - *out = (char *) source; return CAIRO_STATUS_SUCCESS; } @@ -750,6 +758,7 @@ cairo_gl_shader_emit_color (cairo_output_stream_t *stream, } break; case CAIRO_GL_OPERAND_LINEAR_GRADIENT: + if (op->gradient.gradient->n_stops != 2) { if (needs_glsl330 == CAIRO_GLSL_VERSION_330) { _cairo_output_stream_printf (stream, "in vec2 %s_texcoords;\n" @@ -789,8 +798,94 @@ cairo_gl_shader_emit_color (cairo_output_stream_t *stream, "}\n", textstr, rectstr, namestr, namestr, namestr); } + } else { // else of if (op->gradient.gradient->n_stops != 2) + if (needs_glsl330 == CAIRO_GLSL_VERSION_330) { + _cairo_output_stream_printf (stream, + "in vec2 %s_texcoords;\n" + "uniform vec2 %s_texdims;\n" + "uniform sampler2D%s %s_sampler;\n" + "uniform vec4 %s_color_1;\n" + "uniform vec4 %s_color_2;\n" + "uniform float %s_offset_1;\n" + "uniform float %s_offset_2;\n" + "\n" + "vec4 get_%s()\n" + "{\n", + namestr, namestr, rectstr, namestr, namestr, + namestr, namestr, namestr, namestr); + } + else { + _cairo_output_stream_printf (stream, + "varying vec2 %s_texcoords;\n" + "uniform vec2 %s_texdims;\n" + "uniform sampler2D%s %s_sampler;\n" + "uniform vec4 %s_color_1;\n" + "uniform vec4 %s_color_2;\n" + "uniform float %s_offset_1;\n" + "uniform float %s_offset_2;\n" + "\n" + "vec4 get_%s()\n" + "{\n", + namestr, namestr, rectstr, namestr, namestr, + namestr, namestr, namestr, namestr); + } + + if ((ctx->gl_flavor == CAIRO_GL_FLAVOR_ES2 || + ctx->gl_flavor == CAIRO_GL_FLAVOR_ES3) && + _cairo_gl_shader_needs_border_fade (op)) + { + _cairo_output_stream_printf (stream, + " float border_fade = %s_border_fade (%s_texcoords.x, %s_texdims.x);\n" + " vec4 texel;\n" + " float scale;\n" + " float factor;\n" + " float upper_t = %s_texcoords.x;\n" + " if (upper_t <= %s_offset_1) {\n" + " texel = %s_color_1;\n" + " } else if (upper_t >= %s_offset_2) {\n" + " texel = %s_color_2;\n" + " } else {\n" + " scale = %s_offset_2 - %s_offset_1;\n" + " factor = (upper_t - %s_offset_1)/scale;\n" + " texel = mix (%s_color_1, %s_color_2, factor);\n" + " }\n" + " texel = vec4(texel.rgb * texel.a, texel.a);\n" + " return texel * border_fade;\n" + "}\n", + namestr, namestr, namestr, + namestr, namestr, namestr, namestr, + namestr, + namestr, namestr, namestr, namestr, namestr); + } + else + { + _cairo_output_stream_printf (stream, + " vec4 texel;\n" + " float scale;\n" + " float factor;\n" + " float upper_t = (vec2(%s_wrap (vec2 (%s_texcoords.x, 0.5)))).x;\n" + " if (upper_t <= %s_offset_1) {\n" + " texel = %s_color_1;\n" + " } else if (upper_t >= %s_offset_2) {\n" + " texel = %s_color_2;\n" + " } else {\n" + " scale = %s_offset_2 - %s_offset_1;\n" + " factor = (upper_t - %s_offset_1)/scale;\n" + " texel = mix (%s_color_1, %s_color_2, factor);\n" + " }\n" + " texel = vec4(texel.rgb * texel.a, texel.a);\n" + " return texel;\n" + "}\n", + namestr, namestr, namestr, namestr, namestr, namestr, + namestr, namestr, namestr, namestr, namestr + ); + } + + } //end of if (op->gradient.gradient->n_stops != 2) + break; case CAIRO_GL_OPERAND_RADIAL_GRADIENT_A0: + if (op->gradient.gradient->n_stops != 2) { if (needs_glsl330 == CAIRO_GLSL_VERSION_330) { _cairo_output_stream_printf (stream, "in vec2 %s_texcoords;\n" @@ -850,8 +945,108 @@ cairo_gl_shader_emit_color (cairo_output_stream_t *stream, "}\n", textstr, rectstr, namestr, namestr); } + } else { // else of if (op->gradient.gradient->n_stops != 2) + if (needs_glsl330 == CAIRO_GLSL_VERSION_330) { + _cairo_output_stream_printf (stream, + "in vec2 %s_texcoords;\n" + "uniform vec2 %s_texdims;\n" + "uniform sampler2D%s %s_sampler;\n" + "uniform vec3 %s_circle_d;\n" + "uniform float %s_radius_0;\n" + "uniform vec4 %s_color_1;\n" + "uniform vec4 %s_color_2;\n" + "uniform float %s_offset_1;\n" + "uniform float %s_offset_2;\n" + "\n" + "vec4 get_%s()\n" + "{\n" + " vec3 pos = vec3 (%s_texcoords, %s_radius_0);\n" + " \n" + " float B = dot (pos, %s_circle_d);\n" + " float C = dot (pos, vec3 (pos.xy, -pos.z));\n" + " \n" + " float t = 0.5 * C / B;\n" + " float is_valid = step (-%s_radius_0, t * %s_circle_d.z);\n", + namestr, namestr, rectstr, namestr, namestr, namestr, namestr, + namestr, namestr, namestr, namestr, + namestr, namestr, namestr, namestr, namestr); + } else { + _cairo_output_stream_printf (stream, + "varying vec2 %s_texcoords;\n" + "uniform vec2 %s_texdims;\n" + "uniform sampler2D%s %s_sampler;\n" + "uniform vec3 %s_circle_d;\n" + "uniform float %s_radius_0;\n" + "uniform vec4 %s_color_1;\n" + "uniform vec4 %s_color_2;\n" + "uniform float %s_offset_1;\n" + "uniform float %s_offset_2;\n" + "\n" + "vec4 get_%s()\n" + "{\n" + " vec3 pos = vec3 (%s_texcoords, %s_radius_0);\n" + " \n" + " float B = dot (pos, %s_circle_d);\n" + " float C = dot (pos, vec3 (pos.xy, -pos.z));\n" + " \n" + " float t = 0.5 * C / B;\n" + " float is_valid = step (-%s_radius_0, t * %s_circle_d.z);\n", + namestr, namestr, rectstr, namestr, namestr, namestr, namestr, + namestr, namestr, namestr, namestr, + namestr, namestr, namestr, namestr, namestr); + } + + if ((ctx->gl_flavor == CAIRO_GL_FLAVOR_ES2 || + ctx->gl_flavor == CAIRO_GL_FLAVOR_ES3) && + _cairo_gl_shader_needs_border_fade (op)) + { + _cairo_output_stream_printf (stream, + " float border_fade = %s_border_fade (t, %s_texdims.x);\n" + " vec4 texel;\n" + " float scale;\n" + " float factor;\n" + " if (t <= %s_offset_1) {\n" + " texel = %s_color_1;\n" + " } else if (t >= %s_offset_2) {\n" + " texel = %s_color_2;\n" + " } else {\n" + " scale = %s_offset_2 - %s_offset_1;\n" + " factor = (t - %s_offset_1)/scale;\n" + " texel = mix (%s_color_1, %s_color_2, factor);\n" + " }\n" + " texel = vec4(texel.rgb * texel.a, texel.a);\n" + " return mix (vec4 (0.0), texel * border_fade, is_valid);\n" + "}\n", + namestr, namestr, namestr, namestr, namestr, namestr, + namestr, namestr, namestr, namestr, namestr); + } + else + { + _cairo_output_stream_printf (stream, + " vec4 texel;\n" + " float scale;\n" + " float factor;\n" + " float upper_t = (vec2(%s_wrap (vec2 (t, 0.5)))).x;\n" + " if (upper_t <= %s_offset_1) {\n" + " texel = %s_color_1;\n" + " } else if (upper_t >= %s_offset_2) {\n" + " texel = %s_color_2;\n" + " } else {\n" + " scale = %s_offset_2 - %s_offset_1;\n" + " factor = (upper_t - %s_offset_1)/scale;\n" + " texel = mix (%s_color_1, %s_color_2, factor);\n" + " }\n" + " texel = vec4(texel.rgb * texel.a, texel.a);\n" + " return mix (vec4 (0.0), texel, is_valid);\n" + "}\n", + namestr, namestr, namestr, namestr, namestr, + namestr, namestr, namestr, namestr, namestr); + } + + } //end of if (op->gradient.gradient->n_stops != 2) break; case CAIRO_GL_OPERAND_RADIAL_GRADIENT_NONE: + if (op->gradient.gradient->n_stops != 2) { if (needs_glsl330 == CAIRO_GLSL_VERSION_330) { _cairo_output_stream_printf (stream, "in vec2 %s_texcoords;\n" @@ -925,8 +1120,122 @@ cairo_gl_shader_emit_color (cairo_output_stream_t *stream, "}\n", textstr, rectstr, namestr, namestr); } + } else { //else of if (op->gradient.gradient->n_stops != 2) + if (needs_glsl330 == CAIRO_GLSL_VERSION_330) { + _cairo_output_stream_printf (stream, + "in vec2 %s_texcoords;\n" + "uniform vec2 %s_texdims;\n" + "uniform sampler2D%s %s_sampler;\n" + "uniform vec3 %s_circle_d;\n" + "uniform float %s_a;\n" + "uniform float %s_radius_0;\n" + "uniform vec4 %s_color_1;\n" + "uniform vec4 %s_color_2;\n" + "uniform float %s_offset_1;\n" + "uniform float %s_offset_2;\n" + "\n" + "vec4 get_%s()\n" + "{\n" + " vec3 pos = vec3 (%s_texcoords, %s_radius_0);\n" + " \n" + " float B = dot (pos, %s_circle_d);\n" + " float C = dot (pos, vec3 (pos.xy, -pos.z));\n" + " \n" + " float det = dot (vec2 (B, %s_a), vec2 (B, -C));\n" + " float sqrtdet = sqrt (abs (det));\n" + " vec2 t = (B + vec2 (sqrtdet, -sqrtdet)) / %s_a;\n" + " \n" + " vec2 is_valid = step (vec2 (0.0), t) * step (t, vec2(1.0));\n" + " float has_color = step (0., det) * max (is_valid.x, is_valid.y);\n" + " \n" + " float upper_t = mix (t.y, t.x, is_valid.x);\n", + namestr, namestr, rectstr, namestr, namestr, namestr, namestr, + namestr, namestr, namestr, namestr, + namestr, namestr, namestr, namestr, namestr, namestr); + } else { + _cairo_output_stream_printf (stream, + "varying vec2 %s_texcoords;\n" + "uniform vec2 %s_texdims;\n" + "uniform sampler2D%s %s_sampler;\n" + "uniform vec3 %s_circle_d;\n" + "uniform float %s_a;\n" + "uniform float %s_radius_0;\n" + "uniform vec4 %s_color_1;\n" + "uniform vec4 %s_color_2;\n" + "uniform float %s_offset_1;\n" + "uniform float %s_offset_2;\n" + "\n" + "vec4 get_%s()\n" + "{\n" + " vec3 pos = vec3 (%s_texcoords, %s_radius_0);\n" + " \n" + " float B = dot (pos, %s_circle_d);\n" + " float C = dot (pos, vec3 (pos.xy, -pos.z));\n" + " \n" + " float det = dot (vec2 (B, %s_a), vec2 (B, -C));\n" + " float sqrtdet = sqrt (abs (det));\n" + " vec2 t = (B + vec2 (sqrtdet, -sqrtdet)) / %s_a;\n" + " \n" + " vec2 is_valid = step (vec2 (0.0), t) * step (t, vec2(1.0));\n" + " float has_color = step (0., det) * max (is_valid.x, is_valid.y);\n" + " \n" + " float upper_t = mix (t.y, t.x, is_valid.x);\n", + namestr, namestr, rectstr, namestr, namestr, namestr, namestr, + namestr, namestr, namestr, namestr, + namestr, namestr, namestr, namestr, namestr, namestr); + } + + if ((ctx->gl_flavor == CAIRO_GL_FLAVOR_ES2 || + ctx->gl_flavor == CAIRO_GL_FLAVOR_ES3) && + _cairo_gl_shader_needs_border_fade (op)) + { + _cairo_output_stream_printf (stream, + " float border_fade = %s_border_fade (upper_t, %s_texdims.x);\n" + " vec4 texel;\n" + " float scale;\n" + " float factor;\n" + " if (upper_t <= %s_offset_1) {\n" + " texel = %s_color_1;\n" + " } else if (upper_t >= %s_offset_2) {\n" + " texel = %s_color_2;\n" + " } else {\n" + " scale = %s_offset_2 - %s_offset_1;\n" + " factor = (upper_t - %s_offset_1)/scale;\n" + " texel = mix (%s_color_1, %s_color_2, factor);\n" + " }\n" + " texel = vec4(texel.rgb * texel.a, texel.a);\n" + " return mix (vec4 (0.0), texel * border_fade, has_color);\n" + "}\n", + namestr, namestr, namestr, namestr, namestr, namestr, + namestr, namestr, namestr, namestr, namestr); + } + else + { + _cairo_output_stream_printf (stream, + " vec4 texel;\n" + " float scale;\n" + " float factor;\n" + " float upper_tw = (vec2(%s_wrap (vec2(upper_t, 0.5)))).x;\n" + " if (upper_tw <= %s_offset_1) {\n" + " texel = %s_color_1;\n" + " } else if (upper_tw >= %s_offset_2) {\n" + " texel = %s_color_2;\n" + " } else {\n" + " scale = %s_offset_2 - %s_offset_1;\n" + " factor = (upper_tw - %s_offset_1)/scale;\n" + " texel = mix (%s_color_1, %s_color_2, factor);\n" + " }\n" + " texel = vec4(texel.rgb * texel.a, texel.a);\n" + " return mix (vec4 (0.0), texel, has_color);\n" + "}\n", + namestr, namestr, namestr, namestr, namestr, + namestr, namestr, namestr, namestr, namestr); + } + + } //end of if (op->gradient.gradient->n_stops != 2) break; case CAIRO_GL_OPERAND_RADIAL_GRADIENT_EXT: + if (op->gradient.gradient->n_stops != 2) { if (needs_glsl330 == CAIRO_GLSL_VERSION_330) { _cairo_output_stream_printf (stream, "in vec2 %s_texcoords;\n" @@ -982,10 +1291,113 @@ cairo_gl_shader_emit_color (cairo_output_stream_t *stream, " vec4 texel = texture%s%s (%s_sampler, %s_wrap (vec2(upper_t, 0.5)));\n" " return mix (vec4 (0.0), texel, has_color);\n" "}\n", + namestr, rectstr, namestr, namestr, namestr, namestr, namestr, namestr, namestr, namestr, namestr, namestr, namestr, namestr, textstr, rectstr, namestr, namestr); } + } else { //else of if (op->gradient.gradient->n_stops != 2) + if (needs_glsl330 == CAIRO_GLSL_VERSION_330) { + _cairo_output_stream_printf (stream, + "in vec2 %s_texcoords;\n" + "uniform sampler2D%s %s_sampler;\n" + "uniform vec3 %s_circle_d;\n" + "uniform float %s_a;\n" + "uniform float %s_radius_0;\n" + "uniform vec4 %s_color_1;\n" + "uniform vec4 %s_color_2;\n" + "uniform float %s_offset_1;\n" + "uniform float %s_offset_2;\n" + "\n" + "vec4 get_%s()\n" + "{\n" + " vec3 pos = vec3 (%s_texcoords, %s_radius_0);\n" + " \n" + " float B = dot (pos, %s_circle_d);\n" + " float C = dot (pos, vec3 (pos.xy, -pos.z));\n" + " \n" + " float det = dot (vec2 (B, %s_a), vec2 (B, -C));\n" + " float sqrtdet = sqrt (abs (det));\n" + " vec2 t = (B + vec2 (sqrtdet, -sqrtdet)) / %s_a;\n" + " \n" + " vec2 is_valid = step (vec2 (-%s_radius_0), t * %s_circle_d.z);\n" + " float has_color = step (0., det) * max (is_valid.x, is_valid.y);\n" + " \n" + " float upper_t = mix (t.y, t.x, is_valid.x);\n" + " vec4 texel;\n" + " float scale;\n" + " float factor;\n" + " float upper_tw = (vec2(%s_wrap (vec2(upper_t, 0.5)))).x;\n" + " if (upper_tw <= %s_offset_1) {\n" + " texel = %s_color_1;\n" + " } else if (upper_tw >= %s_offset_2) {\n" + " texel = %s_color_2;\n" + " } else {\n" + " scale = %s_offset_2 - %s_offset_1;\n" + " factor = (upper_tw - %s_offset_1)/scale;\n" + " texel = mix (%s_color_1, %s_color_2, factor);\n" + " }\n" + " texel = vec4(texel.rgb * texel.a, texel.a);\n" + " return mix (vec4 (0.0), texel, has_color);\n" + "}\n", + namestr, rectstr, namestr, namestr, namestr, namestr, + namestr, namestr, namestr, namestr, + namestr, namestr, namestr, namestr, namestr, + namestr, namestr, namestr, + namestr, namestr, namestr, namestr, namestr, namestr, namestr, + namestr, namestr, namestr); + } else { + _cairo_output_stream_printf (stream, + "varying vec2 %s_texcoords;\n" + "uniform sampler2D%s %s_sampler;\n" + "uniform vec3 %s_circle_d;\n" + "uniform float %s_a;\n" + "uniform float %s_radius_0;\n" + "uniform vec4 %s_color_1;\n" + "uniform vec4 %s_color_2;\n" + "uniform float %s_offset_1;\n" + "uniform float %s_offset_2;\n" + "\n" + "vec4 get_%s()\n" + "{\n" + " vec3 pos = vec3 (%s_texcoords, %s_radius_0);\n" + " \n" + " float B = dot (pos, %s_circle_d);\n" + " float C = dot (pos, vec3 (pos.xy, -pos.z));\n" + " \n" + " float det = dot (vec2 (B, %s_a), vec2 (B, -C));\n" + " float sqrtdet = sqrt (abs (det));\n" + " vec2 t = (B + vec2 (sqrtdet, -sqrtdet)) / %s_a;\n" + " \n" + " vec2 is_valid = step (vec2 (-%s_radius_0), t * %s_circle_d.z);\n" + " float has_color = step (0., det) * max (is_valid.x, is_valid.y);\n" + " \n" + " float upper_t = mix (t.y, t.x, is_valid.x);\n" + " vec4 texel;\n" + " float scale;\n" + " float factor;\n" + " float upper_tw = (vec2(%s_wrap (vec2(upper_t, 0.5)))).x;\n" + " if (upper_tw <= %s_offset_1) {\n" + " texel = %s_color_1;\n" + " } else if (upper_tw >= %s_offset_2) {\n" + " texel = %s_color_2;\n" + " } else {\n" + " scale = %s_offset_2 - %s_offset_1;\n" + " factor = (upper_tw - %s_offset_1)/scale;\n" + " texel = mix (%s_color_1, %s_color_2, factor);\n" + " }\n" + " texel = vec4(texel.rgb * texel.a, texel.a);\n" + " return mix (vec4 (0.0), texel, has_color);\n" + "}\n", + namestr, rectstr, namestr, namestr, namestr, namestr, + namestr, namestr, namestr, namestr, + namestr, namestr, namestr, namestr, namestr, + namestr, namestr, namestr, + namestr, namestr, namestr, namestr, namestr, namestr, namestr, + namestr, namestr, namestr); + } + + } // end of if (op->gradient.gradient->n_stops != 2) break; } } @@ -1117,7 +1529,12 @@ _cairo_gl_shader_emit_wrap (cairo_gl_context_t *ctx, } } else { - if (! ctx->has_npot_repeat && + if (((! ctx->has_npot_repeat) || + ((operand->type == CAIRO_GL_OPERAND_LINEAR_GRADIENT || + operand->type == CAIRO_GL_OPERAND_RADIAL_GRADIENT_A0 || + operand->type == CAIRO_GL_OPERAND_RADIAL_GRADIENT_NONE || + operand->type == CAIRO_GL_OPERAND_RADIAL_GRADIENT_EXT) && + operand->gradient.gradient->n_stops == 2)) && (extend == CAIRO_EXTEND_REPEAT || extend == CAIRO_EXTEND_REFLECT)) { if (extend == CAIRO_EXTEND_REPEAT) { @@ -1435,6 +1852,15 @@ _cairo_gl_shader_compile_and_link (cairo_gl_context_t *ctx, _cairo_gl_get_op_uniform_location (ctx, shader, i, "blur_y_axis"); shader->alpha_location[i] = _cairo_gl_get_op_uniform_location (ctx, shader, i, "alpha"); + + shader->color_1_location[i] = + _cairo_gl_get_op_uniform_location (ctx, shader, i, "color_1"); + shader->color_2_location[i] = + _cairo_gl_get_op_uniform_location (ctx, shader, i, "color_2"); + shader->offset_1_location[i] = + _cairo_gl_get_op_uniform_location (ctx, shader, i, "offset_1"); + shader->offset_2_location[i] = + _cairo_gl_get_op_uniform_location (ctx, shader, i, "offset_2"); } return CAIRO_STATUS_SUCCESS; @@ -1539,6 +1965,7 @@ _cairo_gl_shader_bind_vec4 (cairo_gl_context_t *ctx, float value2, float value3) { cairo_gl_dispatch_t *dispatch = &ctx->dispatch; + assert (location != -1); dispatch->Uniform4f (location, value0, value1, value2, value3); } @@ -1605,6 +2032,22 @@ _cairo_gl_get_shader_by_type (cairo_gl_context_t *ctx, use_coverage, CAIRO_GL_VAR_NONE); + if (source->type == CAIRO_GL_OPERAND_LINEAR_GRADIENT || + source->type == CAIRO_GL_OPERAND_RADIAL_GRADIENT_A0 || + source->type == CAIRO_GL_OPERAND_RADIAL_GRADIENT_NONE || + source->type == CAIRO_GL_OPERAND_RADIAL_GRADIENT_EXT) + lookup.src_n_stops_is_two = source->gradient.gradient->n_stops == 2; + else + lookup.src_n_stops_is_two = FALSE; + + if (mask->type == CAIRO_GL_OPERAND_LINEAR_GRADIENT || + mask->type == CAIRO_GL_OPERAND_RADIAL_GRADIENT_A0 || + mask->type == CAIRO_GL_OPERAND_RADIAL_GRADIENT_NONE || + mask->type == CAIRO_GL_OPERAND_RADIAL_GRADIENT_EXT) + lookup.mask_n_stops_is_two = mask->gradient.gradient->n_stops == 2; + else + lookup.mask_n_stops_is_two = FALSE; + lookup.src = source->type; lookup.mask = mask->type; lookup.dest = CAIRO_GL_OPERAND_NONE; |