[cogl/wip/virtual-framebuffer: 22/37] stash - add cogl-virtual-framebuffer
- From: Robert Bragg <rbragg src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [cogl/wip/virtual-framebuffer: 22/37] stash - add cogl-virtual-framebuffer
- Date: Wed, 23 Nov 2011 17:00:35 +0000 (UTC)
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]