This removes the requirement for user space to pin a buffer before
setting a mode that is backed by the pixels from that buffer.

Signed-off-by: Kristian Høgsberg <k...@redhat.com>
---
 drivers/gpu/drm/drm_crtc_helper.c    |   20 ++++++++++-----
 drivers/gpu/drm/i915/intel_display.c |   44 +++++++++++++++++++++++++++------
 include/drm/drm_crtc_helper.h        |    9 ++++--
 3 files changed, 55 insertions(+), 18 deletions(-)

diff --git a/drivers/gpu/drm/drm_crtc_helper.c 
b/drivers/gpu/drm/drm_crtc_helper.c
index f914044..3082841 100644
--- a/drivers/gpu/drm/drm_crtc_helper.c
+++ b/drivers/gpu/drm/drm_crtc_helper.c
@@ -432,7 +432,8 @@ static void drm_setup_crtcs(struct drm_device *dev)
  */
 bool drm_crtc_helper_set_mode(struct drm_crtc *crtc,
                              struct drm_display_mode *mode,
-                             int x, int y)
+                             int x, int y,
+                             struct drm_framebuffer *old_fb)
 {
        struct drm_device *dev = crtc->dev;
        struct drm_display_mode *adjusted_mode, saved_mode;
@@ -462,7 +463,8 @@ bool drm_crtc_helper_set_mode(struct drm_crtc *crtc,
 
        if (drm_mode_equal(&saved_mode, &crtc->mode)) {
                if (saved_x != crtc->x || saved_y != crtc->y) {
-                       crtc_funcs->mode_set_base(crtc, crtc->x, crtc->y);
+                       crtc_funcs->mode_set_base(crtc, crtc->x, crtc->y,
+                                                 old_fb);
                        goto done;
                }
        }
@@ -501,7 +503,7 @@ bool drm_crtc_helper_set_mode(struct drm_crtc *crtc,
        /* Set up the DPLL and any encoders state that needs to adjust or depend
         * on the DPLL.
         */
-       crtc_funcs->mode_set(crtc, mode, adjusted_mode, x, y);
+       crtc_funcs->mode_set(crtc, mode, adjusted_mode, x, y, old_fb);
 
        list_for_each_entry(encoder, &dev->mode_config.encoder_list, head) {
 
@@ -564,6 +566,7 @@ int drm_crtc_helper_set_config(struct drm_mode_set *set)
        struct drm_device *dev;
        struct drm_crtc **save_crtcs, *new_crtc;
        struct drm_encoder **save_encoders, *new_encoder;
+       struct drm_framebuffer *old_fb;
        bool save_enabled;
        bool changed = false;
        bool flip_or_move = false;
@@ -684,13 +687,15 @@ int drm_crtc_helper_set_config(struct drm_mode_set *set)
                changed = true;
 
        if (changed) {
+               old_fb = set->crtc->fb;
                set->crtc->fb = set->fb;
                set->crtc->enabled = (set->mode != NULL);
                if (set->mode != NULL) {
                        DRM_DEBUG("attempting to set mode from userspace\n");
                        drm_mode_debug_printmodeline(set->mode);
                        if (!drm_crtc_helper_set_mode(set->crtc, set->mode,
-                                                     set->x, set->y)) {
+                                                     set->x, set->y,
+                                                     old_fb)) {
                                ret = -EINVAL;
                                goto fail_set_mode;
                        }
@@ -701,9 +706,10 @@ int drm_crtc_helper_set_config(struct drm_mode_set *set)
                }
                drm_helper_disable_unused_functions(dev);
        } else if (flip_or_move) {
+               old_fb = set->crtc->fb;
                if (set->crtc->fb != set->fb)
                        set->crtc->fb = set->fb;
-               crtc_funcs->mode_set_base(set->crtc, set->x, set->y);
+               crtc_funcs->mode_set_base(set->crtc, set->x, set->y, old_fb);
        }
 
        kfree(save_encoders);
@@ -811,8 +817,8 @@ int drm_helper_resume_force_mode(struct drm_device *dev)
                if (!crtc->enabled)
                        continue;
 
-               ret = drm_crtc_helper_set_mode(crtc, &crtc->mode, crtc->x,
-                                              crtc->y);
+               ret = drm_crtc_helper_set_mode(crtc, &crtc->mode,
+                                              crtc->x, crtc->y, crtc->fb);
 
                if (ret == false)
                        DRM_ERROR("failed to set mode on crtc %p\n", crtc);
diff --git a/drivers/gpu/drm/i915/intel_display.c 
b/drivers/gpu/drm/i915/intel_display.c
index 5689e44..8e5a242 100644
--- a/drivers/gpu/drm/i915/intel_display.c
+++ b/drivers/gpu/drm/i915/intel_display.c
@@ -344,7 +344,8 @@ intel_wait_for_vblank(struct drm_device *dev)
 }
 
 void
-intel_pipe_set_base(struct drm_crtc *crtc, int x, int y)
+intel_pipe_set_base(struct drm_crtc *crtc, int x, int y,
+                   struct drm_framebuffer *old_fb)
 {
        struct drm_device *dev = crtc->dev;
        struct drm_i915_private *dev_priv = dev->dev_private;
@@ -359,7 +360,7 @@ intel_pipe_set_base(struct drm_crtc *crtc, int x, int y)
        int dspsurf = (pipe == 0 ? DSPASURF : DSPBSURF);
        int dspstride = (pipe == 0) ? DSPASTRIDE : DSPBSTRIDE;
        int dspcntr_reg = (pipe == 0) ? DSPACNTR : DSPBCNTR;
-       u32 dspcntr;
+       u32 dspcntr, alignment;
 
        /* no fb bound */
        if (!crtc->fb) {
@@ -368,10 +369,32 @@ intel_pipe_set_base(struct drm_crtc *crtc, int x, int y)
        }
 
        intel_fb = to_intel_framebuffer(crtc->fb);
-
        obj = intel_fb->obj;
        obj_priv = obj->driver_private;
 
+       switch (obj_priv->tiling_mode) {
+       case I915_TILING_NONE:
+               alignment = 64 * 1024;
+               break;
+       case I915_TILING_X:
+               if (IS_I9XX(dev))
+                       alignment = 1024 * 1024;
+               else
+                       alignment = 512 * 1024;
+               break;
+       case I915_TILING_Y:
+               /* FIXME: Is this true? */
+               DRM_ERROR("Y tiled not allowed for scan out buffers\n");
+               return;
+       default:
+               BUG();
+       }
+
+       if (i915_gem_object_pin(intel_fb->obj, alignment))
+               return;
+
+       i915_gem_object_set_to_gtt_domain(intel_fb->obj, 1);
+
        Start = obj_priv->gtt_offset;
        Offset = y * crtc->fb->pitch + x * (crtc->fb->bits_per_pixel / 8);
 
@@ -409,6 +432,12 @@ intel_pipe_set_base(struct drm_crtc *crtc, int x, int y)
                I915_READ(dspbase);
        }
 
+       intel_wait_for_vblank(dev);
+       
+       if (old_fb) {
+               intel_fb = to_intel_framebuffer(old_fb);
+               i915_gem_object_unpin(intel_fb->obj);
+       }
 
        if (!dev->primary->master)
                return;
@@ -680,7 +709,8 @@ static int intel_panel_fitter_pipe (struct drm_device *dev)
 static void intel_crtc_mode_set(struct drm_crtc *crtc,
                                struct drm_display_mode *mode,
                                struct drm_display_mode *adjusted_mode,
-                               int x, int y)
+                               int x, int y,
+                               struct drm_framebuffer *old_fb)
 {
        struct drm_device *dev = crtc->dev;
        struct drm_i915_private *dev_priv = dev->dev_private;
@@ -915,9 +945,7 @@ static void intel_crtc_mode_set(struct drm_crtc *crtc,
        I915_WRITE(dspcntr_reg, dspcntr);
 
        /* Flush the plane changes */
-       intel_pipe_set_base(crtc, x, y);
-
-       intel_wait_for_vblank(dev);
+       intel_pipe_set_base(crtc, x, y, old_fb);
 
        drm_vblank_post_modeset(dev, pipe);
 }
@@ -1153,7 +1181,7 @@ struct drm_crtc *intel_get_load_detect_pipe(struct 
intel_output *intel_output,
        if (!crtc->enabled) {
                if (!mode)
                        mode = &load_detect_mode;
-               drm_crtc_helper_set_mode(crtc, mode, 0, 0);
+               drm_crtc_helper_set_mode(crtc, mode, 0, 0, crtc->fb);
        } else {
                if (intel_crtc->dpms_mode != DRM_MODE_DPMS_ON) {
                        crtc_funcs = crtc->helper_private;
diff --git a/include/drm/drm_crtc_helper.h b/include/drm/drm_crtc_helper.h
index a341828..4bc04cf 100644
--- a/include/drm/drm_crtc_helper.h
+++ b/include/drm/drm_crtc_helper.h
@@ -55,10 +55,12 @@ struct drm_crtc_helper_funcs {
                           struct drm_display_mode *adjusted_mode);
        /* Actually set the mode */
        void (*mode_set)(struct drm_crtc *crtc, struct drm_display_mode *mode,
-                        struct drm_display_mode *adjusted_mode, int x, int y);
+                        struct drm_display_mode *adjusted_mode, int x, int y,
+                        struct drm_framebuffer *old_fb);
 
        /* Move the crtc on the current fb to the given position *optional* */
-       void (*mode_set_base)(struct drm_crtc *crtc, int x, int y);
+       void (*mode_set_base)(struct drm_crtc *crtc, int x, int y,
+                             struct drm_framebuffer *old_fb);
 };
 
 struct drm_encoder_helper_funcs {
@@ -93,7 +95,8 @@ extern bool drm_helper_initial_config(struct drm_device *dev, 
bool can_grow);
 extern int drm_crtc_helper_set_config(struct drm_mode_set *set);
 extern bool drm_crtc_helper_set_mode(struct drm_crtc *crtc,
                                     struct drm_display_mode *mode,
-                                    int x, int y);
+                                    int x, int y,
+                                    struct drm_framebuffer *old_fb);
 extern bool drm_helper_crtc_in_use(struct drm_crtc *crtc);
 
 extern int drm_helper_mode_fill_fb_struct(struct drm_framebuffer *fb,
-- 
1.6.0.5


------------------------------------------------------------------------------
SF.Net email is Sponsored by MIX09, March 18-20, 2009 in Las Vegas, Nevada.
The future of the web can't happen without you.  Join us at MIX09 to help
pave the way to the Next Web now. Learn more and register at
http://ad.doubleclick.net/clk;208669438;13503038;i?http://2009.visitmix.com/
--
_______________________________________________
Dri-devel mailing list
Dri-devel@lists.sourceforge.net
https://lists.sourceforge.net/lists/listinfo/dri-devel

Reply via email to