[cairo-commit] 3 commits - src/cairo-gl-composite.c src/cairo-gl.h src/cairo-gl-private.h src/cairo-gl-shaders.c src/cairo-glx-context.c
Eric Anholt
anholt at kemper.freedesktop.org
Sat Feb 26 14:11:38 PST 2011
src/cairo-gl-composite.c | 6 ----
src/cairo-gl-private.h | 5 ----
src/cairo-gl-shaders.c | 58 +++++++++++++++++++++++++++--------------------
src/cairo-gl.h | 26 +++++++++++++++++++++
src/cairo-glx-context.c | 12 ++++++++-
5 files changed, 72 insertions(+), 35 deletions(-)
New commits:
commit 17169a1e5130b8a287f07eb43d41f0b51307cc57
Author: Eric Anholt <eric at anholt.net>
Date: Mon Feb 21 13:37:00 2011 -0800
gl: Bind samplers just once at program compile time.
We never bound any other value to the sampler uniforms, so why bother
resetting them all the time?
[ 0] before firefox-talos-gfx 29.972 30.493 0.89% 3/3
[ 0] after firefox-talos-gfx 29.397 29.599 1.27% 3/3
Signed-off-by: Eric Anholt <eric at anholt.net>
diff --git a/src/cairo-gl-composite.c b/src/cairo-gl-composite.c
index d5b3c5c..c8f84a9 100644
--- a/src/cairo-gl-composite.c
+++ b/src/cairo-gl-composite.c
@@ -401,13 +401,9 @@ _cairo_gl_operand_bind_to_shader (cairo_gl_context_t *ctx,
_cairo_gl_shader_bind_float (ctx,
uniform_name,
operand->gradient.radius_0);
- /* fall through */
+ break;
case CAIRO_GL_OPERAND_LINEAR_GRADIENT:
case CAIRO_GL_OPERAND_TEXTURE:
- strcpy (custom_part, "_sampler");
- _cairo_gl_shader_bind_texture(ctx,
- uniform_name,
- tex_unit);
break;
}
}
diff --git a/src/cairo-gl-private.h b/src/cairo-gl-private.h
index 475f14a..73818b1 100644
--- a/src/cairo-gl-private.h
+++ b/src/cairo-gl-private.h
@@ -548,11 +548,6 @@ _cairo_gl_shader_bind_matrix4f (cairo_gl_context_t *ctx,
GLfloat* gl_m);
cairo_private void
-_cairo_gl_shader_bind_texture (cairo_gl_context_t *ctx,
- const char *name,
- GLuint tex_unit);
-
-cairo_private void
_cairo_gl_set_shader (cairo_gl_context_t *ctx,
cairo_gl_shader_t *shader);
diff --git a/src/cairo-gl-shaders.c b/src/cairo-gl-shaders.c
index a17491e..39e4e30 100644
--- a/src/cairo-gl-shaders.c
+++ b/src/cairo-gl-shaders.c
@@ -99,12 +99,6 @@ typedef struct cairo_gl_shader_impl {
GLfloat* gl_m);
void
- (*bind_texture) (cairo_gl_context_t *ctx,
- cairo_gl_shader_t *shader,
- const char *name,
- cairo_gl_tex_t tex_unit);
-
- void
(*use) (cairo_gl_context_t *ctx,
cairo_gl_shader_t *shader);
} shader_impl_t;
@@ -291,16 +285,6 @@ bind_matrix4f_core_2_0 (cairo_gl_context_t *ctx,
}
static void
-bind_texture_core_2_0 (cairo_gl_context_t *ctx, cairo_gl_shader_t *shader,
- const char *name, cairo_gl_tex_t tex_unit)
-{
- cairo_gl_dispatch_t *dispatch = &ctx->dispatch;
- GLint location = dispatch->GetUniformLocation (shader->program, name);
- assert (location != -1);
- dispatch->Uniform1i (location, tex_unit);
-}
-
-static void
use_program_core_2_0 (cairo_gl_context_t *ctx,
cairo_gl_shader_t *shader)
{
@@ -321,7 +305,6 @@ static const cairo_gl_shader_impl_t shader_impl_core_2_0 = {
bind_vec4_core_2_0,
bind_matrix_core_2_0,
bind_matrix4f_core_2_0,
- bind_texture_core_2_0,
use_program_core_2_0,
};
@@ -788,6 +771,38 @@ _cairo_gl_shader_compile (cairo_gl_context_t *ctx,
return status;
}
+/* We always bind the source to texture unit 0 if present, and mask to
+ * texture unit 1 if present, so we can just initialize these once at
+ * compile time.
+ */
+static void
+_cairo_gl_shader_set_samplers (cairo_gl_context_t *ctx,
+ cairo_gl_shader_t *shader)
+{
+ cairo_gl_dispatch_t *dispatch = &ctx->dispatch;
+ GLint location;
+ GLint saved_program;
+
+ /* We have to save/restore the current program because we might be
+ * asked for a different program while a shader is bound. This shouldn't
+ * be a performance issue, since this is only called once per compile.
+ */
+ glGetIntegerv (GL_CURRENT_PROGRAM, &saved_program);
+ dispatch->UseProgram (shader->program);
+
+ location = dispatch->GetUniformLocation (shader->program, "source_sampler");
+ if (location != -1) {
+ dispatch->Uniform1i (location, CAIRO_GL_TEX_SOURCE);
+ }
+
+ location = dispatch->GetUniformLocation (shader->program, "mask_sampler");
+ if (location != -1) {
+ dispatch->Uniform1i (location, CAIRO_GL_TEX_MASK);
+ }
+
+ dispatch->UseProgram (saved_program);
+}
+
void
_cairo_gl_shader_bind_float (cairo_gl_context_t *ctx,
const char *name,
@@ -839,13 +854,6 @@ _cairo_gl_shader_bind_matrix4f (cairo_gl_context_t *ctx,
}
void
-_cairo_gl_shader_bind_texture (cairo_gl_context_t *ctx,
- const char *name, GLuint tex_unit)
-{
- ctx->shader_impl->bind_texture (ctx, ctx->current_shader, name, tex_unit);
-}
-
-void
_cairo_gl_set_shader (cairo_gl_context_t *ctx,
cairo_gl_shader_t *shader)
{
@@ -913,6 +921,8 @@ _cairo_gl_get_shader_by_type (cairo_gl_context_t *ctx,
return status;
}
+ _cairo_gl_shader_set_samplers (ctx, &entry->shader);
+
status = _cairo_cache_insert (&ctx->shaders, &entry->base);
if (unlikely (status)) {
_cairo_gl_shader_fini (ctx, &entry->shader);
commit 2fae22a3f2914a6e79436bafe94d19100d7cf6bf
Author: Eric Anholt <eric at anholt.net>
Date: Mon Jan 31 20:47:15 2011 -0800
gl: Take advantage of GLX_MESA_multithread_makecurrent to avoid unbinding.
Because of GLX's unfortunate requirement that only one context have a
thread current at a time, we had to unbind the context, triggering a
flush, and eating of all the CPU. With a small tweak to the GLX spec
by GLX_MESA_multithread_makecurrent, and a small tweak to Mesa that
consisted mostly of deleting the "is this thread already bound
elsewhere?" check, we can bind our context to any thread and use it
safely as long as our usage of it is mutexed, which cairo-gl should
already be doing.
[ 0] before firefox-talos-gfx 50.260 50.525 0.25% 3/3
[ 0] after firefox-talos-gfx 32.091 32.422 0.65% 3/3
diff --git a/src/cairo-glx-context.c b/src/cairo-glx-context.c
index 83963fb..f89fa32 100644
--- a/src/cairo-glx-context.c
+++ b/src/cairo-glx-context.c
@@ -52,6 +52,8 @@ typedef struct _cairo_glx_context {
Display *display;
Window dummy_window;
GLXContext context;
+
+ cairo_bool_t has_multithread_makecurrent;
} cairo_glx_context_t;
typedef struct _cairo_glx_surface {
@@ -92,7 +94,9 @@ _glx_release (void *abstract_ctx)
{
cairo_glx_context_t *ctx = abstract_ctx;
- glXMakeCurrent (ctx->display, None, None);
+ if (!ctx->has_multithread_makecurrent) {
+ glXMakeCurrent (ctx->display, None, None);
+ }
}
static void
@@ -174,6 +178,7 @@ cairo_glx_device_create (Display *dpy, GLXContext gl_ctx)
cairo_glx_context_t *ctx;
cairo_status_t status;
Window dummy = None;
+ const char *glx_extensions;
status = _glx_dummy_ctx (dpy, gl_ctx, &dummy);
if (unlikely (status))
@@ -206,6 +211,11 @@ cairo_glx_device_create (Display *dpy, GLXContext gl_ctx)
return _cairo_gl_context_create_in_error (status);
}
+ glx_extensions = glXQueryExtensionsString (dpy, DefaultScreen (dpy));
+ if (strstr(glx_extensions, "GLX_MESA_multithread_makecurrent")) {
+ ctx->has_multithread_makecurrent = TRUE;
+ }
+
ctx->base.release (ctx);
return &ctx->base.base;
commit 2e67809be0a2febd52c75948fabd7ac81227e5e3
Author: Eric Anholt <eric at anholt.net>
Date: Sun Jan 30 23:41:39 2011 -0800
gl: Add a first bit of general documentation on cairo-gl usage.
Since its inception, cairo-gl has been plagued by the "how am I really
supposed to use it?" problem. This lays down my expectations for how
cairo-gl will interact with other usage of the GL API.
diff --git a/src/cairo-gl.h b/src/cairo-gl.h
index 131d114..9efde43 100644
--- a/src/cairo-gl.h
+++ b/src/cairo-gl.h
@@ -31,6 +31,32 @@
* The Initial Developer of the Original Code is Eric Anholt.
*/
+/**
+ * @file cairo-gl.h
+ *
+ * The cairo-gl backend provides an implementation of possibly
+ * hardware-accelerated cairo rendering by targeting the OpenGL API.
+ * The goal of the cairo-gl backend is to provide better performance
+ * with equal functionality to cairo-image where possible. It does
+ * not directly provide for applying additional OpenGL effects to
+ * cairo surfaces.
+ *
+ * Cairo-gl allows interoperability with other GL rendering through GL
+ * context sharing. Cairo-gl surfaces are created in reference to a
+ * cairo_device_t, which represents an GL context created by the user.
+ * When that GL context is created with its sharePtr set to another
+ * context (or vice versa), its objects (textures backing cairo-gl
+ * surfaces) can be accessed in the other OpenGL context. This allows
+ * cairo-gl to maintain its drawing state in one context while the
+ * user's 3D rendering occurs in the user's other context.
+ *
+ * However, as only one context can be current to a thread at a time,
+ * cairo-gl may make its context current to the thread on any cairo
+ * call which interacts with a cairo-gl surface or the cairo-gl
+ * device. As a result, the user must make their own context current
+ * between any cairo calls and their own OpenGL rendering.
+ */
+
#ifndef CAIRO_GL_H
#define CAIRO_GL_H
More information about the cairo-commit
mailing list