drm/xe/display: Re-use display vmas when possible
authorMaarten Lankhorst <dev@lankhorst.se>
Fri, 6 Dec 2024 18:20:32 +0000 (19:20 +0100)
committerMaarten Lankhorst <dev@lankhorst.se>
Tue, 21 Jan 2025 08:47:57 +0000 (09:47 +0100)
i915 has this really nice, infrastructure where everything becomes
complicated, GGTT needs eviction, etc..

Lets not do that, and make the dumbest possible interface instead.
Try to retrieve the VMA from old_plane_state, or intel_fbdev if kernel
fb.

Link: https://patchwork.freedesktop.org/patch/msgid/20241206182032.196307-1-dev@lankhorst.se
Signed-off-by: Maarten Lankhorst <dev@lankhorst.se>
Reviewed-by: Animesh Manna <animesh.manna@intel.com>
Tested-by: Jani Saarinen <jani.saarinen@intel.com>
drivers/gpu/drm/i915/display/intel_atomic_plane.c
drivers/gpu/drm/i915/display/intel_cursor.c
drivers/gpu/drm/i915/display/intel_fb_pin.c
drivers/gpu/drm/i915/display/intel_fb_pin.h
drivers/gpu/drm/i915/display/intel_fbdev.c
drivers/gpu/drm/i915/display/intel_fbdev.h
drivers/gpu/drm/xe/compat-i915-headers/i915_vma.h
drivers/gpu/drm/xe/display/xe_fb_pin.c

index 5e0e074968671c0a11a072d98f6f77fc41326add..c558143f4f8244535cf459c5c3990c0d0457366d 100644 (file)
@@ -1135,7 +1135,7 @@ intel_prepare_plane_fb(struct drm_plane *_plane,
        if (!obj)
                return 0;
 
-       ret = intel_plane_pin_fb(new_plane_state);
+       ret = intel_plane_pin_fb(new_plane_state, old_plane_state);
        if (ret)
                return ret;
 
index 57cf8f46a4589f981c530f8c0cce80ab1f5884dd..ae7243ad6e0ca29ad6f9f3e0ee942cbc3ee287d7 100644 (file)
@@ -865,7 +865,7 @@ intel_legacy_cursor_update(struct drm_plane *_plane,
        if (ret)
                goto out_free;
 
-       ret = intel_plane_pin_fb(new_plane_state);
+       ret = intel_plane_pin_fb(new_plane_state, old_plane_state);
        if (ret)
                goto out_free;
 
index d3a86f9c6bc86b89a3f72c7ea927850e07663247..dd3ac7f98dfcc570852c03132d460c16da5035d7 100644 (file)
@@ -252,7 +252,8 @@ intel_plane_fb_min_phys_alignment(const struct intel_plane_state *plane_state)
        return plane->min_alignment(plane, fb, 0);
 }
 
-int intel_plane_pin_fb(struct intel_plane_state *plane_state)
+int intel_plane_pin_fb(struct intel_plane_state *plane_state,
+                      const struct intel_plane_state *old_plane_state)
 {
        struct intel_plane *plane = to_intel_plane(plane_state->uapi.plane);
        const struct intel_framebuffer *fb =
index ac0319b53af0883b231bf0ee1081a64d02c012e5..0fc6d90446381123043ef14164f2d45df4b8d9ce 100644 (file)
@@ -23,7 +23,8 @@ intel_fb_pin_to_ggtt(const struct drm_framebuffer *fb,
 
 void intel_fb_unpin_vma(struct i915_vma *vma, unsigned long flags);
 
-int intel_plane_pin_fb(struct intel_plane_state *plane_state);
+int intel_plane_pin_fb(struct intel_plane_state *new_plane_state,
+                      const struct intel_plane_state *old_plane_state);
 void intel_plane_unpin_fb(struct intel_plane_state *old_plane_state);
 
 #endif
index 00852ff5b24701b54619d12be73a6213f5442934..6c08081333976a588ed7c09ae5e44987e90207c0 100644 (file)
@@ -695,3 +695,8 @@ struct intel_framebuffer *intel_fbdev_framebuffer(struct intel_fbdev *fbdev)
 
        return to_intel_framebuffer(fbdev->helper.fb);
 }
+
+struct i915_vma *intel_fbdev_vma_pointer(struct intel_fbdev *fbdev)
+{
+       return fbdev ? fbdev->vma : NULL;
+}
index 08de2d5b343389b3af4f24322aeea00c3cbbdd8f..24a3434558cb6354516f7295d1a7b346f54fb5e0 100644 (file)
@@ -17,6 +17,8 @@ struct intel_framebuffer;
 void intel_fbdev_setup(struct drm_i915_private *dev_priv);
 void intel_fbdev_set_suspend(struct drm_device *dev, int state, bool synchronous);
 struct intel_framebuffer *intel_fbdev_framebuffer(struct intel_fbdev *fbdev);
+struct i915_vma *intel_fbdev_vma_pointer(struct intel_fbdev *fbdev);
+
 #else
 static inline void intel_fbdev_setup(struct drm_i915_private *dev_priv)
 {
@@ -30,6 +32,12 @@ static inline struct intel_framebuffer *intel_fbdev_framebuffer(struct intel_fbd
 {
        return NULL;
 }
+
+static inline struct i915_vma *intel_fbdev_vma_pointer(struct intel_fbdev *fbdev)
+{
+       return NULL;
+}
+
 #endif
 
 #endif /* __INTEL_FBDEV_H__ */
index bdae8392e1253355ade81f79a648e50320f019f7..4465c40f81341bffef5746fe4838a772041f50cb 100644 (file)
@@ -10,6 +10,8 @@
 
 #include "xe_ggtt_types.h"
 
+#include <linux/refcount.h>
+
 /* We don't want these from i915_drm.h in case of Xe */
 #undef I915_TILING_X
 #undef I915_TILING_Y
@@ -19,6 +21,7 @@
 struct xe_bo;
 
 struct i915_vma {
+       refcount_t ref;
        struct xe_bo *bo, *dpt;
        struct xe_ggtt_node *node;
 };
index 9fa51b84737ca3de4733fe34f123fbcee74c2096..25ce032bb293fb8128bdbe564d7351ef775e7c75 100644 (file)
@@ -9,6 +9,7 @@
 #include "intel_dpt.h"
 #include "intel_fb.h"
 #include "intel_fb_pin.h"
+#include "intel_fbdev.h"
 #include "xe_bo.h"
 #include "xe_device.h"
 #include "xe_ggtt.h"
@@ -287,6 +288,7 @@ static struct i915_vma *__xe_pin_fb_vma(const struct intel_framebuffer *fb,
        if (!vma)
                return ERR_PTR(-ENODEV);
 
+       refcount_set(&vma->ref, 1);
        if (IS_DGFX(to_xe_device(bo->ttm.base.dev)) &&
            intel_fb_rc_ccs_cc_plane(&fb->base) >= 0 &&
            !(bo->flags & XE_BO_FLAG_NEEDS_CPU_ACCESS)) {
@@ -347,6 +349,9 @@ static void __xe_unpin_fb_vma(struct i915_vma *vma)
 {
        u8 tile_id = vma->node->ggtt->tile->id;
 
+       if (!refcount_dec_and_test(&vma->ref))
+               return;
+
        if (vma->dpt)
                xe_bo_unpin_map_no_vm(vma->dpt);
        else if (!xe_ggtt_node_allocated(vma->bo->ggtt_node[tile_id]) ||
@@ -377,25 +382,58 @@ void intel_fb_unpin_vma(struct i915_vma *vma, unsigned long flags)
        __xe_unpin_fb_vma(vma);
 }
 
-int intel_plane_pin_fb(struct intel_plane_state *plane_state)
+static bool reuse_vma(struct intel_plane_state *new_plane_state,
+                     const struct intel_plane_state *old_plane_state)
 {
-       struct drm_framebuffer *fb = plane_state->hw.fb;
+       struct intel_framebuffer *fb = to_intel_framebuffer(new_plane_state->hw.fb);
+       struct xe_device *xe = to_xe_device(fb->base.dev);
+       struct i915_vma *vma;
+
+       if (old_plane_state->hw.fb == new_plane_state->hw.fb &&
+           !memcmp(&old_plane_state->view.gtt,
+                   &new_plane_state->view.gtt,
+                   sizeof(new_plane_state->view.gtt))) {
+               vma = old_plane_state->ggtt_vma;
+               goto found;
+       }
+
+       if (fb == intel_fbdev_framebuffer(xe->display.fbdev.fbdev)) {
+               vma = intel_fbdev_vma_pointer(xe->display.fbdev.fbdev);
+               if (vma)
+                       goto found;
+       }
+
+       return false;
+
+found:
+       refcount_inc(&vma->ref);
+       new_plane_state->ggtt_vma = vma;
+       return true;
+}
+
+int intel_plane_pin_fb(struct intel_plane_state *new_plane_state,
+                      const struct intel_plane_state *old_plane_state)
+{
+       struct drm_framebuffer *fb = new_plane_state->hw.fb;
        struct drm_gem_object *obj = intel_fb_bo(fb);
        struct xe_bo *bo = gem_to_xe_bo(obj);
        struct i915_vma *vma;
        struct intel_framebuffer *intel_fb = to_intel_framebuffer(fb);
-       struct intel_plane *plane = to_intel_plane(plane_state->uapi.plane);
+       struct intel_plane *plane = to_intel_plane(new_plane_state->uapi.plane);
        u64 phys_alignment = plane->min_alignment(plane, fb, 0);
 
+       if (reuse_vma(new_plane_state, old_plane_state))
+               return 0;
+
        /* We reject creating !SCANOUT fb's, so this is weird.. */
        drm_WARN_ON(bo->ttm.base.dev, !(bo->flags & XE_BO_FLAG_SCANOUT));
 
-       vma = __xe_pin_fb_vma(intel_fb, &plane_state->view.gtt, phys_alignment);
+       vma = __xe_pin_fb_vma(intel_fb, &new_plane_state->view.gtt, phys_alignment);
 
        if (IS_ERR(vma))
                return PTR_ERR(vma);
 
-       plane_state->ggtt_vma = vma;
+       new_plane_state->ggtt_vma = vma;
        return 0;
 }