renderer-native: Move shadow fb construction to the stage view

The stage view will need a more involved approach to shadow buffers, in
order to implement things such double buffered shadow buffers and damage
detection.

https://gitlab.gnome.org/GNOME/mutter/-/merge_requests/1237
This commit is contained in:
Jonas Ådahl 2020-04-30 17:53:30 +02:00 committed by Georges Basile Stavracas Neto
parent 6db94a0b77
commit f4d9953b9c
2 changed files with 106 additions and 34 deletions

View File

@ -35,7 +35,7 @@ enum
PROP_LAYOUT,
PROP_FRAMEBUFFER,
PROP_OFFSCREEN,
PROP_SHADOWFB,
PROP_USE_SHADOWFB,
PROP_SCALE,
PROP_LAST
@ -54,6 +54,7 @@ typedef struct _ClutterStageViewPrivate
CoglOffscreen *offscreen;
CoglPipeline *offscreen_pipeline;
gboolean use_shadowfb;
CoglOffscreen *shadowfb;
CoglPipeline *shadowfb_pipeline;
@ -214,6 +215,80 @@ clutter_stage_view_copy_to_framebuffer (ClutterStageView *view,
cogl_framebuffer_pop_matrix (dst_framebuffer);
}
static CoglOffscreen *
create_offscreen_framebuffer (CoglContext *context,
int width,
int height,
GError **error)
{
CoglOffscreen *framebuffer;
CoglTexture2D *texture;
texture = cogl_texture_2d_new_with_size (context, width, height);
cogl_primitive_texture_set_auto_mipmap (COGL_PRIMITIVE_TEXTURE (texture),
FALSE);
if (!cogl_texture_allocate (COGL_TEXTURE (texture), error))
{
cogl_object_unref (texture);
return FALSE;
}
framebuffer = cogl_offscreen_new_with_texture (COGL_TEXTURE (texture));
cogl_object_unref (texture);
if (!cogl_framebuffer_allocate (COGL_FRAMEBUFFER (framebuffer), error))
{
cogl_object_unref (framebuffer);
return FALSE;
}
return framebuffer;
}
static gboolean
init_offscreen_shadowfb (ClutterStageView *view,
CoglContext *cogl_context,
int width,
int height,
GError **error)
{
ClutterStageViewPrivate *priv =
clutter_stage_view_get_instance_private (view);
CoglOffscreen *offscreen;
offscreen = create_offscreen_framebuffer (cogl_context, width, height, error);
if (!offscreen)
return FALSE;
priv->shadowfb = offscreen;
return TRUE;
}
static void
init_shadowfb (ClutterStageView *view)
{
ClutterStageViewPrivate *priv =
clutter_stage_view_get_instance_private (view);
g_autoptr (GError) error = NULL;
int width;
int height;
CoglContext *cogl_context;
width = cogl_framebuffer_get_width (priv->framebuffer);
height = cogl_framebuffer_get_height (priv->framebuffer);
cogl_context = cogl_framebuffer_get_context (priv->framebuffer);
if (!init_offscreen_shadowfb (view, cogl_context, width, height, &error))
{
g_warning ("Failed to initialize single buffered shadow fb for %s: %s",
priv->name, error->message);
}
else
{
g_message ("Initialized single buffered shadow fb for %s", priv->name);
}
}
void
clutter_stage_view_after_paint (ClutterStageView *view)
{
@ -457,8 +532,8 @@ clutter_stage_view_get_property (GObject *object,
case PROP_OFFSCREEN:
g_value_set_boxed (value, priv->offscreen);
break;
case PROP_SHADOWFB:
g_value_set_boxed (value, priv->shadowfb);
case PROP_USE_SHADOWFB:
g_value_set_boolean (value, priv->use_shadowfb);
break;
case PROP_SCALE:
g_value_set_float (value, priv->scale);
@ -508,8 +583,8 @@ clutter_stage_view_set_property (GObject *object,
case PROP_OFFSCREEN:
priv->offscreen = g_value_dup_boxed (value);
break;
case PROP_SHADOWFB:
priv->shadowfb = g_value_dup_boxed (value);
case PROP_USE_SHADOWFB:
priv->use_shadowfb = g_value_get_boolean (value);
break;
case PROP_SCALE:
priv->scale = g_value_get_float (value);
@ -519,6 +594,19 @@ clutter_stage_view_set_property (GObject *object,
}
}
static void
clutter_stage_view_constructed (GObject *object)
{
ClutterStageView *view = CLUTTER_STAGE_VIEW (object);
ClutterStageViewPrivate *priv =
clutter_stage_view_get_instance_private (view);
if (priv->use_shadowfb)
init_shadowfb (view);
G_OBJECT_CLASS (clutter_stage_view_parent_class)->constructed (object);
}
static void
clutter_stage_view_dispose (GObject *object)
{
@ -558,6 +646,7 @@ clutter_stage_view_class_init (ClutterStageViewClass *klass)
object_class->get_property = clutter_stage_view_get_property;
object_class->set_property = clutter_stage_view_set_property;
object_class->constructed = clutter_stage_view_constructed;
object_class->dispose = clutter_stage_view_dispose;
obj_props[PROP_NAME] =
@ -595,11 +684,11 @@ clutter_stage_view_class_init (ClutterStageViewClass *klass)
G_PARAM_CONSTRUCT_ONLY |
G_PARAM_STATIC_STRINGS);
obj_props[PROP_SHADOWFB] =
g_param_spec_boxed ("shadowfb",
"Shadow framebuffer",
"Framebuffer used as intermediate shadow buffer",
COGL_TYPE_HANDLE,
obj_props[PROP_USE_SHADOWFB] =
g_param_spec_boolean ("use-shadowfb",
"Use shadowfb",
"Whether to use one or more shadow framebuffers",
FALSE,
G_PARAM_READWRITE |
G_PARAM_CONSTRUCT_ONLY |
G_PARAM_STATIC_STRINGS);

View File

@ -3150,7 +3150,7 @@ meta_renderer_native_create_view (MetaRenderer *renderer,
MetaMonitorTransform view_transform;
CoglOnscreen *onscreen = NULL;
CoglOffscreen *offscreen = NULL;
CoglOffscreen *shadowfb = NULL;
gboolean use_shadowfb;
float scale;
int onscreen_width;
int onscreen_height;
@ -3202,24 +3202,8 @@ meta_renderer_native_create_view (MetaRenderer *renderer,
g_error ("Failed to allocate back buffer texture: %s", error->message);
}
if (should_force_shadow_fb (renderer_native,
renderer_native->primary_gpu_kms))
{
int shadow_width;
int shadow_height;
/* The shadowfb must be the same size as the on-screen framebuffer */
shadow_width = cogl_framebuffer_get_width (COGL_FRAMEBUFFER (onscreen));
shadow_height = cogl_framebuffer_get_height (COGL_FRAMEBUFFER (onscreen));
shadowfb = meta_renderer_native_create_offscreen (renderer_native,
cogl_context,
shadow_width,
shadow_height,
&error);
if (!shadowfb)
g_error ("Failed to allocate shadow buffer texture: %s", error->message);
}
use_shadowfb = should_force_shadow_fb (renderer_native,
renderer_native->primary_gpu_kms);
if (meta_is_stage_views_scaled ())
scale = meta_logical_monitor_get_scale (logical_monitor);
@ -3235,11 +3219,10 @@ meta_renderer_native_create_view (MetaRenderer *renderer,
"scale", scale,
"framebuffer", onscreen,
"offscreen", offscreen,
"shadowfb", shadowfb,
"use-shadowfb", use_shadowfb,
"transform", view_transform,
NULL);
g_clear_pointer (&offscreen, cogl_object_unref);
g_clear_pointer (&shadowfb, cogl_object_unref);
meta_onscreen_native_set_view (onscreen, view);