From: Tvrtko Ursulin <tvrtko.ursu...@intel.com>

Just adding the rotated UV plane at the end of the rotated Y plane.

Signed-off-by: Tvrtko Ursulin <tvrtko.ursu...@intel.com>
---
 drivers/gpu/drm/i915/i915_gem_gtt.c  | 47 ++++++++++++++++++++++++++++++------
 drivers/gpu/drm/i915/i915_gem_gtt.h  |  1 +
 drivers/gpu/drm/i915/intel_display.c |  1 +
 3 files changed, 41 insertions(+), 8 deletions(-)

diff --git a/drivers/gpu/drm/i915/i915_gem_gtt.c 
b/drivers/gpu/drm/i915/i915_gem_gtt.c
index d7f2e5d..bf3ee44 100644
--- a/drivers/gpu/drm/i915/i915_gem_gtt.c
+++ b/drivers/gpu/drm/i915/i915_gem_gtt.c
@@ -2693,12 +2693,18 @@ intel_calc_tiled_geometry(struct drm_device *dev,
                          unsigned int plane)
 {
        unsigned int tile_height, tile_pitch;
+       unsigned int height;
+
+       if (rot_info->pixel_format == DRM_FORMAT_NV12 && plane == 1)
+               height = rot_info->height / 2;
+       else
+               height = rot_info->height;
 
        tile_height = intel_tile_height(dev, rot_info->pixel_format,
                                        rot_info->fb_modifier, plane);
        tile_pitch = PAGE_SIZE / tile_height;
        *width_pages = DIV_ROUND_UP(rot_info->pitch, tile_pitch);
-       *height_pages = DIV_ROUND_UP(rot_info->height, tile_height);
+       *height_pages = DIV_ROUND_UP(height, tile_height);
 
        return (*width_pages) * (*height_pages);
 }
@@ -2709,12 +2715,15 @@ intel_rotate_fb_obj_pages(struct i915_ggtt_view 
*ggtt_view,
 {
        struct drm_device *dev = obj->base.dev;
        struct intel_rotation_info *rot_info = &ggtt_view->rotation_info;
-       unsigned long pages, rot_pages;
+       unsigned long pages, rot_pages, rot_pages_uv = 0;
        struct sg_page_iter sg_iter;
        unsigned long i;
        dma_addr_t *page_addr_list;
        struct sg_table *st;
        unsigned int width_pages, height_pages;
+       unsigned int width_pages_uv, height_pages_uv;
+       unsigned int uv_start_page;
+       struct scatterlist *sg;
        int ret = -ENOMEM;
 
        pages = obj->base.size / PAGE_SIZE;
@@ -2723,6 +2732,13 @@ intel_rotate_fb_obj_pages(struct i915_ggtt_view 
*ggtt_view,
        rot_pages = intel_calc_tiled_geometry(dev, rot_info,
                                              &width_pages, &height_pages, 0);
 
+       /* Account for UV plane with NV12. */
+       if (rot_info->pixel_format == DRM_FORMAT_NV12) {
+               rot_pages_uv = intel_calc_tiled_geometry(dev, rot_info,
+                                                        &width_pages_uv,
+                                                        &height_pages_uv, 1);
+       }
+
        /* Allocate a temporary list of source pages for random access. */
        page_addr_list = drm_malloc_ab(pages, sizeof(dma_addr_t));
        if (!page_addr_list)
@@ -2733,7 +2749,7 @@ intel_rotate_fb_obj_pages(struct i915_ggtt_view 
*ggtt_view,
        if (!st)
                goto err_st_alloc;
 
-       ret = sg_alloc_table(st, rot_pages, GFP_KERNEL);
+       ret = sg_alloc_table(st, rot_pages + rot_pages_uv, GFP_KERNEL);
        if (ret)
                goto err_sg_alloc;
 
@@ -2745,13 +2761,28 @@ intel_rotate_fb_obj_pages(struct i915_ggtt_view 
*ggtt_view,
        }
 
        /* Rotate the pages. */
-       rotate_pages(page_addr_list, 0, width_pages, height_pages, st, NULL);
+       sg = rotate_pages(page_addr_list, 0,
+                         width_pages, height_pages,
+                         st, NULL);
+
+       /* Append the UV plane if NV12. */
+       if (rot_info->pixel_format == DRM_FORMAT_NV12) {
+               uv_start_page = rot_pages;
+
+               /* Check for tile-row un-alignment. */
+               if (offset_in_page(rot_info->uv_offset))
+                       uv_start_page--;
+
+               rotate_pages(page_addr_list, uv_start_page,
+                            width_pages_uv, height_pages_uv,
+                            st, sg);
+       }
 
        DRM_DEBUG_KMS(
-                     "Created rotated page mapping for object size %lu 
(pitch=%u, height=%u, pixel_format=0x%x, %ux%u tiles, %lu pages).\n",
+                     "Created rotated page mapping for object size %lu 
(pitch=%u, height=%u, pixel_format=0x%x, %ux%u tiles, %lu pages (%lu plane 
0)).\n",
                      obj->base.size, rot_info->pitch, rot_info->height,
                      rot_info->pixel_format, width_pages, height_pages,
-                     rot_pages);
+                     rot_pages + rot_pages_uv, rot_pages);
 
        drm_free_large(page_addr_list);
 
@@ -2763,10 +2794,10 @@ err_st_alloc:
        drm_free_large(page_addr_list);
 
        DRM_DEBUG_KMS(
-                     "Failed to create rotated mapping for object size %lu! 
(%d) (pitch=%u, height=%u, pixel_format=0x%x, %ux%u tiles, %lu pages)\n",
+                     "Failed to create rotated mapping for object size %lu! 
(%d) (pitch=%u, height=%u, pixel_format=0x%x, %ux%u tiles, %lu pages (%lu plane 
0))\n",
                      obj->base.size, ret, rot_info->pitch, rot_info->height,
                      rot_info->pixel_format, width_pages, height_pages,
-                     rot_pages);
+                     rot_pages + rot_pages_uv, rot_pages);
        return ERR_PTR(ret);
 }
 
diff --git a/drivers/gpu/drm/i915/i915_gem_gtt.h 
b/drivers/gpu/drm/i915/i915_gem_gtt.h
index 4e6cac5..5118da1 100644
--- a/drivers/gpu/drm/i915/i915_gem_gtt.h
+++ b/drivers/gpu/drm/i915/i915_gem_gtt.h
@@ -123,6 +123,7 @@ enum i915_ggtt_view_type {
 struct intel_rotation_info {
        unsigned int height;
        unsigned int pitch;
+       unsigned int uv_offset;
        uint32_t pixel_format;
        uint64_t fb_modifier;
 };
diff --git a/drivers/gpu/drm/i915/intel_display.c 
b/drivers/gpu/drm/i915/intel_display.c
index a87faca..b4bf998 100644
--- a/drivers/gpu/drm/i915/intel_display.c
+++ b/drivers/gpu/drm/i915/intel_display.c
@@ -2346,6 +2346,7 @@ intel_fill_fb_ggtt_view(struct i915_ggtt_view *view, 
struct drm_framebuffer *fb,
        info->pixel_format = fb->pixel_format;
        info->pitch = fb->pitches[0];
        info->fb_modifier = fb->modifier[0];
+       info->uv_offset = fb->offsets[1];
 
        return 0;
 }
-- 
2.4.0

_______________________________________________
Intel-gfx mailing list
Intel-gfx@lists.freedesktop.org
http://lists.freedesktop.org/mailman/listinfo/intel-gfx

Reply via email to