summaryrefslogtreecommitdiff
path: root/src/cairo-gl-shaders.c
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 /src/cairo-gl-shaders.c
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>
Diffstat (limited to 'src/cairo-gl-shaders.c')
-rw-r--r--src/cairo-gl-shaders.c352
1 files changed, 351 insertions, 1 deletions
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);
}