|
@@ -50,13 +50,25 @@ bool drm_rect_intersect(struct drm_rect *r1, const struct drm_rect *r2)
|
|
|
}
|
|
|
EXPORT_SYMBOL(drm_rect_intersect);
|
|
|
|
|
|
+static u32 clip_scaled(u32 src, u32 dst, u32 clip)
|
|
|
+{
|
|
|
+ u64 tmp = mul_u32_u32(src, dst - clip);
|
|
|
+
|
|
|
+ /*
|
|
|
+ * Round toward 1.0 when clipping so that we don't accidentally
|
|
|
+ * change upscaling to downscaling or vice versa.
|
|
|
+ */
|
|
|
+ if (src < (dst << 16))
|
|
|
+ return DIV_ROUND_UP_ULL(tmp, dst);
|
|
|
+ else
|
|
|
+ return DIV_ROUND_DOWN_ULL(tmp, dst);
|
|
|
+}
|
|
|
+
|
|
|
/**
|
|
|
* drm_rect_clip_scaled - perform a scaled clip operation
|
|
|
* @src: source window rectangle
|
|
|
* @dst: destination window rectangle
|
|
|
* @clip: clip rectangle
|
|
|
- * @hscale: horizontal scaling factor
|
|
|
- * @vscale: vertical scaling factor
|
|
|
*
|
|
|
* Clip rectangle @dst by rectangle @clip. Clip rectangle @src by the
|
|
|
* same amounts multiplied by @hscale and @vscale.
|
|
@@ -66,33 +78,44 @@ EXPORT_SYMBOL(drm_rect_intersect);
|
|
|
* %false otherwise
|
|
|
*/
|
|
|
bool drm_rect_clip_scaled(struct drm_rect *src, struct drm_rect *dst,
|
|
|
- const struct drm_rect *clip,
|
|
|
- int hscale, int vscale)
|
|
|
+ const struct drm_rect *clip)
|
|
|
{
|
|
|
int diff;
|
|
|
|
|
|
diff = clip->x1 - dst->x1;
|
|
|
if (diff > 0) {
|
|
|
- int64_t tmp = src->x1 + (int64_t) diff * hscale;
|
|
|
- src->x1 = clamp_t(int64_t, tmp, INT_MIN, INT_MAX);
|
|
|
+ u32 new_src_w = clip_scaled(drm_rect_width(src),
|
|
|
+ drm_rect_width(dst), diff);
|
|
|
+
|
|
|
+ src->x1 = clamp_t(int64_t, src->x2 - new_src_w, INT_MIN, INT_MAX);
|
|
|
+ dst->x1 = clip->x1;
|
|
|
}
|
|
|
diff = clip->y1 - dst->y1;
|
|
|
if (diff > 0) {
|
|
|
- int64_t tmp = src->y1 + (int64_t) diff * vscale;
|
|
|
- src->y1 = clamp_t(int64_t, tmp, INT_MIN, INT_MAX);
|
|
|
+ u32 new_src_h = clip_scaled(drm_rect_height(src),
|
|
|
+ drm_rect_height(dst), diff);
|
|
|
+
|
|
|
+ src->y1 = clamp_t(int64_t, src->y2 - new_src_h, INT_MIN, INT_MAX);
|
|
|
+ dst->y1 = clip->y1;
|
|
|
}
|
|
|
diff = dst->x2 - clip->x2;
|
|
|
if (diff > 0) {
|
|
|
- int64_t tmp = src->x2 - (int64_t) diff * hscale;
|
|
|
- src->x2 = clamp_t(int64_t, tmp, INT_MIN, INT_MAX);
|
|
|
+ u32 new_src_w = clip_scaled(drm_rect_width(src),
|
|
|
+ drm_rect_width(dst), diff);
|
|
|
+
|
|
|
+ src->x2 = clamp_t(int64_t, src->x1 + new_src_w, INT_MIN, INT_MAX);
|
|
|
+ dst->x2 = clip->x2;
|
|
|
}
|
|
|
diff = dst->y2 - clip->y2;
|
|
|
if (diff > 0) {
|
|
|
- int64_t tmp = src->y2 - (int64_t) diff * vscale;
|
|
|
- src->y2 = clamp_t(int64_t, tmp, INT_MIN, INT_MAX);
|
|
|
+ u32 new_src_h = clip_scaled(drm_rect_height(src),
|
|
|
+ drm_rect_height(dst), diff);
|
|
|
+
|
|
|
+ src->y2 = clamp_t(int64_t, src->y1 + new_src_h, INT_MIN, INT_MAX);
|
|
|
+ dst->y2 = clip->y2;
|
|
|
}
|
|
|
|
|
|
- return drm_rect_intersect(dst, clip);
|
|
|
+ return drm_rect_visible(dst);
|
|
|
}
|
|
|
EXPORT_SYMBOL(drm_rect_clip_scaled);
|
|
|
|