[cogl/wip/virtual-framebuffer: 22/37] stash - add cogl-virtual-framebuffer



commit d7fe9cbb083e2faf0f45c581c170f7dc2b5b3b53
Author: Robert Bragg <robert linux intel com>
Date:   Mon Nov 14 18:33:53 2011 +0000

    stash - add cogl-virtual-framebuffer

 cogl/Makefile.am                    |    3 +
 cogl/cogl-framebuffer-private.h     |    3 +-
 cogl/cogl-framebuffer.c             |    6 +-
 cogl/cogl-virtual-framebuffer.c     |  278 +++++++++++++++++++++++++++++++++++
 cogl/cogl-virtual-framebuffer.h     |  101 +++++++++++++
 cogl/cogl.h                         |    1 +
 examples/Makefile.am                |    4 +-
 examples/cogl-virtual-framebuffer.c |   96 ++++++++++++
 8 files changed, 489 insertions(+), 3 deletions(-)
---
diff --git a/cogl/Makefile.am b/cogl/Makefile.am
index 8f3acfb..8a0151e 100644
--- a/cogl/Makefile.am
+++ b/cogl/Makefile.am
@@ -90,6 +90,7 @@ cogl_public_h = \
 	$(srcdir)/cogl-primitive.h 		\
 	$(srcdir)/cogl-clip-state.h		\
 	$(srcdir)/cogl-framebuffer.h		\
+	$(srcdir)/cogl-virtual-framebuffer.h	\
 	$(srcdir)/cogl-onscreen.h		\
 	$(srcdir)/cogl-clutter.h       		\
 	$(srcdir)/cogl.h			\
@@ -309,6 +310,8 @@ cogl_sources_c = \
 	$(srcdir)/cogl-framebuffer-private.h		\
 	$(srcdir)/cogl-framebuffer.c 			\
 	$(srcdir)/cogl-onscreen-private.h		\
+	$(srcdir)/cogl-virtual-framebuffer-private.h	\
+	$(srcdir)/cogl-virtual-framebuffer.c		\
 	$(srcdir)/cogl-onscreen.c 			\
 	$(srcdir)/cogl-profile.h 			\
 	$(srcdir)/cogl-profile.c 			\
diff --git a/cogl/cogl-framebuffer-private.h b/cogl/cogl-framebuffer-private.h
index b0ba352..4becbe8 100644
--- a/cogl/cogl-framebuffer-private.h
+++ b/cogl/cogl-framebuffer-private.h
@@ -41,7 +41,8 @@
 
 typedef enum _CoglFramebufferType {
   COGL_FRAMEBUFFER_TYPE_ONSCREEN,
-  COGL_FRAMEBUFFER_TYPE_OFFSCREEN
+  COGL_FRAMEBUFFER_TYPE_OFFSCREEN,
+  COGL_FRAMEBUFFER_TYPE_VIRTUAL
 } CoglFramebufferType;
 
 typedef struct
diff --git a/cogl/cogl-framebuffer.c b/cogl/cogl-framebuffer.c
index 76845af..881ccad 100644
--- a/cogl/cogl-framebuffer.c
+++ b/cogl/cogl-framebuffer.c
@@ -35,6 +35,7 @@
 #include "cogl-util.h"
 #include "cogl-texture-private.h"
 #include "cogl-framebuffer-private.h"
+#include "cogl-virtual-framebuffer-private.h"
 #include "cogl-onscreen-template-private.h"
 #include "cogl-clip-stack.h"
 #include "cogl-journal-private.h"
@@ -136,7 +137,8 @@ _cogl_is_framebuffer (void *object)
     return FALSE;
 
   return obj->klass->type == _cogl_object_onscreen_get_type ()
-    || obj->klass->type == _cogl_object_offscreen_get_type ();
+    || obj->klass->type == _cogl_object_offscreen_get_type ()
+    || obj->klass->type == _cogl_object_virtual_framebuffer_get_type ();
 }
 
 void
@@ -1321,6 +1323,8 @@ bind_gl_framebuffer (CoglContext *ctx,
                      GLenum target,
                      CoglFramebuffer *framebuffer)
 {
+  _COGL_RETURN_IF_FAIL (!cogl_is_virtual_framebuffer (framebuffer));
+
   if (framebuffer->type == COGL_FRAMEBUFFER_TYPE_OFFSCREEN)
     GE (ctx, glBindFramebuffer (target,
                            COGL_OFFSCREEN (framebuffer)->fbo_handle));
diff --git a/cogl/cogl-virtual-framebuffer.c b/cogl/cogl-virtual-framebuffer.c
new file mode 100644
index 0000000..59fc7eb
--- /dev/null
+++ b/cogl/cogl-virtual-framebuffer.c
@@ -0,0 +1,278 @@
+/*
+ * Cogl
+ *
+ * An object oriented GL/GLES Abstraction/Utility Layer
+ *
+ * Copyright (C) 2011 Intel Corporation.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library. If not, see <http://www.gnu.org/licenses/>.
+ *
+ *
+ */
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include "cogl-util.h"
+#include "cogl-framebuffer-private.h"
+#include "cogl-virtual-framebuffer-private.h"
+#include "cogl-context-private.h"
+#include "cogl-object-private.h"
+
+#include <glib.h>
+
+static void
+_cogl_virtual_framebuffer_free (CoglVirtualFramebuffer *virtual_framebuffer);
+
+COGL_OBJECT_INTERNAL_DEFINE (VirtualFramebuffer, virtual_framebuffer);
+
+CoglVirtualFramebuffer *
+cogl_virtual_framebuffer_new (CoglContext *context,
+                              int width,
+                              int height)
+{
+  CoglVirtualFramebuffer *virtual_framebuffer =
+    g_new0 (CoglVirtualFramebuffer, 1);
+
+  _cogl_framebuffer_init (COGL_FRAMEBUFFER (virtual_framebuffer),
+                          context,
+                          COGL_FRAMEBUFFER_TYPE_VIRTUAL,
+                          COGL_PIXEL_FORMAT_RGBA_8888, /* arbitrary */
+                          width,
+                          height);
+
+  COGL_FRAMEBUFFER (virtual_framebuffer)->allocated = TRUE;
+
+  return _cogl_virtual_framebuffer_object_new (virtual_framebuffer);
+}
+
+void
+cogl_virtual_framebuffer_add_slice (CoglVirtualFramebuffer *virtual_framebuffer,
+                                    CoglFramebuffer *slice,
+                                    int sample_x,
+                                    int sample_y,
+                                    int sample_width,
+                                    int sample_height,
+                                    int virtual_x,
+                                    int virtual_y)
+{
+  CoglFramebufferSlice *new_slice = g_new0 (CoglFramebufferSlice, 1);
+
+  new_slice->framebuffer = cogl_object_ref (slice);
+  new_slice->sample_region[0] = sample_x;
+  new_slice->sample_region[1] = sample_y;
+  if (sample_width == -1)
+    sample_width = cogl_framebuffer_get_width (slice);
+  new_slice->sample_region[2] = sample_width;
+  if (sample_height == -1)
+    sample_height = cogl_framebuffer_get_height (slice);
+  new_slice->sample_region[3] = sample_height;
+  new_slice->virtual_x = virtual_x;
+  new_slice->virtual_y = virtual_y;
+
+  if (virtual_framebuffer->slices == NULL)
+    {
+      CoglFramebuffer *fb = COGL_FRAMEBUFFER (virtual_framebuffer);
+      fb->format = cogl_framebuffer_get_color_format (fb);
+    }
+
+  virtual_framebuffer->slices =
+    g_list_prepend (virtual_framebuffer->slices, new_slice);
+}
+
+static void
+_cogl_framebuffer_slice_free (CoglFramebufferSlice *slice)
+{
+  cogl_object_unref (slice->framebuffer);
+  g_free (slice);
+}
+
+static void
+_cogl_virtual_framebuffer_free (CoglVirtualFramebuffer *virtual_framebuffer)
+{
+  CoglFramebuffer *framebuffer = COGL_FRAMEBUFFER (virtual_framebuffer);
+  GList *l;
+
+  for (l = virtual_framebuffer->slices; l; l = l->next)
+    _cogl_framebuffer_slice_free (l->data);
+
+  g_list_free (virtual_framebuffer->slices);
+
+  /* Chain up to parent */
+  _cogl_framebuffer_free (framebuffer);
+
+  g_free (virtual_framebuffer);
+}
+
+static CoglFramebufferSlice *
+lookup_slice (CoglVirtualFramebuffer *virtual_framebuffer,
+              CoglFramebuffer *slice)
+{
+  GList *l;
+
+  for (l = virtual_framebuffer->slices; l; l = l->next)
+    {
+      CoglFramebufferSlice *current_slice = l->data;
+      if (current_slice->framebuffer == slice)
+        return current_slice;
+    }
+
+  return NULL;
+}
+
+void
+cogl_virtual_framebuffer_remove_slice (
+                                    CoglVirtualFramebuffer *virtual_framebuffer,
+                                    CoglFramebuffer *slice)
+{
+  CoglFramebufferSlice *match = lookup_slice (virtual_framebuffer, slice);
+
+  _COGL_RETURN_IF_FAIL (match);
+
+  _cogl_framebuffer_slice_free (match);
+}
+
+void
+cogl_virtual_framebuffer_move_slice (
+                                    CoglVirtualFramebuffer *virtual_framebuffer,
+                                    CoglFramebuffer *slice,
+                                    int virtual_x,
+                                    int virtual_y)
+{
+  CoglFramebufferSlice *match = lookup_slice (virtual_framebuffer, slice);
+
+  _COGL_RETURN_IF_FAIL (match);
+
+  /* XXX: do we need to flush anything here? */
+
+  match->virtual_x = virtual_x;
+  match->virtual_y = virtual_y;
+}
+
+void
+cogl_virtual_framebuffer_set_slice_sample_region (
+                                    CoglVirtualFramebuffer *virtual_framebuffer,
+                                    CoglFramebuffer *slice,
+                                    int x,
+                                    int y,
+                                    int width,
+                                    int height)
+{
+  CoglFramebufferSlice *match = lookup_slice (virtual_framebuffer, slice);
+
+  _COGL_RETURN_IF_FAIL (match);
+
+  /* XXX: do we need to flush anything here? */
+
+  match->sample_region[0] = x;
+  match->sample_region[1] = y;
+
+  if (width == -1)
+    width = cogl_framebuffer_get_width (slice);
+  match->sample_region[2] = width;
+  if (height == -1)
+    height = cogl_framebuffer_get_height (slice);
+  match->sample_region[3] = height;
+}
+
+int
+cogl_virtual_framebuffer_get_slice_sample_x (
+                                    CoglVirtualFramebuffer *virtual_framebuffer,
+                                    CoglFramebuffer *slice)
+{
+
+  CoglFramebufferSlice *match = lookup_slice (virtual_framebuffer, slice);
+
+  _COGL_RETURN_VAL_IF_FAIL (match, 0);
+
+  /* XXX: do we need to flush anything here? */
+
+  return match->sample_region[0];
+}
+
+int
+cogl_virtual_framebuffer_get_slice_sample_y (
+                                    CoglVirtualFramebuffer *virtual_framebuffer,
+                                    CoglFramebuffer *slice)
+{
+  CoglFramebufferSlice *match = lookup_slice (virtual_framebuffer, slice);
+
+  _COGL_RETURN_VAL_IF_FAIL (match, 0);
+
+  /* XXX: do we need to flush anything here? */
+
+  return match->sample_region[1];
+}
+
+int
+cogl_virtual_framebuffer_get_slice_sample_width (
+                                    CoglVirtualFramebuffer *virtual_framebuffer,
+                                    CoglFramebuffer *slice)
+{
+  CoglFramebufferSlice *match = lookup_slice (virtual_framebuffer, slice);
+
+  _COGL_RETURN_VAL_IF_FAIL (match, 0);
+
+  /* XXX: do we need to flush anything here? */
+
+  return match->sample_region[2];
+}
+
+int
+cogl_virtual_framebuffer_get_slice_sample_height (
+                                    CoglVirtualFramebuffer *virtual_framebuffer,
+                                    CoglFramebuffer *slice)
+{
+  CoglFramebufferSlice *match = lookup_slice (virtual_framebuffer, slice);
+
+  _COGL_RETURN_VAL_IF_FAIL (match, 0);
+
+  /* XXX: do we need to flush anything here? */
+
+  return match->sample_region[3];
+}
+
+void
+cogl_virtual_framebuffer_set_size (CoglVirtualFramebuffer *virtual_framebuffer,
+                                   int width,
+                                   int height)
+{
+  CoglFramebuffer *fb = COGL_FRAMEBUFFER (virtual_framebuffer);
+
+  /* XXX: do we need to flush anything here? */
+
+  fb->width = width;
+  fb->height = height;
+}
+
+void
+_cogl_virtual_framebuffer_foreach (CoglVirtualFramebuffer *virtual_framebuffer,
+                                   CoglVirtialFramebufferCallback callback,
+                                   void *user_data)
+{
+  GList *l;
+  gboolean cont = TRUE;
+
+  for (l = virtual_framebuffer->slices; l && cont; l = l->next)
+    {
+      CoglFramebufferSlice *slice = l->data;
+      cont = callback (virtual_framebuffer,
+                       slice->framebuffer,
+                       slice->sample_region,
+                       slice->virtual_x,
+                       slice->virtual_y,
+                       user_data);
+    }
+}
diff --git a/cogl/cogl-virtual-framebuffer.h b/cogl/cogl-virtual-framebuffer.h
new file mode 100644
index 0000000..c34a4d4
--- /dev/null
+++ b/cogl/cogl-virtual-framebuffer.h
@@ -0,0 +1,101 @@
+/*
+ * Cogl
+ *
+ * An object oriented GL/GLES Abstraction/Utility Layer
+ *
+ * Copyright (C) 2011 Intel Corporation.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library. If not, see
+ * <http://www.gnu.org/licenses/>.
+ *
+ *
+ * Authors:
+ *   Robert Bragg <robert linux intel com>
+ */
+
+#if !defined(__COGL_H_INSIDE__) && !defined(CLUTTER_COMPILATION)
+#error "Only <cogl/cogl.h> can be included directly."
+#endif
+
+#ifndef _COGL_VIRTUAL_FRAMEBUFFER_H_
+#define _COGL_VIRTUAL_FRAMEBUFFER_H_
+
+#include <cogl/cogl-context.h>
+#include <cogl/cogl-framebuffer.h>
+#include <glib.h>
+
+G_BEGIN_DECLS
+
+typedef struct _CoglVirtualFramebuffer CoglVirtualFramebuffer;
+#define COGL_VIRTUAL_FRAMEBUFFER(X) ((CoglVirtualFramebuffer *)(X))
+
+CoglVirtualFramebuffer *
+cogl_virtual_framebuffer_new (CoglContext *context,
+                              int width,
+                              int height);
+
+void
+cogl_virtual_framebuffer_add_slice (CoglVirtualFramebuffer *virtual_framebuffer,
+                                    CoglFramebuffer *slice,
+                                    int sample_x,
+                                    int sample_y,
+                                    int sample_width,
+                                    int sample_height,
+                                    int virtual_x,
+                                    int virtual_y);
+void
+cogl_virtual_framebuffer_remove_slice (
+                                    CoglVirtualFramebuffer *virtual_framebuffer,
+                                    CoglFramebuffer *slice);
+void
+cogl_virtual_framebuffer_move_slice (
+                                    CoglVirtualFramebuffer *virtual_framebuffer,
+                                    CoglFramebuffer *slice,
+                                    int virtual_x,
+                                    int virtual_y);
+void
+cogl_virtual_framebuffer_set_slice_sample_region (
+                                    CoglVirtualFramebuffer *virtual_framebuffer,
+                                    CoglFramebuffer *slice,
+                                    int x,
+                                    int y,
+                                    int width,
+                                    int height);
+int
+cogl_virtual_framebuffer_get_slice_sample_x (
+                                    CoglVirtualFramebuffer *virtual_framebuffer,
+                                    CoglFramebuffer *slice);
+int
+cogl_virtual_framebuffer_get_slice_sample_y (
+                                    CoglVirtualFramebuffer *virtual_framebuffer,
+                                    CoglFramebuffer *slice);
+
+int
+cogl_virtual_framebuffer_get_slice_sample_width (
+                                    CoglVirtualFramebuffer *virtual_framebuffer,
+                                    CoglFramebuffer *slice);
+
+int
+cogl_virtual_framebuffer_get_slice_sample_height (
+                                    CoglVirtualFramebuffer *virtual_framebuffer,
+                                    CoglFramebuffer *slice);
+
+void
+cogl_virtual_framebuffer_set_size (CoglVirtualFramebuffer *virtual_framebuffer,
+                                   int width,
+                                   int height);
+
+G_END_DECLS
+
+#endif /* _COGL_VIRTUAL_FRAMEBUFFER_H_ */
diff --git a/cogl/cogl.h b/cogl/cogl.h
index 772886b..51644fb 100644
--- a/cogl/cogl.h
+++ b/cogl/cogl.h
@@ -95,6 +95,7 @@ typedef struct _CoglFramebuffer CoglFramebuffer;
 #include <cogl/cogl-pipeline-state.h>
 #include <cogl/cogl-pipeline-layer-state.h>
 #include <cogl/cogl-framebuffer.h>
+#include <cogl/cogl-virtual-framebuffer.h>
 #include <cogl/cogl-onscreen.h>
 #if defined (COGL_HAS_EGL_PLATFORM_WAYLAND_SUPPORT)
 #include <cogl/cogl-wayland-renderer.h>
diff --git a/examples/Makefile.am b/examples/Makefile.am
index 8403a46..6922922 100644
--- a/examples/Makefile.am
+++ b/examples/Makefile.am
@@ -18,7 +18,7 @@ common_ldadd = \
 	$(COGL_DEP_LIBS) \
 	$(top_builddir)/cogl/libcogl.la
 
-programs = cogl-hello cogl-info cogl-msaa
+programs = cogl-hello cogl-info cogl-msaa cogl-virtual-framebuffer
 examples_datadir = $(pkgdatadir)/examples-data
 examples_data_DATA =
 
@@ -28,6 +28,8 @@ cogl_info_SOURCES = cogl-info.c
 cogl_info_LDADD = $(common_ldadd)
 cogl_msaa_SOURCES = cogl-msaa.c
 cogl_msaa_LDADD = $(common_ldadd)
+cogl_virtual_framebuffer_SOURCES = cogl-virtual-framebuffer.c
+cogl_virtual_framebuffer_LDADD = $(common_ldadd)
 
 if BUILD_COGL_PANGO
 programs += cogl-crate
diff --git a/examples/cogl-virtual-framebuffer.c b/examples/cogl-virtual-framebuffer.c
new file mode 100644
index 0000000..54eae3c
--- /dev/null
+++ b/examples/cogl-virtual-framebuffer.c
@@ -0,0 +1,96 @@
+#include <cogl/cogl.h>
+#include <glib.h>
+#include <stdio.h>
+
+CoglColor black;
+
+#define TEX_WIDTH 300
+#define TEX_HEIGHT 220
+
+int
+main (int argc, char **argv)
+{
+    CoglContext *ctx;
+    CoglOnscreen *onscreen;
+    CoglTexture2D *textures[4];
+    CoglHandle offscreens[4];
+    CoglVirtualFramebuffer *vfb;
+    CoglFramebuffer *fb;
+    GError *error = NULL;
+    CoglVertexP2C4 triangle_vertices[] = {
+        {0, 0.7, 0xff, 0x00, 0x00, 0x80},
+        {-0.7, -0.7, 0x00, 0xff, 0x00, 0xff},
+        {0.7, -0.7, 0x00, 0x00, 0xff, 0xff}
+    };
+    CoglPrimitive *triangle;
+    int i;
+
+    ctx = cogl_context_new (NULL, &error);
+    if (!ctx) {
+        fprintf (stderr, "Failed to create context: %s\n", error->message);
+        return 1;
+    }
+
+    for (i = 0; i < 4; i++)
+      {
+        textures[i] = cogl_texture_2d_new_with_size (ctx,
+                                                     300, 220,
+                                                     COGL_PIXEL_FORMAT_RGBA_8888,
+                                                     &error);
+        if (!textures[i])
+          {
+            fprintf (stderr, "Failed to allocated texture: %s\n", error->message);
+            return 1;
+          }
+        offscreens[i] =
+          cogl_offscreen_new_to_texture (COGL_TEXTURE (textures[i]));
+      }
+
+    vfb = cogl_virtual_framebuffer_new (ctx, 640, 480);
+    cogl_virtual_framebuffer_add_slice (vfb, offscreens[0],
+                                        0, 0, -1, -1,
+                                        10, 10);
+    cogl_virtual_framebuffer_add_slice (vfb, offscreens[1],
+                                        0, 0, -1, -1,
+                                        330, 10);
+    cogl_virtual_framebuffer_add_slice (vfb, offscreens[2],
+                                        0, 0, -1, -1,
+                                        10, 250);
+    cogl_virtual_framebuffer_add_slice (vfb, offscreens[3],
+                                        0, 0, -1, -1,
+                                        330, 250);
+
+    onscreen = cogl_onscreen_new (ctx, 640, 480);
+    /* Eventually there will be an implicit allocate on first use so this
+     * will become optional... */
+    fb = COGL_FRAMEBUFFER (onscreen);
+    if (!cogl_framebuffer_allocate (fb, &error)) {
+        fprintf (stderr, "Failed to allocate framebuffer: %s\n", error->message);
+        return 1;
+    }
+
+    cogl_onscreen_show (onscreen);
+
+    cogl_push_framebuffer (COGL_FRAMEBUFFER (vfb));
+
+    triangle = cogl_primitive_new_p2c4 (COGL_VERTICES_MODE_TRIANGLES,
+                                        3, triangle_vertices);
+    for (;;) {
+        cogl_clear (&black, COGL_BUFFER_BIT_COLOR);
+        cogl_primitive_draw (triangle);
+
+        /* Now draw the slices of the virtual framebuffer onscreen */
+        cogl_set_source_texture (COGL_TEXTURE (textures[0]));
+        cogl_rectangle (10, 10, 10 + TEX_WIDTH, 10 + TEX_HEIGHT);
+        cogl_set_source_texture (COGL_TEXTURE (textures[1]));
+        cogl_rectangle (330, 10, 330 + TEX_WIDTH, 10 + TEX_HEIGHT);
+        cogl_set_source_texture (COGL_TEXTURE (textures[2]));
+        cogl_rectangle (10, 250, 10 + TEX_WIDTH, 250 + TEX_HEIGHT);
+        cogl_set_source_texture (COGL_TEXTURE (textures[3]));
+        cogl_rectangle (330, 250, 330 + TEX_WIDTH, 250 + TEX_HEIGHT);
+
+        cogl_framebuffer_swap_buffers (fb);
+    }
+
+    return 0;
+}



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