diff --git a/clutter/clutter/clutter-stage-view.c b/clutter/clutter/clutter-stage-view.c index 1580a8493..c24fab4f7 100644 --- a/clutter/clutter/clutter-stage-view.c +++ b/clutter/clutter/clutter-stage-view.c @@ -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,14 +684,14 @@ 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, - G_PARAM_READWRITE | - G_PARAM_CONSTRUCT_ONLY | - G_PARAM_STATIC_STRINGS); + 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); obj_props[PROP_SCALE] = g_param_spec_float ("scale", diff --git a/src/backends/native/meta-renderer-native.c b/src/backends/native/meta-renderer-native.c index 7b47174a0..43611d3e4 100644 --- a/src/backends/native/meta-renderer-native.c +++ b/src/backends/native/meta-renderer-native.c @@ -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);