diff --git a/gsk/gl/gskglrenderer.c b/gsk/gl/gskglrenderer.c index 2730f2466f..0e8e29b95c 100644 --- a/gsk/gl/gskglrenderer.c +++ b/gsk/gl/gskglrenderer.c @@ -24,10 +24,13 @@ #include #include #include +#include #include #include #include #include +#include +#include #include "gskglcommandqueueprivate.h" #include "gskgldriverprivate.h" @@ -289,6 +292,12 @@ gsk_gl_renderer_render (GskRenderer *renderer, surface = gdk_draw_context_get_surface (GDK_DRAW_CONTEXT (self->context)); scale = gdk_gl_context_get_scale (self->context); + if (cairo_region_is_empty (update_area)) + { + gdk_draw_context_empty_frame (GDK_DRAW_CONTEXT (self->context)); + return; + } + viewport.origin.x = 0; viewport.origin.y = 0; viewport.size.width = gdk_surface_get_width (surface) * scale; @@ -305,7 +314,7 @@ gsk_gl_renderer_render (GskRenderer *renderer, clear_framebuffer = update_area_requires_clear (surface, render_region); gsk_gl_driver_begin_frame (self->driver, self->command_queue); - job = gsk_gl_render_job_new (self->driver, &viewport, scale, render_region, 0, clear_framebuffer); + job = gsk_gl_render_job_new (self->driver, &viewport, scale, render_region, 0, clear_framebuffer, offload); if (GSK_RENDERER_DEBUG_CHECK (GSK_RENDERER (self), FALLBACK)) gsk_gl_render_job_set_debug_fallback (job, TRUE); gsk_gl_render_job_render (job, root); @@ -377,7 +386,7 @@ gsk_gl_renderer_render_texture (GskRenderer *renderer, gdk_format = GDK_MEMORY_R32G32B32A32_FLOAT_PREMULTIPLIED; format = GL_RGBA32F; } - else + else { format = GL_RGBA8; gdk_format = GDK_MEMORY_R8G8B8A8_PREMULTIPLIED; @@ -391,7 +400,7 @@ gsk_gl_renderer_render_texture (GskRenderer *renderer, &render_target)) { gsk_gl_driver_begin_frame (self->driver, self->command_queue); - job = gsk_gl_render_job_new (self->driver, viewport, 1, NULL, render_target->framebuffer_id, TRUE); + job = gsk_gl_render_job_new (self->driver, viewport, 1, NULL, render_target->framebuffer_id, TRUE, NULL); if (GSK_RENDERER_DEBUG_CHECK (GSK_RENDERER (self), FALLBACK)) gsk_gl_render_job_set_debug_fallback (job, TRUE); gsk_gl_render_job_render_flipped (job, root); diff --git a/gsk/gl/gskglrenderjob.c b/gsk/gl/gskglrenderjob.c index 141d537138..5e7910f7c5 100644 --- a/gsk/gl/gskglrenderjob.c +++ b/gsk/gl/gskglrenderjob.c @@ -31,9 +31,13 @@ #include #include #include +#include +#include #include #include #include +#include +#include #include #include @@ -44,10 +48,12 @@ #include "gskglprogramprivate.h" #include "gskglrenderjobprivate.h" #include "gskglshadowlibraryprivate.h" +#include "gskdebugprivate.h" #include "ninesliceprivate.h" #include "fp16private.h" +#define ALLOW_OFFLOAD_FOR_ANY_TEXTURE 1 #define ORTHO_NEAR_PLANE -10000 #define ORTHO_FAR_PLANE 10000 @@ -174,6 +180,8 @@ struct _GskGLRenderJob * looking at the format of the framebuffer we are rendering on. */ int target_format; + + GskOffload *offload; }; typedef struct _GskGLRenderOffscreen @@ -3998,6 +4006,36 @@ gsk_gl_render_job_visit_repeat_node (GskGLRenderJob *job, } } +static inline void +gsk_gl_render_job_visit_subsurface_node (GskGLRenderJob *job, + const GskRenderNode *node) +{ + GdkSubsurface *subsurface; + + subsurface = (GdkSubsurface *) gsk_subsurface_node_get_subsurface (node); + + if (job->offload && + gsk_offload_subsurface_is_offloaded (job->offload, subsurface)) + { + /* Clear the area so we can see through */ + if (gsk_gl_render_job_begin_draw (job, CHOOSE_PROGRAM (job, color))) + { + GskGLCommandBatch *batch; + guint16 color[4]; + rgba_to_half (&(GdkRGBA){0,0,0,0}, color); + + batch = gsk_gl_command_queue_get_batch (job->command_queue); + batch->draw.blend = 0; + gsk_gl_render_job_draw_rect_with_color (job, &node->bounds, color); + gsk_gl_render_job_end_draw (job); + } + } + else + { + gsk_gl_render_job_visit_node (job, gsk_subsurface_node_get_child (node)); + } +} + static void gsk_gl_render_job_visit_node (GskGLRenderJob *job, const GskRenderNode *node) @@ -4195,8 +4233,7 @@ gsk_gl_render_job_visit_node (GskGLRenderJob *job, break; case GSK_SUBSURFACE_NODE: - // FIXME do something here - gsk_gl_render_job_visit_node (job, gsk_subsurface_node_get_child (node)); + gsk_gl_render_job_visit_subsurface_node (job, node); break; case GSK_NOT_A_RENDER_NODE: @@ -4520,6 +4557,7 @@ gsk_gl_render_job_render (GskGLRenderJob *job, gsk_gl_command_queue_clear (job->command_queue, 0, &job->viewport); gsk_gl_render_job_visit_node (job, root); gdk_gl_context_pop_debug_group (job->command_queue->context); + gdk_profiler_add_mark (start_time, GDK_PROFILER_CURRENT_TIME-start_time, "Build GL command queue", ""); #if 0 @@ -4580,7 +4618,8 @@ gsk_gl_render_job_new (GskGLDriver *driver, float scale, const cairo_region_t *region, guint framebuffer, - gboolean clear_framebuffer) + gboolean clear_framebuffer, + GskOffload *offload) { const graphene_rect_t *clip_rect = viewport; graphene_rect_t transformed_extents; @@ -4616,6 +4655,7 @@ gsk_gl_render_job_new (GskGLDriver *driver, job->scale_y = scale; job->viewport = *viewport; job->target_format = get_framebuffer_format (job->command_queue->context, framebuffer); + job->offload = offload; gsk_gl_render_job_set_alpha (job, 1.0f); gsk_gl_render_job_set_projection_from_rect (job, viewport, NULL); diff --git a/gsk/gl/gskglrenderjobprivate.h b/gsk/gl/gskglrenderjobprivate.h index 32edae12a3..04aee7024d 100644 --- a/gsk/gl/gskglrenderjobprivate.h +++ b/gsk/gl/gskglrenderjobprivate.h @@ -27,7 +27,8 @@ GskGLRenderJob *gsk_gl_render_job_new (GskGLDriver *dri float scale, const cairo_region_t *region, guint framebuffer, - gboolean clear_framebuffer); + gboolean clear_framebuffer, + GskOffload *offload); void gsk_gl_render_job_free (GskGLRenderJob *job); void gsk_gl_render_job_render (GskGLRenderJob *job, GskRenderNode *root);