[Intel-gfx] [PATCH v3 6/8] drm/i915: Overcome display engine stride limits via GTT remapping
Chris Wilson
chris at chris-wilson.co.uk
Tue Oct 23 19:16:56 UTC 2018
Quoting Ville Syrjala (2018-09-25 20:37:12)
> +static bool intel_plane_needs_remap(const struct intel_plane_state *plane_state)
> +{
> + struct intel_plane *plane = to_intel_plane(plane_state->base.plane);
> + struct drm_i915_private *dev_priv = to_i915(plane->base.dev);
> + const struct drm_framebuffer *fb = plane_state->base.fb;
> + unsigned int rotation = plane_state->base.rotation;
> + u32 stride, max_stride;
> +
> + /* We don't want to deal with remapping with cursors */
> + if (plane->id == PLANE_CURSOR)
> + return false;
> +
> + /* No fence for the remapped vma */
Should work now (with a minor tweak to plane_can_fence), right?
> + if (INTEL_GEN(dev_priv) < 4)
> + return false;
> +
> + /* New CCS hash mode makes remapping impossible */
> + if (is_ccs_modifier(fb->modifier))
> + return false;
> +
> + /* FIXME other color planes? */
> + stride = intel_fb_pitch(fb, 0, rotation);
> + max_stride = plane->max_stride(plane, fb->format->format,
> + fb->modifier, rotation);
> +
> + return stride > max_stride;
> +}
> +
> static int
> intel_fill_fb_info(struct drm_i915_private *dev_priv,
> struct drm_framebuffer *fb)
> @@ -2676,6 +2741,182 @@ intel_fill_fb_info(struct drm_i915_private *dev_priv,
> return 0;
> }
>
> +static void
> +intel_plane_remap_gtt(struct intel_plane_state *plane_state)
> +{
> + struct drm_i915_private *dev_priv =
> + to_i915(plane_state->base.plane->dev);
> + struct drm_framebuffer *fb = plane_state->base.fb;
> + struct intel_framebuffer *intel_fb = to_intel_framebuffer(fb);
> + struct intel_rotation_info *info = &plane_state->view.rotated;
> + unsigned int rotation = plane_state->base.rotation;
> + int i, num_planes = fb->format->num_planes;
> + unsigned int tile_size = intel_tile_size(dev_priv);
> + unsigned int tile_width, tile_height;
> + unsigned int aligned_x, aligned_y;
> + unsigned int aligned_w, aligned_h;
> + unsigned int src_x, src_y;
> + unsigned int src_w, src_h;
> + unsigned int x, y;
> + u32 gtt_offset = 0;
> +
> + memset(&plane_state->view, 0, sizeof(plane_state->view));
> + plane_state->view.type = drm_rotation_90_or_270(rotation) ?
> + I915_GGTT_VIEW_ROTATED : I915_GGTT_VIEW_REMAPPED;
> +
> + src_x = plane_state->base.src.x1 >> 16;
> + src_y = plane_state->base.src.y1 >> 16;
> + src_w = drm_rect_width(&plane_state->base.src) >> 16;
> + src_h = drm_rect_height(&plane_state->base.src) >> 16;
> +
> + WARN_ON(is_ccs_modifier(fb->modifier));
> +
> + /* Align our viewport start to tile boundary */
> + intel_tile_dims(fb, 0, &tile_width, &tile_height);
> +
> + x = src_x & (tile_width - 1);
> + y = src_y & (tile_height - 1);
> +
> + aligned_x = src_x - x;
> + aligned_y = src_y - y;
> +
> + aligned_w = x + src_w;
> + aligned_h = y + src_h;
> +
> + /* Make src coordinates relative to the aligned viewport */
> + drm_rect_translate(&plane_state->base.src,
> + -(aligned_x << 16), -(aligned_y << 16));
> +
> + /* Rotate src coordinates to match rotated GTT view */
> + if (drm_rotation_90_or_270(rotation))
> + drm_rect_rotate(&plane_state->base.src,
> + aligned_w << 16, aligned_h << 16,
> + DRM_MODE_ROTATE_270);
> +
> + for (i = 0; i < num_planes; i++) {
> + unsigned int hsub = i ? fb->format->hsub : 1;
> + unsigned int vsub = i ? fb->format->vsub : 1;
> + unsigned int cpp = fb->format->cpp[i];
> + unsigned int width, height;
> + unsigned int pitch_tiles;
> + unsigned int x, y;
> + u32 offset;
> +
> + intel_tile_dims(fb, i, &tile_width, &tile_height);
> +
> + x = aligned_x / hsub;
> + y = aligned_y / vsub;
> + width = aligned_w / hsub;
aligned_w here seems to be just x2.
Did I miss aligned_w = ALIGN(aligned_w, tile_width) - aligned_x?
> + height = aligned_h / vsub;
> +
> + /*
> + * First pixel of the aligned src viewport
> + * from the start of the normal gtt mapping.
> + */
> + x += intel_fb->normal[i].x;
> + y += intel_fb->normal[i].y;
> +
> + offset = intel_compute_aligned_offset(dev_priv, &x, &y,
> + fb, i, fb->pitches[i],
> + DRM_MODE_ROTATE_0, tile_size);
> + offset /= tile_size;
> +
> + info->plane[i].offset = offset;
> + info->plane[i].stride = DIV_ROUND_UP(fb->pitches[i],
> + tile_width * cpp);
> + info->plane[i].width = DIV_ROUND_UP(x + width, tile_width);
> + info->plane[i].height = DIV_ROUND_UP(y + height, tile_height);
I thought .width here would be in pages? Ok tile_width != fence_stride
and does produce pages just fine.
And shouldn't width here be adjusted for x? Similarly for height?
-Chris
More information about the Intel-gfx
mailing list