[cairo-commit] src/cairo-gl-device.c src/cairo-gl-private.h src/cairo-gl-surface.c

Martin Robinson mrobinson at kemper.freedesktop.org
Fri Apr 26 15:08:49 PDT 2013


 src/cairo-gl-device.c  |   98 ++++++++++++++++++++++++++++---------------------
 src/cairo-gl-private.h |    9 ++--
 src/cairo-gl-surface.c |    2 -
 3 files changed, 63 insertions(+), 46 deletions(-)

New commits:
commit 8da704ca7c43dda796657e86c5221736b1983122
Author: Martin Robinson <mrobinson at igalia.com>
Date:   Wed Apr 10 22:25:49 2013 +0000

    gl: Separate framebuffer bind from destination selection
    
    Disentangle the action of binding the framebuffer from setting the
    destination. This straightens up the code a bit and avoids some redundant
    operations (such as reacquiring the context) when simply switching from
    the multi-sample framebuffer to the single-sample framebuffer and vice
    versa.

diff --git a/src/cairo-gl-device.c b/src/cairo-gl-device.c
index b30c49c..97e3fb8 100644
--- a/src/cairo-gl-device.c
+++ b/src/cairo-gl-device.c
@@ -615,8 +615,8 @@ _gl_identity_ortho (GLfloat *m,
 
 #if CAIRO_HAS_GL_SURFACE
 static void
-_cairo_gl_activate_surface_as_multisampling (cairo_gl_context_t *ctx,
-					     cairo_gl_surface_t *surface)
+bind_multisample_framebuffer (cairo_gl_context_t *ctx,
+			       cairo_gl_surface_t *surface)
 {
     assert (surface->supports_msaa);
     assert (ctx->gl_flavor == CAIRO_GL_FLAVOR_DESKTOP);
@@ -624,7 +624,6 @@ _cairo_gl_activate_surface_as_multisampling (cairo_gl_context_t *ctx,
     _cairo_gl_ensure_framebuffer (ctx, surface);
     _cairo_gl_ensure_multisampling (ctx, surface);
 
-
     if (surface->msaa_active) {
 	glEnable (GL_MULTISAMPLE);
 	ctx->dispatch.BindFramebuffer (GL_FRAMEBUFFER, surface->msaa_fb);
@@ -643,18 +642,17 @@ _cairo_gl_activate_surface_as_multisampling (cairo_gl_context_t *ctx,
 				   0, 0, surface->width, surface->height,
 				   GL_COLOR_BUFFER_BIT, GL_NEAREST);
     ctx->dispatch.BindFramebuffer (GL_FRAMEBUFFER, surface->msaa_fb);
-    surface->msaa_active = TRUE;
 }
 #endif
 
-void
-_cairo_gl_activate_surface_as_nonmultisampling (cairo_gl_context_t *ctx,
-						cairo_gl_surface_t *surface)
+#if CAIRO_HAS_GL_SURFACE
+static void
+bind_singlesample_framebuffer (cairo_gl_context_t *ctx,
+			       cairo_gl_surface_t *surface)
 {
     assert (ctx->gl_flavor == CAIRO_GL_FLAVOR_DESKTOP);
     _cairo_gl_ensure_framebuffer (ctx, surface);
 
-#if CAIRO_HAS_GL_SURFACE
     if (! surface->msaa_active) {
 	glDisable (GL_MULTISAMPLE);
 	ctx->dispatch.BindFramebuffer (GL_FRAMEBUFFER, surface->fb);
@@ -673,8 +671,38 @@ _cairo_gl_activate_surface_as_nonmultisampling (cairo_gl_context_t *ctx,
 				   0, 0, surface->width, surface->height,
 				   GL_COLOR_BUFFER_BIT, GL_NEAREST);
     ctx->dispatch.BindFramebuffer (GL_FRAMEBUFFER, surface->fb);
-    surface->msaa_active = FALSE;
+}
+#endif
+
+void
+_cairo_gl_context_bind_framebuffer (cairo_gl_context_t *ctx,
+				    cairo_gl_surface_t *surface,
+				    cairo_bool_t multisampling)
+{
+    /* OpenGL ES surfaces only have either a multisample framebuffer or a
+     * singlesample framebuffer, so we cannot switch back and forth. */
+    if (ctx->gl_flavor == CAIRO_GL_FLAVOR_ES) {
+	_cairo_gl_ensure_framebuffer (ctx, surface);
+	ctx->dispatch.BindFramebuffer (GL_FRAMEBUFFER, surface->fb);
+	return;
+    }
+
+#if CAIRO_HAS_GL_SURFACE
+    if (_cairo_gl_surface_is_texture (surface)) {
+	if (multisampling)
+	    bind_multisample_framebuffer (ctx, surface);
+	else
+	    bind_singlesample_framebuffer (ctx, surface);
+    } else {
+	ctx->dispatch.BindFramebuffer (GL_FRAMEBUFFER, 0);
+	if (multisampling)
+	    glEnable (GL_MULTISAMPLE);
+	else
+	    glDisable (GL_MULTISAMPLE);
+    }
 #endif
+
+    surface->msaa_active = multisampling;
 }
 
 void
@@ -682,51 +710,39 @@ _cairo_gl_context_set_destination (cairo_gl_context_t *ctx,
                                    cairo_gl_surface_t *surface,
                                    cairo_bool_t multisampling)
 {
-    /* OpenGL ES surfaces are always in MSAA mode once it's been turned on,
-     * so we don't need to check whether we are switching modes for that
-     * surface type. */
-    if (ctx->current_target == surface && ! surface->needs_update &&
-	(ctx->gl_flavor == CAIRO_GL_FLAVOR_ES ||
-	 surface->msaa_active == multisampling))
+    cairo_bool_t changing_surface = ctx->current_target != surface;
+    cairo_bool_t changing_sampling = surface->msaa_active != multisampling;
+    if (! changing_surface && ! changing_sampling)
 	return;
 
+    if (! changing_surface) {
+	/* The decision whether or not to use multisampling happen when
+	 * we create an OpenGL ES surface, so switching modes is a no-op. */
+	if (ctx->gl_flavor == CAIRO_GL_FLAVOR_ES)
+	    return;
+
+	_cairo_gl_composite_flush (ctx);
+	_cairo_gl_context_bind_framebuffer (ctx, surface, multisampling);
+	return;
+    }
+
     _cairo_gl_composite_flush (ctx);
 
     ctx->current_target = surface;
     surface->needs_update = FALSE;
 
-    if (_cairo_gl_surface_is_texture (surface)) {
-	if (ctx->gl_flavor == CAIRO_GL_FLAVOR_ES) {
-	    _cairo_gl_ensure_framebuffer (ctx, surface);
-	    ctx->dispatch.BindFramebuffer (GL_FRAMEBUFFER, surface->fb);
-#if CAIRO_HAS_GL_SURFACE
-	} else if (multisampling)
-	    _cairo_gl_activate_surface_as_multisampling (ctx, surface);
-	else {
-	    _cairo_gl_activate_surface_as_nonmultisampling (ctx, surface);
-#endif
-	}
-    } else {
-        ctx->make_current (ctx, surface);
-
-#if CAIRO_HAS_GL_SURFACE
-	if (multisampling)
-	    glEnable(GL_MULTISAMPLE);
-	else
-	    glDisable(GL_MULTISAMPLE);
-#endif
-
-        surface->msaa_active = multisampling;
-        ctx->dispatch.BindFramebuffer (GL_FRAMEBUFFER, 0);
+    if (! _cairo_gl_surface_is_texture (surface)) {
+	ctx->make_current (ctx, surface);
 
 #if CAIRO_HAS_GL_SURFACE
-        glDrawBuffer (GL_BACK_LEFT);
-        glReadBuffer (GL_BACK_LEFT);
+	glDrawBuffer (GL_BACK_LEFT);
+	glReadBuffer (GL_BACK_LEFT);
 #endif
     }
 
-    glDisable (GL_DITHER);
+    _cairo_gl_context_bind_framebuffer (ctx, surface, multisampling);
 
+    glDisable (GL_DITHER);
     glViewport (0, 0, surface->width, surface->height);
 
     if (_cairo_gl_surface_is_texture (surface))
diff --git a/src/cairo-gl-private.h b/src/cairo-gl-private.h
index c99bd16..d49e3d9 100644
--- a/src/cairo-gl-private.h
+++ b/src/cairo-gl-private.h
@@ -492,14 +492,15 @@ _cairo_gl_context_release (cairo_gl_context_t *ctx, cairo_status_t status)
 }
 
 cairo_private void
-_cairo_gl_activate_surface_as_nonmultisampling (cairo_gl_context_t *ctx,
-						cairo_gl_surface_t *surface);
-
-cairo_private void
 _cairo_gl_context_set_destination (cairo_gl_context_t *ctx,
 				   cairo_gl_surface_t *surface,
 				   cairo_bool_t multisampling);
 
+cairo_private void
+_cairo_gl_context_bind_framebuffer (cairo_gl_context_t *ctx,
+				    cairo_gl_surface_t *surface,
+				    cairo_bool_t multisampling);
+
 cairo_private cairo_gl_emit_rect_t
 _cairo_gl_context_choose_emit_rect (cairo_gl_context_t *ctx);
 
diff --git a/src/cairo-gl-surface.c b/src/cairo-gl-surface.c
index 144dccc..d7a7836 100644
--- a/src/cairo-gl-surface.c
+++ b/src/cairo-gl-surface.c
@@ -1309,7 +1309,7 @@ _cairo_gl_surface_resolve_multisampling (cairo_gl_surface_t *surface)
     ctx->current_target = surface;
 
 #if CAIRO_HAS_GL_SURFACE
-    _cairo_gl_activate_surface_as_nonmultisampling (ctx, surface);
+    _cairo_gl_context_bind_framebuffer (ctx, surface, FALSE);
 #endif
 
     status = _cairo_gl_context_release (ctx, status);


More information about the cairo-commit mailing list