2 * Copyright (C) 2011-2013 Intel Corporation
4 * Permission is hereby granted, free of charge, to any person obtaining a
5 * copy of this software and associated documentation files (the "Software"),
6 * to deal in the Software without restriction, including without limitation
7 * the rights to use, copy, modify, merge, publish, distribute, sublicense,
8 * and/or sell copies of the Software, and to permit persons to whom the
9 * Software is furnished to do so, subject to the following conditions:
11 * The above copyright notice and this permission notice (including the next
12 * paragraph) shall be included in all copies or substantial portions of the
15 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
18 * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
24 #include <linux/errno.h>
25 #include <linux/export.h>
26 #include <linux/kernel.h>
28 #include <drm/drm_rect.h>
31 * drm_rect_intersect - intersect two rectangles
32 * @r1: first rectangle
33 * @r2: second rectangle
35 * Calculate the intersection of rectangles @r1 and @r2.
36 * @r1 will be overwritten with the intersection.
39 * %true if rectangle @r1 is still visible after the operation,
42 bool drm_rect_intersect(struct drm_rect *r1, const struct drm_rect *r2)
44 r1->x1 = max(r1->x1, r2->x1);
45 r1->y1 = max(r1->y1, r2->y1);
46 r1->x2 = min(r1->x2, r2->x2);
47 r1->y2 = min(r1->y2, r2->y2);
49 return drm_rect_visible(r1);
51 EXPORT_SYMBOL(drm_rect_intersect);
54 * drm_rect_clip_scaled - perform a scaled clip operation
55 * @src: source window rectangle
56 * @dst: destination window rectangle
57 * @clip: clip rectangle
58 * @hscale: horizontal scaling factor
59 * @vscale: vertical scaling factor
61 * Clip rectangle @dst by rectangle @clip. Clip rectangle @src by the
62 * same amounts multiplied by @hscale and @vscale.
65 * %true if rectangle @dst is still visible after being clipped,
68 bool drm_rect_clip_scaled(struct drm_rect *src, struct drm_rect *dst,
69 const struct drm_rect *clip,
70 int hscale, int vscale)
74 diff = clip->x1 - dst->x1;
76 int64_t tmp = src->x1 + (int64_t) diff * hscale;
77 src->x1 = clamp_t(int64_t, tmp, INT_MIN, INT_MAX);
79 diff = clip->y1 - dst->y1;
81 int64_t tmp = src->y1 + (int64_t) diff * vscale;
82 src->y1 = clamp_t(int64_t, tmp, INT_MIN, INT_MAX);
84 diff = dst->x2 - clip->x2;
86 int64_t tmp = src->x2 - (int64_t) diff * hscale;
87 src->x2 = clamp_t(int64_t, tmp, INT_MIN, INT_MAX);
89 diff = dst->y2 - clip->y2;
91 int64_t tmp = src->y2 - (int64_t) diff * vscale;
92 src->y2 = clamp_t(int64_t, tmp, INT_MIN, INT_MAX);
95 return drm_rect_intersect(dst, clip);
97 EXPORT_SYMBOL(drm_rect_clip_scaled);
99 static int drm_calc_scale(int src, int dst)
103 if (WARN_ON(src < 0 || dst < 0))
109 if (src > (dst << 16))
110 return DIV_ROUND_UP(src, dst);
118 * drm_rect_calc_hscale - calculate the horizontal scaling factor
119 * @src: source window rectangle
120 * @dst: destination window rectangle
121 * @min_hscale: minimum allowed horizontal scaling factor
122 * @max_hscale: maximum allowed horizontal scaling factor
124 * Calculate the horizontal scaling factor as
125 * (@src width) / (@dst width).
127 * If the scale is below 1 << 16, round down. If the scale is above
128 * 1 << 16, round up. This will calculate the scale with the most
129 * pessimistic limit calculation.
132 * The horizontal scaling factor, or errno of out of limits.
134 int drm_rect_calc_hscale(const struct drm_rect *src,
135 const struct drm_rect *dst,
136 int min_hscale, int max_hscale)
138 int src_w = drm_rect_width(src);
139 int dst_w = drm_rect_width(dst);
140 int hscale = drm_calc_scale(src_w, dst_w);
142 if (hscale < 0 || dst_w == 0)
145 if (hscale < min_hscale || hscale > max_hscale)
150 EXPORT_SYMBOL(drm_rect_calc_hscale);
153 * drm_rect_calc_vscale - calculate the vertical scaling factor
154 * @src: source window rectangle
155 * @dst: destination window rectangle
156 * @min_vscale: minimum allowed vertical scaling factor
157 * @max_vscale: maximum allowed vertical scaling factor
159 * Calculate the vertical scaling factor as
160 * (@src height) / (@dst height).
162 * If the scale is below 1 << 16, round down. If the scale is above
163 * 1 << 16, round up. This will calculate the scale with the most
164 * pessimistic limit calculation.
167 * The vertical scaling factor, or errno of out of limits.
169 int drm_rect_calc_vscale(const struct drm_rect *src,
170 const struct drm_rect *dst,
171 int min_vscale, int max_vscale)
173 int src_h = drm_rect_height(src);
174 int dst_h = drm_rect_height(dst);
175 int vscale = drm_calc_scale(src_h, dst_h);
177 if (vscale < 0 || dst_h == 0)
180 if (vscale < min_vscale || vscale > max_vscale)
185 EXPORT_SYMBOL(drm_rect_calc_vscale);
188 * drm_calc_hscale_relaxed - calculate the horizontal scaling factor
189 * @src: source window rectangle
190 * @dst: destination window rectangle
191 * @min_hscale: minimum allowed horizontal scaling factor
192 * @max_hscale: maximum allowed horizontal scaling factor
194 * Calculate the horizontal scaling factor as
195 * (@src width) / (@dst width).
197 * If the calculated scaling factor is below @min_vscale,
198 * decrease the height of rectangle @dst to compensate.
200 * If the calculated scaling factor is above @max_vscale,
201 * decrease the height of rectangle @src to compensate.
203 * If the scale is below 1 << 16, round down. If the scale is above
204 * 1 << 16, round up. This will calculate the scale with the most
205 * pessimistic limit calculation.
208 * The horizontal scaling factor.
210 int drm_rect_calc_hscale_relaxed(struct drm_rect *src,
211 struct drm_rect *dst,
212 int min_hscale, int max_hscale)
214 int src_w = drm_rect_width(src);
215 int dst_w = drm_rect_width(dst);
216 int hscale = drm_calc_scale(src_w, dst_w);
218 if (hscale < 0 || dst_w == 0)
221 if (hscale < min_hscale) {
222 int max_dst_w = src_w / min_hscale;
224 drm_rect_adjust_size(dst, max_dst_w - dst_w, 0);
229 if (hscale > max_hscale) {
230 int max_src_w = dst_w * max_hscale;
232 drm_rect_adjust_size(src, max_src_w - src_w, 0);
239 EXPORT_SYMBOL(drm_rect_calc_hscale_relaxed);
242 * drm_rect_calc_vscale_relaxed - calculate the vertical scaling factor
243 * @src: source window rectangle
244 * @dst: destination window rectangle
245 * @min_vscale: minimum allowed vertical scaling factor
246 * @max_vscale: maximum allowed vertical scaling factor
248 * Calculate the vertical scaling factor as
249 * (@src height) / (@dst height).
251 * If the calculated scaling factor is below @min_vscale,
252 * decrease the height of rectangle @dst to compensate.
254 * If the calculated scaling factor is above @max_vscale,
255 * decrease the height of rectangle @src to compensate.
257 * If the scale is below 1 << 16, round down. If the scale is above
258 * 1 << 16, round up. This will calculate the scale with the most
259 * pessimistic limit calculation.
262 * The vertical scaling factor.
264 int drm_rect_calc_vscale_relaxed(struct drm_rect *src,
265 struct drm_rect *dst,
266 int min_vscale, int max_vscale)
268 int src_h = drm_rect_height(src);
269 int dst_h = drm_rect_height(dst);
270 int vscale = drm_calc_scale(src_h, dst_h);
272 if (vscale < 0 || dst_h == 0)
275 if (vscale < min_vscale) {
276 int max_dst_h = src_h / min_vscale;
278 drm_rect_adjust_size(dst, 0, max_dst_h - dst_h);
283 if (vscale > max_vscale) {
284 int max_src_h = dst_h * max_vscale;
286 drm_rect_adjust_size(src, 0, max_src_h - src_h);
293 EXPORT_SYMBOL(drm_rect_calc_vscale_relaxed);
296 * drm_rect_debug_print - print the rectangle information
297 * @prefix: prefix string
298 * @r: rectangle to print
299 * @fixed_point: rectangle is in 16.16 fixed point format
301 void drm_rect_debug_print(const char *prefix, const struct drm_rect *r, bool fixed_point)
304 DRM_DEBUG_KMS("%s" DRM_RECT_FP_FMT "\n", prefix, DRM_RECT_FP_ARG(r));
306 DRM_DEBUG_KMS("%s" DRM_RECT_FMT "\n", prefix, DRM_RECT_ARG(r));
308 EXPORT_SYMBOL(drm_rect_debug_print);
311 * drm_rect_rotate - Rotate the rectangle
312 * @r: rectangle to be rotated
313 * @width: Width of the coordinate space
314 * @height: Height of the coordinate space
315 * @rotation: Transformation to be applied
317 * Apply @rotation to the coordinates of rectangle @r.
319 * @width and @height combined with @rotation define
320 * the location of the new origin.
322 * @width correcsponds to the horizontal and @height
323 * to the vertical axis of the untransformed coordinate
326 void drm_rect_rotate(struct drm_rect *r,
327 int width, int height,
328 unsigned int rotation)
332 if (rotation & (DRM_MODE_REFLECT_X | DRM_MODE_REFLECT_Y)) {
335 if (rotation & DRM_MODE_REFLECT_X) {
336 r->x1 = width - tmp.x2;
337 r->x2 = width - tmp.x1;
340 if (rotation & DRM_MODE_REFLECT_Y) {
341 r->y1 = height - tmp.y2;
342 r->y2 = height - tmp.y1;
346 switch (rotation & DRM_MODE_ROTATE_MASK) {
347 case DRM_MODE_ROTATE_0:
349 case DRM_MODE_ROTATE_90:
353 r->y1 = width - tmp.x2;
354 r->y2 = width - tmp.x1;
356 case DRM_MODE_ROTATE_180:
358 r->x1 = width - tmp.x2;
359 r->x2 = width - tmp.x1;
360 r->y1 = height - tmp.y2;
361 r->y2 = height - tmp.y1;
363 case DRM_MODE_ROTATE_270:
365 r->x1 = height - tmp.y2;
366 r->x2 = height - tmp.y1;
374 EXPORT_SYMBOL(drm_rect_rotate);
377 * drm_rect_rotate_inv - Inverse rotate the rectangle
378 * @r: rectangle to be rotated
379 * @width: Width of the coordinate space
380 * @height: Height of the coordinate space
381 * @rotation: Transformation whose inverse is to be applied
383 * Apply the inverse of @rotation to the coordinates
386 * @width and @height combined with @rotation define
387 * the location of the new origin.
389 * @width correcsponds to the horizontal and @height
390 * to the vertical axis of the original untransformed
391 * coordinate space, so that you never have to flip
392 * them when doing a rotatation and its inverse.
393 * That is, if you do ::
395 * drm_rect_rotate(&r, width, height, rotation);
396 * drm_rect_rotate_inv(&r, width, height, rotation);
398 * you will always get back the original rectangle.
400 void drm_rect_rotate_inv(struct drm_rect *r,
401 int width, int height,
402 unsigned int rotation)
406 switch (rotation & DRM_MODE_ROTATE_MASK) {
407 case DRM_MODE_ROTATE_0:
409 case DRM_MODE_ROTATE_90:
411 r->x1 = width - tmp.y2;
412 r->x2 = width - tmp.y1;
416 case DRM_MODE_ROTATE_180:
418 r->x1 = width - tmp.x2;
419 r->x2 = width - tmp.x1;
420 r->y1 = height - tmp.y2;
421 r->y2 = height - tmp.y1;
423 case DRM_MODE_ROTATE_270:
427 r->y1 = height - tmp.x2;
428 r->y2 = height - tmp.x1;
434 if (rotation & (DRM_MODE_REFLECT_X | DRM_MODE_REFLECT_Y)) {
437 if (rotation & DRM_MODE_REFLECT_X) {
438 r->x1 = width - tmp.x2;
439 r->x2 = width - tmp.x1;
442 if (rotation & DRM_MODE_REFLECT_Y) {
443 r->y1 = height - tmp.y2;
444 r->y2 = height - tmp.y1;
448 EXPORT_SYMBOL(drm_rect_rotate_inv);