[gtk/wip/chergert/glproto: 682/920] more offscreen drawing work
- From: Christian Hergert <chergert src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [gtk/wip/chergert/glproto: 682/920] more offscreen drawing work
- Date: Mon, 8 Feb 2021 19:15:37 +0000 (UTC)
commit 714253185b197f60ca87b3ad4423d4feb4ba1b15
Author: Christian Hergert <chergert redhat com>
Date: Mon Jan 11 19:24:54 2021 -0800
more offscreen drawing work
gsk/next/gskglrenderjob.c | 152 +++++++++++++++++++++++++++++++++++++++++++++-
1 file changed, 150 insertions(+), 2 deletions(-)
---
diff --git a/gsk/next/gskglrenderjob.c b/gsk/next/gskglrenderjob.c
index c22ccb2dbf..db3258b5bf 100644
--- a/gsk/next/gskglrenderjob.c
+++ b/gsk/next/gskglrenderjob.c
@@ -83,6 +83,18 @@ struct _GskGLRenderJob
guint debug_fallback : 1;
};
+typedef struct GskGLRenderState
+{
+ graphene_rect_t viewport;
+ graphene_matrix_t projection;
+ guint framebuffer;
+ float alpha;
+ float offset_x;
+ float offset_y;
+ float scale_x;
+ float scale_y;
+} GskGLRenderState;
+
typedef struct _GskGLRenderClip
{
GskRoundedRect rect;
@@ -539,6 +551,43 @@ gsk_gl_render_job_offset (GskGLRenderJob *job,
job->offset_y += offset_y;
}
+static void
+gsk_gl_render_state_save (GskGLRenderState *state,
+ GskGLRenderJob *job)
+{
+ g_assert (state != NULL);
+ g_assert (job != NULL);
+
+ memcpy (&state->viewport, &job->viewport, sizeof state->viewport);
+ memcpy (&state->projection, &job->projection, sizeof state->projection);
+
+ state->framebuffer = job->command_queue->attachments->fbo.id;
+ state->alpha = job->alpha;
+ state->offset_x = job->offset_x;
+ state->offset_y = job->offset_y;
+ state->scale_x = job->scale_x;
+ state->scale_y = job->scale_y;
+}
+
+static void
+gsk_gl_render_state_restore (GskGLRenderState *state,
+ GskGLRenderJob *job)
+{
+ g_assert (state != NULL);
+ g_assert (job != NULL);
+
+ memcpy (&job->viewport, &state->viewport, sizeof state->viewport);
+ memcpy (&job->projection, &state->projection, sizeof state->projection);
+
+ gsk_gl_command_queue_bind_framebuffer (job->command_queue, state->framebuffer);
+
+ job->alpha = state->alpha;
+ job->offset_x = state->offset_x;
+ job->offset_y = state->offset_y;
+ job->scale_x = state->scale_x;
+ job->scale_y = state->scale_y;
+}
+
static void
gsk_gl_render_job_transform_bounds (GskGLRenderJob *job,
const graphene_rect_t *rect,
@@ -1018,6 +1067,8 @@ gsk_gl_render_job_visit_clipped_child (GskGLRenderJob *job,
gsk_gl_render_job_visit_node_with_offscreen (job, child, &offscreen);
gsk_gl_render_job_pop_clip (job);
+ g_assert (offscreen.texture_id);
+
gsk_gl_program_begin_draw (job->driver->blit,
&job->viewport,
&job->projection,
@@ -1138,9 +1189,12 @@ gsk_gl_render_job_visit_rounded_clip_node (GskGLRenderJob *job,
}
gsk_gl_render_job_push_clip (job, &scaled_clip);
- gsk_gl_render_job_visit_node_with_offscreen (job, child, &offscreen);
+ if (!gsk_gl_render_job_visit_node_with_offscreen (job, child, &offscreen))
+ g_assert_not_reached ();
gsk_gl_render_job_pop_clip (job);
+ g_assert (offscreen.texture_id);
+
gsk_gl_program_begin_draw (job->driver->blit,
&job->viewport,
&job->projection,
@@ -1613,6 +1667,8 @@ gsk_gl_render_job_visit_cross_fade_node (GskGLRenderJob *job,
return;
}
+ g_assert (offscreen_start.texture_id);
+
if (!gsk_gl_render_job_visit_node_with_offscreen (job, end_node, &offscreen_end))
{
float prev_alpha = job->alpha;
@@ -1621,6 +1677,8 @@ gsk_gl_render_job_visit_cross_fade_node (GskGLRenderJob *job,
return;
}
+ g_assert (offscreen_end.texture_id);
+
gsk_gl_program_begin_draw (job->driver->cross_fade,
&job->viewport,
&job->projection,
@@ -1664,6 +1722,8 @@ gsk_gl_render_job_visit_opacity_node (GskGLRenderJob *job,
gsk_gl_render_job_visit_node_with_offscreen (job, child, &offscreen);
+ g_assert (offscreen.texture_id);
+
gsk_gl_program_begin_draw (job->driver->blit,
&job->viewport,
&job->projection,
@@ -2008,7 +2068,95 @@ gsk_gl_render_job_visit_node_with_offscreen (GskGLRenderJob *job,
return TRUE;
}
- return FALSE;
+ float width = offscreen->bounds->size.width;
+ float height = offscreen->bounds->size.height;
+ float scale_x = job->scale_x;
+ float scale_y = job->scale_y;
+
+ g_assert (job->command_queue->max_texture_size > 0);
+
+ /* Tweak the scale factor so that the required texture doesn't
+ * exceed the max texture limit. This will render with a lower
+ * resolution, but this is better than clipping.
+ */
+ {
+ int max_texture_size = job->command_queue->max_texture_size;
+
+ width = ceilf (width * scale_x);
+ if (width > max_texture_size)
+ {
+ scale_x *= (float)max_texture_size / width;
+ width = max_texture_size;
+ }
+
+ height = ceilf (height * scale_y);
+ if (height > max_texture_size)
+ {
+ scale_y *= (float)max_texture_size / height;
+ height = max_texture_size;
+ }
+ }
+
+ guint framebuffer_id;
+ guint texture_id;
+ GskGLRenderState state;
+
+ gsk_gl_render_state_save (&state, job);
+
+ gsk_next_driver_create_render_target (job->driver,
+ width, height,
+ &texture_id, &framebuffer_id);
+
+ if (gdk_gl_context_has_debug (job->command_queue->context))
+ {
+ gdk_gl_context_label_object_printf (job->command_queue->context,
+ GL_TEXTURE, texture_id,
+ "Offscreen<%s> %d",
+ g_type_name_from_instance ((GTypeInstance *) node),
+ texture_id);
+ gdk_gl_context_label_object_printf (job->command_queue->context,
+ GL_FRAMEBUFFER, framebuffer_id,
+ "Offscreen<%s> FB %d",
+ g_type_name_from_instance ((GTypeInstance *) node),
+ framebuffer_id);
+ }
+
+ job->viewport.origin.x = offscreen->bounds->origin.x * scale_x;
+ job->viewport.origin.y = offscreen->bounds->origin.y * scale_y;
+ job->viewport.size.width = width;
+ job->viewport.size.height = height;
+
+ gsk_gl_command_queue_bind_framebuffer (job->command_queue, framebuffer_id);
+ gsk_gl_command_queue_clear (job->command_queue, 0, &job->viewport);
+
+ init_projection_matrix (&job->projection, &job->viewport);
+ gsk_gl_render_job_set_modelview (job, gsk_transform_scale (NULL, scale_x, scale_y));
+
+ if (offscreen->reset_clip)
+ gsk_gl_render_job_push_clip (job, &(GskRoundedRect) { .bounds = job->viewport });
+
+ job->offset_x = 0;
+ job->offset_y = 0;
+
+ gsk_gl_render_job_visit_node (job, node);
+
+ if (offscreen->reset_clip)
+ gsk_gl_render_job_pop_clip (job);
+
+ gsk_gl_render_job_pop_modelview (job);
+
+ gsk_gl_render_state_restore (&state, job);
+
+ offscreen->was_offscreen = TRUE;
+ offscreen->texture_id = texture_id;
+ init_full_texture_region (&offscreen->area);
+
+ gsk_next_driver_autorelease_framebuffer (job->driver, framebuffer_id);
+
+ if (!offscreen->do_not_cache)
+ gsk_next_driver_cache_texture (job->driver, &key, texture_id);
+
+ return TRUE;
}
void
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]