summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--cogl/Makefile.am3
-rw-r--r--cogl/cogl-framebuffer-private.h8
-rw-r--r--cogl/cogl-framebuffer.c23
-rw-r--r--cogl/cogl-virtual-framebuffer.c289
-rw-r--r--cogl/cogl-virtual-framebuffer.h118
-rw-r--r--cogl/cogl.h1
-rw-r--r--examples/Makefile.am4
-rw-r--r--examples/cogl-virtual-framebuffer.c96
8 files changed, 538 insertions, 4 deletions
diff --git a/cogl/Makefile.am b/cogl/Makefile.am
index 46a1a8c8..35d02bf5 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 fce41e67..1085c66e 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
@@ -115,6 +116,11 @@ struct _CoglFramebuffer
CoglClipState clip_state;
+ /* The stencil buffer matches what's required for this
+ * clip stack. NULL means the stencil buffer contents
+ * are undefined. */
+ CoglClipStack *clip_stack_of_current_stencil;
+
gboolean dirty_bitmasks;
int red_bits;
int blue_bits;
diff --git a/cogl/cogl-framebuffer.c b/cogl/cogl-framebuffer.c
index 8e989921..28bfbda9 100644
--- a/cogl/cogl-framebuffer.c
+++ b/cogl/cogl-framebuffer.c
@@ -35,6 +35,8 @@
#include "cogl-util.h"
#include "cogl-texture-private.h"
#include "cogl-framebuffer-private.h"
+#include "cogl-virtual-framebuffer-private.h"
+#include "cogl-virtual-framebuffer.h"
#include "cogl-onscreen-template-private.h"
#include "cogl-clip-stack.h"
#include "cogl-journal-private.h"
@@ -137,7 +139,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
@@ -171,6 +174,7 @@ _cogl_framebuffer_init (CoglFramebuffer *framebuffer,
/* Initialise the clip stack */
_cogl_clip_state_init (&framebuffer->clip_state);
+ framebuffer->clip_stack_of_current_stencil = NULL;
framebuffer->journal = _cogl_journal_new ();
@@ -413,6 +417,15 @@ cogl_framebuffer_clear4f (CoglFramebuffer *framebuffer,
_cogl_framebuffer_clear_without_flush4f (framebuffer, buffers,
red, green, blue, alpha);
+ /* We are clobbering the stencil state so we can no longer assume it
+ * will match any clip_stack.
+ *
+ * Note: although NULL is a valid clip_stack value that's ok because
+ * in that case it doesn't matter what the stencil buffer contains.
+ */
+ if (buffers & COGL_BUFFER_BIT_STENCIL)
+ framebuffer->clip_stack_of_current_stencil = NULL;
+
/* This is a debugging variable used to visually display the quad
* batches from the journal. It is reset here to increase the
* chances of getting the same colours for each frame during an
@@ -532,6 +545,7 @@ cogl_framebuffer_set_viewport (CoglFramebuffer *framebuffer,
framebuffer->viewport_width = width;
framebuffer->viewport_height = height;
+#warning "XXX: I think we also need to dirty the clip state here too"
if (framebuffer->context->current_draw_buffer == framebuffer)
framebuffer->context->current_draw_buffer_changes |=
COGL_FRAMEBUFFER_STATE_VIEWPORT;
@@ -1327,6 +1341,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));
@@ -1513,6 +1529,8 @@ _cogl_framebuffer_flush_clip_state (CoglFramebuffer *framebuffer)
{
CoglClipStack *stack = _cogl_clip_state_get_stack (&framebuffer->clip_state);
_cogl_clip_stack_flush (stack, framebuffer);
+#warning "should we take a reference here?"
+ framebuffer->clip_stack_of_current_stencil = stack;
}
static void
@@ -1601,7 +1619,8 @@ _cogl_framebuffer_flush_state (CoglFramebuffer *draw_buffer,
unsigned long differences;
int bit;
- _COGL_RETURN_IF_FAIL (!cogl_is_virtual_framebuffer (framebuffer));
+ _COGL_RETURN_IF_FAIL (!cogl_is_virtual_framebuffer (draw_buffer));
+ _COGL_RETURN_IF_FAIL (!cogl_is_virtual_framebuffer (read_buffer));
/* We can assume that any state that has changed for the current
* framebuffer is different to the currently flushed value. */
diff --git a/cogl/cogl-virtual-framebuffer.c b/cogl/cogl-virtual-framebuffer.c
new file mode 100644
index 00000000..a4eb6bd4
--- /dev/null
+++ b/cogl/cogl-virtual-framebuffer.c
@@ -0,0 +1,289 @@
+/*
+ * 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-virtual-framebuffer.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_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)
+{
+ GList *l;
+
+ for (l = virtual_framebuffer->slices; l; l = l->next)
+ {
+ CoglFramebufferSlice *current_slice = l->data;
+ if (current_slice->framebuffer == slice)
+ {
+ _cogl_framebuffer_slice_free (current_slice);
+ virtual_framebuffer->slices =
+ g_list_remove_list (virtual_framebuffer->slices, l);
+ return;
+ }
+ }
+
+ g_warn_if_reached ();
+}
+
+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 00000000..69aa77e4
--- /dev/null
+++ b/cogl/cogl-virtual-framebuffer.h
@@ -0,0 +1,118 @@
+/*
+ * 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))
+
+#define cogl_is_virtual_framebuffer cogl_is_virtual_framebuffer_EXP
+/**
+ * cogl_is_virtual_framebuffer:
+ * @object: A pointer to a #CoglObject
+ *
+ * Gets whether the given object implements the virtual framebuffer
+ * interface.
+ *
+ * Return value: %TRUE if object implements the
+ * #CoglVirtualFramebuffer interface %FALSE otherwise.
+ *
+ * Since: 1.10
+ * Stability: Unstable
+ */
+gboolean
+cogl_is_virtual_framebuffer (void *object);
+
+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 772886b8..51644fb6 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 8403a460..69229224 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 00000000..54eae3c5
--- /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;
+}