[cogl/wip/gles2-context] framebuffer: make foreign context current on cogl_push_framebuffer
- From: Tomeu Vizoso <tomeuv src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [cogl/wip/gles2-context] framebuffer: make foreign context current on cogl_push_framebuffer
- Date: Mon, 19 Dec 2011 18:41:57 +0000 (UTC)
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]