diff --git a/gsk/ngl/gsknglrenderjob.c b/gsk/ngl/gsknglrenderjob.c index d285eb24b0..e3436e10f4 100644 --- a/gsk/ngl/gsknglrenderjob.c +++ b/gsk/ngl/gsknglrenderjob.c @@ -162,6 +162,11 @@ struct _GskNglRenderJob /* If we should be rendering red zones over fallback nodes */ guint debug_fallback : 1; + + /* Format we want to use for intermediate textures, determined by + * looking at the format of the framebuffer we are rendering on. + */ + int target_format; }; typedef struct _GskNglRenderOffscreen @@ -198,6 +203,16 @@ static gboolean gsk_ngl_render_job_visit_node_with_offscreen (GskNglRenderJob const GskRenderNode *node, GskNglRenderOffscreen *offscreen); +static inline int +get_target_format (GskNglRenderJob *job, + const GskRenderNode *node) +{ + if (gsk_render_node_prefers_high_depth (node)) + return job->target_format; + + return GL_RGBA8; +} + static inline void init_full_texture_region (GskNglRenderOffscreen *offscreen) { @@ -1258,7 +1273,7 @@ blur_offscreen (GskNglRenderJob *job, if (!gsk_ngl_driver_create_render_target (job->driver, MAX (texture_to_blur_width, 1), MAX (texture_to_blur_height, 1), - GL_RGBA8, + job->target_format, GL_NEAREST, GL_NEAREST, &pass1)) return 0; @@ -1269,7 +1284,7 @@ blur_offscreen (GskNglRenderJob *job, if (!gsk_ngl_driver_create_render_target (job->driver, texture_to_blur_width, texture_to_blur_height, - GL_RGBA8, + job->target_format, GL_NEAREST, GL_NEAREST, &pass2)) return gsk_ngl_driver_release_render_target (job->driver, pass1, FALSE); @@ -2181,7 +2196,7 @@ gsk_ngl_render_job_visit_blurred_inset_shadow_node (GskNglRenderJob *job, if (!gsk_ngl_driver_create_render_target (job->driver, texture_width, texture_height, - GL_RGBA8, + get_target_format (job, node), GL_NEAREST, GL_NEAREST, &render_target)) g_assert_not_reached (); @@ -2452,7 +2467,7 @@ gsk_ngl_render_job_visit_blurred_outset_shadow_node (GskNglRenderJob *job, gsk_ngl_driver_create_render_target (job->driver, texture_width, texture_height, - GL_RGBA8, + get_target_format (job, node), GL_NEAREST, GL_NEAREST, &render_target); @@ -3860,7 +3875,7 @@ gsk_ngl_render_job_visit_node_with_offscreen (GskNglRenderJob *job, if (!gsk_ngl_driver_create_render_target (job->driver, scaled_width, scaled_height, - GL_RGBA8, + get_target_format (job, node), filter, filter, &render_target)) g_assert_not_reached (); @@ -3959,7 +3974,7 @@ gsk_ngl_render_job_render_flipped (GskNglRenderJob *job, if (!gsk_ngl_command_queue_create_render_target (job->command_queue, MAX (1, job->viewport.size.width), MAX (1, job->viewport.size.height), - GL_RGBA8, + job->target_format, GL_NEAREST, GL_NEAREST, &framebuffer_id, &texture_id)) return; @@ -4050,6 +4065,22 @@ gsk_ngl_render_job_set_debug_fallback (GskNglRenderJob *job, job->debug_fallback = !!debug_fallback; } +static int +get_framebuffer_format (guint framebuffer) +{ + int size; + + glBindFramebuffer (GL_FRAMEBUFFER, framebuffer); + glGetFramebufferAttachmentParameteriv (GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_FRAMEBUFFER_ATTACHMENT_RED_SIZE, &size); + + if (size >= 32) + return GL_RGBA32F; + else if (size >= 16) + return GL_RGBA16F; + else + return GL_RGBA8; +} + GskNglRenderJob * gsk_ngl_render_job_new (GskNglDriver *driver, const graphene_rect_t *viewport, @@ -4076,6 +4107,7 @@ gsk_ngl_render_job_new (GskNglDriver *driver, job->scale_x = scale_factor; job->scale_y = scale_factor; job->viewport = *viewport; + job->target_format = get_framebuffer_format (framebuffer); gsk_ngl_render_job_set_alpha (job, 1.0f); gsk_ngl_render_job_set_projection_from_rect (job, viewport, NULL);