[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