diff --git a/clutter/clutter/clutter-stage-view-private.h b/clutter/clutter/clutter-stage-view-private.h index 31ac7e144eadddebee386b0e380a46f12e2dacd7..b143912f5811cb4fb31ce8aadfcd27adff737e99 100644 --- a/clutter/clutter/clutter-stage-view-private.h +++ b/clutter/clutter/clutter-stage-view-private.h @@ -54,6 +54,9 @@ gboolean clutter_stage_view_has_full_redraw_clip (ClutterStageView *view); gboolean clutter_stage_view_has_redraw_clip (ClutterStageView *view); +CLUTTER_EXPORT +const MtkRegion * clutter_stage_view_peek_redraw_clip (ClutterStageView *view); + CLUTTER_EXPORT MtkRegion * clutter_stage_view_take_accumulated_redraw_clip (ClutterStageView *view); diff --git a/clutter/clutter/clutter-stage-view.c b/clutter/clutter/clutter-stage-view.c index 88cffec851d62e084b851b5d6b692bb666eeef72..a1940d0df2c6518d78143f91fad9e96cd1008e3b 100644 --- a/clutter/clutter/clutter-stage-view.c +++ b/clutter/clutter/clutter-stage-view.c @@ -857,6 +857,15 @@ clutter_stage_view_has_full_redraw_clip (ClutterStageView *view) return priv->has_redraw_clip && !priv->redraw_clip; } +const MtkRegion * +clutter_stage_view_peek_redraw_clip (ClutterStageView *view) +{ + ClutterStageViewPrivate *priv = + clutter_stage_view_get_instance_private (view); + + return priv->redraw_clip; +} + MtkRegion * clutter_stage_view_take_accumulated_redraw_clip (ClutterStageView *view) { diff --git a/cogl/cogl/cogl-scanout.c b/cogl/cogl/cogl-scanout.c index f9b44ff85290c75e6c203ad977685d5da17b8077..fd2597f82c196f357dffb127207136af1fae4831 100644 --- a/cogl/cogl/cogl-scanout.c +++ b/cogl/cogl/cogl-scanout.c @@ -45,6 +45,7 @@ struct _CoglScanout GObject parent; CoglScanoutBuffer *scanout_buffer; + uint32_t plane_id; gboolean has_src_rect; graphene_rect_t src_rect; @@ -148,6 +149,19 @@ cogl_scanout_get_dst_rect (CoglScanout *scanout, *dst_rect = scanout->dst_rect; } +uint32_t +cogl_scanout_get_plane_id (CoglScanout *scanout) +{ + return scanout->plane_id; +} + +void +cogl_scanout_set_plane_id (CoglScanout *scanout, + uint32_t plane_id) +{ + scanout->plane_id = plane_id; +} + static void cogl_scanout_finalize (GObject *object) { diff --git a/cogl/cogl/cogl-scanout.h b/cogl/cogl/cogl-scanout.h index 5b64bfdd6f2acf962206c410aac0b7e70ac11b96..41f57a762379cb29c8027e090812ae7ce2a50378 100644 --- a/cogl/cogl/cogl-scanout.h +++ b/cogl/cogl/cogl-scanout.h @@ -91,3 +91,10 @@ void cogl_scanout_set_src_rect (CoglScanout *scanout, COGL_EXPORT void cogl_scanout_get_dst_rect (CoglScanout *scanout, MtkRectangle *dst_rect); + +COGL_EXPORT +uint32_t cogl_scanout_get_plane_id (CoglScanout *scanout); + +COGL_EXPORT +void cogl_scanout_set_plane_id (CoglScanout *scanout, + uint32_t plane_id); diff --git a/src/backends/meta-stage-impl.c b/src/backends/meta-stage-impl.c index e6f3b18a0a4515bb31e3219ec5029fc821fd6440..8bff76a00d533dfcec912bf073b643aba302c9fe 100644 --- a/src/backends/meta-stage-impl.c +++ b/src/backends/meta-stage-impl.c @@ -782,22 +782,53 @@ meta_stage_impl_redraw_view (ClutterStageWindow *stage_window, scanout = clutter_stage_view_take_scanout (stage_view); if (scanout) { - g_autoptr (GError) error = NULL; + const MtkRegion *redraw_clip; + MtkRectangle redraw_clip_rect; + MtkRectangle scanout_rect; - if (meta_stage_impl_scanout_view (stage_impl, - stage_view, - scanout, - frame, - &error)) + redraw_clip = clutter_stage_view_peek_redraw_clip (stage_view); + if (redraw_clip) + redraw_clip_rect = mtk_region_get_extents (redraw_clip); + else + clutter_stage_view_get_layout (stage_view, &redraw_clip_rect); + cogl_scanout_get_dst_rect (scanout, &scanout_rect); + + if (mtk_rectangle_contains_rect (&scanout_rect, &redraw_clip_rect)) { - clutter_stage_view_accumulate_redraw_clip (stage_view); - return; - } + g_autoptr (GError) error = NULL; - if (!g_error_matches (error, - COGL_SCANOUT_ERROR, - COGL_SCANOUT_ERROR_INHIBITED)) - g_warning ("Failed to scan out client buffer: %s", error->message); + if (meta_stage_impl_scanout_view (stage_impl, + stage_view, + scanout, + frame, + &error)) + { + clutter_stage_view_accumulate_redraw_clip (stage_view); + return; + } + + if (g_error_matches (error, + COGL_SCANOUT_ERROR, + COGL_SCANOUT_ERROR_INHIBITED)) + { + meta_topic (META_DEBUG_RENDER, + "Skipping scanout: inhibited"); + } + else + { + g_warning ("Failed to scan out client buffer: %s", error->message); + } + } + else + { + meta_topic (META_DEBUG_RENDER, + "Skipping scanout: redraw clip (%d,%d,%d,%d) exceeds " + "scanout area (%d,%d,%d,%d)", + redraw_clip_rect.x, redraw_clip_rect.y, + redraw_clip_rect.width, redraw_clip_rect.height, + scanout_rect.x, scanout_rect.y, + scanout_rect.width, scanout_rect.height); + } } meta_stage_impl_redraw_view_primary (stage_impl, stage_view, frame); diff --git a/src/backends/native/meta-crtc-kms.h b/src/backends/native/meta-crtc-kms.h index 3829825346296ff33821d6664930349777aa1f95..7e125a9eec9c23e17d7d4782bd2acf6ea70f0396 100644 --- a/src/backends/native/meta-crtc-kms.h +++ b/src/backends/native/meta-crtc-kms.h @@ -39,6 +39,22 @@ G_DECLARE_FINAL_TYPE (MetaCrtcKms, meta_crtc_kms, MetaKmsPlane * meta_crtc_kms_get_assigned_primary_plane (MetaCrtcKms *crtc_kms); +MetaKmsPlaneAssignment * meta_crtc_kms_assign_plane_by_id (MetaCrtcKms *crtc_kms, + uint32_t plane_id, + MetaDrmBuffer *buffer, + MetaKmsUpdate *kms_update, + MetaKmsAssignPlaneFlag flags, + const MtkRectangle *src_rect, + const MtkRectangle *dst_rect); + +MetaKmsPlaneAssignment * meta_crtc_kms_assign_plane (MetaCrtcKms *crtc_kms, + MetaKmsPlane *kms_plane, + MetaDrmBuffer *buffer, + MetaKmsUpdate *kms_update, + MetaKmsAssignPlaneFlag flags, + const MtkRectangle *src_rect, + const MtkRectangle *dst_rect); + MetaKmsPlane * meta_crtc_kms_get_assigned_cursor_plane (MetaCrtcKms *crtc_kms); void meta_crtc_kms_assign_planes (MetaCrtcKms *crtc_kms, diff --git a/src/backends/native/meta-drm-buffer.c b/src/backends/native/meta-drm-buffer.c index 1c83984c94f655a05f5552075c4957391a4658bc..9c896aeb897db0279b07755072f4907754c3d77e 100644 --- a/src/backends/native/meta-drm-buffer.c +++ b/src/backends/native/meta-drm-buffer.c @@ -53,6 +53,9 @@ typedef struct _MetaDrmBufferPrivate uint32_t fb_id; uint32_t handle; + + MtkRectangle src_rect; + MtkRectangle dst_rect; } MetaDrmBufferPrivate; G_DEFINE_ABSTRACT_TYPE_WITH_PRIVATE (MetaDrmBuffer, meta_drm_buffer, diff --git a/src/backends/native/meta-onscreen-native.c b/src/backends/native/meta-onscreen-native.c index 3e4d8c3dd706e1f218c30ef28bc6e7a778b598eb..06600400ceda88108a2e11a3ae8b14024e0e46dd 100644 --- a/src/backends/native/meta-onscreen-native.c +++ b/src/backends/native/meta-onscreen-native.c @@ -548,17 +548,17 @@ apply_color_range (MetaKmsPlaneAssignment *kms_plane_assignment, } static MetaKmsPlaneAssignment * -assign_primary_plane (MetaCrtcKms *crtc_kms, - MetaDrmBuffer *buffer, - MetaKmsUpdate *kms_update, - MetaKmsAssignPlaneFlag flags, - const graphene_rect_t *src_rect, - const MtkRectangle *dst_rect) +assign_plane (MetaCrtcKms *crtc_kms, + MetaKmsPlane *kms_plane, + MetaDrmBuffer *buffer, + MetaKmsUpdate *kms_update, + MetaKmsAssignPlaneFlag flags, + const graphene_rect_t *src_rect, + const MtkRectangle *dst_rect) { MetaCrtc *crtc = META_CRTC (crtc_kms); MetaFixed16Rectangle src_rect_fixed16; MetaKmsCrtc *kms_crtc; - MetaKmsPlane *primary_kms_plane; MetaKmsPlaneAssignment *plane_assignment; src_rect_fixed16 = (MetaFixed16Rectangle) { @@ -577,21 +577,78 @@ assign_primary_plane (MetaCrtcKms *crtc_kms, dst_rect->x, dst_rect->y, dst_rect->width, dst_rect->height); kms_crtc = meta_crtc_kms_get_kms_crtc (crtc_kms); - primary_kms_plane = meta_crtc_kms_get_assigned_primary_plane (crtc_kms); plane_assignment = meta_kms_update_assign_plane (kms_update, kms_crtc, - primary_kms_plane, + kms_plane, buffer, src_rect_fixed16, *dst_rect, flags); - apply_transform (crtc_kms, plane_assignment, primary_kms_plane); - apply_color_encoding (plane_assignment, primary_kms_plane); - apply_color_range (plane_assignment, primary_kms_plane); + apply_transform (crtc_kms, plane_assignment, kms_plane); + apply_color_encoding (plane_assignment, kms_plane); + apply_color_range (plane_assignment, kms_plane); return plane_assignment; } +static MetaKmsPlaneAssignment * +assign_primary_plane (MetaCrtcKms *crtc_kms, + MetaDrmBuffer *buffer, + MetaKmsUpdate *kms_update, + MetaKmsAssignPlaneFlag flags, + const graphene_rect_t *src_rect, + const MtkRectangle *dst_rect) +{ + MetaKmsPlane *primary_kms_plane; + + primary_kms_plane = meta_crtc_kms_get_assigned_primary_plane (crtc_kms); + + return assign_plane (crtc_kms, + primary_kms_plane, + buffer, + kms_update, + flags, + src_rect, + dst_rect); +} + +static MetaKmsPlaneAssignment * +assign_plane_by_id (MetaCrtcKms *crtc_kms, + uint32_t plane_id, + MetaDrmBuffer *buffer, + MetaKmsUpdate *kms_update, + MetaKmsAssignPlaneFlag flags, + const graphene_rect_t *src_rect, + const MtkRectangle *dst_rect) +{ + MetaKmsCrtc *kms_crtc; + MetaKmsDevice *kms_device; + MetaKmsPlane *plane = NULL; + GList *l; + + kms_crtc = meta_crtc_kms_get_kms_crtc (crtc_kms); + kms_device = meta_kms_crtc_get_device (kms_crtc); + + for (l = meta_kms_device_get_planes (kms_device); l; l = l->next) + { + MetaKmsPlane *current_plane = l->data; + + if (meta_kms_plane_get_id (current_plane) == plane_id) + plane = current_plane; + } + + if (!plane) + return NULL; + + return assign_plane (crtc_kms, + plane, + buffer, + kms_update, + flags, + src_rect, + dst_rect); +} + static gboolean meta_onscreen_native_flip_crtc (CoglOnscreen *onscreen, ClutterFrame *frame, @@ -638,10 +695,56 @@ meta_onscreen_native_flip_crtc (CoglOnscreen *onscreen, scanout = meta_frame_native_get_scanout (frame_native); + /* Unset the previously used overlay plane if required */ + if (onscreen_native->presented_frame) + { + MetaFrameNative* frame_native_presented; + CoglScanout *scanout_presented; + + frame_native_presented = + meta_frame_native_from_frame (onscreen_native->presented_frame); + scanout_presented = meta_frame_native_get_scanout (frame_native_presented); + + if (scanout_presented) + { + uint32_t plane_id_presented; + uint32_t plane_id_next = 0; + + plane_id_presented = cogl_scanout_get_plane_id (scanout_presented); + + if (scanout) + plane_id_next = cogl_scanout_get_plane_id (scanout); + + if (plane_id_presented != plane_id_next) + { + plane_assignment = assign_plane_by_id (crtc_kms, + plane_id_presented, + NULL, + kms_update, + 0, + &src_rect, + &dst_rect); + } + } + } + if (scanout) { + uint32_t plane_id; + + plane_id = cogl_scanout_get_plane_id (scanout); + cogl_scanout_get_src_rect (scanout, &src_rect); cogl_scanout_get_dst_rect (scanout, &dst_rect); + + plane_assignment = assign_plane_by_id (crtc_kms, + plane_id, + buffer, + kms_update, + flags, + &src_rect, + &dst_rect); + g_assert (plane_assignment); } else { @@ -657,17 +760,17 @@ meta_onscreen_native_flip_crtc (CoglOnscreen *onscreen, .width = meta_drm_buffer_get_width (buffer), .height = meta_drm_buffer_get_height (buffer) }; - } - plane_assignment = assign_primary_plane (crtc_kms, - buffer, - kms_update, - flags, - &src_rect, - &dst_rect); + plane_assignment = assign_primary_plane (crtc_kms, + buffer, + kms_update, + flags, + &src_rect, + &dst_rect); - if (region && !mtk_region_is_empty (region)) - meta_kms_plane_assignment_set_fb_damage (plane_assignment, region); + if (region && !mtk_region_is_empty (region)) + meta_kms_plane_assignment_set_fb_damage (plane_assignment, region); + } break; case META_RENDERER_NATIVE_MODE_SURFACELESS: g_assert_not_reached (); @@ -1926,38 +2029,91 @@ meta_onscreen_native_is_buffer_scanout_compatible (CoglOnscreen *onscreen, MetaKmsUpdate *test_update; MetaDrmBuffer *buffer; g_autoptr (MetaKmsFeedback) kms_feedback = NULL; - MetaKmsFeedbackResult result; + MetaKmsFeedbackResult result = META_KMS_FEEDBACK_FAILED; graphene_rect_t src_rect; MtkRectangle dst_rect; + MetaKmsPlane *kms_plane; + GList *l; gpu_kms = META_GPU_KMS (meta_crtc_get_gpu (crtc)); kms_device = meta_gpu_kms_get_kms_device (gpu_kms); kms_crtc = meta_crtc_kms_get_kms_crtc (crtc_kms); - test_update = meta_kms_update_new (kms_device); - + buffer = META_DRM_BUFFER (cogl_scanout_get_buffer (scanout)); cogl_scanout_get_src_rect (scanout, &src_rect); cogl_scanout_get_dst_rect (scanout, &dst_rect); - buffer = META_DRM_BUFFER (cogl_scanout_get_buffer (scanout)); - assign_primary_plane (crtc_kms, - buffer, - test_update, - META_KMS_ASSIGN_PLANE_FLAG_DISABLE_IMPLICIT_SYNC, - &src_rect, - &dst_rect); + for (l = meta_kms_device_get_planes (kms_device); l; l = l->next) + { + kms_plane = l->data; + const GError *error; - meta_topic (META_DEBUG_KMS, - "Posting direct scanout test update for CRTC %u (%s) synchronously", - meta_kms_crtc_get_id (kms_crtc), - meta_kms_device_get_path (kms_device)); + if (meta_kms_plane_get_plane_type (kms_plane) != META_KMS_PLANE_TYPE_OVERLAY) + continue; + + if (!meta_kms_plane_is_usable_with (kms_plane, kms_crtc)) + continue; + + test_update = meta_kms_update_new (kms_device); + assign_plane (crtc_kms, + kms_plane, + buffer, + test_update, + META_KMS_ASSIGN_PLANE_FLAG_DISABLE_IMPLICIT_SYNC, + &src_rect, + &dst_rect); + kms_feedback = + meta_kms_device_process_update_sync (kms_device, test_update, + META_KMS_UPDATE_FLAG_TEST_ONLY); + + result = meta_kms_feedback_get_result (kms_feedback); + if (result == META_KMS_FEEDBACK_PASSED) + { + cogl_scanout_set_plane_id (scanout, + meta_kms_plane_get_id (kms_plane)); + return TRUE; + } + + error = meta_kms_feedback_get_error (kms_feedback); + meta_topic (META_DEBUG_KMS, + "Test update for overlay plane %d failed: %s", + meta_kms_plane_get_id (kms_plane), + error ? error->message : NULL); + } + + /*if (FALSE) + { + const GError *error; + + kms_plane = meta_kms_device_get_primary_plane_for (kms_device, kms_crtc); + + test_update = meta_kms_update_new (kms_device); + assign_primary_plane (crtc_kms, + kms_plane, + buffer, + test_update, + META_KMS_ASSIGN_PLANE_FLAG_DISABLE_IMPLICIT_SYNC, + &src_rect, + &dst_rect); + kms_feedback = + meta_kms_device_process_update_sync (kms_device, test_update, + META_KMS_UPDATE_FLAG_TEST_ONLY); - kms_feedback = - meta_kms_device_process_update_sync (kms_device, test_update, - META_KMS_UPDATE_FLAG_TEST_ONLY); + result = meta_kms_feedback_get_result (kms_feedback); + if (result == META_KMS_FEEDBACK_PASSED) + { + cogl_scanout_set_plane_id (scanout, + meta_kms_plane_get_id (kms_plane)); + return TRUE; + } - result = meta_kms_feedback_get_result (kms_feedback); - return result == META_KMS_FEEDBACK_PASSED; + error = meta_kms_feedback_get_error (kms_feedback); + meta_topic (META_DEBUG_KMS, + "Test update for primary plane failed: %s", + error ? error->message : NULL); + }*/ + + return FALSE; } static void diff --git a/src/compositor/meta-compositor-view-native.c b/src/compositor/meta-compositor-view-native.c index 9c52182cac5ed7022187e1517e51711768939aa6..9d87b151e23daa219c4bd4f5cc5f1bc17a7815ec 100644 --- a/src/compositor/meta-compositor-view-native.c +++ b/src/compositor/meta-compositor-view-native.c @@ -162,14 +162,10 @@ find_candidate (MetaCompositorView *compositor_view, return NULL; } - if (!G_APPROX_VALUE (actor_box.x1, view_rect.x, - CLUTTER_COORDINATE_EPSILON) || - !G_APPROX_VALUE (actor_box.y1, view_rect.y, - CLUTTER_COORDINATE_EPSILON) || - !G_APPROX_VALUE (actor_box.x2, view_rect.x + view_rect.width, - CLUTTER_COORDINATE_EPSILON) || - !G_APPROX_VALUE (actor_box.y2, view_rect.y + view_rect.height, - CLUTTER_COORDINATE_EPSILON)) + if (actor_box.x1 < view_rect.x || + actor_box.y1 < view_rect.y || + actor_box.x2 > view_rect.x + view_rect.width || + actor_box.y2 > view_rect.y + view_rect.height) { meta_topic (META_DEBUG_RENDER, "No %s candidate: paint-box (%f,%f,%f,%f) does " diff --git a/src/compositor/meta-window-actor-wayland.c b/src/compositor/meta-window-actor-wayland.c index 540975a6a3e63d65abbc3d7a8766e9c172d3b745..9eea255dff7c121e4fe07e751e0bab1ede6d3f06 100644 --- a/src/compositor/meta-window-actor-wayland.c +++ b/src/compositor/meta-window-actor-wayland.c @@ -352,10 +352,6 @@ meta_window_actor_wayland_get_scanout_candidate (MetaWindowActor *actor) ClutterActor *child_actor; ClutterActorIter iter; MetaSurfaceActor *topmost_surface_actor = NULL; - int n_visible_surface_actors = 0; - MetaWindow *window; - ClutterActorBox window_box; - ClutterActorBox surface_box; if (clutter_actor_get_last_child (CLUTTER_ACTOR (self)) != surface_container) { @@ -377,66 +373,13 @@ meta_window_actor_wayland_get_scanout_candidate (MetaWindowActor *actor) continue; topmost_surface_actor = surface_actor; - n_visible_surface_actors++; } if (!topmost_surface_actor) - { - meta_topic (META_DEBUG_RENDER, - "No surface-actor for window-actor"); - return NULL; - } - - window = meta_window_actor_get_meta_window (actor); - if (meta_window_is_fullscreen (window) && n_visible_surface_actors == 1) - return topmost_surface_actor; - - if (meta_window_is_fullscreen (window) && n_visible_surface_actors == 2) - { - MetaSurfaceActorWayland *bg_surface_actor = NULL; - MetaWaylandSurface *bg_surface; - MetaWaylandBuffer *buffer; - MetaWaylandSinglePixelBuffer *sp_buffer; - - clutter_actor_iter_init (&iter, surface_container); - while (clutter_actor_iter_next (&iter, &child_actor)) - { - MetaSurfaceActor *surface_actor; - - if (!clutter_actor_is_mapped (child_actor)) - continue; - - surface_actor = META_SURFACE_ACTOR (child_actor); - if (meta_surface_actor_is_obscured (surface_actor)) - continue; - - bg_surface_actor = META_SURFACE_ACTOR_WAYLAND (surface_actor); - break; - } - g_assert (bg_surface_actor); - - bg_surface = meta_surface_actor_wayland_get_surface (bg_surface_actor); - buffer = meta_wayland_surface_get_buffer (bg_surface); - - sp_buffer = buffer->single_pixel.single_pixel_buffer; - if (sp_buffer && - meta_wayland_single_pixel_buffer_is_opaque_black (sp_buffer)) - return topmost_surface_actor; - } + meta_topic (META_DEBUG_RENDER, + "No surface-actor for window-actor"); - if (meta_surface_actor_is_opaque (topmost_surface_actor) && - clutter_actor_get_paint_box (CLUTTER_ACTOR (actor), &window_box) && - clutter_actor_get_paint_box (CLUTTER_ACTOR (topmost_surface_actor), - &surface_box) && - G_APPROX_VALUE (window_box.x1, surface_box.x1, CLUTTER_COORDINATE_EPSILON) && - G_APPROX_VALUE (window_box.y1, surface_box.y1, CLUTTER_COORDINATE_EPSILON) && - G_APPROX_VALUE (window_box.x2, surface_box.x2, CLUTTER_COORDINATE_EPSILON) && - G_APPROX_VALUE (window_box.y2, surface_box.y2, CLUTTER_COORDINATE_EPSILON)) - return topmost_surface_actor; - - meta_topic (META_DEBUG_RENDER, - "Could not find suitable scanout candidate for window-actor"); - return NULL; + return topmost_surface_actor; } static void diff --git a/src/wayland/meta-wayland-dma-buf.c b/src/wayland/meta-wayland-dma-buf.c index 08e37dfd599a49304db2bcb245ca8228656e3802..e2c645aa52caefbbea0a655c97fae0743f886c86 100644 --- a/src/wayland/meta-wayland-dma-buf.c +++ b/src/wayland/meta-wayland-dma-buf.c @@ -691,10 +691,10 @@ meta_wayland_dma_buf_try_acquire_scanout (MetaWaylandBuffer *buffer, format_info = meta_format_info_from_drm_format (dma_buf->drm_format); g_assert (format_info); - if (format_info->opaque_substitute != DRM_FORMAT_INVALID && + if (FALSE /*format_info->opaque_substitute != DRM_FORMAT_INVALID && crtc_supports_modifier (crtc_kms, format_info->opaque_substitute, - dma_buf->drm_modifier)) + dma_buf->drm_modifier)*/) { drm_format = format_info->opaque_substitute; }