[gtk/wip/chergert/macos-iosurface: 18/21] gsk/gl: support non-standard default framebuffer
- From: Christian Hergert <chergert src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [gtk/wip/chergert/macos-iosurface: 18/21] gsk/gl: support non-standard default framebuffer
- Date: Tue, 22 Feb 2022 04:55:53 +0000 (UTC)
commit 97526af542d0e1e7807e6e49b3a9c111b170327f
Author: Christian Hergert <christian hergert me>
Date: Thu Feb 10 21:51:15 2022 -0800
gsk/gl: support non-standard default framebuffer
There are situations where our "default framebuffer" is not actually
zero, yet we still want to apply a scissor rect.
Generally, 0 is the default framebuffer. But on platforms where we need
to bind a platform-specific feature to a GL_FRAMEBUFFER, we might have a
default that is not 0. For example, on macOS we bind an IOSurfaceRef to
a GL_TEXTURE_RECTANGLE which then is assigned as the backing store for a
framebuffer. This is different than using gsk_gl_renderer_render_texture()
in that we don't want to incur an extra copy to the destination surface
nor do we even have a way to pass a texture_id into render_texture().
gdk/gdkglcontext.c | 7 +++++++
gdk/gdkglcontextprivate.h | 2 ++
gsk/gl/gskglcommandqueue.c | 29 ++++++++++++++++++++---------
gsk/gl/gskglcommandqueueprivate.h | 3 ++-
gsk/gl/gskglrenderjob.c | 18 ++++++++++++++++--
5 files changed, 47 insertions(+), 12 deletions(-)
---
diff --git a/gdk/gdkglcontext.c b/gdk/gdkglcontext.c
index 373f2fefd5..be514c0ac6 100644
--- a/gdk/gdkglcontext.c
+++ b/gdk/gdkglcontext.c
@@ -648,6 +648,12 @@ gdk_gl_context_surface_resized (GdkDrawContext *draw_context)
gdk_gl_context_clear_old_updated_area (context);
}
+static guint
+gdk_gl_context_real_get_default_framebuffer (GdkGLContext *self)
+{
+ return 0;
+}
+
static void
gdk_gl_context_class_init (GdkGLContextClass *klass)
{
@@ -659,6 +665,7 @@ gdk_gl_context_class_init (GdkGLContextClass *klass)
klass->is_shared = gdk_gl_context_real_is_shared;
klass->make_current = gdk_gl_context_real_make_current;
klass->clear_current = gdk_gl_context_real_clear_current;
+ klass->get_default_framebuffer = gdk_gl_context_real_get_default_framebuffer;
draw_context_class->begin_frame = gdk_gl_context_real_begin_frame;
draw_context_class->end_frame = gdk_gl_context_real_end_frame;
diff --git a/gdk/gdkglcontextprivate.h b/gdk/gdkglcontextprivate.h
index ff11349b3e..0a3739f090 100644
--- a/gdk/gdkglcontextprivate.h
+++ b/gdk/gdkglcontextprivate.h
@@ -71,6 +71,8 @@ struct _GdkGLContextClass
gboolean (* is_shared) (GdkGLContext *self,
GdkGLContext *other);
+
+ guint (* get_default_framebuffer) (GdkGLContext *self);
};
typedef struct {
diff --git a/gsk/gl/gskglcommandqueue.c b/gsk/gl/gskglcommandqueue.c
index 3af8c1eb09..266a158822 100644
--- a/gsk/gl/gskglcommandqueue.c
+++ b/gsk/gl/gskglcommandqueue.c
@@ -675,9 +675,9 @@ gsk_gl_command_queue_split_draw (GskGLCommandQueue *self)
}
void
-gsk_gl_command_queue_clear (GskGLCommandQueue *self,
- guint clear_bits,
- const graphene_rect_t *viewport)
+gsk_gl_command_queue_clear (GskGLCommandQueue *self,
+ guint clear_bits,
+ const graphene_rect_t *viewport)
{
GskGLCommandBatch *batch;
@@ -750,11 +750,12 @@ static inline void
apply_scissor (gboolean *state,
guint framebuffer,
const graphene_rect_t *scissor,
- gboolean has_scissor)
+ gboolean has_scissor,
+ guint default_framebuffer)
{
g_assert (framebuffer != (guint)-1);
- if (framebuffer != 0 || !has_scissor)
+ if (framebuffer != default_framebuffer || !has_scissor)
{
if (*state != FALSE)
{
@@ -935,15 +936,25 @@ gsk_gl_command_queue_sort_batches (GskGLCommandQueue *self)
* @self: a `GskGLCommandQueue`
* @surface_height: the height of the backing surface
* @scale_factor: the scale factor of the backing surface
- * #scissor: (nullable): the scissor clip if any
+ * @scissor: (nullable): the scissor clip if any
+ * @default_framebuffer: the default framebuffer id if not zero
*
* Executes all of the batches in the command queue.
+ *
+ * Typically, the scissor rect is only applied id rendering to the
+ * default framebuffer which is zero in most cases. However, if
+ * default_framebuffer is not zero, it will be checked to see if the
+ * rendering target matches so that the scissor rect is applied. This
+ * should be used in cases where rendering to the backbuffer for display
+ * is not the default GL framebuffer of zero. The current example of
+ * this is rendering to IOSurface on macOS.
*/
void
gsk_gl_command_queue_execute (GskGLCommandQueue *self,
guint surface_height,
guint scale_factor,
- const cairo_region_t *scissor)
+ const cairo_region_t *scissor,
+ guint default_framebuffer)
{
G_GNUC_UNUSED guint count = 0;
graphene_rect_t scissor_test;
@@ -1049,7 +1060,7 @@ gsk_gl_command_queue_execute (GskGLCommandQueue *self,
case GSK_GL_COMMAND_KIND_CLEAR:
if (apply_framebuffer (&framebuffer, batch->clear.framebuffer))
{
- apply_scissor (&scissor_state, framebuffer, &scissor_test, has_scissor);
+ apply_scissor (&scissor_state, framebuffer, &scissor_test, has_scissor, default_framebuffer);
n_fbos++;
}
@@ -1073,7 +1084,7 @@ gsk_gl_command_queue_execute (GskGLCommandQueue *self,
if (apply_framebuffer (&framebuffer, batch->draw.framebuffer))
{
- apply_scissor (&scissor_state, framebuffer, &scissor_test, has_scissor);
+ apply_scissor (&scissor_state, framebuffer, &scissor_test, has_scissor, default_framebuffer);
n_fbos++;
}
diff --git a/gsk/gl/gskglcommandqueueprivate.h b/gsk/gl/gskglcommandqueueprivate.h
index 4147283e6d..48911305a8 100644
--- a/gsk/gl/gskglcommandqueueprivate.h
+++ b/gsk/gl/gskglcommandqueueprivate.h
@@ -278,7 +278,8 @@ void gsk_gl_command_queue_end_frame (GskGLCommandQueue
void gsk_gl_command_queue_execute (GskGLCommandQueue *self,
guint surface_height,
guint scale_factor,
- const cairo_region_t *scissor);
+ const cairo_region_t *scissor,
+ guint default_framebuffer);
int gsk_gl_command_queue_upload_texture (GskGLCommandQueue *self,
GdkTexture *texture,
int min_filter,
diff --git a/gsk/gl/gskglrenderjob.c b/gsk/gl/gskglrenderjob.c
index 0efa8ae108..f52db80062 100644
--- a/gsk/gl/gskglrenderjob.c
+++ b/gsk/gl/gskglrenderjob.c
@@ -123,6 +123,7 @@ struct _GskGLRenderJob
* GL context.
*/
guint framebuffer;
+ guint default_framebuffer;
/* The viewport we are using. This state is updated as we process render
* nodes in the specific visitor callbacks.
@@ -4053,7 +4054,7 @@ gsk_gl_render_job_render_flipped (GskGLRenderJob *job,
gsk_gl_render_job_end_draw (job);
gdk_gl_context_push_debug_group (job->command_queue->context, "Executing command queue");
- gsk_gl_command_queue_execute (job->command_queue, surface_height, 1, NULL);
+ gsk_gl_command_queue_execute (job->command_queue, surface_height, 1, NULL, job->default_framebuffer);
gdk_gl_context_pop_debug_group (job->command_queue->context);
glDeleteFramebuffers (1, &framebuffer_id);
@@ -4102,7 +4103,7 @@ gsk_gl_render_job_render (GskGLRenderJob *job,
start_time = GDK_PROFILER_CURRENT_TIME;
gsk_gl_command_queue_make_current (job->command_queue);
gdk_gl_context_push_debug_group (job->command_queue->context, "Executing command queue");
- gsk_gl_command_queue_execute (job->command_queue, surface_height, scale_factor, job->region);
+ gsk_gl_command_queue_execute (job->command_queue, surface_height, scale_factor, job->region,
job->default_framebuffer);
gdk_gl_context_pop_debug_group (job->command_queue->context);
gdk_profiler_add_mark (start_time, GDK_PROFILER_CURRENT_TIME-start_time, "Execute GL command queue", "");
}
@@ -4150,17 +4151,30 @@ gsk_gl_render_job_new (GskGLDriver *driver,
const graphene_rect_t *clip_rect = viewport;
graphene_rect_t transformed_extents;
GskGLRenderJob *job;
+ GdkGLContext *context;
+ GLint default_framebuffer = 0;
g_return_val_if_fail (GSK_IS_GL_DRIVER (driver), NULL);
g_return_val_if_fail (viewport != NULL, NULL);
g_return_val_if_fail (scale_factor > 0, NULL);
+ /* Check for non-standard framebuffer binding as we might not be using
+ * the default framebuffer on systems like macOS where we've bound an
+ * IOSurface to a GL_TEXTURE_RECTANGLE. Otherwise, no scissor clip will
+ * be applied in the command queue causing overdrawing.
+ */
+ context = driver->command_queue->context;
+ default_framebuffer = GDK_GL_CONTEXT_GET_CLASS (context)->get_default_framebuffer (context);
+ if (framebuffer == 0 && default_framebuffer != 0)
+ framebuffer = default_framebuffer;
+
job = g_slice_new0 (GskGLRenderJob);
job->driver = g_object_ref (driver);
job->command_queue = job->driver->command_queue;
job->clip = g_array_sized_new (FALSE, FALSE, sizeof (GskGLRenderClip), 16);
job->modelview = g_array_sized_new (FALSE, FALSE, sizeof (GskGLRenderModelview), 16);
job->framebuffer = framebuffer;
+ job->default_framebuffer = default_framebuffer;
job->offset_x = 0;
job->offset_y = 0;
job->scale_x = scale_factor;
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]