diff --git a/clutter/clutter/clutter-stage-view.c b/clutter/clutter/clutter-stage-view.c index 91ced3b43..60c0d070c 100644 --- a/clutter/clutter/clutter-stage-view.c +++ b/clutter/clutter/clutter-stage-view.c @@ -40,7 +40,6 @@ enum PROP_STAGE, PROP_LAYOUT, PROP_FRAMEBUFFER, - PROP_OFFSCREEN, PROP_USE_SHADOWFB, PROP_COLOR_STATE, PROP_OUTPUT_COLOR_STATE, @@ -75,6 +74,7 @@ typedef struct _ClutterStageViewPrivate ClutterColorState *color_state; ClutterColorState *output_color_state; + guint ensure_offscreen_idle_id; CoglOffscreen *offscreen; CoglPipeline *offscreen_pipeline; @@ -140,6 +140,8 @@ clutter_stage_view_get_framebuffer (ClutterStageView *view) ClutterStageViewPrivate *priv = clutter_stage_view_get_instance_private (view); + g_warn_if_fail (priv->ensure_offscreen_idle_id == 0); + if (priv->offscreen) return COGL_FRAMEBUFFER (priv->offscreen); else if (priv->shadow.framebuffer) @@ -165,11 +167,19 @@ clutter_stage_view_get_onscreen (ClutterStageView *view) return priv->framebuffer; } -static CoglPipeline * -clutter_stage_view_create_offscreen_pipeline (CoglOffscreen *offscreen) +static void +ensure_stage_view_offscreen (ClutterStageView *view); + +static void +ensure_stage_view_offscreen_pipeline (ClutterStageView *view) { - CoglFramebuffer *framebuffer = COGL_FRAMEBUFFER (offscreen); - CoglPipeline *pipeline; + ClutterStageViewPrivate *priv = + clutter_stage_view_get_instance_private (view); + CoglFramebuffer *framebuffer = COGL_FRAMEBUFFER (priv->offscreen); + g_autoptr (CoglPipeline) pipeline = NULL; + + if (priv->offscreen_pipeline) + return; pipeline = cogl_pipeline_new (cogl_framebuffer_get_context (framebuffer)); cogl_pipeline_set_static_name (pipeline, "ClutterStageView (offscreen)"); @@ -178,56 +188,68 @@ clutter_stage_view_create_offscreen_pipeline (CoglOffscreen *offscreen) COGL_PIPELINE_FILTER_NEAREST, COGL_PIPELINE_FILTER_NEAREST); cogl_pipeline_set_layer_texture (pipeline, 0, - cogl_offscreen_get_texture (offscreen)); + cogl_offscreen_get_texture (priv->offscreen)); cogl_pipeline_set_layer_wrap_mode (pipeline, 0, COGL_PIPELINE_WRAP_MODE_CLAMP_TO_EDGE); - return pipeline; -} + if (priv->transform != MTK_MONITOR_TRANSFORM_NORMAL) + { + graphene_matrix_t matrix; -static void -setup_offscreen_transform (ClutterStageView *view, - CoglPipeline *pipeline) -{ - ClutterStageViewPrivate *priv = - clutter_stage_view_get_instance_private (view); - graphene_matrix_t matrix; - - if (priv->transform == MTK_MONITOR_TRANSFORM_NORMAL) - return; - - clutter_stage_view_get_offscreen_transformation_matrix (view, &matrix); - cogl_pipeline_set_layer_matrix (pipeline, 0, &matrix); -} - -static void -clutter_stage_view_ensure_offscreen_blit_pipeline (ClutterStageView *view) -{ - ClutterStageViewPrivate *priv = - clutter_stage_view_get_instance_private (view); - - g_assert (priv->offscreen != NULL); - - if (priv->offscreen_pipeline) - return; - - priv->offscreen_pipeline = - clutter_stage_view_create_offscreen_pipeline (priv->offscreen); - - setup_offscreen_transform (view, priv->offscreen_pipeline); + clutter_stage_view_get_offscreen_transformation_matrix (view, &matrix); + cogl_pipeline_set_layer_matrix (pipeline, 0, &matrix); + } clutter_color_state_add_pipeline_transform (priv->color_state, priv->output_color_state, - priv->offscreen_pipeline); + pipeline); + + g_set_object (&priv->offscreen_pipeline, g_steal_pointer (&pipeline)); } -void -clutter_stage_view_invalidate_offscreen_blit_pipeline (ClutterStageView *view) +static gboolean +on_ensure_offscreen_idle (gpointer data) +{ + ClutterStageView *view = CLUTTER_STAGE_VIEW (data); + ClutterStageViewPrivate *priv = + clutter_stage_view_get_instance_private (view); + + ensure_stage_view_offscreen (view); + ensure_stage_view_offscreen_pipeline (view); + + priv->ensure_offscreen_idle_id = 0; + return G_SOURCE_REMOVE; +} + +static void +clutter_stage_view_invalidate_offscreen (ClutterStageView *view) { ClutterStageViewPrivate *priv = clutter_stage_view_get_instance_private (view); + if (priv->frame_clock) + { + clutter_stage_view_add_redraw_clip (view, NULL); + clutter_stage_view_schedule_update (view); + } + + if (priv->transform == MTK_MONITOR_TRANSFORM_NORMAL && + clutter_color_state_equals (priv->color_state, priv->output_color_state)) + { + g_clear_object (&priv->offscreen_pipeline); + g_clear_object (&priv->offscreen); + g_clear_handle_id (&priv->ensure_offscreen_idle_id, g_source_remove); + return; + } + g_clear_object (&priv->offscreen_pipeline); + + if (priv->ensure_offscreen_idle_id != 0) + return; + + priv->ensure_offscreen_idle_id = g_idle_add_full (CLUTTER_PRIORITY_REDRAW - 1, + on_ensure_offscreen_idle, + view, NULL); } static void @@ -240,7 +262,7 @@ set_color_state (ClutterStageView *view, g_set_object (dest_color_state, color_state); - clutter_stage_view_invalidate_offscreen_blit_pipeline (view); + clutter_stage_view_invalidate_offscreen (view); } static void @@ -386,6 +408,91 @@ create_offscreen (ClutterStageView *view, return g_steal_pointer (&framebuffer); } +static CoglOffscreen * +create_offscreen_with_formats (ClutterStageView *view, + CoglPixelFormat *formats, + size_t n_formats, + int width, + int height, + GError **error) +{ + g_autoptr (GError) local_error = NULL; + size_t i; + + for (i = 0; i < n_formats; i++) + { + CoglOffscreen *offscreen; + + g_clear_error (&local_error); + + offscreen = create_offscreen (view, formats[i], width, height, &local_error); + if (offscreen) + return offscreen; + } + + g_propagate_error (error, g_steal_pointer (&local_error)); + return NULL; +} + +static void +ensure_stage_view_offscreen (ClutterStageView *view) +{ + ClutterStageViewPrivate *priv = + clutter_stage_view_get_instance_private (view); + ClutterEncodingRequiredFormat required_format; + CoglPixelFormat formats[10]; + size_t n_formats = 0; + int offscreen_width, offscreen_height; + int onscreen_width, onscreen_height; + g_autoptr (CoglOffscreen) offscreen = NULL; + g_autoptr (GError) local_error = NULL; + + if (priv->offscreen) + return; + + required_format = clutter_color_state_required_format (priv->color_state); + + if (required_format <= CLUTTER_ENCODING_REQUIRED_FORMAT_UINT8) + { + formats[n_formats++] = + cogl_framebuffer_get_internal_format (priv->framebuffer); + } + else + { + formats[n_formats++] = COGL_PIXEL_FORMAT_XRGB_FP_16161616; + formats[n_formats++] = COGL_PIXEL_FORMAT_XBGR_FP_16161616; + formats[n_formats++] = COGL_PIXEL_FORMAT_RGBA_FP_16161616_PRE; + formats[n_formats++] = COGL_PIXEL_FORMAT_BGRA_FP_16161616_PRE; + formats[n_formats++] = COGL_PIXEL_FORMAT_ARGB_FP_16161616_PRE; + formats[n_formats++] = COGL_PIXEL_FORMAT_ABGR_FP_16161616_PRE; + } + + onscreen_width = cogl_framebuffer_get_width (priv->framebuffer); + onscreen_height = cogl_framebuffer_get_height (priv->framebuffer); + + if (mtk_monitor_transform_is_rotated (priv->transform)) + { + offscreen_width = onscreen_height; + offscreen_height = onscreen_width; + } + else + { + offscreen_width = onscreen_width; + offscreen_height = onscreen_height; + } + + offscreen = create_offscreen_with_formats (view, + formats, + n_formats, + offscreen_width, + offscreen_height, + &local_error); + if (!offscreen) + g_error ("Failed to allocate back buffer texture: %s", local_error->message); + + g_set_object (&priv->offscreen, g_steal_pointer (&offscreen)); +} + static void init_shadowfb (ClutterStageView *view) { @@ -419,10 +526,10 @@ clutter_stage_view_after_paint (ClutterStageView *view, ClutterStageViewPrivate *priv = clutter_stage_view_get_instance_private (view); + g_warn_if_fail (priv->ensure_offscreen_idle_id == 0); + if (priv->offscreen) { - clutter_stage_view_ensure_offscreen_blit_pipeline (view); - if (priv->shadow.framebuffer) { CoglFramebuffer *shadowfb = @@ -522,6 +629,8 @@ clutter_stage_view_foreach_front_buffer (ClutterStageView *view, ClutterStageViewPrivate *priv = clutter_stage_view_get_instance_private (view); + g_warn_if_fail (priv->ensure_offscreen_idle_id == 0); + if (priv->offscreen) { callback (COGL_FRAMEBUFFER (priv->offscreen), user_data); @@ -1049,7 +1158,7 @@ clutter_stage_view_set_transform (ClutterStageView *view, priv->transform = transform; - clutter_stage_view_invalidate_offscreen_blit_pipeline (CLUTTER_STAGE_VIEW (view)); + clutter_stage_view_invalidate_offscreen (CLUTTER_STAGE_VIEW (view)); } MtkMonitorTransform @@ -1085,9 +1194,6 @@ clutter_stage_view_get_property (GObject *object, case PROP_FRAMEBUFFER: g_value_set_object (value, priv->framebuffer); break; - case PROP_OFFSCREEN: - g_value_set_object (value, priv->offscreen); - break; case PROP_USE_SHADOWFB: g_value_set_boolean (value, priv->use_shadowfb); break; @@ -1139,9 +1245,6 @@ clutter_stage_view_set_property (GObject *object, case PROP_FRAMEBUFFER: clutter_stage_view_set_framebuffer (view, g_value_get_object (value)); break; - case PROP_OFFSCREEN: - priv->offscreen = g_value_dup_object (value); - break; case PROP_USE_SHADOWFB: priv->use_shadowfb = g_value_get_boolean (value); break; @@ -1212,6 +1315,7 @@ clutter_stage_view_dispose (GObject *object) g_clear_pointer (&priv->redraw_clip, mtk_region_unref); g_clear_pointer (&priv->accumulated_redraw_clip, mtk_region_unref); g_clear_pointer (&priv->frame_clock, clutter_frame_clock_destroy); + g_clear_handle_id (&priv->ensure_offscreen_idle_id, g_source_remove); G_OBJECT_CLASS (clutter_stage_view_parent_class)->dispose (object); } @@ -1279,13 +1383,6 @@ clutter_stage_view_class_init (ClutterStageViewClass *klass) G_PARAM_CONSTRUCT | G_PARAM_STATIC_STRINGS); - obj_props[PROP_OFFSCREEN] = - g_param_spec_object ("offscreen", NULL, NULL, - COGL_TYPE_OFFSCREEN, - G_PARAM_READWRITE | - G_PARAM_CONSTRUCT_ONLY | - G_PARAM_STATIC_STRINGS); - obj_props[PROP_USE_SHADOWFB] = g_param_spec_boolean ("use-shadowfb", NULL, NULL, FALSE, diff --git a/clutter/clutter/clutter-stage-view.h b/clutter/clutter/clutter-stage-view.h index 280cc9252..19d1a254b 100644 --- a/clutter/clutter/clutter-stage-view.h +++ b/clutter/clutter/clutter-stage-view.h @@ -55,8 +55,6 @@ CLUTTER_EXPORT CoglFramebuffer *clutter_stage_view_get_framebuffer (ClutterStageView *view); CLUTTER_EXPORT CoglFramebuffer *clutter_stage_view_get_onscreen (ClutterStageView *view); -CLUTTER_EXPORT -void clutter_stage_view_invalidate_offscreen_blit_pipeline (ClutterStageView *view); CLUTTER_EXPORT float clutter_stage_view_get_scale (ClutterStageView *view); diff --git a/src/backends/native/meta-renderer-native.c b/src/backends/native/meta-renderer-native.c index 943277456..9cc263fce 100644 --- a/src/backends/native/meta-renderer-native.c +++ b/src/backends/native/meta-renderer-native.c @@ -1255,36 +1255,6 @@ meta_renderer_native_create_offscreen (MetaRendererNative *renderer_native, return fb; } -static CoglOffscreen * -create_offscreen_with_formats (MetaRendererNative *renderer_native, - CoglPixelFormat *formats, - size_t n_formats, - int width, - int height, - GError **error) -{ - g_autoptr (GError) local_error = NULL; - size_t i; - - for (i = 0; i < n_formats; i++) - { - CoglOffscreen *offscreen; - - g_clear_error (&local_error); - - offscreen = meta_renderer_native_create_offscreen (renderer_native, - formats[i], - width, - height, - &local_error); - if (offscreen) - return offscreen; - } - - g_propagate_error (error, g_steal_pointer (&local_error)); - return NULL; -} - static const CoglWinsysVtable * get_native_cogl_winsys_vtable (CoglRenderer *cogl_renderer) { @@ -1389,7 +1359,6 @@ meta_renderer_native_create_view (MetaRenderer *renderer, g_autoptr (ClutterColorState) blending_color_state = NULL; MtkMonitorTransform view_transform; g_autoptr (CoglFramebuffer) framebuffer = NULL; - g_autoptr (CoglOffscreen) offscreen = NULL; gboolean use_shadowfb; float scale; int onscreen_width; @@ -1491,60 +1460,6 @@ meta_renderer_native_create_view (MetaRenderer *renderer, output, crtc); - if (view_transform != MTK_MONITOR_TRANSFORM_NORMAL || - !clutter_color_state_equals (color_state, blending_color_state)) - { - int offscreen_width; - int offscreen_height; - CoglPixelFormat formats[10]; - size_t n_formats = 0; - CoglPixelFormat format; - ClutterEncodingRequiredFormat required_format = - clutter_color_state_required_format (blending_color_state); - - if (required_format <= CLUTTER_ENCODING_REQUIRED_FORMAT_UINT8) - { - formats[n_formats++] = cogl_framebuffer_get_internal_format (framebuffer); - } - else - { - formats[n_formats++] = COGL_PIXEL_FORMAT_XRGB_FP_16161616; - formats[n_formats++] = COGL_PIXEL_FORMAT_XBGR_FP_16161616; - formats[n_formats++] = COGL_PIXEL_FORMAT_RGBA_FP_16161616_PRE; - formats[n_formats++] = COGL_PIXEL_FORMAT_BGRA_FP_16161616_PRE; - formats[n_formats++] = COGL_PIXEL_FORMAT_ARGB_FP_16161616_PRE; - formats[n_formats++] = COGL_PIXEL_FORMAT_ABGR_FP_16161616_PRE; - } - - if (mtk_monitor_transform_is_rotated (view_transform)) - { - offscreen_width = onscreen_height; - offscreen_height = onscreen_width; - } - else - { - offscreen_width = onscreen_width; - offscreen_height = onscreen_height; - } - - offscreen = create_offscreen_with_formats (renderer_native, - formats, - n_formats, - offscreen_width, - offscreen_height, - &local_error); - if (!offscreen) - g_error ("Failed to allocate back buffer texture: %s", local_error->message); - - format = - cogl_framebuffer_get_internal_format (COGL_FRAMEBUFFER (offscreen)); - meta_topic (META_DEBUG_RENDER, - "Using an additional intermediate %s offscreen (%dx%d) for %s", - cogl_pixel_format_to_string (format), - offscreen_width, offscreen_height, - meta_output_get_name (output)); - } - if (meta_backend_is_stage_views_scaled (backend)) scale = meta_logical_monitor_get_scale (logical_monitor); else @@ -1553,6 +1468,7 @@ meta_renderer_native_create_view (MetaRenderer *renderer, mtk_rectangle_from_graphene_rect (&crtc_config->layout, MTK_ROUNDING_STRATEGY_ROUND, &view_layout); + view_native = g_object_new (META_TYPE_RENDERER_VIEW_NATIVE, "name", meta_output_get_name (output), "stage", meta_backend_get_stage (backend), @@ -1560,7 +1476,6 @@ meta_renderer_native_create_view (MetaRenderer *renderer, "crtc", crtc, "scale", scale, "framebuffer", framebuffer, - "offscreen", offscreen, "color-state", blending_color_state, "output-color-state", color_state, "use-shadowfb", use_shadowfb,