summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--packaging/cairo.spec33
-rw-r--r--src/cairo-gl-device.c15
-rw-r--r--src/cairo-gl-gradient.c58
-rw-r--r--src/cairo-gl-operand.c29
-rw-r--r--src/cairo-gl-private.h12
-rw-r--r--src/cairo-gl-shaders.c453
6 files changed, 533 insertions, 67 deletions
diff --git a/packaging/cairo.spec b/packaging/cairo.spec
index 2cf96ec5f..39165e6cf 100644
--- a/packaging/cairo.spec
+++ b/packaging/cairo.spec
@@ -55,7 +55,7 @@ identical output on all output media while taking advantage of display
hardware acceleration when available.
%package -n libcairo
-License: LGPL-2.1+ or MPL-1.1
+License: MPL-1.1 or LGPL-2.1+
Summary: Vector Graphics Library with Cross-Device Output Support
Group: Graphics/Libraries
Provides: cairo = %{version}
@@ -69,7 +69,7 @@ identical output on all output media while taking advantage of display
hardware acceleration when available.
%package -n libcairo-gobject
-License: LGPL-2.1+ or MPL-1.1
+License: MPL-1.1 or LGPL-2.1+
Summary: Vector Graphics Library with Cross-Device Output Support
Group: Graphics/Libraries
@@ -84,7 +84,7 @@ This library contains GType declarations for Cairo types. It is also
meant to support gobject-introspection binding creation.
%package -n libcairo-script-interpreter
-License: LGPL-2.1+ or MPL-1.1
+License: MPL-1.1 or LGPL-2.1+
Summary: Vector Graphics Library with Cross-Device Output Support
Group: Graphics/Libraries
@@ -95,22 +95,6 @@ in-memory image buffers, and PostScript. Cairo is designed to produce
identical output on all output media while taking advantage of display
hardware acceleration when available.
-%package -n tools
-License: GPL-3.0+
-Summary: Vector Graphics Library with Cross-Device Output Support -- Utilities
-Group: Development/Libraries
-# We need an explicit requires since nothing links to the cairo library
-#Requires: libcairo = %{version}
-
-%description -n tools
-Cairo is a vector graphics library with cross-device output support.
-Currently supported output targets include the X Window System,
-in-memory image buffers, and PostScript. Cairo is designed to produce
-identical output on all output media while taking advantage of display
-hardware acceleration when available.
-
-This package contains various cairo utilities.
-
%package devel
License: MPL-1.1 or LGPL-2.1+
Summary: Development environment for cairo
@@ -203,17 +187,6 @@ make %{?_smp_mflags} V=1
%license util/cairo-script/COPYING
%{_libdir}/libcairo-script-interpreter.so.*
-#%files -n tools
-#%manifest %{name}.manifest
-#%defattr(-, root, root)
-#%license util/cairo-trace/COPYING util/cairo-trace/COPYING-GPL-3
-#%{_bindir}/cairo-sphinx
-#%{_bindir}/cairo-trace
-#%dir %{_libdir}/cairo
-#%{_libdir}/cairo/cairo-fdr.so*
-#%{_libdir}/cairo/cairo-sphinx.so*
-#%{_libdir}/cairo/libcairo-trace.so*
-
%files devel
%manifest %{name}.manifest
%defattr(-, root, root)
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;