Message ID | 20231117171833.25816-1-ville.syrjala@linux.intel.com (mailing list archive) |
---|---|
State | New, archived |
Headers | show |
Series | [1/3] drm/i915/fbc: Split plane size vs. surface size checks apart | expand |
Took a while to comprehend what the spec says and how it translate into code but I think this is correct fix. entire set is Reviewed-by: Juha-Pekka Heikkila <juhapekka.heikkila@gmail.com> On 17.11.2023 19.18, Ville Syrjala wrote: > From: Ville Syrjälä <ville.syrjala@linux.intel.com> > > Do separate checks for the visible plane size vs. the surface > size (which I take to mean offset+size). For now both use the > same max w/h, but we can relax the surface size limits as > a followup. > > Signed-off-by: Ville Syrjälä <ville.syrjala@linux.intel.com> > --- > drivers/gpu/drm/i915/display/intel_fbc.c | 32 +++++++++++++++++++++++- > 1 file changed, 31 insertions(+), 1 deletion(-) > > diff --git a/drivers/gpu/drm/i915/display/intel_fbc.c b/drivers/gpu/drm/i915/display/intel_fbc.c > index b73cf1c5ba33..fe21371db38c 100644 > --- a/drivers/gpu/drm/i915/display/intel_fbc.c > +++ b/drivers/gpu/drm/i915/display/intel_fbc.c > @@ -1050,6 +1050,31 @@ static bool intel_fbc_hw_tracking_covers_screen(const struct intel_plane_state * > return effective_w <= max_w && effective_h <= max_h; > } > > +static bool intel_fbc_plane_size_valid(const struct intel_plane_state *plane_state) > +{ > + struct drm_i915_private *i915 = to_i915(plane_state->uapi.plane->dev); > + unsigned int w, h, max_w, max_h; > + > + if (DISPLAY_VER(i915) >= 10) { > + max_w = 5120; > + max_h = 4096; > + } else if (DISPLAY_VER(i915) >= 8 || IS_HASWELL(i915)) { > + max_w = 4096; > + max_h = 4096; > + } else if (IS_G4X(i915) || DISPLAY_VER(i915) >= 5) { > + max_w = 4096; > + max_h = 2048; > + } else { > + max_w = 2048; > + max_h = 1536; > + } > + > + w = drm_rect_width(&plane_state->uapi.src) >> 16; > + h = drm_rect_height(&plane_state->uapi.src) >> 16; > + > + return w <= max_w && h <= max_h; > +} > + > static bool i8xx_fbc_tiling_valid(const struct intel_plane_state *plane_state) > { > const struct drm_framebuffer *fb = plane_state->hw.fb; > @@ -1247,11 +1272,16 @@ static int intel_fbc_check_plane(struct intel_atomic_state *state, > return 0; > } > > - if (!intel_fbc_hw_tracking_covers_screen(plane_state)) { > + if (!intel_fbc_plane_size_valid(plane_state)) { > plane_state->no_fbc_reason = "plane size too big"; > return 0; > } > > + if (!intel_fbc_hw_tracking_covers_screen(plane_state)) { > + plane_state->no_fbc_reason = "surface size too big"; > + return 0; > + } > + > /* > * Work around a problem on GEN9+ HW, where enabling FBC on a plane > * having a Y offset that isn't divisible by 4 causes FIFO underrun
diff --git a/drivers/gpu/drm/i915/display/intel_fbc.c b/drivers/gpu/drm/i915/display/intel_fbc.c index b73cf1c5ba33..fe21371db38c 100644 --- a/drivers/gpu/drm/i915/display/intel_fbc.c +++ b/drivers/gpu/drm/i915/display/intel_fbc.c @@ -1050,6 +1050,31 @@ static bool intel_fbc_hw_tracking_covers_screen(const struct intel_plane_state * return effective_w <= max_w && effective_h <= max_h; } +static bool intel_fbc_plane_size_valid(const struct intel_plane_state *plane_state) +{ + struct drm_i915_private *i915 = to_i915(plane_state->uapi.plane->dev); + unsigned int w, h, max_w, max_h; + + if (DISPLAY_VER(i915) >= 10) { + max_w = 5120; + max_h = 4096; + } else if (DISPLAY_VER(i915) >= 8 || IS_HASWELL(i915)) { + max_w = 4096; + max_h = 4096; + } else if (IS_G4X(i915) || DISPLAY_VER(i915) >= 5) { + max_w = 4096; + max_h = 2048; + } else { + max_w = 2048; + max_h = 1536; + } + + w = drm_rect_width(&plane_state->uapi.src) >> 16; + h = drm_rect_height(&plane_state->uapi.src) >> 16; + + return w <= max_w && h <= max_h; +} + static bool i8xx_fbc_tiling_valid(const struct intel_plane_state *plane_state) { const struct drm_framebuffer *fb = plane_state->hw.fb; @@ -1247,11 +1272,16 @@ static int intel_fbc_check_plane(struct intel_atomic_state *state, return 0; } - if (!intel_fbc_hw_tracking_covers_screen(plane_state)) { + if (!intel_fbc_plane_size_valid(plane_state)) { plane_state->no_fbc_reason = "plane size too big"; return 0; } + if (!intel_fbc_hw_tracking_covers_screen(plane_state)) { + plane_state->no_fbc_reason = "surface size too big"; + return 0; + } + /* * Work around a problem on GEN9+ HW, where enabling FBC on a plane * having a Y offset that isn't divisible by 4 causes FIFO underrun