summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authornisanthmp <nisanth.mp@samsung.com>2015-12-02 12:57:34 +0530
committernisanthmp <nisanth.mp@samsung.com>2015-12-18 13:20:33 +0530
commit629101d0a6e2af32727ca0b14acaceddb0897e6c (patch)
tree9c6820465caf673ca40d5b1a9f91c1cd90dd003a
parentca3e6d75aaf63e5f77bc31975d77a20cbc5407ca (diff)
downloadcairo-629101d0a6e2af32727ca0b14acaceddb0897e6c.tar.gz
cairo-629101d0a6e2af32727ca0b14acaceddb0897e6c.tar.bz2
cairo-629101d0a6e2af32727ca0b14acaceddb0897e6c.zip
Pattern/GL: Avoid texture creation for radial gradients
with 2 color stops When there are only two color stops in the gradient, we can avoid creating textures before hand, and directly calculate the gradient color in the fragment shader. This speeds up gradient pattern rendering. Change-Id: I758b7bc8f37293edbe546fcc4a55f71a7f3c55ae Signed-off-by: nisanthmp <nisanth.mp@samsung.com>
-rw-r--r--src/cairo-gl-gradient-private.h3
-rw-r--r--src/cairo-gl-gradient.c61
-rw-r--r--src/cairo-gl-operand.c30
-rw-r--r--src/cairo-gl-private.h12
-rw-r--r--src/cairo-gl-shaders.c352
5 files changed, 423 insertions, 35 deletions
diff --git a/src/cairo-gl-gradient-private.h b/src/cairo-gl-gradient-private.h
index d66f3dc3b..8d95f701e 100644
--- a/src/cairo-gl-gradient-private.h
+++ b/src/cairo-gl-gradient-private.h
@@ -94,7 +94,8 @@ cairo_private cairo_int_status_t
_cairo_gl_gradient_create (cairo_gl_context_t *ctx,
unsigned int n_stops,
const cairo_gradient_stop_t *stops,
- cairo_gl_gradient_t **gradient_out);
+ cairo_gl_gradient_t **gradient_out,
+ cairo_pattern_type_t pat_type);
cairo_private_no_warn cairo_gl_gradient_t *
_cairo_gl_gradient_reference (cairo_gl_gradient_t *gradient);
diff --git a/src/cairo-gl-gradient.c b/src/cairo-gl-gradient.c
index b204b0ba4..a6084ce84 100644
--- a/src/cairo-gl-gradient.c
+++ b/src/cairo-gl-gradient.c
@@ -233,7 +233,8 @@ cairo_int_status_t
_cairo_gl_gradient_create (cairo_gl_context_t *ctx,
unsigned int n_stops,
const cairo_gradient_stop_t *stops,
- cairo_gl_gradient_t **gradient_out)
+ cairo_gl_gradient_t **gradient_out,
+ cairo_pattern_type_t pat_type)
{
unsigned long hash;
cairo_gl_gradient_t *gradient;
@@ -269,36 +270,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 (pat_type != CAIRO_PATTERN_TYPE_RADIAL || 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..443d06a5f 100644
--- a/src/cairo-gl-operand.c
+++ b/src/cairo-gl-operand.c
@@ -65,7 +65,7 @@ _cairo_gl_create_gradient_texture (cairo_gl_surface_t *dst,
if (unlikely (status))
return status;
- status = _cairo_gl_gradient_create (ctx, pattern->n_stops, pattern->stops, gradient);
+ status = _cairo_gl_gradient_create (ctx, pattern->n_stops, pattern->stops, gradient, pattern->base.type);
return _cairo_gl_context_release (ctx, status);
}
@@ -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);
@@ -1219,6 +1220,28 @@ _cairo_gl_operand_bind_to_shader (cairo_gl_context_t *ctx,
_cairo_gl_shader_bind_float (ctx,
ctx->current_shader->radius_0_location[tex_unit],
operand->gradient.radius_0);
+ 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_LINEAR_GRADIENT:
case CAIRO_GL_OPERAND_TEXTURE:
@@ -1311,10 +1334,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 +1450,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..623f8d604 100644
--- a/src/cairo-gl-shaders.c
+++ b/src/cairo-gl-shaders.c
@@ -551,7 +551,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;
}
@@ -791,6 +790,7 @@ cairo_gl_shader_emit_color (cairo_output_stream_t *stream,
}
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 +850,116 @@ 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"
+//two_color_mod
+#if 1
+ "uniform vec4 %s_color_1;\n"
+ "uniform vec4 %s_color_2;\n"
+ "uniform float %s_offset_1;\n"
+ "uniform float %s_offset_2;\n"
+#endif
+ "\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"
+//two_color_mod
+#if 1
+ "uniform vec4 %s_color_1;\n"
+ "uniform vec4 %s_color_2;\n"
+ "uniform float %s_offset_1;\n"
+ "uniform float %s_offset_2;\n"
+#endif
+ "\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 = texture%s%s (%s_sampler, vec2 (t, 0.5));\n"
+//two_color_mod
+ " 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"
+ " 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 = texture%s%s (%s_sampler, %s_wrap (vec2 (t, 0.5)));\n"
+//two_color_mod
+ " 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"
+ " 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 +1033,130 @@ 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"
+//two_color_mod
+#if 1
+ "uniform vec4 %s_color_1;\n"
+ "uniform vec4 %s_color_2;\n"
+ "uniform float %s_offset_1;\n"
+ "uniform float %s_offset_2;\n"
+#endif
+ "\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"
+//two_color_mod
+#if 1
+ "uniform vec4 %s_color_1;\n"
+ "uniform vec4 %s_color_2;\n"
+ "uniform float %s_offset_1;\n"
+ "uniform float %s_offset_2;\n"
+#endif
+ "\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 = texture%s%s (%s_sampler, vec2 (upper_t, 0.5));\n"
+//two_color_mod
+ " 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"
+ " 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 = texture%s%s (%s_sampler, %s_wrap (vec2(upper_t, 0.5)));\n"
+//two_color_mod
+ " 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"
+ " 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 +1212,119 @@ 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"
+//two_color_mod
+#if 1
+ "uniform vec4 %s_color_1;\n"
+ "uniform vec4 %s_color_2;\n"
+ "uniform float %s_offset_1;\n"
+ "uniform float %s_offset_2;\n"
+#endif
+ "\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"
+//two_color_mod
+ " 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"
+ " 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"
+//two_color_mod
+#if 1
+ "uniform vec4 %s_color_1;\n"
+ "uniform vec4 %s_color_2;\n"
+ "uniform float %s_offset_1;\n"
+ "uniform float %s_offset_2;\n"
+#endif
+ "\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"
+//two_color_mod
+ " 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"
+ " 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;
}
}
@@ -1435,6 +1774,16 @@ _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");
+
+//two_color_mod
+ 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 +1888,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);
}