0,0 → 1,295 |
/* |
* Copyright (C) 2011-2013 Intel Corporation |
* |
* Permission is hereby granted, free of charge, to any person obtaining a |
* copy of this software and associated documentation files (the "Software"), |
* to deal in the Software without restriction, including without limitation |
* the rights to use, copy, modify, merge, publish, distribute, sublicense, |
* and/or sell copies of the Software, and to permit persons to whom the |
* Software is furnished to do so, subject to the following conditions: |
* |
* The above copyright notice and this permission notice (including the next |
* paragraph) shall be included in all copies or substantial portions of the |
* Software. |
* |
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR |
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, |
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL |
* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER |
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, |
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE |
* SOFTWARE. |
*/ |
|
#include <linux/errno.h> |
#include <linux/export.h> |
#include <linux/kernel.h> |
#include <drm/drmP.h> |
#include <drm/drm_rect.h> |
|
/** |
* drm_rect_intersect - intersect two rectangles |
* @r1: first rectangle |
* @r2: second rectangle |
* |
* Calculate the intersection of rectangles @r1 and @r2. |
* @r1 will be overwritten with the intersection. |
* |
* RETURNS: |
* %true if rectangle @r1 is still visible after the operation, |
* %false otherwise. |
*/ |
bool drm_rect_intersect(struct drm_rect *r1, const struct drm_rect *r2) |
{ |
r1->x1 = max(r1->x1, r2->x1); |
r1->y1 = max(r1->y1, r2->y1); |
r1->x2 = min(r1->x2, r2->x2); |
r1->y2 = min(r1->y2, r2->y2); |
|
return drm_rect_visible(r1); |
} |
EXPORT_SYMBOL(drm_rect_intersect); |
|
/** |
* 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. |
* |
* RETURNS: |
* %true if rectangle @dst is still visible after being clipped, |
* %false otherwise |
*/ |
bool drm_rect_clip_scaled(struct drm_rect *src, struct drm_rect *dst, |
const struct drm_rect *clip, |
int hscale, int vscale) |
{ |
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); |
} |
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); |
} |
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); |
} |
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); |
} |
|
return drm_rect_intersect(dst, clip); |
} |
EXPORT_SYMBOL(drm_rect_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_rect_calc_hscale - calculate the horizontal scaling factor |
* @src: source window rectangle |
* @dst: destination window rectangle |
* @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_rect_calc_hscale(const struct drm_rect *src, |
const struct drm_rect *dst, |
int min_hscale, int max_hscale) |
{ |
int src_w = drm_rect_width(src); |
int dst_w = drm_rect_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_rect_calc_hscale); |
|
/** |
* drm_rect_calc_vscale - calculate the vertical scaling factor |
* @src: source window rectangle |
* @dst: destination window rectangle |
* @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_rect_calc_vscale(const struct drm_rect *src, |
const struct drm_rect *dst, |
int min_vscale, int max_vscale) |
{ |
int src_h = drm_rect_height(src); |
int dst_h = drm_rect_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_rect_calc_vscale); |
|
/** |
* drm_calc_hscale_relaxed - calculate the horizontal scaling factor |
* @src: source window rectangle |
* @dst: destination window rectangle |
* @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 rectangle @dst to compensate. |
* |
* If the calculated scaling factor is above @max_vscale, |
* decrease the height of rectangle @src to compensate. |
* |
* RETURNS: |
* The horizontal scaling factor. |
*/ |
int drm_rect_calc_hscale_relaxed(struct drm_rect *src, |
struct drm_rect *dst, |
int min_hscale, int max_hscale) |
{ |
int src_w = drm_rect_width(src); |
int dst_w = drm_rect_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_rect_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_rect_adjust_size(src, max_src_w - src_w, 0); |
|
return max_hscale; |
} |
|
return hscale; |
} |
EXPORT_SYMBOL(drm_rect_calc_hscale_relaxed); |
|
/** |
* drm_rect_calc_vscale_relaxed - calculate the vertical scaling factor |
* @src: source window rectangle |
* @dst: destination window rectangle |
* @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 rectangle @dst to compensate. |
* |
* If the calculated scaling factor is above @max_vscale, |
* decrease the height of rectangle @src to compensate. |
* |
* RETURNS: |
* The vertical scaling factor. |
*/ |
int drm_rect_calc_vscale_relaxed(struct drm_rect *src, |
struct drm_rect *dst, |
int min_vscale, int max_vscale) |
{ |
int src_h = drm_rect_height(src); |
int dst_h = drm_rect_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_rect_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_rect_adjust_size(src, 0, max_src_h - src_h); |
|
return max_vscale; |
} |
|
return vscale; |
} |
EXPORT_SYMBOL(drm_rect_calc_vscale_relaxed); |
|
/** |
* drm_rect_debug_print - print the rectangle information |
* @r: rectangle to print |
* @fixed_point: rectangle is in 16.16 fixed point format |
*/ |
void drm_rect_debug_print(const struct drm_rect *r, bool fixed_point) |
{ |
int w = drm_rect_width(r); |
int h = drm_rect_height(r); |
|
if (fixed_point) |
DRM_DEBUG_KMS("%d.%06ux%d.%06u%+d.%06u%+d.%06u\n", |
w >> 16, ((w & 0xffff) * 15625) >> 10, |
h >> 16, ((h & 0xffff) * 15625) >> 10, |
r->x1 >> 16, ((r->x1 & 0xffff) * 15625) >> 10, |
r->y1 >> 16, ((r->y1 & 0xffff) * 15625) >> 10); |
else |
DRM_DEBUG_KMS("%dx%d%+d%+d\n", w, h, r->x1, r->y1); |
} |
EXPORT_SYMBOL(drm_rect_debug_print); |