[PATCH 2/4] drm: Add drm_calc_{hscale, vscale}() utility functions

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



From: Ville Syrj?l? <ville.syrjala at linux.intel.com>

These functions calculcate the scaling factor based on the source and
destination regions.

There are two version of the functions, the strict ones that will
return an error if the min/max scaling factor is exceeded, and the
relaxed versions that will adjust the src/dst regions in order to
keep the scaling factor withing the limits.

v2: Return error instead of adjusting regions, refactor common parts
    into one function, and split into strict and relaxed versions.

Signed-off-by: Ville Syrj?l? <ville.syrjala at linux.intel.com>
---
 drivers/gpu/drm/drm_region.c | 173 +++++++++++++++++++++++++++++++++++++++++++
 include/drm/drm_region.h     |   8 ++
 2 files changed, 181 insertions(+)

diff --git a/drivers/gpu/drm/drm_region.c b/drivers/gpu/drm/drm_region.c
index 41a3929..c694424 100644
--- a/drivers/gpu/drm/drm_region.c
+++ b/drivers/gpu/drm/drm_region.c
@@ -93,3 +93,176 @@ bool drm_region_clip_scaled(struct drm_region *src, struct drm_region *dst,
 	return drm_region_clip(dst, clip);
 }
 EXPORT_SYMBOL(drm_region_clip_scaled);
+
+static int drm_calc_scale(int src, int dst)
+{
+	int scale = 0;
+
+	if (src < 0 || dst < 0)
+		return -EINVAL;
+
+	if (dst == 0)
+		return 0;
+
+	scale = src / dst;
+
+	return scale;
+}
+
+/**
+ * drm_calc_hscale - calculate the horizontal scaling factor
+ * @src: source window region
+ * @dst: destination window region
+ * @min_hscale: minimum allowed horizontal scaling factor
+ * @max_hscale: maximum allowed horizontal scaling factor
+ *
+ * Calculate the horizontal scaling factor as
+ * (@src width) / (@dst width).
+ *
+ * RETURNS:
+ * The horizontal scaling factor, or errno of out of limits.
+ */
+int drm_calc_hscale(struct drm_region *src, struct drm_region *dst,
+		    int min_hscale, int max_hscale)
+{
+	int src_w = drm_region_width(src);
+	int dst_w = drm_region_width(dst);
+	int hscale = drm_calc_scale(src_w, dst_w);
+
+	if (hscale < 0 || dst_w == 0)
+		return hscale;
+
+	if (hscale < min_hscale || hscale > max_hscale)
+		return -ERANGE;
+
+	return hscale;
+}
+EXPORT_SYMBOL(drm_calc_hscale);
+
+/**
+ * drm_calc_vscale - calculate the vertical scaling factor
+ * @src: source window region
+ * @dst: destination window region
+ * @min_vscale: minimum allowed vertical scaling factor
+ * @max_vscale: maximum allowed vertical scaling factor
+ *
+ * Calculate the vertical scaling factor as
+ * (@src height) / (@dst height).
+ *
+ * RETURNS:
+ * The vertical scaling factor, or errno of out of limits.
+ */
+int drm_calc_vscale(struct drm_region *src, struct drm_region *dst,
+		    int min_vscale, int max_vscale)
+{
+	int src_h = drm_region_height(src);
+	int dst_h = drm_region_height(dst);
+	int vscale = drm_calc_scale(src_h, dst_h);
+
+	if (vscale < 0 || dst_h == 0)
+		return vscale;
+
+	if (vscale < min_vscale || vscale > max_vscale)
+		return -ERANGE;
+
+	return vscale;
+}
+EXPORT_SYMBOL(drm_calc_vscale);
+
+/**
+ * drm_calc_hscale_relaxed - calculate the horizontal scaling factor
+ * @src: source window region
+ * @dst: destination window region
+ * @min_hscale: minimum allowed horizontal scaling factor
+ * @max_hscale: maximum allowed horizontal scaling factor
+ *
+ * Calculate the horizontal scaling factor as
+ * (@src width) / (@dst width).
+ *
+ * If the calculated scaling factor is below @min_vscale,
+ * decrease the height of region @dst to compensate.
+ *
+ * If the calculcated scaling factor is above @max_vscale,
+ * decrease the height of region @src to compensate.
+ *
+ * RETURNS:
+ * The horizontal scaling factor.
+ */
+int drm_calc_hscale_relaxed(struct drm_region *src, struct drm_region *dst,
+			    int min_hscale, int max_hscale)
+{
+	int src_w = drm_region_width(src);
+	int dst_w = drm_region_width(dst);
+	int hscale = drm_calc_scale(src_w, dst_w);
+
+	if (hscale < 0 || dst_w == 0)
+		return hscale;
+
+	if (hscale < min_hscale) {
+		int max_dst_w = src_w / min_hscale;
+
+		drm_region_adjust_size(dst, max_dst_w - dst_w, 0);
+
+		return min_hscale;
+	}
+
+	if (hscale > max_hscale) {
+		int max_src_w = dst_w * max_hscale;
+
+		drm_region_adjust_size(src, max_src_w - src_w, 0);
+
+		return max_hscale;
+	}
+
+	return hscale;
+}
+EXPORT_SYMBOL(drm_calc_hscale_relaxed);
+
+/**
+ * drm_calc_vscale_relaxed - calculate the vertical scaling factor
+ * @src: source window region
+ * @dst: destination window region
+ * @min_vscale: minimum allowed vertical scaling factor
+ * @max_vscale: maximum allowed vertical scaling factor
+ *
+ * Calculate the vertical scaling factor as
+ * (@src height) / (@dst height).
+ *
+ * If the calculated scaling factor is below @min_vscale,
+ * decrease the height of region @dst to compensate.
+ *
+ * If the calculcated scaling factor is above @max_vscale,
+ * decrease the height of region @src to compensate.
+ *
+ * RETURNS:
+ * The vertical scaling factor.
+ */
+int drm_calc_vscale_relaxed(struct drm_region *src, struct drm_region *dst,
+			    int min_vscale, int max_vscale)
+{
+	int src_h = drm_region_height(src);
+	int dst_h = drm_region_height(dst);
+	int vscale = drm_calc_scale(src_h, dst_h);
+
+	if (vscale < 0 || dst_h == 0)
+		return vscale;
+
+	if (vscale < min_vscale) {
+		int max_dst_h = src_h / min_vscale;
+
+		drm_region_adjust_size(dst, 0, max_dst_h - dst_h);
+
+		return min_vscale;
+	}
+
+	if (vscale > max_vscale) {
+		int max_src_h = dst_h * max_vscale;
+
+		drm_region_adjust_size(src, 0, max_src_h - src_h);
+
+		return max_vscale;
+	}
+
+	return vscale;
+}
+EXPORT_SYMBOL(drm_calc_vscale_relaxed);
diff --git a/include/drm/drm_region.h b/include/drm/drm_region.h
index 81bed21..c12d953 100644
--- a/include/drm/drm_region.h
+++ b/include/drm/drm_region.h
@@ -128,5 +128,13 @@ bool drm_region_clip(struct drm_region *r, const struct drm_region *clip);
 bool drm_region_clip_scaled(struct drm_region *src, struct drm_region *dst,
 			    const struct drm_region *clip,
 			    int hscale, int vscale);
+int drm_calc_hscale(struct drm_region *src, struct drm_region *dst,
+		    int min_hscale, int max_hscale);
+int drm_calc_vscale(struct drm_region *src, struct drm_region *dst,
+		    int min_vscale, int max_vscale);
+int drm_calc_hscale_relaxed(struct drm_region *src, struct drm_region *dst,
+			    int min_hscale, int max_hscale);
+int drm_calc_vscale_relaxed(struct drm_region *src, struct drm_region *dst,
+			    int min_vscale, int max_vscale);
 
 #endif
-- 
1.7.12.4



[Index of Archives]     [Linux USB Devel]     [Linux Audio Users]     [Yosemite News]     [Linux Kernel]     [Linux SCSI]
  Powered by Linux