[cogl/wip/gles2-context] framebuffer: make foreign context current on cogl_push_framebuffer



commit 0ea46314e3caabe8cea7bbf2a06314cb21ed10b3
Author: Tomeu Vizoso <tomeu vizoso collabora com>
Date:   Mon Dec 19 19:41:01 2011 +0100

    framebuffer: make foreign context current on cogl_push_framebuffer

 cogl/cogl-context-private.h     |    1 +
 cogl/cogl-framebuffer-private.h |    3 +
 cogl/cogl-framebuffer.c         |  152 ++++++++++++++++++++++-----------------
 cogl/winsys/cogl-winsys-egl.c   |    1 +
 examples/cogl-gles2-context.c   |   65 ++++++++---------
 5 files changed, 123 insertions(+), 99 deletions(-)
---
diff --git a/cogl/cogl-context-private.h b/cogl/cogl-context-private.h
index b67c7e7..d575a43 100644
--- a/cogl/cogl-context-private.h
+++ b/cogl/cogl-context-private.h
@@ -165,6 +165,7 @@ struct _CoglContext
   unsigned long     current_draw_buffer_changes;
   CoglFramebuffer  *current_draw_buffer;
   CoglFramebuffer  *current_read_buffer;
+  CoglGLES2Context *current_gles2_context;
 
   /* Primitives */
   CoglPath         *current_path;
diff --git a/cogl/cogl-framebuffer-private.h b/cogl/cogl-framebuffer-private.h
index 281ab0e..45c32b9 100644
--- a/cogl/cogl-framebuffer-private.h
+++ b/cogl/cogl-framebuffer-private.h
@@ -150,6 +150,9 @@ struct _CoglFramebuffer
   int                 clear_clip_x1;
   int                 clear_clip_y1;
   gboolean            clear_clip_dirty;
+
+  CoglGLES2Context   *gles2_context;
+  GLuint              foreign_fbo_gl_handle;
 };
 
 typedef struct _CoglOffscreen
diff --git a/cogl/cogl-framebuffer.c b/cogl/cogl-framebuffer.c
index cadd6ae..45ca731 100644
--- a/cogl/cogl-framebuffer.c
+++ b/cogl/cogl-framebuffer.c
@@ -595,6 +595,8 @@ _cogl_framebuffer_add_dependency (CoglFramebuffer *framebuffer,
 {
   GList *l;
 
+  g_return_if_fail (framebuffer != dependency);
+
   for (l = framebuffer->deps; l; l = l->next)
     {
       CoglFramebuffer *existing_dep = l->data;
@@ -1278,7 +1280,66 @@ _cogl_push_framebuffers (CoglFramebuffer *draw_buffer,
 void
 cogl_push_framebuffer (CoglFramebuffer *buffer)
 {
+  CoglOffscreen *offscreen;
+  CoglContext *ctx = buffer->context;
+  const CoglWinsysVtable *winsys;
+  GLuint tex_gl_handle;
+  GLenum tex_gl_target;
+  GLenum status;
+  GHashTableIter iter;
+  gpointer key, value;
+
   _cogl_push_framebuffers (buffer, buffer);
+
+  if (buffer->gles2_context == NULL)
+    return;
+
+  /* FIXME: Deal with onscreen framebuffers */
+  g_return_if_fail (buffer->type == COGL_FRAMEBUFFER_TYPE_OFFSCREEN);
+
+  g_return_if_fail (cogl_framebuffer_allocate (buffer, NULL));
+
+  /* Make current the GL context being pushed */
+  winsys = ctx->display->renderer->winsys_vtable;
+  g_return_if_fail (winsys->make_current (buffer->gles2_context, NULL));
+  ctx->current_gles2_context = buffer->gles2_context;
+
+  if (buffer->foreign_fbo_gl_handle == 0)
+    ctx->glGenFramebuffers(1, &buffer->foreign_fbo_gl_handle);
+
+  GE (ctx, glBindFramebuffer (GL_FRAMEBUFFER, buffer->foreign_fbo_gl_handle));
+
+  offscreen = COGL_OFFSCREEN (buffer);
+
+  if (!cogl_texture_get_gl_texture (offscreen->texture,
+                                    &tex_gl_handle, &tex_gl_target))
+    return;
+
+  GE (ctx, glFramebufferTexture2D (GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0,
+                                   tex_gl_target, tex_gl_handle,
+                                   offscreen->texture_level));
+
+  g_hash_table_iter_init (&iter, offscreen->renderbuffers);
+  while (g_hash_table_iter_next (&iter, &key, &value)) 
+    {
+      GLuint attachment = GPOINTER_TO_UINT (key);
+      GLuint renderbuffer = GPOINTER_TO_UINT (value);
+      if (attachment & _ATTACHMENT_DEPTH)
+        {
+          GE (ctx, glFramebufferRenderbuffer (GL_FRAMEBUFFER,
+                                              GL_DEPTH_ATTACHMENT,
+                                              GL_RENDERBUFFER, renderbuffer));
+        }
+      if (attachment & _ATTACHMENT_STENCIL)
+        {
+          GE (ctx, glFramebufferRenderbuffer (GL_FRAMEBUFFER,
+                                              GL_STENCIL_ATTACHMENT,
+                                              GL_RENDERBUFFER, renderbuffer));
+        }
+    }
+
+  status = ctx->glCheckFramebufferStatus (GL_FRAMEBUFFER);
+  g_return_if_fail (status == GL_FRAMEBUFFER_COMPLETE);
 }
 
 /* XXX: deprecated API */
@@ -1318,6 +1379,9 @@ cogl_pop_framebuffer (void)
                               to_restore->read_buffer);
     }
 
+  if (to_pop->draw_buffer->gles2_context != NULL)
+    ctx->glFlush ();
+
   cogl_object_unref (to_pop->draw_buffer);
   cogl_object_unref (to_pop->read_buffer);
   g_slice_free (CoglFramebufferStackEntry, to_pop);
@@ -1340,8 +1404,16 @@ bind_gl_framebuffer (CoglContext *ctx,
                      CoglFramebuffer *framebuffer)
 {
   if (framebuffer->type == COGL_FRAMEBUFFER_TYPE_OFFSCREEN)
-    GE (ctx, glBindFramebuffer (target,
-                           COGL_OFFSCREEN (framebuffer)->fbo_handle));
+    {
+        if (framebuffer->gles2_context == NULL && FALSE)
+          {
+            const CoglWinsysVtable *winsys = ctx->display->renderer->winsys_vtable;
+            winsys->make_current (NULL, NULL);
+          }
+
+        GE (ctx, glBindFramebuffer (target,
+                                    COGL_OFFSCREEN (framebuffer)->fbo_handle));
+    }
   else
     {
       const CoglWinsysVtable *winsys =
@@ -1646,6 +1718,12 @@ _cogl_framebuffer_flush_state (CoglFramebuffer *draw_buffer,
       ctx->current_draw_buffer_state_flushed = 0;
     }
 
+  if (ctx->current_gles2_context != draw_buffer->gles2_context)
+    {
+      differences |= COGL_FRAMEBUFFER_STATE_BIND;
+      ctx->current_gles2_context = draw_buffer->gles2_context;
+    }
+
   if (ctx->current_read_buffer != read_buffer &&
       state & COGL_FRAMEBUFFER_STATE_BIND)
     {
@@ -2426,68 +2504,15 @@ cogl_framebuffer_push_gles2_context (CoglFramebuffer *framebuffer,
                                      GError **error)
 {
   CoglContext *ctx = gles2_ctx->context;
-  CoglOffscreen *offscreen = COGL_OFFSCREEN (framebuffer);
-  const CoglWinsysVtable *winsys;
-  GLuint tex_gl_handle;
-  GLenum tex_gl_target;
-  GLuint fbo_gl_handle;
-  gboolean result;
-  GLenum status;
-  GHashTableIter iter;
-  gpointer key, value;
 
   if (!cogl_has_feature (ctx, COGL_FEATURE_ID_GLES2_CONTEXT))
     return FALSE;
 
-  if (!cogl_framebuffer_allocate (framebuffer, NULL))
-    return FALSE;
-
-  /* Make current the GL context being pushed */
-  winsys = ctx->display->renderer->winsys_vtable;
-  result = winsys->make_current (gles2_ctx, error);
-  if (!result)
-    return FALSE;
-
-  /* Ensure we have a framebuffer in this context */
-  fbo_gl_handle = cogl_object_get_user_data (COGL_OBJECT (framebuffer), (CoglUserDataKey *)gles2_ctx);
-  if (fbo_gl_handle == 0)
-    {
-      ctx->glGenFramebuffers(1, &fbo_gl_handle);
-      cogl_object_set_user_data (COGL_OBJECT (framebuffer), (CoglUserDataKey *)gles2_ctx, fbo_gl_handle, NULL);
-    }
-
-  /* Bind the new framebuffer */
-  GE (ctx, glBindFramebuffer (GL_FRAMEBUFFER, fbo_gl_handle));
-
-  if (!cogl_texture_get_gl_texture (offscreen->texture,
-                                    &tex_gl_handle, &tex_gl_target))
-    return FALSE;
-
-  GE (ctx, glFramebufferTexture2D (GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0,
-                                   tex_gl_target, tex_gl_handle,
-                                   offscreen->texture_level));
-
-  g_hash_table_iter_init (&iter, offscreen->renderbuffers);
-  while (g_hash_table_iter_next (&iter, &key, &value)) 
-    {
-      GLuint attachment = GPOINTER_TO_UINT (key);
-      GLuint renderbuffer = GPOINTER_TO_UINT (value);
-      if (attachment & _ATTACHMENT_DEPTH)
-        {
-          GE (ctx, glFramebufferRenderbuffer (GL_FRAMEBUFFER,
-                                              GL_DEPTH_ATTACHMENT,
-                                              GL_RENDERBUFFER, renderbuffer));
-        }
-      if (attachment & _ATTACHMENT_STENCIL)
-        {
-          GE (ctx, glFramebufferRenderbuffer (GL_FRAMEBUFFER,
-                                              GL_STENCIL_ATTACHMENT,
-                                              GL_RENDERBUFFER, renderbuffer));
-        }
-    }
+  framebuffer->gles2_context = gles2_ctx;
+  /* FIXME: take a ref on the context */
 
-  status = ctx->glCheckFramebufferStatus (GL_FRAMEBUFFER);
-  g_return_val_if_fail (status == GL_FRAMEBUFFER_COMPLETE, FALSE);
+  /* FIXME: If the framebuffer is current, we need to make the new context
+     current here as well, like in cogl_push_framebuffer */
 
   return TRUE;
 }
@@ -2496,12 +2521,9 @@ void
 cogl_framebuffer_pop_gles2_context (CoglFramebuffer *framebuffer)
 {
   //CoglContext *ctx = cogl_framebuffer_get_context (framebuffer);
-  const CoglWinsysVtable *winsys;
 
-  _COGL_GET_CONTEXT (ctx, NO_RETVAL);
-
-  ctx->glFlush ();
+  //_COGL_GET_CONTEXT (ctx, NO_RETVAL);
 
-  winsys = ctx->display->renderer->winsys_vtable;
-  winsys->make_current (NULL, NULL);
+  /* FIXME: If the framebuffer is current, we need to make its context
+     uncurrent here as well, like in cogl_pop_framebuffer */
 }
diff --git a/cogl/winsys/cogl-winsys-egl.c b/cogl/winsys/cogl-winsys-egl.c
index fb6ca43..bd90074 100644
--- a/cogl/winsys/cogl-winsys-egl.c
+++ b/cogl/winsys/cogl-winsys-egl.c
@@ -1872,6 +1872,7 @@ _cogl_winsys_make_current (CoglGLES2Context *gles2_ctx,
                    COGL_WINSYS_ERROR_MAKE_CURRENT,
                    "%s", get_error_string ());
     }
+  ((CoglContextEGL *)ctx->winsys)->current_surface = egl_surface;
 
   return result;
 }
diff --git a/examples/cogl-gles2-context.c b/examples/cogl-gles2-context.c
index 279db1c..16b3b7d 100644
--- a/examples/cogl-gles2-context.c
+++ b/examples/cogl-gles2-context.c
@@ -7,45 +7,39 @@ CoglColor black;
 #define OFFSCREEN_WIDTH 100
 #define OFFSCREEN_HEIGHT 100
 
-CoglTexture *
-get_offscreen_texture (CoglContext *ctx)
+void
+update_offscreen_texture (CoglContext *ctx, CoglTexture *offscreen_texture)
 {
+  static CoglGLES2Context *gles2_ctx = NULL;
+  static CoglGLES2Vtable *vtable = NULL;
+  static CoglFramebuffer *offscreen_framebuffer = NULL;
   GError *error = NULL;
 
-  CoglGLES2Context *gles2_ctx;
-  CoglGLES2Vtable *vtable;
-  CoglTexture *offscreen_texture = NULL;
-  CoglFramebuffer *offscreen_framebuffer;
-
-  /* Prepare offscreen framebuffer */
-  gles2_ctx = cogl_gles2_context_new (ctx, &error);
-  if (!gles2_ctx) {
-      g_error ("Failed to create GLES2 context: %s\n", error->message);
-      return NULL;
-  }
-
-  vtable = cogl_gles2_context_get_vtable (gles2_ctx);
-
-  offscreen_texture = cogl_texture_new_with_size (OFFSCREEN_WIDTH, OFFSCREEN_HEIGHT,
-                                                  COGL_TEXTURE_NO_SLICING,
-                                                  COGL_PIXEL_FORMAT_ANY);
+  if (gles2_ctx == NULL)
+    {
+      /* Prepare offscreen framebuffer */
+      gles2_ctx = cogl_gles2_context_new (ctx, &error);
+      if (!gles2_ctx) {
+          g_error ("Failed to create GLES2 context: %s\n", error->message);
+      }
+
+      vtable = cogl_gles2_context_get_vtable (gles2_ctx);
+
+      offscreen_framebuffer = cogl_offscreen_new_to_texture (offscreen_texture);
+      if (!cogl_framebuffer_push_gles2_context (offscreen_framebuffer,
+                                           gles2_ctx,
+                                           &error)) {
+          g_error ("Failed to push GLES2 context: %s\n", error->message);
+      }
+    }
 
-  offscreen_framebuffer = cogl_offscreen_new_to_texture (offscreen_texture);
+  cogl_push_framebuffer (offscreen_framebuffer);
 
   /* Clear offscreen framebuffer with green */
-  if (!cogl_framebuffer_push_gles2_context (offscreen_framebuffer,
-                                       gles2_ctx,
-                                       &error)) {
-      g_error ("Failed to push GLES2 context: %s\n", error->message);
-      return NULL;
-  }
+  vtable->glClearColor(g_random_double (), g_random_double (), g_random_double (), 1.0f);
+  vtable->glClear(GL_COLOR_BUFFER_BIT);
 
-  vtable->glClearColor(0.0f, 1.0f, 0.0f, 1.0f);
-  vtable->glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
-
-  cogl_framebuffer_pop_gles2_context (offscreen_framebuffer);
-
-  return offscreen_texture;
+  cogl_pop_framebuffer ();
 }
 
 int
@@ -83,16 +77,19 @@ main (int argc, char **argv)
     /* Prepare onscreen primitive */
     triangle = cogl_primitive_new_p2c4 (COGL_VERTICES_MODE_TRIANGLES,
                                         3, triangle_vertices);
+
+    offscreen_texture = cogl_texture_new_with_size (OFFSCREEN_WIDTH, OFFSCREEN_HEIGHT,
+                                                    COGL_TEXTURE_NO_SLICING,
+                                                    COGL_PIXEL_FORMAT_ANY);
     for (;;) {
         /* Draw scene with Cogl */
         cogl_push_framebuffer (fb);
         cogl_clear (&black, COGL_BUFFER_BIT_COLOR);
 
-        offscreen_texture = get_offscreen_texture (ctx);
-
         cogl_set_source_color4f (0.0f, 0.0f, 0.0f, 1.0f);
         cogl_primitive_draw (triangle);
 
+        update_offscreen_texture (ctx, offscreen_texture);
         cogl_set_source_texture (offscreen_texture);
         cogl_rectangle_with_texture_coords (-0.5, -0.5, 0.5, 0.5,
                                             0, 0, 1.0, 1.0);



[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]