[mutter] cogl/gl-framebuffer: Split up into FBO and back drivers
- From: Marge Bot <marge-bot src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [mutter] cogl/gl-framebuffer: Split up into FBO and back drivers
- Date: Sat, 30 Jan 2021 09:39:49 +0000 (UTC)
commit 60e1516b1c5ba4ae6632007384e2f9b6d2d13ce5
Author: Jonas Ã…dahl <jadahl gmail com>
Date: Mon Oct 19 21:19:15 2020 +0200
cogl/gl-framebuffer: Split up into FBO and back drivers
One is for when we're painting to the back buffer (onscreen), and the
other when we're painting to an FBO (offscreen).
Part-of: <https://gitlab.gnome.org/GNOME/mutter/-/merge_requests/1514>
cogl/cogl/cogl-driver.h | 4 -
cogl/cogl/cogl-framebuffer-driver.c | 7 +
cogl/cogl/cogl-framebuffer-driver.h | 9 +
cogl/cogl/cogl-framebuffer-private.h | 10 +-
cogl/cogl/cogl-framebuffer.c | 42 +-
cogl/cogl/cogl-offscreen.c | 1 +
cogl/cogl/driver/gl/cogl-framebuffer-gl-private.h | 27 +-
cogl/cogl/driver/gl/cogl-framebuffer-gl.c | 687 +--------------------
cogl/cogl/driver/gl/cogl-gl-framebuffer-back.c | 239 +++++++
cogl/cogl/driver/gl/cogl-gl-framebuffer-back.h | 41 ++
cogl/cogl/driver/gl/cogl-gl-framebuffer-fbo.c | 611 ++++++++++++++++++
cogl/cogl/driver/gl/cogl-gl-framebuffer-fbo.h | 41 ++
cogl/cogl/driver/gl/cogl-util-gl-private.h | 83 +++
cogl/cogl/driver/gl/cogl-util-gl.c | 58 +-
cogl/cogl/driver/gl/gl/cogl-driver-gl.c | 1 -
cogl/cogl/driver/gl/gles/cogl-driver-gles.c | 1 -
cogl/cogl/driver/nop/cogl-driver-nop.c | 1 -
.../cogl/driver/nop/cogl-framebuffer-nop-private.h | 4 -
cogl/cogl/driver/nop/cogl-framebuffer-nop.c | 7 -
cogl/cogl/driver/nop/cogl-nop-framebuffer.c | 13 +
cogl/cogl/meson.build | 4 +
cogl/cogl/winsys/cogl-onscreen-glx.c | 6 +
cogl/cogl/winsys/cogl-onscreen-xlib.c | 6 +
src/backends/native/meta-onscreen-native.c | 5 +
24 files changed, 1165 insertions(+), 743 deletions(-)
---
diff --git a/cogl/cogl/cogl-driver.h b/cogl/cogl/cogl-driver.h
index e2cf989279..5e698debd2 100644
--- a/cogl/cogl/cogl-driver.h
+++ b/cogl/cogl/cogl-driver.h
@@ -93,10 +93,6 @@ struct _CoglDriverVtable
float blue,
float alpha);
- void
- (* framebuffer_query_bits) (CoglFramebuffer *framebuffer,
- CoglFramebufferBits *bits);
-
void
(* framebuffer_finish) (CoglFramebuffer *framebuffer);
diff --git a/cogl/cogl/cogl-framebuffer-driver.c b/cogl/cogl/cogl-framebuffer-driver.c
index 1559de0f63..d1bbf82a0c 100644
--- a/cogl/cogl/cogl-framebuffer-driver.c
+++ b/cogl/cogl/cogl-framebuffer-driver.c
@@ -58,6 +58,13 @@ cogl_framebuffer_driver_get_framebuffer (CoglFramebufferDriver *driver)
return priv->framebuffer;
}
+void
+cogl_framebuffer_driver_query_bits (CoglFramebufferDriver *driver,
+ CoglFramebufferBits *bits)
+{
+ COGL_FRAMEBUFFER_DRIVER_GET_CLASS (driver)->query_bits (driver, bits);
+}
+
static void
cogl_framebuffer_driver_get_property (GObject *object,
guint prop_id,
diff --git a/cogl/cogl/cogl-framebuffer-driver.h b/cogl/cogl/cogl-framebuffer-driver.h
index 1ef6ce058c..8f06e9e055 100644
--- a/cogl/cogl/cogl-framebuffer-driver.h
+++ b/cogl/cogl/cogl-framebuffer-driver.h
@@ -30,6 +30,8 @@
#include "cogl-framebuffer.h"
+typedef struct _CoglFramebufferBits CoglFramebufferBits;
+
#define COGL_TYPE_FRAMEBUFFER_DRIVER (cogl_framebuffer_driver_get_type ())
G_DECLARE_DERIVABLE_TYPE (CoglFramebufferDriver,
cogl_framebuffer_driver,
@@ -39,9 +41,16 @@ G_DECLARE_DERIVABLE_TYPE (CoglFramebufferDriver,
struct _CoglFramebufferDriverClass
{
GObjectClass parent_cleass;
+
+ void (* query_bits) (CoglFramebufferDriver *driver,
+ CoglFramebufferBits *bits);
};
CoglFramebuffer *
cogl_framebuffer_driver_get_framebuffer (CoglFramebufferDriver *driver);
+void
+cogl_framebuffer_driver_query_bits (CoglFramebufferDriver *driver,
+ CoglFramebufferBits *bits);
+
#endif /* COGL_FRAMEBUFFER_DRIVER_H */
diff --git a/cogl/cogl/cogl-framebuffer-private.h b/cogl/cogl/cogl-framebuffer-private.h
index f00a5bc4b8..0c9af2d92b 100644
--- a/cogl/cogl/cogl-framebuffer-private.h
+++ b/cogl/cogl/cogl-framebuffer-private.h
@@ -40,8 +40,16 @@
#include "cogl-attribute-private.h"
#include "cogl-clip-stack.h"
+typedef enum
+{
+ COGL_FRAMEBUFFER_DRIVER_TYPE_FBO,
+ COGL_FRAMEBUFFER_DRIVER_TYPE_BACK,
+} CoglFramebufferDriverType;
+
struct _CoglFramebufferDriverConfig
{
+ CoglFramebufferDriverType type;
+
gboolean disable_depth_and_stencil;
};
@@ -98,7 +106,7 @@ typedef enum
COGL_READ_PIXELS_NO_FLIP = 1L << 30
} CoglPrivateReadPixelsFlags;
-typedef struct
+typedef struct _CoglFramebufferBits
{
int red;
int blue;
diff --git a/cogl/cogl/cogl-framebuffer.c b/cogl/cogl/cogl-framebuffer.c
index b83c3c19af..4bd4673da6 100644
--- a/cogl/cogl/cogl-framebuffer.c
+++ b/cogl/cogl/cogl-framebuffer.c
@@ -1126,15 +1126,24 @@ cogl_context_flush_framebuffer_state (CoglContext *ctx,
state);
}
-int
-cogl_framebuffer_get_red_bits (CoglFramebuffer *framebuffer)
+static void
+cogl_framebuffer_query_bits (CoglFramebuffer *framebuffer,
+ CoglFramebufferBits *bits)
{
CoglFramebufferPrivate *priv =
cogl_framebuffer_get_instance_private (framebuffer);
- CoglContext *ctx = priv->context;
+
+ g_return_if_fail (priv->driver);
+
+ cogl_framebuffer_driver_query_bits (priv->driver, bits);
+}
+
+int
+cogl_framebuffer_get_red_bits (CoglFramebuffer *framebuffer)
+{
CoglFramebufferBits bits;
- ctx->driver_vtable->framebuffer_query_bits (framebuffer, &bits);
+ cogl_framebuffer_query_bits (framebuffer, &bits);
return bits.red;
}
@@ -1142,12 +1151,9 @@ cogl_framebuffer_get_red_bits (CoglFramebuffer *framebuffer)
int
cogl_framebuffer_get_green_bits (CoglFramebuffer *framebuffer)
{
- CoglFramebufferPrivate *priv =
- cogl_framebuffer_get_instance_private (framebuffer);
- CoglContext *ctx = priv->context;
CoglFramebufferBits bits;
- ctx->driver_vtable->framebuffer_query_bits (framebuffer, &bits);
+ cogl_framebuffer_query_bits (framebuffer, &bits);
return bits.green;
}
@@ -1155,12 +1161,9 @@ cogl_framebuffer_get_green_bits (CoglFramebuffer *framebuffer)
int
cogl_framebuffer_get_blue_bits (CoglFramebuffer *framebuffer)
{
- CoglFramebufferPrivate *priv =
- cogl_framebuffer_get_instance_private (framebuffer);
- CoglContext *ctx = priv->context;
CoglFramebufferBits bits;
- ctx->driver_vtable->framebuffer_query_bits (framebuffer, &bits);
+ cogl_framebuffer_query_bits (framebuffer, &bits);
return bits.blue;
}
@@ -1168,12 +1171,9 @@ cogl_framebuffer_get_blue_bits (CoglFramebuffer *framebuffer)
int
cogl_framebuffer_get_alpha_bits (CoglFramebuffer *framebuffer)
{
- CoglFramebufferPrivate *priv =
- cogl_framebuffer_get_instance_private (framebuffer);
- CoglContext *ctx = priv->context;
CoglFramebufferBits bits;
- ctx->driver_vtable->framebuffer_query_bits (framebuffer, &bits);
+ cogl_framebuffer_query_bits (framebuffer, &bits);
return bits.alpha;
}
@@ -1181,12 +1181,9 @@ cogl_framebuffer_get_alpha_bits (CoglFramebuffer *framebuffer)
int
cogl_framebuffer_get_depth_bits (CoglFramebuffer *framebuffer)
{
- CoglFramebufferPrivate *priv =
- cogl_framebuffer_get_instance_private (framebuffer);
- CoglContext *ctx = priv->context;
CoglFramebufferBits bits;
- ctx->driver_vtable->framebuffer_query_bits (framebuffer, &bits);
+ cogl_framebuffer_query_bits (framebuffer, &bits);
return bits.depth;
}
@@ -1194,12 +1191,9 @@ cogl_framebuffer_get_depth_bits (CoglFramebuffer *framebuffer)
int
_cogl_framebuffer_get_stencil_bits (CoglFramebuffer *framebuffer)
{
- CoglFramebufferPrivate *priv =
- cogl_framebuffer_get_instance_private (framebuffer);
- CoglContext *ctx = priv->context;
CoglFramebufferBits bits;
- ctx->driver_vtable->framebuffer_query_bits (framebuffer, &bits);
+ cogl_framebuffer_query_bits (framebuffer, &bits);
return bits.stencil;
}
diff --git a/cogl/cogl/cogl-offscreen.c b/cogl/cogl/cogl-offscreen.c
index ae05f73433..a9b25cc796 100644
--- a/cogl/cogl/cogl-offscreen.c
+++ b/cogl/cogl/cogl-offscreen.c
@@ -56,6 +56,7 @@ _cogl_offscreen_new_with_texture_full (CoglTexture *texture,
g_return_val_if_fail (cogl_is_texture (texture), NULL);
driver_config = (CoglFramebufferDriverConfig) {
+ .type = COGL_FRAMEBUFFER_DRIVER_TYPE_FBO,
.disable_depth_and_stencil =
!!(flags & COGL_OFFSCREEN_DISABLE_DEPTH_AND_STENCIL),
};
diff --git a/cogl/cogl/driver/gl/cogl-framebuffer-gl-private.h
b/cogl/cogl/driver/gl/cogl-framebuffer-gl-private.h
index 2f96f6f8f7..3f0ddb5398 100644
--- a/cogl/cogl/driver/gl/cogl-framebuffer-gl-private.h
+++ b/cogl/cogl/driver/gl/cogl-framebuffer-gl-private.h
@@ -34,20 +34,22 @@
#ifndef __COGL_FRAMEBUFFER_GL_PRIVATE_H__
#define __COGL_FRAMEBUFFER_GL_PRIVATE_H__
+#include "cogl-attribute-private.h"
#include "cogl-framebuffer-driver.h"
+#include "cogl-gl-header.h"
#define COGL_TYPE_GL_FRAMEBUFFER (cogl_gl_framebuffer_get_type ())
-G_DECLARE_FINAL_TYPE (CoglGlFramebuffer, cogl_gl_framebuffer,
- COGL, GL_FRAMEBUFFER,
- CoglFramebufferDriver)
+G_DECLARE_DERIVABLE_TYPE (CoglGlFramebuffer, cogl_gl_framebuffer,
+ COGL, GL_FRAMEBUFFER,
+ CoglFramebufferDriver)
-gboolean
-_cogl_offscreen_gl_allocate (CoglOffscreen *offscreen,
- CoglOffscreenFlags flags,
- GError **error);
+struct _CoglGlFramebufferClass
+{
+ CoglFramebufferDriverClass parent_class;
-void
-_cogl_offscreen_gl_free (CoglOffscreen *offscreen);
+ void (* bind) (CoglGlFramebuffer *gl_framebuffer,
+ GLenum target);
+};
void
_cogl_framebuffer_gl_clear (CoglFramebuffer *framebuffer,
@@ -57,10 +59,6 @@ _cogl_framebuffer_gl_clear (CoglFramebuffer *framebuffer,
float blue,
float alpha);
-void
-_cogl_framebuffer_gl_query_bits (CoglFramebuffer *framebuffer,
- CoglFramebufferBits *bits);
-
void
_cogl_framebuffer_gl_finish (CoglFramebuffer *framebuffer);
@@ -72,7 +70,8 @@ _cogl_framebuffer_gl_discard_buffers (CoglFramebuffer *framebuffer,
unsigned long buffers);
void
-_cogl_framebuffer_gl_bind (CoglFramebuffer *framebuffer, GLenum target);
+cogl_gl_framebuffer_bind (CoglGlFramebuffer *gl_framebuffer,
+ GLenum target);
void
_cogl_framebuffer_gl_draw_attributes (CoglFramebuffer *framebuffer,
diff --git a/cogl/cogl/driver/gl/cogl-framebuffer-gl.c b/cogl/cogl/driver/gl/cogl-framebuffer-gl.c
index 95e4a39b6c..4700e449b6 100644
--- a/cogl/cogl/driver/gl/cogl-framebuffer-gl.c
+++ b/cogl/cogl/driver/gl/cogl-framebuffer-gl.c
@@ -40,116 +40,12 @@
#include "driver/gl/cogl-framebuffer-gl-private.h"
#include "driver/gl/cogl-bitmap-gl-private.h"
#include "driver/gl/cogl-buffer-gl-private.h"
-#include "driver/gl/cogl-texture-gl-private.h"
#include <glib.h>
#include <string.h>
-#ifndef GL_FRAMEBUFFER
-#define GL_FRAMEBUFFER 0x8D40
-#endif
-#ifndef GL_RENDERBUFFER
-#define GL_RENDERBUFFER 0x8D41
-#endif
-#ifndef GL_STENCIL_ATTACHMENT
-#define GL_STENCIL_ATTACHMENT 0x8D00
-#endif
-#ifndef GL_COLOR_ATTACHMENT0
-#define GL_COLOR_ATTACHMENT0 0x8CE0
-#endif
-#ifndef GL_FRAMEBUFFER_COMPLETE
-#define GL_FRAMEBUFFER_COMPLETE 0x8CD5
-#endif
-#ifndef GL_STENCIL_INDEX8
-#define GL_STENCIL_INDEX8 0x8D48
-#endif
-#ifndef GL_DEPTH_STENCIL
-#define GL_DEPTH_STENCIL 0x84F9
-#endif
-#ifndef GL_DEPTH24_STENCIL8
-#define GL_DEPTH24_STENCIL8 0x88F0
-#endif
-#ifndef GL_DEPTH_ATTACHMENT
-#define GL_DEPTH_ATTACHMENT 0x8D00
-#endif
-#ifndef GL_DEPTH_STENCIL_ATTACHMENT
-#define GL_DEPTH_STENCIL_ATTACHMENT 0x821A
-#endif
-#ifndef GL_DEPTH_COMPONENT16
-#define GL_DEPTH_COMPONENT16 0x81A5
-#endif
-#ifndef GL_FRAMEBUFFER_ATTACHMENT_RED_SIZE
-#define GL_FRAMEBUFFER_ATTACHMENT_RED_SIZE 0x8212
-#endif
-#ifndef GL_FRAMEBUFFER_ATTACHMENT_GREEN_SIZE
-#define GL_FRAMEBUFFER_ATTACHMENT_GREEN_SIZE 0x8213
-#endif
-#ifndef GL_FRAMEBUFFER_ATTACHMENT_BLUE_SIZE
-#define GL_FRAMEBUFFER_ATTACHMENT_BLUE_SIZE 0x8214
-#endif
-#ifndef GL_FRAMEBUFFER_ATTACHMENT_ALPHA_SIZE
-#define GL_FRAMEBUFFER_ATTACHMENT_ALPHA_SIZE 0x8215
-#endif
-#ifndef GL_FRAMEBUFFER_ATTACHMENT_DEPTH_SIZE
-#define GL_FRAMEBUFFER_ATTACHMENT_DEPTH_SIZE 0x8216
-#endif
-#ifndef GL_FRAMEBUFFER_ATTACHMENT_STENCIL_SIZE
-#define GL_FRAMEBUFFER_ATTACHMENT_STENCIL_SIZE 0x8217
-#endif
-#ifndef GL_READ_FRAMEBUFFER
-#define GL_READ_FRAMEBUFFER 0x8CA8
-#endif
-#ifndef GL_DRAW_FRAMEBUFFER
-#define GL_DRAW_FRAMEBUFFER 0x8CA9
-#endif
-#ifndef GL_TEXTURE_SAMPLES_IMG
-#define GL_TEXTURE_SAMPLES_IMG 0x9136
-#endif
-#ifndef GL_PACK_INVERT_MESA
-#define GL_PACK_INVERT_MESA 0x8758
-#endif
-#ifndef GL_PACK_REVERSE_ROW_ORDER_ANGLE
-#define GL_PACK_REVERSE_ROW_ORDER_ANGLE 0x93A4
-#endif
-#ifndef GL_BACK_LEFT
-#define GL_BACK_LEFT 0x0402
-#endif
-#ifndef GL_BACK_RIGHT
-#define GL_BACK_RIGHT 0x0403
-#endif
-
-#ifndef GL_COLOR
-#define GL_COLOR 0x1800
-#endif
-#ifndef GL_DEPTH
-#define GL_DEPTH 0x1801
-#endif
-#ifndef GL_STENCIL
-#define GL_STENCIL 0x1802
-#endif
-
-typedef struct _CoglGlFbo
-{
- GLuint fbo_handle;
- GList *renderbuffers;
- int samples_per_pixel;
-} CoglGlFbo;
-
-typedef struct _CoglGlFramebufferPrivate
-{
- CoglGlFbo gl_fbo;
-
- gboolean dirty_bitmasks;
- CoglFramebufferBits bits;
-} CoglGlFramebufferPrivate;
-
-struct _CoglGlFramebuffer
-{
- CoglFramebufferDriver parent;
-};
-
-G_DEFINE_TYPE_WITH_PRIVATE (CoglGlFramebuffer, cogl_gl_framebuffer,
- COGL_TYPE_FRAMEBUFFER_DRIVER)
+G_DEFINE_ABSTRACT_TYPE (CoglGlFramebuffer, cogl_gl_framebuffer,
+ COGL_TYPE_FRAMEBUFFER_DRIVER)
static void
_cogl_framebuffer_gl_flush_viewport_state (CoglFramebuffer *framebuffer)
@@ -352,464 +248,12 @@ cogl_gl_framebuffer_flush_state_differences (CoglGlFramebuffer *gl_framebuffer,
COGL_FLAGS_FOREACH_END;
}
-static CoglGlFramebuffer *
-cogl_gl_framebuffer_from_framebuffer (CoglFramebuffer *framebuffer)
-{
- CoglFramebufferDriver *driver = cogl_framebuffer_get_driver (framebuffer);
-
- g_assert (driver);
-
- return COGL_GL_FRAMEBUFFER (driver);
-}
-
void
-_cogl_framebuffer_gl_bind (CoglFramebuffer *framebuffer, GLenum target)
-{
- CoglContext *ctx = cogl_framebuffer_get_context (framebuffer);
-
- if (COGL_IS_OFFSCREEN (framebuffer))
- {
- CoglGlFramebuffer *gl_framebuffer =
- cogl_gl_framebuffer_from_framebuffer (framebuffer);
- CoglGlFramebufferPrivate *priv =
- cogl_gl_framebuffer_get_instance_private (gl_framebuffer);
-
- GE (ctx, glBindFramebuffer (target, priv->gl_fbo.fbo_handle));
- }
- else
- {
- const CoglWinsysVtable *winsys =
- _cogl_framebuffer_get_winsys (framebuffer);
- winsys->onscreen_bind (COGL_ONSCREEN (framebuffer));
- GE (ctx, glBindFramebuffer (target, 0));
-
- /* Initialise the glDrawBuffer state the first time the context
- * is bound to the default framebuffer. If the winsys is using a
- * surfaceless context for the initial make current then the
- * default draw buffer will be GL_NONE so we need to correct
- * that. We can't do it any earlier because binding GL_BACK when
- * there is no default framebuffer won't work */
- if (!ctx->was_bound_to_onscreen)
- {
- if (ctx->glDrawBuffer)
- {
- GE (ctx, glDrawBuffer (GL_BACK));
- }
- else if (ctx->glDrawBuffers)
- {
- /* glDrawBuffer isn't available on GLES 3.0 so we need
- * to be able to use glDrawBuffers as well. On GLES 2
- * neither is available but the state should always be
- * GL_BACK anyway so we don't need to set anything. On
- * desktop GL this must be GL_BACK_LEFT instead of
- * GL_BACK but as this code path will only be hit for
- * GLES we can just use GL_BACK. */
- static const GLenum buffers[] = { GL_BACK };
-
- GE (ctx, glDrawBuffers (G_N_ELEMENTS (buffers), buffers));
- }
-
- ctx->was_bound_to_onscreen = TRUE;
- }
- }
-}
-
-static GList *
-try_creating_renderbuffers (CoglContext *ctx,
- int width,
- int height,
- CoglOffscreenAllocateFlags flags,
- int n_samples)
-{
- GList *renderbuffers = NULL;
- GLuint gl_depth_stencil_handle;
-
- if (flags & COGL_OFFSCREEN_ALLOCATE_FLAG_DEPTH_STENCIL)
- {
- GLenum format;
-
- /* WebGL adds a GL_DEPTH_STENCIL_ATTACHMENT and requires that we
- * use the GL_DEPTH_STENCIL format. */
- /* Although GL_OES_packed_depth_stencil is mostly equivalent to
- * GL_EXT_packed_depth_stencil, one notable difference is that
- * GL_OES_packed_depth_stencil doesn't allow GL_DEPTH_STENCIL to
- * be passed as an internal format to glRenderbufferStorage.
- */
- if (_cogl_has_private_feature
- (ctx, COGL_PRIVATE_FEATURE_EXT_PACKED_DEPTH_STENCIL))
- format = GL_DEPTH_STENCIL;
- else
- {
- g_return_val_if_fail (
- _cogl_has_private_feature (ctx,
- COGL_PRIVATE_FEATURE_OES_PACKED_DEPTH_STENCIL),
- NULL);
- format = GL_DEPTH24_STENCIL8;
- }
-
- /* Create a renderbuffer for depth and stenciling */
- GE (ctx, glGenRenderbuffers (1, &gl_depth_stencil_handle));
- GE (ctx, glBindRenderbuffer (GL_RENDERBUFFER, gl_depth_stencil_handle));
- if (n_samples)
- GE (ctx, glRenderbufferStorageMultisampleIMG (GL_RENDERBUFFER,
- n_samples,
- format,
- width, height));
- else
- GE (ctx, glRenderbufferStorage (GL_RENDERBUFFER, format,
- width, height));
- GE (ctx, glBindRenderbuffer (GL_RENDERBUFFER, 0));
-
-
- GE (ctx, glFramebufferRenderbuffer (GL_FRAMEBUFFER,
- GL_STENCIL_ATTACHMENT,
- GL_RENDERBUFFER,
- gl_depth_stencil_handle));
- GE (ctx, glFramebufferRenderbuffer (GL_FRAMEBUFFER,
- GL_DEPTH_ATTACHMENT,
- GL_RENDERBUFFER,
- gl_depth_stencil_handle));
- renderbuffers =
- g_list_prepend (renderbuffers,
- GUINT_TO_POINTER (gl_depth_stencil_handle));
- }
-
- if (flags & COGL_OFFSCREEN_ALLOCATE_FLAG_DEPTH)
- {
- GLuint gl_depth_handle;
-
- GE (ctx, glGenRenderbuffers (1, &gl_depth_handle));
- GE (ctx, glBindRenderbuffer (GL_RENDERBUFFER, gl_depth_handle));
- /* For now we just ask for GL_DEPTH_COMPONENT16 since this is all that's
- * available under GLES */
- if (n_samples)
- GE (ctx, glRenderbufferStorageMultisampleIMG (GL_RENDERBUFFER,
- n_samples,
- GL_DEPTH_COMPONENT16,
- width, height));
- else
- GE (ctx, glRenderbufferStorage (GL_RENDERBUFFER, GL_DEPTH_COMPONENT16,
- width, height));
- GE (ctx, glBindRenderbuffer (GL_RENDERBUFFER, 0));
- GE (ctx, glFramebufferRenderbuffer (GL_FRAMEBUFFER,
- GL_DEPTH_ATTACHMENT,
- GL_RENDERBUFFER, gl_depth_handle));
- renderbuffers =
- g_list_prepend (renderbuffers, GUINT_TO_POINTER (gl_depth_handle));
- }
-
- if (flags & COGL_OFFSCREEN_ALLOCATE_FLAG_STENCIL)
- {
- GLuint gl_stencil_handle;
-
- GE (ctx, glGenRenderbuffers (1, &gl_stencil_handle));
- GE (ctx, glBindRenderbuffer (GL_RENDERBUFFER, gl_stencil_handle));
- if (n_samples)
- GE (ctx, glRenderbufferStorageMultisampleIMG (GL_RENDERBUFFER,
- n_samples,
- GL_STENCIL_INDEX8,
- width, height));
- else
- GE (ctx, glRenderbufferStorage (GL_RENDERBUFFER, GL_STENCIL_INDEX8,
- width, height));
- GE (ctx, glBindRenderbuffer (GL_RENDERBUFFER, 0));
- GE (ctx, glFramebufferRenderbuffer (GL_FRAMEBUFFER,
- GL_STENCIL_ATTACHMENT,
- GL_RENDERBUFFER, gl_stencil_handle));
- renderbuffers =
- g_list_prepend (renderbuffers, GUINT_TO_POINTER (gl_stencil_handle));
- }
-
- return renderbuffers;
-}
-
-static void
-delete_renderbuffers (CoglContext *ctx, GList *renderbuffers)
-{
- GList *l;
-
- for (l = renderbuffers; l; l = l->next)
- {
- GLuint renderbuffer = GPOINTER_TO_UINT (l->data);
- GE (ctx, glDeleteRenderbuffers (1, &renderbuffer));
- }
-
- g_list_free (renderbuffers);
-}
-
-/*
- * NB: This function may be called with a standalone GLES2 context
- * bound so we can create a shadow framebuffer that wraps the same
- * CoglTexture as the given CoglOffscreen. This function shouldn't
- * modify anything in
- */
-static gboolean
-try_creating_fbo (CoglContext *ctx,
- CoglTexture *texture,
- int texture_level,
- int texture_level_width,
- int texture_level_height,
- const CoglFramebufferConfig *config,
- CoglOffscreenAllocateFlags flags,
- CoglGlFbo *gl_fbo)
-{
- GLuint tex_gl_handle;
- GLenum tex_gl_target;
- GLenum status;
- int n_samples;
-
- if (!cogl_texture_get_gl_texture (texture, &tex_gl_handle, &tex_gl_target))
- return FALSE;
-
- if (tex_gl_target != GL_TEXTURE_2D
-#ifdef HAVE_COGL_GL
- && tex_gl_target != GL_TEXTURE_RECTANGLE_ARB
-#endif
- )
- return FALSE;
-
- if (config->samples_per_pixel)
- {
- if (!ctx->glFramebufferTexture2DMultisampleIMG)
- return FALSE;
- n_samples = config->samples_per_pixel;
- }
- else
- n_samples = 0;
-
- /* We are about to generate and bind a new fbo, so we pretend to
- * change framebuffer state so that the old framebuffer will be
- * rebound again before drawing. */
- ctx->current_draw_buffer_changes |= COGL_FRAMEBUFFER_STATE_BIND;
-
- /* Generate framebuffer */
- ctx->glGenFramebuffers (1, &gl_fbo->fbo_handle);
- GE (ctx, glBindFramebuffer (GL_FRAMEBUFFER, gl_fbo->fbo_handle));
-
- if (n_samples)
- {
- GE (ctx, glFramebufferTexture2DMultisampleIMG (GL_FRAMEBUFFER,
- GL_COLOR_ATTACHMENT0,
- tex_gl_target, tex_gl_handle,
- n_samples,
- texture_level));
- }
- else
- GE (ctx, glFramebufferTexture2D (GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0,
- tex_gl_target, tex_gl_handle,
- texture_level));
-
- if (flags)
- {
- gl_fbo->renderbuffers =
- try_creating_renderbuffers (ctx,
- texture_level_width,
- texture_level_height,
- flags,
- n_samples);
- }
-
- /* Make sure it's complete */
- status = ctx->glCheckFramebufferStatus (GL_FRAMEBUFFER);
-
- if (status != GL_FRAMEBUFFER_COMPLETE)
- {
- GE (ctx, glDeleteFramebuffers (1, &gl_fbo->fbo_handle));
-
- delete_renderbuffers (ctx, gl_fbo->renderbuffers);
- gl_fbo->renderbuffers = NULL;
-
- return FALSE;
- }
-
- /* Update the real number of samples_per_pixel now that we have a
- * complete framebuffer */
- if (n_samples)
- {
- GLenum attachment = GL_COLOR_ATTACHMENT0;
- GLenum pname = GL_TEXTURE_SAMPLES_IMG;
- int texture_samples;
-
- GE( ctx, glGetFramebufferAttachmentParameteriv (GL_FRAMEBUFFER,
- attachment,
- pname,
- &texture_samples) );
- gl_fbo->samples_per_pixel = texture_samples;
- }
-
- return TRUE;
-}
-
-CoglFramebufferDriver *
-_cogl_driver_gl_create_framebuffer_driver (CoglContext *context,
- CoglFramebuffer *framebuffer,
- const CoglFramebufferDriverConfig *driver_config,
- GError **error)
+cogl_gl_framebuffer_bind (CoglGlFramebuffer *gl_framebuffer,
+ GLenum target)
{
- CoglOffscreenAllocateFlags allocate_flags;
- CoglOffscreen *offscreen;
- CoglGlFramebuffer *gl_framebuffer;
- CoglGlFramebufferPrivate *priv;
- CoglGlFbo *gl_fbo;
- const CoglFramebufferConfig *config;
- CoglTexture *texture;
- int texture_level;
- int level_width;
- int level_height;
-
- if (COGL_IS_ONSCREEN (framebuffer))
- {
- return g_object_new (COGL_TYPE_GL_FRAMEBUFFER,
- "framebuffer", framebuffer,
- NULL);
- }
-
- offscreen = COGL_OFFSCREEN (framebuffer);
- texture = cogl_offscreen_get_texture (offscreen);
- texture_level = cogl_offscreen_get_texture_level (offscreen);
-
- g_return_val_if_fail (texture_level < _cogl_texture_get_n_levels (texture),
- FALSE);
-
- _cogl_texture_get_level_size (texture,
- texture_level,
- &level_width,
- &level_height,
- NULL);
-
- /* XXX: The framebuffer_object spec isn't clear in defining whether attaching
- * a texture as a renderbuffer with mipmap filtering enabled while the
- * mipmaps have not been uploaded should result in an incomplete framebuffer
- * object. (different drivers make different decisions)
- *
- * To avoid an error with drivers that do consider this a problem we
- * explicitly set non mipmapped filters here. These will later be reset when
- * the texture is actually used for rendering according to the filters set on
- * the corresponding CoglPipeline.
- */
- _cogl_texture_gl_flush_legacy_texobj_filters (texture,
- GL_NEAREST, GL_NEAREST);
-
- config = cogl_framebuffer_get_config (framebuffer);
-
- gl_framebuffer = g_object_new (COGL_TYPE_GL_FRAMEBUFFER,
- "framebuffer", framebuffer,
- NULL);
- priv = cogl_gl_framebuffer_get_instance_private (gl_framebuffer);
- gl_fbo = &priv->gl_fbo;
-
- if ((driver_config->disable_depth_and_stencil &&
- try_creating_fbo (context,
- texture,
- texture_level,
- level_width,
- level_height,
- config,
- allocate_flags = 0,
- gl_fbo)) ||
-
- (context->have_last_offscreen_allocate_flags &&
- try_creating_fbo (context,
- texture,
- texture_level,
- level_width,
- level_height,
- config,
- allocate_flags = context->last_offscreen_allocate_flags,
- gl_fbo)) ||
-
- (
- /* NB: WebGL introduces a DEPTH_STENCIL_ATTACHMENT and doesn't
- * need an extension to handle _FLAG_DEPTH_STENCIL */
- (_cogl_has_private_feature
- (context, COGL_PRIVATE_FEATURE_EXT_PACKED_DEPTH_STENCIL) ||
- _cogl_has_private_feature
- (context, COGL_PRIVATE_FEATURE_OES_PACKED_DEPTH_STENCIL)) &&
- try_creating_fbo (context,
- texture,
- texture_level,
- level_width,
- level_height,
- config,
- allocate_flags = COGL_OFFSCREEN_ALLOCATE_FLAG_DEPTH_STENCIL,
- gl_fbo)) ||
-
- try_creating_fbo (context,
- texture,
- texture_level,
- level_width,
- level_height,
- config,
- allocate_flags = COGL_OFFSCREEN_ALLOCATE_FLAG_DEPTH |
- COGL_OFFSCREEN_ALLOCATE_FLAG_STENCIL,
- gl_fbo) ||
-
- try_creating_fbo (context,
- texture,
- texture_level,
- level_width,
- level_height,
- config,
- allocate_flags = COGL_OFFSCREEN_ALLOCATE_FLAG_STENCIL,
- gl_fbo) ||
-
- try_creating_fbo (context,
- texture,
- texture_level,
- level_width,
- level_height,
- config,
- allocate_flags = COGL_OFFSCREEN_ALLOCATE_FLAG_DEPTH,
- gl_fbo) ||
-
- try_creating_fbo (context,
- texture,
- texture_level,
- level_width,
- level_height,
- config,
- allocate_flags = 0,
- gl_fbo))
- {
- cogl_framebuffer_update_samples_per_pixel (framebuffer,
- gl_fbo->samples_per_pixel);
-
- if (!driver_config->disable_depth_and_stencil)
- {
- /* Record that the last set of flags succeeded so that we can
- try that set first next time */
- context->last_offscreen_allocate_flags = allocate_flags;
- context->have_last_offscreen_allocate_flags = TRUE;
- }
-
- return COGL_FRAMEBUFFER_DRIVER (gl_framebuffer);
- }
- else
- {
- g_object_unref (gl_framebuffer);
- g_set_error (error, COGL_FRAMEBUFFER_ERROR,
- COGL_FRAMEBUFFER_ERROR_ALLOCATE,
- "Failed to create an OpenGL framebuffer object");
- return NULL;
- }
-}
-
-static void
-cogl_gl_framebuffer_dispose (GObject *object)
-{
- CoglGlFramebuffer *gl_framebuffer = COGL_GL_FRAMEBUFFER (object);
- CoglGlFramebufferPrivate *priv =
- cogl_gl_framebuffer_get_instance_private (gl_framebuffer);
- CoglFramebufferDriver *driver = COGL_FRAMEBUFFER_DRIVER (object);
- CoglFramebuffer *framebuffer =
- cogl_framebuffer_driver_get_framebuffer (driver);
- CoglContext *ctx = cogl_framebuffer_get_context (framebuffer);
-
- G_OBJECT_CLASS (cogl_gl_framebuffer_parent_class)->dispose (object);
-
- delete_renderbuffers (ctx, priv->gl_fbo.renderbuffers);
-
- GE (ctx, glDeleteFramebuffers (1, &priv->gl_fbo.fbo_handle));
+ COGL_GL_FRAMEBUFFER_GET_CLASS (gl_framebuffer)->bind (gl_framebuffer,
+ target);
}
void
@@ -857,118 +301,6 @@ _cogl_framebuffer_gl_clear (CoglFramebuffer *framebuffer,
GE (ctx, glClear (gl_buffers));
}
-static inline void
-_cogl_framebuffer_init_bits (CoglFramebuffer *framebuffer)
-{
- CoglGlFramebuffer *gl_framebuffer =
- cogl_gl_framebuffer_from_framebuffer (framebuffer);
- CoglGlFramebufferPrivate *priv =
- cogl_gl_framebuffer_get_instance_private (gl_framebuffer);
- CoglContext *ctx = cogl_framebuffer_get_context (framebuffer);
-
- if (!priv->dirty_bitmasks)
- return;
-
- cogl_framebuffer_allocate (framebuffer, NULL);
-
- cogl_context_flush_framebuffer_state (ctx,
- framebuffer,
- framebuffer,
- COGL_FRAMEBUFFER_STATE_BIND);
-
-#ifdef HAVE_COGL_GL
- if ((ctx->driver == COGL_DRIVER_GL3 &&
- COGL_IS_ONSCREEN (framebuffer)) ||
- (_cogl_has_private_feature (ctx, COGL_PRIVATE_FEATURE_QUERY_FRAMEBUFFER_BITS) &&
- COGL_IS_OFFSCREEN (framebuffer)))
- {
- gboolean is_offscreen = COGL_IS_OFFSCREEN (framebuffer);
- const struct {
- GLenum attachment, pname;
- size_t offset;
- } params[] = {
- { is_offscreen ? GL_COLOR_ATTACHMENT0 : GL_BACK_LEFT,
- GL_FRAMEBUFFER_ATTACHMENT_RED_SIZE,
- offsetof (CoglFramebufferBits, red) },
- { is_offscreen ? GL_COLOR_ATTACHMENT0 : GL_BACK_LEFT,
- GL_FRAMEBUFFER_ATTACHMENT_GREEN_SIZE,
- offsetof (CoglFramebufferBits, green) },
- { is_offscreen ? GL_COLOR_ATTACHMENT0 : GL_BACK_LEFT,
- GL_FRAMEBUFFER_ATTACHMENT_BLUE_SIZE,
- offsetof (CoglFramebufferBits, blue) },
- { is_offscreen ? GL_COLOR_ATTACHMENT0 : GL_BACK_LEFT,
- GL_FRAMEBUFFER_ATTACHMENT_ALPHA_SIZE,
- offsetof (CoglFramebufferBits, alpha) },
- { is_offscreen ? GL_DEPTH_ATTACHMENT : GL_DEPTH,
- GL_FRAMEBUFFER_ATTACHMENT_DEPTH_SIZE,
- offsetof (CoglFramebufferBits, depth) },
- { is_offscreen ? GL_STENCIL_ATTACHMENT : GL_STENCIL,
- GL_FRAMEBUFFER_ATTACHMENT_STENCIL_SIZE,
- offsetof (CoglFramebufferBits, stencil) },
- };
- int i;
-
- for (i = 0; i < G_N_ELEMENTS (params); i++)
- {
- int *value =
- (int *) ((uint8_t *) &priv->bits + params[i].offset);
- GE( ctx, glGetFramebufferAttachmentParameteriv (GL_FRAMEBUFFER,
- params[i].attachment,
- params[i].pname,
- value) );
- }
- }
- else
-#endif /* HAVE_COGL_GL */
- {
- GE (ctx, glGetIntegerv (GL_RED_BITS, &priv->bits.red));
- GE (ctx, glGetIntegerv (GL_GREEN_BITS, &priv->bits.green));
- GE (ctx, glGetIntegerv (GL_BLUE_BITS, &priv->bits.blue));
- GE (ctx, glGetIntegerv (GL_ALPHA_BITS, &priv->bits.alpha));
- GE (ctx, glGetIntegerv (GL_DEPTH_BITS, &priv->bits.depth));
- GE (ctx, glGetIntegerv (GL_STENCIL_BITS, &priv->bits.stencil));
- }
-
- /* If we don't have alpha textures then the alpha bits are actually
- * stored in the red component */
- if (!_cogl_has_private_feature (ctx, COGL_PRIVATE_FEATURE_ALPHA_TEXTURES) &&
- COGL_IS_OFFSCREEN (framebuffer) &&
- cogl_framebuffer_get_internal_format (framebuffer) == COGL_PIXEL_FORMAT_A_8)
- {
- priv->bits.alpha = priv->bits.red;
- priv->bits.red = 0;
- }
-
- COGL_NOTE (OFFSCREEN,
- "RGBA/D/S Bits for framebuffer[%p, %s]: %d, %d, %d, %d, %d, %d",
- framebuffer,
- COGL_IS_OFFSCREEN (framebuffer) ? "offscreen" : "onscreen",
- priv->bits.red,
- priv->bits.blue,
- priv->bits.green,
- priv->bits.alpha,
- priv->bits.depth,
- priv->bits.stencil);
-
- priv->dirty_bitmasks = FALSE;
-}
-
-void
-_cogl_framebuffer_gl_query_bits (CoglFramebuffer *framebuffer,
- CoglFramebufferBits *bits)
-{
- CoglGlFramebuffer *gl_framebuffer =
- cogl_gl_framebuffer_from_framebuffer (framebuffer);
- CoglGlFramebufferPrivate *priv =
- cogl_gl_framebuffer_get_instance_private (gl_framebuffer);
-
- _cogl_framebuffer_init_bits (framebuffer);
-
- /* TODO: cache these in some driver specific location not
- * directly as part of CoglFramebuffer. */
- *bits = priv->bits;
-}
-
void
_cogl_framebuffer_gl_finish (CoglFramebuffer *framebuffer)
{
@@ -1365,16 +697,9 @@ EXIT:
static void
cogl_gl_framebuffer_init (CoglGlFramebuffer *gl_framebuffer)
{
- CoglGlFramebufferPrivate *priv =
- cogl_gl_framebuffer_get_instance_private (gl_framebuffer);
-
- priv->dirty_bitmasks = TRUE;
}
static void
cogl_gl_framebuffer_class_init (CoglGlFramebufferClass *klass)
{
- GObjectClass *object_class = G_OBJECT_CLASS (klass);
-
- object_class->dispose = cogl_gl_framebuffer_dispose;
}
diff --git a/cogl/cogl/driver/gl/cogl-gl-framebuffer-back.c b/cogl/cogl/driver/gl/cogl-gl-framebuffer-back.c
new file mode 100644
index 0000000000..8a49d6f80f
--- /dev/null
+++ b/cogl/cogl/driver/gl/cogl-gl-framebuffer-back.c
@@ -0,0 +1,239 @@
+/*
+ * Copyright (C) 2007,2008,2009,2012 Intel Corporation.
+ * Copyright (C) 2018 DisplayLink (UK) Ltd.
+ * Copyright (C) 2020 Red Hat
+ *
+ * Permission is hereby granted, free of charge, to any person
+ * obtaining a copy of this software and associated documentation
+ * files (the "Software"), to deal in the Software without
+ * restriction, including without limitation the rights to use, copy,
+ * modify, merge, publish, distribute, sublicense, and/or sell copies
+ * of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be
+ * included in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
+ * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
+ * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ *
+ */
+
+#include "cogl-config.h"
+
+#include "driver/gl/cogl-gl-framebuffer-back.h"
+
+#include <gio/gio.h>
+
+#include "cogl-context-private.h"
+#include "cogl-framebuffer-private.h"
+#include "cogl-offscreen-private.h"
+#include "driver/gl/cogl-util-gl-private.h"
+
+struct _CoglGlFramebufferBack
+{
+ CoglGlFramebuffer parent;
+
+ gboolean dirty_bitmasks;
+ CoglFramebufferBits bits;
+};
+
+G_DEFINE_TYPE (CoglGlFramebufferBack, cogl_gl_framebuffer_back,
+ COGL_TYPE_GL_FRAMEBUFFER)
+
+static gboolean
+ensure_bits_initialized (CoglGlFramebufferBack *gl_framebuffer_back)
+{
+ CoglFramebufferDriver *driver = COGL_FRAMEBUFFER_DRIVER (gl_framebuffer_back);
+ CoglFramebuffer *framebuffer =
+ cogl_framebuffer_driver_get_framebuffer (driver);
+ CoglContext *ctx = cogl_framebuffer_get_context (framebuffer);
+ CoglFramebufferBits *bits = &gl_framebuffer_back->bits;
+ g_autoptr (GError) error = NULL;
+
+ if (!gl_framebuffer_back->dirty_bitmasks)
+ return TRUE;
+
+ cogl_context_flush_framebuffer_state (ctx,
+ framebuffer,
+ framebuffer,
+ COGL_FRAMEBUFFER_STATE_BIND);
+
+#ifdef HAVE_COGL_GL
+ if (ctx->driver == COGL_DRIVER_GL3)
+ {
+ const struct {
+ GLenum attachment, pname;
+ size_t offset;
+ } params[] = {
+ {
+ .attachment = GL_BACK_LEFT,
+ .pname = GL_FRAMEBUFFER_ATTACHMENT_RED_SIZE,
+ .offset = offsetof (CoglFramebufferBits, red),
+ },
+ {
+ .attachment = GL_BACK_LEFT,
+ .pname = GL_FRAMEBUFFER_ATTACHMENT_GREEN_SIZE,
+ .offset = offsetof (CoglFramebufferBits, green),
+ },
+ {
+ .attachment = GL_BACK_LEFT,
+ .pname = GL_FRAMEBUFFER_ATTACHMENT_BLUE_SIZE,
+ .offset = offsetof (CoglFramebufferBits, blue),
+ },
+ {
+ .attachment = GL_BACK_LEFT,
+ .pname = GL_FRAMEBUFFER_ATTACHMENT_ALPHA_SIZE,
+ .offset = offsetof (CoglFramebufferBits, alpha),
+ },
+ {
+ .attachment = GL_DEPTH,
+ .pname = GL_FRAMEBUFFER_ATTACHMENT_DEPTH_SIZE,
+ .offset = offsetof (CoglFramebufferBits, depth),
+ },
+ {
+ .attachment = GL_STENCIL,
+ .pname = GL_FRAMEBUFFER_ATTACHMENT_STENCIL_SIZE,
+ .offset = offsetof (CoglFramebufferBits, stencil),
+ },
+ };
+ int i;
+
+ for (i = 0; i < G_N_ELEMENTS (params); i++)
+ {
+ int *value =
+ (int *) ((uint8_t *) bits + params[i].offset);
+
+ GE (ctx, glGetFramebufferAttachmentParameteriv (GL_FRAMEBUFFER,
+ params[i].attachment,
+ params[i].pname,
+ value));
+ }
+ }
+ else
+#endif /* HAVE_COGL_GL */
+ {
+ GE (ctx, glGetIntegerv (GL_RED_BITS, &bits->red));
+ GE (ctx, glGetIntegerv (GL_GREEN_BITS, &bits->green));
+ GE (ctx, glGetIntegerv (GL_BLUE_BITS, &bits->blue));
+ GE (ctx, glGetIntegerv (GL_ALPHA_BITS, &bits->alpha));
+ GE (ctx, glGetIntegerv (GL_DEPTH_BITS, &bits->depth));
+ GE (ctx, glGetIntegerv (GL_STENCIL_BITS, &bits->stencil));
+ }
+
+ COGL_NOTE (FRAMEBUFFER,
+ "RGBA/D/S Bits for framebuffer[%p, %s]: %d, %d, %d, %d, %d, %d",
+ framebuffer,
+ COGL_IS_OFFSCREEN (framebuffer) ? "offscreen" : "onscreen",
+ bits->red,
+ bits->blue,
+ bits->green,
+ bits->alpha,
+ bits->depth,
+ bits->stencil);
+
+ gl_framebuffer_back->dirty_bitmasks = FALSE;
+
+ return TRUE;
+}
+
+static void
+cogl_gl_framebuffer_back_query_bits (CoglFramebufferDriver *driver,
+ CoglFramebufferBits *bits)
+{
+ CoglGlFramebufferBack *gl_framebuffer_back = COGL_GL_FRAMEBUFFER_BACK (driver);
+
+ if (!ensure_bits_initialized (gl_framebuffer_back))
+ return;
+
+ *bits = gl_framebuffer_back->bits;
+}
+
+static void
+cogl_gl_framebuffer_back_bind (CoglGlFramebuffer *gl_framebuffer,
+ GLenum target)
+{
+ CoglGlFramebufferBack *gl_framebuffer_back =
+ COGL_GL_FRAMEBUFFER_BACK (gl_framebuffer);
+ CoglFramebufferDriver *driver = COGL_FRAMEBUFFER_DRIVER (gl_framebuffer_back);
+ CoglFramebuffer *framebuffer =
+ cogl_framebuffer_driver_get_framebuffer (driver);
+ CoglContext *ctx = cogl_framebuffer_get_context (framebuffer);
+ const CoglWinsysVtable *winsys =
+ _cogl_framebuffer_get_winsys (framebuffer);
+
+ winsys->onscreen_bind (COGL_ONSCREEN (framebuffer));
+
+ GE (ctx, glBindFramebuffer (target, 0));
+
+ /* Initialise the glDrawBuffer state the first time the context
+ * is bound to the default framebuffer. If the winsys is using a
+ * surfaceless context for the initial make current then the
+ * default draw buffer will be GL_NONE so we need to correct
+ * that. We can't do it any earlier because binding GL_BACK when
+ * there is no default framebuffer won't work */
+ if (!ctx->was_bound_to_onscreen)
+ {
+ if (ctx->glDrawBuffer)
+ {
+ GE (ctx, glDrawBuffer (GL_BACK));
+ }
+ else if (ctx->glDrawBuffers)
+ {
+ /* glDrawBuffer isn't available on GLES 3.0 so we need
+ * to be able to use glDrawBuffers as well. On GLES 2
+ * neither is available but the state should always be
+ * GL_BACK anyway so we don't need to set anything. On
+ * desktop GL this must be GL_BACK_LEFT instead of
+ * GL_BACK but as this code path will only be hit for
+ * GLES we can just use GL_BACK. */
+ static const GLenum buffers[] = { GL_BACK };
+
+ GE (ctx, glDrawBuffers (G_N_ELEMENTS (buffers), buffers));
+ }
+
+ ctx->was_bound_to_onscreen = TRUE;
+ }
+}
+
+CoglGlFramebufferBack *
+cogl_gl_framebuffer_back_new (CoglFramebuffer *framebuffer,
+ const CoglFramebufferDriverConfig *driver_config,
+ GError **error)
+{
+ if (!COGL_IS_ONSCREEN (framebuffer))
+ {
+ g_set_error (error, G_IO_ERROR, G_IO_ERROR_FAILED,
+ "Incompatible framebuffer");
+ return NULL;
+ }
+
+ return g_object_new (COGL_TYPE_GL_FRAMEBUFFER_BACK,
+ "framebuffer", framebuffer,
+ NULL);
+}
+
+static void
+cogl_gl_framebuffer_back_init (CoglGlFramebufferBack *gl_framebuffer_back)
+{
+ gl_framebuffer_back->dirty_bitmasks = TRUE;
+}
+
+static void
+cogl_gl_framebuffer_back_class_init (CoglGlFramebufferBackClass *klass)
+{
+ CoglFramebufferDriverClass *driver_class =
+ COGL_FRAMEBUFFER_DRIVER_CLASS (klass);
+ CoglGlFramebufferClass *gl_framebuffer_class =
+ COGL_GL_FRAMEBUFFER_CLASS (klass);
+
+ driver_class->query_bits = cogl_gl_framebuffer_back_query_bits;
+
+ gl_framebuffer_class->bind = cogl_gl_framebuffer_back_bind;
+}
diff --git a/cogl/cogl/driver/gl/cogl-gl-framebuffer-back.h b/cogl/cogl/driver/gl/cogl-gl-framebuffer-back.h
new file mode 100644
index 0000000000..417f8a7388
--- /dev/null
+++ b/cogl/cogl/driver/gl/cogl-gl-framebuffer-back.h
@@ -0,0 +1,41 @@
+/*
+ * Copyright (C) 2020 Red Hat
+ *
+ * Permission is hereby granted, free of charge, to any person
+ * obtaining a copy of this software and associated documentation
+ * files (the "Software"), to deal in the Software without
+ * restriction, including without limitation the rights to use, copy,
+ * modify, merge, publish, distribute, sublicense, and/or sell copies
+ * of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be
+ * included in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
+ * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
+ * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ *
+ */
+
+#ifndef COGL_GL_FRAMEBUFFER_BACK_H
+#define COGL_GL_FRAMEBUFFER_BACK_H
+
+#include "cogl-framebuffer-gl-private.h"
+
+#define COGL_TYPE_GL_FRAMEBUFFER_BACK (cogl_gl_framebuffer_back_get_type ())
+G_DECLARE_FINAL_TYPE (CoglGlFramebufferBack, cogl_gl_framebuffer_back,
+ COGL, GL_FRAMEBUFFER_BACK,
+ CoglGlFramebuffer)
+
+CoglGlFramebufferBack *
+cogl_gl_framebuffer_back_new (CoglFramebuffer *framebuffer,
+ const CoglFramebufferDriverConfig *driver_config,
+ GError **error);
+
+#endif /* COGL_GL_FRAMEBUFFER_BACK_H */
diff --git a/cogl/cogl/driver/gl/cogl-gl-framebuffer-fbo.c b/cogl/cogl/driver/gl/cogl-gl-framebuffer-fbo.c
new file mode 100644
index 0000000000..368e04b6fb
--- /dev/null
+++ b/cogl/cogl/driver/gl/cogl-gl-framebuffer-fbo.c
@@ -0,0 +1,611 @@
+/*
+ * Copyright (C) 2007,2008,2009,2012 Intel Corporation.
+ * Copyright (C) 2018 DisplayLink (UK) Ltd.
+ * Copyright (C) 2020 Red Hat
+ *
+ * Permission is hereby granted, free of charge, to any person
+ * obtaining a copy of this software and associated documentation
+ * files (the "Software"), to deal in the Software without
+ * restriction, including without limitation the rights to use, copy,
+ * modify, merge, publish, distribute, sublicense, and/or sell copies
+ * of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be
+ * included in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
+ * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
+ * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ *
+ */
+
+#include "cogl-config.h"
+
+#include "driver/gl/cogl-gl-framebuffer-fbo.h"
+
+#include <gio/gio.h>
+
+#include "cogl-context-private.h"
+#include "cogl-framebuffer-private.h"
+#include "cogl-offscreen-private.h"
+#include "driver/gl/cogl-texture-gl-private.h"
+#include "driver/gl/cogl-util-gl-private.h"
+
+typedef struct _CoglGlFbo
+{
+ GLuint fbo_handle;
+ GList *renderbuffers;
+ int samples_per_pixel;
+} CoglGlFbo;
+
+struct _CoglGlFramebufferFbo
+{
+ CoglGlFramebuffer parent;
+
+ CoglGlFbo gl_fbo;
+
+ gboolean dirty_bitmasks;
+ CoglFramebufferBits bits;
+};
+
+G_DEFINE_TYPE (CoglGlFramebufferFbo, cogl_gl_framebuffer_fbo,
+ COGL_TYPE_GL_FRAMEBUFFER)
+
+static gboolean
+ensure_bits_initialized (CoglGlFramebufferFbo *gl_framebuffer_fbo)
+{
+ CoglFramebufferDriver *driver = COGL_FRAMEBUFFER_DRIVER (gl_framebuffer_fbo);
+ CoglFramebuffer *framebuffer =
+ cogl_framebuffer_driver_get_framebuffer (driver);
+ CoglContext *ctx = cogl_framebuffer_get_context (framebuffer);
+ CoglFramebufferBits *bits = &gl_framebuffer_fbo->bits;
+ g_autoptr (GError) error = NULL;
+
+ if (!gl_framebuffer_fbo->dirty_bitmasks)
+ return TRUE;
+
+ cogl_context_flush_framebuffer_state (ctx,
+ framebuffer,
+ framebuffer,
+ COGL_FRAMEBUFFER_STATE_BIND);
+
+#ifdef HAVE_COGL_GL
+ if (!_cogl_has_private_feature (ctx, COGL_PRIVATE_FEATURE_QUERY_FRAMEBUFFER_BITS))
+ {
+ const struct {
+ GLenum attachment, pname;
+ size_t offset;
+ } params[] = {
+ {
+ .attachment = GL_COLOR_ATTACHMENT0,
+ .pname = GL_FRAMEBUFFER_ATTACHMENT_RED_SIZE,
+ .offset = offsetof (CoglFramebufferBits, red),
+ },
+ {
+ .attachment = GL_COLOR_ATTACHMENT0,
+ .pname = GL_FRAMEBUFFER_ATTACHMENT_GREEN_SIZE,
+ .offset = offsetof (CoglFramebufferBits, green),
+ },
+ {
+ .attachment = GL_COLOR_ATTACHMENT0,
+ .pname = GL_FRAMEBUFFER_ATTACHMENT_BLUE_SIZE,
+ .offset = offsetof (CoglFramebufferBits, blue),
+ },
+ {
+ .attachment = GL_COLOR_ATTACHMENT0,
+ .pname = GL_FRAMEBUFFER_ATTACHMENT_ALPHA_SIZE,
+ .offset = offsetof (CoglFramebufferBits, alpha),
+ },
+ {
+ .attachment = GL_DEPTH_ATTACHMENT,
+ .pname = GL_FRAMEBUFFER_ATTACHMENT_DEPTH_SIZE,
+ .offset = offsetof (CoglFramebufferBits, depth),
+ },
+ {
+ .attachment = GL_STENCIL_ATTACHMENT,
+ .pname = GL_FRAMEBUFFER_ATTACHMENT_STENCIL_SIZE,
+ .offset = offsetof (CoglFramebufferBits, stencil),
+ },
+ };
+ int i;
+
+ for (i = 0; i < G_N_ELEMENTS (params); i++)
+ {
+ int *value =
+ (int *) ((uint8_t *) bits + params[i].offset);
+
+ GE (ctx, glGetFramebufferAttachmentParameteriv (GL_FRAMEBUFFER,
+ params[i].attachment,
+ params[i].pname,
+ value));
+ }
+ }
+ else
+#endif /* HAVE_COGL_GL */
+ {
+ GE (ctx, glGetIntegerv (GL_RED_BITS, &bits->red));
+ GE (ctx, glGetIntegerv (GL_GREEN_BITS, &bits->green));
+ GE (ctx, glGetIntegerv (GL_BLUE_BITS, &bits->blue));
+ GE (ctx, glGetIntegerv (GL_ALPHA_BITS, &bits->alpha));
+ GE (ctx, glGetIntegerv (GL_DEPTH_BITS, &bits->depth));
+ GE (ctx, glGetIntegerv (GL_STENCIL_BITS, &bits->stencil));
+ }
+
+ if (!_cogl_has_private_feature (ctx, COGL_PRIVATE_FEATURE_ALPHA_TEXTURES) &&
+ (cogl_framebuffer_get_internal_format (framebuffer) ==
+ COGL_PIXEL_FORMAT_A_8))
+ {
+ bits->alpha = bits->red;
+ bits->red = 0;
+ }
+
+ COGL_NOTE (FRAMEBUFFER,
+ "RGBA/D/S Bits for framebuffer[%p, %s]: %d, %d, %d, %d, %d, %d",
+ framebuffer,
+ COGL_IS_OFFSCREEN (framebuffer) ? "offscreen" : "onscreen",
+ bits->red,
+ bits->blue,
+ bits->green,
+ bits->alpha,
+ bits->depth,
+ bits->stencil);
+
+ gl_framebuffer_fbo->dirty_bitmasks = FALSE;
+
+ return TRUE;
+}
+
+static void
+cogl_gl_framebuffer_fbo_query_bits (CoglFramebufferDriver *driver,
+ CoglFramebufferBits *bits)
+{
+ CoglGlFramebufferFbo *gl_framebuffer_fbo = COGL_GL_FRAMEBUFFER_FBO (driver);
+
+ if (!ensure_bits_initialized (gl_framebuffer_fbo))
+ return;
+
+ *bits = gl_framebuffer_fbo->bits;
+}
+
+static void
+cogl_gl_framebuffer_fbo_bind (CoglGlFramebuffer *gl_framebuffer,
+ GLenum target)
+{
+ CoglGlFramebufferFbo *gl_framebuffer_fbo =
+ COGL_GL_FRAMEBUFFER_FBO (gl_framebuffer);
+ CoglFramebufferDriver *driver = COGL_FRAMEBUFFER_DRIVER (gl_framebuffer_fbo);
+ CoglFramebuffer *framebuffer =
+ cogl_framebuffer_driver_get_framebuffer (driver);
+ CoglContext *ctx = cogl_framebuffer_get_context (framebuffer);
+
+ GE (ctx, glBindFramebuffer (target, gl_framebuffer_fbo->gl_fbo.fbo_handle));
+}
+
+static GList *
+try_creating_renderbuffers (CoglContext *ctx,
+ int width,
+ int height,
+ CoglOffscreenAllocateFlags flags,
+ int n_samples)
+{
+ GList *renderbuffers = NULL;
+ GLuint gl_depth_stencil_handle;
+
+ if (flags & COGL_OFFSCREEN_ALLOCATE_FLAG_DEPTH_STENCIL)
+ {
+ GLenum format;
+
+ /* WebGL adds a GL_DEPTH_STENCIL_ATTACHMENT and requires that we
+ * use the GL_DEPTH_STENCIL format. */
+ /* Although GL_OES_packed_depth_stencil is mostly equivalent to
+ * GL_EXT_packed_depth_stencil, one notable difference is that
+ * GL_OES_packed_depth_stencil doesn't allow GL_DEPTH_STENCIL to
+ * be passed as an internal format to glRenderbufferStorage.
+ */
+ if (_cogl_has_private_feature
+ (ctx, COGL_PRIVATE_FEATURE_EXT_PACKED_DEPTH_STENCIL))
+ format = GL_DEPTH_STENCIL;
+ else
+ {
+ g_return_val_if_fail (
+ _cogl_has_private_feature (ctx,
+ COGL_PRIVATE_FEATURE_OES_PACKED_DEPTH_STENCIL),
+ NULL);
+ format = GL_DEPTH24_STENCIL8;
+ }
+
+ /* Create a renderbuffer for depth and stenciling */
+ GE (ctx, glGenRenderbuffers (1, &gl_depth_stencil_handle));
+ GE (ctx, glBindRenderbuffer (GL_RENDERBUFFER, gl_depth_stencil_handle));
+ if (n_samples)
+ GE (ctx, glRenderbufferStorageMultisampleIMG (GL_RENDERBUFFER,
+ n_samples,
+ format,
+ width, height));
+ else
+ GE (ctx, glRenderbufferStorage (GL_RENDERBUFFER, format,
+ width, height));
+ GE (ctx, glBindRenderbuffer (GL_RENDERBUFFER, 0));
+
+
+ GE (ctx, glFramebufferRenderbuffer (GL_FRAMEBUFFER,
+ GL_STENCIL_ATTACHMENT,
+ GL_RENDERBUFFER,
+ gl_depth_stencil_handle));
+ GE (ctx, glFramebufferRenderbuffer (GL_FRAMEBUFFER,
+ GL_DEPTH_ATTACHMENT,
+ GL_RENDERBUFFER,
+ gl_depth_stencil_handle));
+ renderbuffers =
+ g_list_prepend (renderbuffers,
+ GUINT_TO_POINTER (gl_depth_stencil_handle));
+ }
+
+ if (flags & COGL_OFFSCREEN_ALLOCATE_FLAG_DEPTH)
+ {
+ GLuint gl_depth_handle;
+
+ GE (ctx, glGenRenderbuffers (1, &gl_depth_handle));
+ GE (ctx, glBindRenderbuffer (GL_RENDERBUFFER, gl_depth_handle));
+ /* For now we just ask for GL_DEPTH_COMPONENT16 since this is all that's
+ * available under GLES */
+ if (n_samples)
+ GE (ctx, glRenderbufferStorageMultisampleIMG (GL_RENDERBUFFER,
+ n_samples,
+ GL_DEPTH_COMPONENT16,
+ width, height));
+ else
+ GE (ctx, glRenderbufferStorage (GL_RENDERBUFFER, GL_DEPTH_COMPONENT16,
+ width, height));
+ GE (ctx, glBindRenderbuffer (GL_RENDERBUFFER, 0));
+ GE (ctx, glFramebufferRenderbuffer (GL_FRAMEBUFFER,
+ GL_DEPTH_ATTACHMENT,
+ GL_RENDERBUFFER, gl_depth_handle));
+ renderbuffers =
+ g_list_prepend (renderbuffers, GUINT_TO_POINTER (gl_depth_handle));
+ }
+
+ if (flags & COGL_OFFSCREEN_ALLOCATE_FLAG_STENCIL)
+ {
+ GLuint gl_stencil_handle;
+
+ GE (ctx, glGenRenderbuffers (1, &gl_stencil_handle));
+ GE (ctx, glBindRenderbuffer (GL_RENDERBUFFER, gl_stencil_handle));
+ if (n_samples)
+ GE (ctx, glRenderbufferStorageMultisampleIMG (GL_RENDERBUFFER,
+ n_samples,
+ GL_STENCIL_INDEX8,
+ width, height));
+ else
+ GE (ctx, glRenderbufferStorage (GL_RENDERBUFFER, GL_STENCIL_INDEX8,
+ width, height));
+ GE (ctx, glBindRenderbuffer (GL_RENDERBUFFER, 0));
+ GE (ctx, glFramebufferRenderbuffer (GL_FRAMEBUFFER,
+ GL_STENCIL_ATTACHMENT,
+ GL_RENDERBUFFER, gl_stencil_handle));
+ renderbuffers =
+ g_list_prepend (renderbuffers, GUINT_TO_POINTER (gl_stencil_handle));
+ }
+
+ return renderbuffers;
+}
+
+static void
+delete_renderbuffers (CoglContext *ctx,
+ GList *renderbuffers)
+{
+ GList *l;
+
+ for (l = renderbuffers; l; l = l->next)
+ {
+ GLuint renderbuffer = GPOINTER_TO_UINT (l->data);
+ GE (ctx, glDeleteRenderbuffers (1, &renderbuffer));
+ }
+
+ g_list_free (renderbuffers);
+}
+
+/*
+ * NB: This function may be called with a standalone GLES2 context
+ * bound so we can create a shadow framebuffer that wraps the same
+ * CoglTexture as the given CoglOffscreen. This function shouldn't
+ * modify anything in
+ */
+static gboolean
+try_creating_fbo (CoglContext *ctx,
+ CoglTexture *texture,
+ int texture_level,
+ int texture_level_width,
+ int texture_level_height,
+ const CoglFramebufferConfig *config,
+ CoglOffscreenAllocateFlags flags,
+ CoglGlFbo *gl_fbo)
+{
+ GLuint tex_gl_handle;
+ GLenum tex_gl_target;
+ GLenum status;
+ int n_samples;
+
+ if (!cogl_texture_get_gl_texture (texture, &tex_gl_handle, &tex_gl_target))
+ return FALSE;
+
+ if (tex_gl_target != GL_TEXTURE_2D
+#ifdef HAVE_COGL_GL
+ && tex_gl_target != GL_TEXTURE_RECTANGLE_ARB
+#endif
+ )
+ return FALSE;
+
+ if (config->samples_per_pixel)
+ {
+ if (!ctx->glFramebufferTexture2DMultisampleIMG)
+ return FALSE;
+ n_samples = config->samples_per_pixel;
+ }
+ else
+ n_samples = 0;
+
+ /* We are about to generate and bind a new fbo, so we pretend to
+ * change framebuffer state so that the old framebuffer will be
+ * rebound again before drawing. */
+ ctx->current_draw_buffer_changes |= COGL_FRAMEBUFFER_STATE_BIND;
+
+ /* Generate framebuffer */
+ ctx->glGenFramebuffers (1, &gl_fbo->fbo_handle);
+ GE (ctx, glBindFramebuffer (GL_FRAMEBUFFER, gl_fbo->fbo_handle));
+
+ if (n_samples)
+ {
+ GE (ctx, glFramebufferTexture2DMultisampleIMG (GL_FRAMEBUFFER,
+ GL_COLOR_ATTACHMENT0,
+ tex_gl_target, tex_gl_handle,
+ n_samples,
+ texture_level));
+ }
+ else
+ GE (ctx, glFramebufferTexture2D (GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0,
+ tex_gl_target, tex_gl_handle,
+ texture_level));
+
+ if (flags)
+ {
+ gl_fbo->renderbuffers =
+ try_creating_renderbuffers (ctx,
+ texture_level_width,
+ texture_level_height,
+ flags,
+ n_samples);
+ }
+
+ /* Make sure it's complete */
+ status = ctx->glCheckFramebufferStatus (GL_FRAMEBUFFER);
+
+ if (status != GL_FRAMEBUFFER_COMPLETE)
+ {
+ GE (ctx, glDeleteFramebuffers (1, &gl_fbo->fbo_handle));
+
+ delete_renderbuffers (ctx, gl_fbo->renderbuffers);
+ gl_fbo->renderbuffers = NULL;
+
+ return FALSE;
+ }
+
+ /* Update the real number of samples_per_pixel now that we have a
+ * complete framebuffer */
+ if (n_samples)
+ {
+ GLenum attachment = GL_COLOR_ATTACHMENT0;
+ GLenum pname = GL_TEXTURE_SAMPLES_IMG;
+ int texture_samples;
+
+ GE( ctx, glGetFramebufferAttachmentParameteriv (GL_FRAMEBUFFER,
+ attachment,
+ pname,
+ &texture_samples) );
+ gl_fbo->samples_per_pixel = texture_samples;
+ }
+
+ return TRUE;
+}
+
+CoglGlFramebufferFbo *
+cogl_gl_framebuffer_fbo_new (CoglFramebuffer *framebuffer,
+ const CoglFramebufferDriverConfig *driver_config,
+ GError **error)
+{
+ CoglContext *context = cogl_framebuffer_get_context (framebuffer);
+ CoglOffscreen *offscreen;
+ CoglTexture *texture;
+ int texture_level;
+ int level_width;
+ int level_height;
+ const CoglFramebufferConfig *config;
+ CoglGlFbo *gl_fbo;
+ CoglGlFramebufferFbo *gl_framebuffer_fbo;
+ CoglOffscreenAllocateFlags allocate_flags;
+
+ if (!COGL_IS_OFFSCREEN (framebuffer))
+ {
+ g_set_error (error, G_IO_ERROR, G_IO_ERROR_FAILED,
+ "Incompatible framebuffer");
+ return NULL;
+ }
+
+ offscreen = COGL_OFFSCREEN (framebuffer);
+ texture = cogl_offscreen_get_texture (offscreen);
+ texture_level = cogl_offscreen_get_texture_level (offscreen);
+
+ g_return_val_if_fail (texture_level < _cogl_texture_get_n_levels (texture),
+ NULL);
+
+ _cogl_texture_get_level_size (texture,
+ texture_level,
+ &level_width,
+ &level_height,
+ NULL);
+
+ /* XXX: The framebuffer_object spec isn't clear in defining whether attaching
+ * a texture as a renderbuffer with mipmap filtering enabled while the
+ * mipmaps have not been uploaded should result in an incomplete framebuffer
+ * object. (different drivers make different decisions)
+ *
+ * To avoid an error with drivers that do consider this a problem we
+ * explicitly set non mipmapped filters here. These will later be reset when
+ * the texture is actually used for rendering according to the filters set on
+ * the corresponding CoglPipeline.
+ */
+ _cogl_texture_gl_flush_legacy_texobj_filters (texture,
+ GL_NEAREST, GL_NEAREST);
+
+ config = cogl_framebuffer_get_config (framebuffer);
+
+ gl_framebuffer_fbo = g_object_new (COGL_TYPE_GL_FRAMEBUFFER_FBO,
+ "framebuffer", framebuffer,
+ NULL);
+ gl_fbo = &gl_framebuffer_fbo->gl_fbo;
+
+ if ((driver_config->disable_depth_and_stencil &&
+ try_creating_fbo (context,
+ texture,
+ texture_level,
+ level_width,
+ level_height,
+ config,
+ allocate_flags = 0,
+ gl_fbo)) ||
+
+ (context->have_last_offscreen_allocate_flags &&
+ try_creating_fbo (context,
+ texture,
+ texture_level,
+ level_width,
+ level_height,
+ config,
+ allocate_flags = context->last_offscreen_allocate_flags,
+ gl_fbo)) ||
+
+ (
+ /* NB: WebGL introduces a DEPTH_STENCIL_ATTACHMENT and doesn't
+ * need an extension to handle _FLAG_DEPTH_STENCIL */
+ (_cogl_has_private_feature
+ (context, COGL_PRIVATE_FEATURE_EXT_PACKED_DEPTH_STENCIL) ||
+ _cogl_has_private_feature
+ (context, COGL_PRIVATE_FEATURE_OES_PACKED_DEPTH_STENCIL)) &&
+ try_creating_fbo (context,
+ texture,
+ texture_level,
+ level_width,
+ level_height,
+ config,
+ allocate_flags = COGL_OFFSCREEN_ALLOCATE_FLAG_DEPTH_STENCIL,
+ gl_fbo)) ||
+
+ try_creating_fbo (context,
+ texture,
+ texture_level,
+ level_width,
+ level_height,
+ config,
+ allocate_flags = COGL_OFFSCREEN_ALLOCATE_FLAG_DEPTH |
+ COGL_OFFSCREEN_ALLOCATE_FLAG_STENCIL,
+ gl_fbo) ||
+
+ try_creating_fbo (context,
+ texture,
+ texture_level,
+ level_width,
+ level_height,
+ config,
+ allocate_flags = COGL_OFFSCREEN_ALLOCATE_FLAG_STENCIL,
+ gl_fbo) ||
+
+ try_creating_fbo (context,
+ texture,
+ texture_level,
+ level_width,
+ level_height,
+ config,
+ allocate_flags = COGL_OFFSCREEN_ALLOCATE_FLAG_DEPTH,
+ gl_fbo) ||
+
+ try_creating_fbo (context,
+ texture,
+ texture_level,
+ level_width,
+ level_height,
+ config,
+ allocate_flags = 0,
+ gl_fbo))
+ {
+ cogl_framebuffer_update_samples_per_pixel (framebuffer,
+ gl_fbo->samples_per_pixel);
+
+ if (!driver_config->disable_depth_and_stencil)
+ {
+ /* Record that the last set of flags succeeded so that we can
+ try that set first next time */
+ context->last_offscreen_allocate_flags = allocate_flags;
+ context->have_last_offscreen_allocate_flags = TRUE;
+ }
+
+ return gl_framebuffer_fbo;
+ }
+ else
+ {
+ g_object_unref (gl_framebuffer_fbo);
+ g_set_error (error, COGL_FRAMEBUFFER_ERROR,
+ COGL_FRAMEBUFFER_ERROR_ALLOCATE,
+ "Failed to create an OpenGL framebuffer object");
+ return NULL;
+ }
+}
+
+static void
+cogl_gl_framebuffer_fbo_dispose (GObject *object)
+{
+ CoglGlFramebufferFbo *gl_framebuffer_fbo = COGL_GL_FRAMEBUFFER_FBO (object);
+ CoglFramebufferDriver *driver = COGL_FRAMEBUFFER_DRIVER (gl_framebuffer_fbo);
+ CoglFramebuffer *framebuffer =
+ cogl_framebuffer_driver_get_framebuffer (driver);
+ CoglContext *ctx = cogl_framebuffer_get_context (framebuffer);
+
+ delete_renderbuffers (ctx, gl_framebuffer_fbo->gl_fbo.renderbuffers);
+ gl_framebuffer_fbo->gl_fbo.renderbuffers = NULL;
+
+ if (gl_framebuffer_fbo->gl_fbo.fbo_handle)
+ {
+ GE (ctx, glDeleteFramebuffers (1,
+ &gl_framebuffer_fbo->gl_fbo.fbo_handle));
+ gl_framebuffer_fbo->gl_fbo.fbo_handle = 0;
+ }
+
+ G_OBJECT_CLASS (cogl_gl_framebuffer_fbo_parent_class)->dispose (object);
+}
+
+static void
+cogl_gl_framebuffer_fbo_init (CoglGlFramebufferFbo *gl_framebuffer_fbo)
+{
+ gl_framebuffer_fbo->dirty_bitmasks = TRUE;
+}
+
+static void
+cogl_gl_framebuffer_fbo_class_init (CoglGlFramebufferFboClass *klass)
+{
+ GObjectClass *object_class = G_OBJECT_CLASS (klass);
+ CoglFramebufferDriverClass *driver_class =
+ COGL_FRAMEBUFFER_DRIVER_CLASS (klass);
+ CoglGlFramebufferClass *gl_framebuffer_class =
+ COGL_GL_FRAMEBUFFER_CLASS (klass);
+
+ object_class->dispose = cogl_gl_framebuffer_fbo_dispose;
+
+ driver_class->query_bits = cogl_gl_framebuffer_fbo_query_bits;
+
+ gl_framebuffer_class->bind = cogl_gl_framebuffer_fbo_bind;
+}
diff --git a/cogl/cogl/driver/gl/cogl-gl-framebuffer-fbo.h b/cogl/cogl/driver/gl/cogl-gl-framebuffer-fbo.h
new file mode 100644
index 0000000000..896847cf89
--- /dev/null
+++ b/cogl/cogl/driver/gl/cogl-gl-framebuffer-fbo.h
@@ -0,0 +1,41 @@
+/*
+ * Copyright (C) 2020 Red Hat
+ *
+ * Permission is hereby granted, free of charge, to any person
+ * obtaining a copy of this software and associated documentation
+ * files (the "Software"), to deal in the Software without
+ * restriction, including without limitation the rights to use, copy,
+ * modify, merge, publish, distribute, sublicense, and/or sell copies
+ * of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be
+ * included in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
+ * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
+ * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ *
+ */
+
+#ifndef COGL_GL_FRAMEBUFFER_FBO_H
+#define COGL_GL_FRAMEBUFFER_FBO_H
+
+#include "driver/gl/cogl-framebuffer-gl-private.h"
+
+#define COGL_TYPE_GL_FRAMEBUFFER_FBO (cogl_gl_framebuffer_fbo_get_type ())
+G_DECLARE_FINAL_TYPE (CoglGlFramebufferFbo, cogl_gl_framebuffer_fbo,
+ COGL, GL_FRAMEBUFFER_FBO,
+ CoglGlFramebuffer)
+
+CoglGlFramebufferFbo *
+cogl_gl_framebuffer_fbo_new (CoglFramebuffer *framebuffer,
+ const CoglFramebufferDriverConfig *driver_config,
+ GError **error);
+
+#endif /* COGL_GL_FRAMEBUFFER_FBO_H */
diff --git a/cogl/cogl/driver/gl/cogl-util-gl-private.h b/cogl/cogl/driver/gl/cogl-util-gl-private.h
index 6bada2cd02..0b7eaa772e 100644
--- a/cogl/cogl/driver/gl/cogl-util-gl-private.h
+++ b/cogl/cogl/driver/gl/cogl-util-gl-private.h
@@ -146,4 +146,87 @@ _cogl_gl_util_parse_gl_version (const char *version_string,
CoglGraphicsResetStatus
_cogl_gl_get_graphics_reset_status (CoglContext *context);
+#ifndef GL_FRAMEBUFFER
+#define GL_FRAMEBUFFER 0x8D40
+#endif
+#ifndef GL_RENDERBUFFER
+#define GL_RENDERBUFFER 0x8D41
+#endif
+#ifndef GL_STENCIL_ATTACHMENT
+#define GL_STENCIL_ATTACHMENT 0x8D00
+#endif
+#ifndef GL_COLOR_ATTACHMENT0
+#define GL_COLOR_ATTACHMENT0 0x8CE0
+#endif
+#ifndef GL_FRAMEBUFFER_COMPLETE
+#define GL_FRAMEBUFFER_COMPLETE 0x8CD5
+#endif
+#ifndef GL_STENCIL_INDEX8
+#define GL_STENCIL_INDEX8 0x8D48
+#endif
+#ifndef GL_DEPTH_STENCIL
+#define GL_DEPTH_STENCIL 0x84F9
+#endif
+#ifndef GL_DEPTH24_STENCIL8
+#define GL_DEPTH24_STENCIL8 0x88F0
+#endif
+#ifndef GL_DEPTH_ATTACHMENT
+#define GL_DEPTH_ATTACHMENT 0x8D00
+#endif
+#ifndef GL_DEPTH_STENCIL_ATTACHMENT
+#define GL_DEPTH_STENCIL_ATTACHMENT 0x821A
+#endif
+#ifndef GL_DEPTH_COMPONENT16
+#define GL_DEPTH_COMPONENT16 0x81A5
+#endif
+#ifndef GL_FRAMEBUFFER_ATTACHMENT_RED_SIZE
+#define GL_FRAMEBUFFER_ATTACHMENT_RED_SIZE 0x8212
+#endif
+#ifndef GL_FRAMEBUFFER_ATTACHMENT_GREEN_SIZE
+#define GL_FRAMEBUFFER_ATTACHMENT_GREEN_SIZE 0x8213
+#endif
+#ifndef GL_FRAMEBUFFER_ATTACHMENT_BLUE_SIZE
+#define GL_FRAMEBUFFER_ATTACHMENT_BLUE_SIZE 0x8214
+#endif
+#ifndef GL_FRAMEBUFFER_ATTACHMENT_ALPHA_SIZE
+#define GL_FRAMEBUFFER_ATTACHMENT_ALPHA_SIZE 0x8215
+#endif
+#ifndef GL_FRAMEBUFFER_ATTACHMENT_DEPTH_SIZE
+#define GL_FRAMEBUFFER_ATTACHMENT_DEPTH_SIZE 0x8216
+#endif
+#ifndef GL_FRAMEBUFFER_ATTACHMENT_STENCIL_SIZE
+#define GL_FRAMEBUFFER_ATTACHMENT_STENCIL_SIZE 0x8217
+#endif
+#ifndef GL_READ_FRAMEBUFFER
+#define GL_READ_FRAMEBUFFER 0x8CA8
+#endif
+#ifndef GL_DRAW_FRAMEBUFFER
+#define GL_DRAW_FRAMEBUFFER 0x8CA9
+#endif
+#ifndef GL_TEXTURE_SAMPLES_IMG
+#define GL_TEXTURE_SAMPLES_IMG 0x9136
+#endif
+#ifndef GL_PACK_INVERT_MESA
+#define GL_PACK_INVERT_MESA 0x8758
+#endif
+#ifndef GL_PACK_REVERSE_ROW_ORDER_ANGLE
+#define GL_PACK_REVERSE_ROW_ORDER_ANGLE 0x93A4
+#endif
+#ifndef GL_BACK_LEFT
+#define GL_BACK_LEFT 0x0402
+#endif
+#ifndef GL_BACK_RIGHT
+#define GL_BACK_RIGHT 0x0403
+#endif
+
+#ifndef GL_COLOR
+#define GL_COLOR 0x1800
+#endif
+#ifndef GL_DEPTH
+#define GL_DEPTH 0x1801
+#endif
+#ifndef GL_STENCIL
+#define GL_STENCIL 0x1802
+#endif
+
#endif /* _COGL_UTIL_GL_PRIVATE_H_ */
diff --git a/cogl/cogl/driver/gl/cogl-util-gl.c b/cogl/cogl/driver/gl/cogl-util-gl.c
index 2c1c4e5441..9b59bef1d6 100644
--- a/cogl/cogl/driver/gl/cogl-util-gl.c
+++ b/cogl/cogl/driver/gl/cogl-util-gl.c
@@ -35,6 +35,8 @@
#include "cogl-types.h"
#include "cogl-context-private.h"
#include "driver/gl/cogl-framebuffer-gl-private.h"
+#include "driver/gl/cogl-gl-framebuffer-fbo.h"
+#include "driver/gl/cogl-gl-framebuffer-back.h"
#include "driver/gl/cogl-pipeline-opengl-private.h"
#include "driver/gl/cogl-util-gl-private.h"
@@ -131,6 +133,46 @@ _cogl_driver_gl_context_deinit (CoglContext *context)
g_free (context->driver_context);
}
+CoglFramebufferDriver *
+_cogl_driver_gl_create_framebuffer_driver (CoglContext *context,
+ CoglFramebuffer *framebuffer,
+ const CoglFramebufferDriverConfig *driver_config,
+ GError **error)
+{
+ g_return_val_if_fail (driver_config, NULL);
+
+ switch (driver_config->type)
+ {
+ case COGL_FRAMEBUFFER_DRIVER_TYPE_FBO:
+ {
+ CoglGlFramebufferFbo *gl_framebuffer_fbo;
+
+ gl_framebuffer_fbo = cogl_gl_framebuffer_fbo_new (framebuffer,
+ driver_config,
+ error);
+ if (!gl_framebuffer_fbo)
+ return NULL;
+
+ return COGL_FRAMEBUFFER_DRIVER (gl_framebuffer_fbo);
+ }
+ case COGL_FRAMEBUFFER_DRIVER_TYPE_BACK:
+ {
+ CoglGlFramebufferBack *gl_framebuffer_back;
+
+ gl_framebuffer_back = cogl_gl_framebuffer_back_new (framebuffer,
+ driver_config,
+ error);
+ if (!gl_framebuffer_back)
+ return NULL;
+
+ return COGL_FRAMEBUFFER_DRIVER (gl_framebuffer_back);
+ }
+ }
+
+ g_assert_not_reached ();
+ return NULL;
+}
+
void
_cogl_driver_gl_flush_framebuffer_state (CoglContext *ctx,
CoglFramebuffer *draw_buffer,
@@ -138,6 +180,7 @@ _cogl_driver_gl_flush_framebuffer_state (CoglContext *ctx,
CoglFramebufferState state)
{
CoglGlFramebuffer *draw_gl_framebuffer;
+ CoglGlFramebuffer *read_gl_framebuffer;
unsigned long differences;
/* We can assume that any state that has changed for the current
@@ -193,13 +236,20 @@ _cogl_driver_gl_flush_framebuffer_state (CoglContext *ctx,
if (G_UNLIKELY (!cogl_framebuffer_is_allocated (read_buffer)))
cogl_framebuffer_allocate (read_buffer, NULL);
+ draw_gl_framebuffer =
+ COGL_GL_FRAMEBUFFER (cogl_framebuffer_get_driver (draw_buffer));
+ read_gl_framebuffer =
+ COGL_GL_FRAMEBUFFER (cogl_framebuffer_get_driver (read_buffer));
+
/* We handle buffer binding separately since the method depends on whether
* we are binding the same buffer for read and write or not unlike all
* other state that only relates to the draw_buffer. */
if (differences & COGL_FRAMEBUFFER_STATE_BIND)
{
if (draw_buffer == read_buffer)
- _cogl_framebuffer_gl_bind (draw_buffer, GL_FRAMEBUFFER);
+ {
+ cogl_gl_framebuffer_bind (draw_gl_framebuffer, GL_FRAMEBUFFER);
+ }
else
{
/* NB: Currently we only take advantage of binding separate
@@ -207,15 +257,13 @@ _cogl_driver_gl_flush_framebuffer_state (CoglContext *ctx,
g_return_if_fail (cogl_has_feature
(ctx, COGL_FEATURE_ID_BLIT_FRAMEBUFFER));
- _cogl_framebuffer_gl_bind (draw_buffer, GL_DRAW_FRAMEBUFFER);
- _cogl_framebuffer_gl_bind (read_buffer, GL_READ_FRAMEBUFFER);
+ cogl_gl_framebuffer_bind (draw_gl_framebuffer, GL_DRAW_FRAMEBUFFER);
+ cogl_gl_framebuffer_bind (read_gl_framebuffer, GL_READ_FRAMEBUFFER);
}
differences &= ~COGL_FRAMEBUFFER_STATE_BIND;
}
- draw_gl_framebuffer =
- COGL_GL_FRAMEBUFFER (cogl_framebuffer_get_driver (draw_buffer));
cogl_gl_framebuffer_flush_state_differences (draw_gl_framebuffer,
differences);
diff --git a/cogl/cogl/driver/gl/gl/cogl-driver-gl.c b/cogl/cogl/driver/gl/gl/cogl-driver-gl.c
index 31f6c898f7..bcb7f566ed 100644
--- a/cogl/cogl/driver/gl/gl/cogl-driver-gl.c
+++ b/cogl/cogl/driver/gl/gl/cogl-driver-gl.c
@@ -572,7 +572,6 @@ _cogl_driver_gl =
_cogl_driver_gl_create_framebuffer_driver,
_cogl_driver_gl_flush_framebuffer_state,
_cogl_framebuffer_gl_clear,
- _cogl_framebuffer_gl_query_bits,
_cogl_framebuffer_gl_finish,
_cogl_framebuffer_gl_flush,
_cogl_framebuffer_gl_discard_buffers,
diff --git a/cogl/cogl/driver/gl/gles/cogl-driver-gles.c b/cogl/cogl/driver/gl/gles/cogl-driver-gles.c
index 506d5250b6..a0688bd51e 100644
--- a/cogl/cogl/driver/gl/gles/cogl-driver-gles.c
+++ b/cogl/cogl/driver/gl/gles/cogl-driver-gles.c
@@ -460,7 +460,6 @@ _cogl_driver_gles =
_cogl_driver_gl_create_framebuffer_driver,
_cogl_driver_gl_flush_framebuffer_state,
_cogl_framebuffer_gl_clear,
- _cogl_framebuffer_gl_query_bits,
_cogl_framebuffer_gl_finish,
_cogl_framebuffer_gl_flush,
_cogl_framebuffer_gl_discard_buffers,
diff --git a/cogl/cogl/driver/nop/cogl-driver-nop.c b/cogl/cogl/driver/nop/cogl-driver-nop.c
index 7dfc1c5bcc..c52a2c2996 100644
--- a/cogl/cogl/driver/nop/cogl-driver-nop.c
+++ b/cogl/cogl/driver/nop/cogl-driver-nop.c
@@ -100,7 +100,6 @@ _cogl_driver_nop =
_cogl_driver_nop_create_framebuffer_driver,
_cogl_driver_nop_flush_framebuffer_state,
_cogl_framebuffer_nop_clear,
- _cogl_framebuffer_nop_query_bits,
_cogl_framebuffer_nop_finish,
_cogl_framebuffer_nop_flush,
_cogl_framebuffer_nop_discard_buffers,
diff --git a/cogl/cogl/driver/nop/cogl-framebuffer-nop-private.h
b/cogl/cogl/driver/nop/cogl-framebuffer-nop-private.h
index 19013c7528..a1cf77c894 100644
--- a/cogl/cogl/driver/nop/cogl-framebuffer-nop-private.h
+++ b/cogl/cogl/driver/nop/cogl-framebuffer-nop-private.h
@@ -45,10 +45,6 @@ _cogl_framebuffer_nop_clear (CoglFramebuffer *framebuffer,
float blue,
float alpha);
-void
-_cogl_framebuffer_nop_query_bits (CoglFramebuffer *framebuffer,
- CoglFramebufferBits *bits);
-
void
_cogl_framebuffer_nop_finish (CoglFramebuffer *framebuffer);
diff --git a/cogl/cogl/driver/nop/cogl-framebuffer-nop.c b/cogl/cogl/driver/nop/cogl-framebuffer-nop.c
index d7fc293f23..70488a1b50 100644
--- a/cogl/cogl/driver/nop/cogl-framebuffer-nop.c
+++ b/cogl/cogl/driver/nop/cogl-framebuffer-nop.c
@@ -45,13 +45,6 @@ _cogl_framebuffer_nop_clear (CoglFramebuffer *framebuffer,
{
}
-void
-_cogl_framebuffer_nop_query_bits (CoglFramebuffer *framebuffer,
- CoglFramebufferBits *bits)
-{
- memset (bits, 0, sizeof (CoglFramebufferBits));
-}
-
void
_cogl_framebuffer_nop_finish (CoglFramebuffer *framebuffer)
{
diff --git a/cogl/cogl/driver/nop/cogl-nop-framebuffer.c b/cogl/cogl/driver/nop/cogl-nop-framebuffer.c
index 85bed95a7c..3e155f3c3d 100644
--- a/cogl/cogl/driver/nop/cogl-nop-framebuffer.c
+++ b/cogl/cogl/driver/nop/cogl-nop-framebuffer.c
@@ -27,6 +27,8 @@
#include "cogl-nop-framebuffer.h"
+#include "cogl-framebuffer-private.h"
+
struct _CoglNopFramebuffer
{
CoglFramebufferDriver parent;
@@ -35,6 +37,13 @@ struct _CoglNopFramebuffer
G_DEFINE_TYPE (CoglNopFramebuffer, cogl_nop_framebuffer,
COGL_TYPE_FRAMEBUFFER_DRIVER)
+static void
+cogl_nop_framebuffer_query_bits (CoglFramebufferDriver *driver,
+ CoglFramebufferBits *bits)
+{
+ memset (bits, 0, sizeof (CoglFramebufferBits));
+}
+
static void
cogl_nop_framebuffer_init (CoglNopFramebuffer *nop_framebuffer)
{
@@ -43,4 +52,8 @@ cogl_nop_framebuffer_init (CoglNopFramebuffer *nop_framebuffer)
static void
cogl_nop_framebuffer_class_init (CoglNopFramebufferClass *klass)
{
+ CoglFramebufferDriverClass *driver_class =
+ COGL_FRAMEBUFFER_DRIVER_CLASS (klass);
+
+ driver_class->query_bits = cogl_nop_framebuffer_query_bits;
}
diff --git a/cogl/cogl/meson.build b/cogl/cogl/meson.build
index 638f5a8273..27ad72b2d4 100644
--- a/cogl/cogl/meson.build
+++ b/cogl/cogl/meson.build
@@ -155,6 +155,10 @@ cogl_common_driver_sources = [
'driver/gl/cogl-util-gl.c',
'driver/gl/cogl-framebuffer-gl-private.h',
'driver/gl/cogl-framebuffer-gl.c',
+ 'driver/gl/cogl-gl-framebuffer-back.c',
+ 'driver/gl/cogl-gl-framebuffer-back.h',
+ 'driver/gl/cogl-gl-framebuffer-fbo.c',
+ 'driver/gl/cogl-gl-framebuffer-fbo.h',
'driver/gl/cogl-texture-gl-private.h',
'driver/gl/cogl-texture-gl.c',
'driver/gl/cogl-texture-2d-gl-private.h',
diff --git a/cogl/cogl/winsys/cogl-onscreen-glx.c b/cogl/cogl/winsys/cogl-onscreen-glx.c
index b578494b09..24ee9cddcb 100644
--- a/cogl/cogl/winsys/cogl-onscreen-glx.c
+++ b/cogl/cogl/winsys/cogl-onscreen-glx.c
@@ -1131,8 +1131,14 @@ cogl_onscreen_glx_new (CoglContext *context,
int width,
int height)
{
+ CoglFramebufferDriverConfig driver_config;
+
+ driver_config = (CoglFramebufferDriverConfig) {
+ .type = COGL_FRAMEBUFFER_DRIVER_TYPE_BACK,
+ };
return g_object_new (COGL_TYPE_ONSCREEN_GLX,
"context", context,
+ "driver-config", &driver_config,
"width", width,
"height", height,
NULL);
diff --git a/cogl/cogl/winsys/cogl-onscreen-xlib.c b/cogl/cogl/winsys/cogl-onscreen-xlib.c
index 97540639a1..8eaf1976dd 100644
--- a/cogl/cogl/winsys/cogl-onscreen-xlib.c
+++ b/cogl/cogl/winsys/cogl-onscreen-xlib.c
@@ -338,8 +338,14 @@ cogl_onscreen_xlib_new (CoglContext *context,
int width,
int height)
{
+ CoglFramebufferDriverConfig driver_config;
+
+ driver_config = (CoglFramebufferDriverConfig) {
+ .type = COGL_FRAMEBUFFER_DRIVER_TYPE_BACK,
+ };
return g_object_new (COGL_TYPE_ONSCREEN_XLIB,
"context", context,
+ "driver-config", &driver_config,
"width", width,
"height", height,
NULL);
diff --git a/src/backends/native/meta-onscreen-native.c b/src/backends/native/meta-onscreen-native.c
index 45bd769bcb..e21d905450 100644
--- a/src/backends/native/meta-onscreen-native.c
+++ b/src/backends/native/meta-onscreen-native.c
@@ -1979,9 +1979,14 @@ meta_onscreen_native_new (MetaRendererNative *renderer_native,
int height)
{
MetaOnscreenNative *onscreen_native;
+ CoglFramebufferDriverConfig driver_config;
+ driver_config = (CoglFramebufferDriverConfig) {
+ .type = COGL_FRAMEBUFFER_DRIVER_TYPE_BACK,
+ };
onscreen_native = g_object_new (META_TYPE_ONSCREEN_NATIVE,
"context", cogl_context,
+ "driver-config", &driver_config,
"width", width,
"height", height,
NULL);
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]