1b5761154SFrançois Tigeot /* 2b5761154SFrançois Tigeot * Copyright (C) 2011-2013 Intel Corporation 3b5761154SFrançois Tigeot * 4b5761154SFrançois Tigeot * Permission is hereby granted, free of charge, to any person obtaining a 5b5761154SFrançois Tigeot * copy of this software and associated documentation files (the "Software"), 6b5761154SFrançois Tigeot * to deal in the Software without restriction, including without limitation 7b5761154SFrançois Tigeot * the rights to use, copy, modify, merge, publish, distribute, sublicense, 8b5761154SFrançois Tigeot * and/or sell copies of the Software, and to permit persons to whom the 9b5761154SFrançois Tigeot * Software is furnished to do so, subject to the following conditions: 10b5761154SFrançois Tigeot * 11b5761154SFrançois Tigeot * The above copyright notice and this permission notice (including the next 12b5761154SFrançois Tigeot * paragraph) shall be included in all copies or substantial portions of the 13b5761154SFrançois Tigeot * Software. 14b5761154SFrançois Tigeot * 15b5761154SFrançois Tigeot * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16b5761154SFrançois Tigeot * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17b5761154SFrançois Tigeot * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL 18b5761154SFrançois Tigeot * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19b5761154SFrançois Tigeot * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20b5761154SFrançois Tigeot * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21b5761154SFrançois Tigeot * SOFTWARE. 22b5761154SFrançois Tigeot */ 23b5761154SFrançois Tigeot 24b5761154SFrançois Tigeot #include <linux/errno.h> 25b5761154SFrançois Tigeot #include <linux/export.h> 26b5761154SFrançois Tigeot #include <linux/kernel.h> 27b5761154SFrançois Tigeot #include <drm/drmP.h> 28b5761154SFrançois Tigeot #include <drm/drm_rect.h> 29b5761154SFrançois Tigeot 30b5761154SFrançois Tigeot /** 31b5761154SFrançois Tigeot * drm_rect_intersect - intersect two rectangles 32b5761154SFrançois Tigeot * @r1: first rectangle 33b5761154SFrançois Tigeot * @r2: second rectangle 34b5761154SFrançois Tigeot * 35b5761154SFrançois Tigeot * Calculate the intersection of rectangles @r1 and @r2. 36b5761154SFrançois Tigeot * @r1 will be overwritten with the intersection. 37b5761154SFrançois Tigeot * 38b5761154SFrançois Tigeot * RETURNS: 39b5761154SFrançois Tigeot * %true if rectangle @r1 is still visible after the operation, 40b5761154SFrançois Tigeot * %false otherwise. 41b5761154SFrançois Tigeot */ 42b5761154SFrançois Tigeot bool drm_rect_intersect(struct drm_rect *r1, const struct drm_rect *r2) 43b5761154SFrançois Tigeot { 44b5761154SFrançois Tigeot r1->x1 = max(r1->x1, r2->x1); 45b5761154SFrançois Tigeot r1->y1 = max(r1->y1, r2->y1); 46b5761154SFrançois Tigeot r1->x2 = min(r1->x2, r2->x2); 47b5761154SFrançois Tigeot r1->y2 = min(r1->y2, r2->y2); 48b5761154SFrançois Tigeot 49b5761154SFrançois Tigeot return drm_rect_visible(r1); 50b5761154SFrançois Tigeot } 51b5761154SFrançois Tigeot EXPORT_SYMBOL(drm_rect_intersect); 52b5761154SFrançois Tigeot 53b5761154SFrançois Tigeot /** 54b5761154SFrançois Tigeot * drm_rect_clip_scaled - perform a scaled clip operation 55b5761154SFrançois Tigeot * @src: source window rectangle 56b5761154SFrançois Tigeot * @dst: destination window rectangle 57b5761154SFrançois Tigeot * @clip: clip rectangle 58b5761154SFrançois Tigeot * @hscale: horizontal scaling factor 59b5761154SFrançois Tigeot * @vscale: vertical scaling factor 60b5761154SFrançois Tigeot * 61b5761154SFrançois Tigeot * Clip rectangle @dst by rectangle @clip. Clip rectangle @src by the 62b5761154SFrançois Tigeot * same amounts multiplied by @hscale and @vscale. 63b5761154SFrançois Tigeot * 64b5761154SFrançois Tigeot * RETURNS: 65b5761154SFrançois Tigeot * %true if rectangle @dst is still visible after being clipped, 66b5761154SFrançois Tigeot * %false otherwise 67b5761154SFrançois Tigeot */ 68b5761154SFrançois Tigeot bool drm_rect_clip_scaled(struct drm_rect *src, struct drm_rect *dst, 69b5761154SFrançois Tigeot const struct drm_rect *clip, 70b5761154SFrançois Tigeot int hscale, int vscale) 71b5761154SFrançois Tigeot { 72b5761154SFrançois Tigeot int diff; 73b5761154SFrançois Tigeot 74b5761154SFrançois Tigeot diff = clip->x1 - dst->x1; 75b5761154SFrançois Tigeot if (diff > 0) { 76b5761154SFrançois Tigeot int64_t tmp = src->x1 + (int64_t) diff * hscale; 77b5761154SFrançois Tigeot src->x1 = clamp_t(int64_t, tmp, INT_MIN, INT_MAX); 78b5761154SFrançois Tigeot } 79b5761154SFrançois Tigeot diff = clip->y1 - dst->y1; 80b5761154SFrançois Tigeot if (diff > 0) { 81b5761154SFrançois Tigeot int64_t tmp = src->y1 + (int64_t) diff * vscale; 82b5761154SFrançois Tigeot src->y1 = clamp_t(int64_t, tmp, INT_MIN, INT_MAX); 83b5761154SFrançois Tigeot } 84b5761154SFrançois Tigeot diff = dst->x2 - clip->x2; 85b5761154SFrançois Tigeot if (diff > 0) { 86b5761154SFrançois Tigeot int64_t tmp = src->x2 - (int64_t) diff * hscale; 87b5761154SFrançois Tigeot src->x2 = clamp_t(int64_t, tmp, INT_MIN, INT_MAX); 88b5761154SFrançois Tigeot } 89b5761154SFrançois Tigeot diff = dst->y2 - clip->y2; 90b5761154SFrançois Tigeot if (diff > 0) { 91b5761154SFrançois Tigeot int64_t tmp = src->y2 - (int64_t) diff * vscale; 92b5761154SFrançois Tigeot src->y2 = clamp_t(int64_t, tmp, INT_MIN, INT_MAX); 93b5761154SFrançois Tigeot } 94b5761154SFrançois Tigeot 95b5761154SFrançois Tigeot return drm_rect_intersect(dst, clip); 96b5761154SFrançois Tigeot } 97b5761154SFrançois Tigeot EXPORT_SYMBOL(drm_rect_clip_scaled); 98b5761154SFrançois Tigeot 99b5761154SFrançois Tigeot static int drm_calc_scale(int src, int dst) 100b5761154SFrançois Tigeot { 101b5761154SFrançois Tigeot int scale = 0; 102b5761154SFrançois Tigeot 103b5761154SFrançois Tigeot if (src < 0 || dst < 0) 104b5761154SFrançois Tigeot return -EINVAL; 105b5761154SFrançois Tigeot 106b5761154SFrançois Tigeot if (dst == 0) 107b5761154SFrançois Tigeot return 0; 108b5761154SFrançois Tigeot 109b5761154SFrançois Tigeot scale = src / dst; 110b5761154SFrançois Tigeot 111b5761154SFrançois Tigeot return scale; 112b5761154SFrançois Tigeot } 113b5761154SFrançois Tigeot 114b5761154SFrançois Tigeot /** 115b5761154SFrançois Tigeot * drm_rect_calc_hscale - calculate the horizontal scaling factor 116b5761154SFrançois Tigeot * @src: source window rectangle 117b5761154SFrançois Tigeot * @dst: destination window rectangle 118b5761154SFrançois Tigeot * @min_hscale: minimum allowed horizontal scaling factor 119b5761154SFrançois Tigeot * @max_hscale: maximum allowed horizontal scaling factor 120b5761154SFrançois Tigeot * 121b5761154SFrançois Tigeot * Calculate the horizontal scaling factor as 122b5761154SFrançois Tigeot * (@src width) / (@dst width). 123b5761154SFrançois Tigeot * 124b5761154SFrançois Tigeot * RETURNS: 125b5761154SFrançois Tigeot * The horizontal scaling factor, or errno of out of limits. 126b5761154SFrançois Tigeot */ 127b5761154SFrançois Tigeot int drm_rect_calc_hscale(const struct drm_rect *src, 128b5761154SFrançois Tigeot const struct drm_rect *dst, 129b5761154SFrançois Tigeot int min_hscale, int max_hscale) 130b5761154SFrançois Tigeot { 131b5761154SFrançois Tigeot int src_w = drm_rect_width(src); 132b5761154SFrançois Tigeot int dst_w = drm_rect_width(dst); 133b5761154SFrançois Tigeot int hscale = drm_calc_scale(src_w, dst_w); 134b5761154SFrançois Tigeot 135b5761154SFrançois Tigeot if (hscale < 0 || dst_w == 0) 136b5761154SFrançois Tigeot return hscale; 137b5761154SFrançois Tigeot 138b5761154SFrançois Tigeot if (hscale < min_hscale || hscale > max_hscale) 139b5761154SFrançois Tigeot return -ERANGE; 140b5761154SFrançois Tigeot 141b5761154SFrançois Tigeot return hscale; 142b5761154SFrançois Tigeot } 143b5761154SFrançois Tigeot EXPORT_SYMBOL(drm_rect_calc_hscale); 144b5761154SFrançois Tigeot 145b5761154SFrançois Tigeot /** 146b5761154SFrançois Tigeot * drm_rect_calc_vscale - calculate the vertical scaling factor 147b5761154SFrançois Tigeot * @src: source window rectangle 148b5761154SFrançois Tigeot * @dst: destination window rectangle 149b5761154SFrançois Tigeot * @min_vscale: minimum allowed vertical scaling factor 150b5761154SFrançois Tigeot * @max_vscale: maximum allowed vertical scaling factor 151b5761154SFrançois Tigeot * 152b5761154SFrançois Tigeot * Calculate the vertical scaling factor as 153b5761154SFrançois Tigeot * (@src height) / (@dst height). 154b5761154SFrançois Tigeot * 155b5761154SFrançois Tigeot * RETURNS: 156b5761154SFrançois Tigeot * The vertical scaling factor, or errno of out of limits. 157b5761154SFrançois Tigeot */ 158b5761154SFrançois Tigeot int drm_rect_calc_vscale(const struct drm_rect *src, 159b5761154SFrançois Tigeot const struct drm_rect *dst, 160b5761154SFrançois Tigeot int min_vscale, int max_vscale) 161b5761154SFrançois Tigeot { 162b5761154SFrançois Tigeot int src_h = drm_rect_height(src); 163b5761154SFrançois Tigeot int dst_h = drm_rect_height(dst); 164b5761154SFrançois Tigeot int vscale = drm_calc_scale(src_h, dst_h); 165b5761154SFrançois Tigeot 166b5761154SFrançois Tigeot if (vscale < 0 || dst_h == 0) 167b5761154SFrançois Tigeot return vscale; 168b5761154SFrançois Tigeot 169b5761154SFrançois Tigeot if (vscale < min_vscale || vscale > max_vscale) 170b5761154SFrançois Tigeot return -ERANGE; 171b5761154SFrançois Tigeot 172b5761154SFrançois Tigeot return vscale; 173b5761154SFrançois Tigeot } 174b5761154SFrançois Tigeot EXPORT_SYMBOL(drm_rect_calc_vscale); 175b5761154SFrançois Tigeot 176b5761154SFrançois Tigeot /** 177b5761154SFrançois Tigeot * drm_calc_hscale_relaxed - calculate the horizontal scaling factor 178b5761154SFrançois Tigeot * @src: source window rectangle 179b5761154SFrançois Tigeot * @dst: destination window rectangle 180b5761154SFrançois Tigeot * @min_hscale: minimum allowed horizontal scaling factor 181b5761154SFrançois Tigeot * @max_hscale: maximum allowed horizontal scaling factor 182b5761154SFrançois Tigeot * 183b5761154SFrançois Tigeot * Calculate the horizontal scaling factor as 184b5761154SFrançois Tigeot * (@src width) / (@dst width). 185b5761154SFrançois Tigeot * 186b5761154SFrançois Tigeot * If the calculated scaling factor is below @min_vscale, 187b5761154SFrançois Tigeot * decrease the height of rectangle @dst to compensate. 188b5761154SFrançois Tigeot * 189b5761154SFrançois Tigeot * If the calculated scaling factor is above @max_vscale, 190b5761154SFrançois Tigeot * decrease the height of rectangle @src to compensate. 191b5761154SFrançois Tigeot * 192b5761154SFrançois Tigeot * RETURNS: 193b5761154SFrançois Tigeot * The horizontal scaling factor. 194b5761154SFrançois Tigeot */ 195b5761154SFrançois Tigeot int drm_rect_calc_hscale_relaxed(struct drm_rect *src, 196b5761154SFrançois Tigeot struct drm_rect *dst, 197b5761154SFrançois Tigeot int min_hscale, int max_hscale) 198b5761154SFrançois Tigeot { 199b5761154SFrançois Tigeot int src_w = drm_rect_width(src); 200b5761154SFrançois Tigeot int dst_w = drm_rect_width(dst); 201b5761154SFrançois Tigeot int hscale = drm_calc_scale(src_w, dst_w); 202b5761154SFrançois Tigeot 203b5761154SFrançois Tigeot if (hscale < 0 || dst_w == 0) 204b5761154SFrançois Tigeot return hscale; 205b5761154SFrançois Tigeot 206b5761154SFrançois Tigeot if (hscale < min_hscale) { 207b5761154SFrançois Tigeot int max_dst_w = src_w / min_hscale; 208b5761154SFrançois Tigeot 209b5761154SFrançois Tigeot drm_rect_adjust_size(dst, max_dst_w - dst_w, 0); 210b5761154SFrançois Tigeot 211b5761154SFrançois Tigeot return min_hscale; 212b5761154SFrançois Tigeot } 213b5761154SFrançois Tigeot 214b5761154SFrançois Tigeot if (hscale > max_hscale) { 215b5761154SFrançois Tigeot int max_src_w = dst_w * max_hscale; 216b5761154SFrançois Tigeot 217b5761154SFrançois Tigeot drm_rect_adjust_size(src, max_src_w - src_w, 0); 218b5761154SFrançois Tigeot 219b5761154SFrançois Tigeot return max_hscale; 220b5761154SFrançois Tigeot } 221b5761154SFrançois Tigeot 222b5761154SFrançois Tigeot return hscale; 223b5761154SFrançois Tigeot } 224b5761154SFrançois Tigeot EXPORT_SYMBOL(drm_rect_calc_hscale_relaxed); 225b5761154SFrançois Tigeot 226b5761154SFrançois Tigeot /** 227b5761154SFrançois Tigeot * drm_rect_calc_vscale_relaxed - calculate the vertical scaling factor 228b5761154SFrançois Tigeot * @src: source window rectangle 229b5761154SFrançois Tigeot * @dst: destination window rectangle 230b5761154SFrançois Tigeot * @min_vscale: minimum allowed vertical scaling factor 231b5761154SFrançois Tigeot * @max_vscale: maximum allowed vertical scaling factor 232b5761154SFrançois Tigeot * 233b5761154SFrançois Tigeot * Calculate the vertical scaling factor as 234b5761154SFrançois Tigeot * (@src height) / (@dst height). 235b5761154SFrançois Tigeot * 236b5761154SFrançois Tigeot * If the calculated scaling factor is below @min_vscale, 237b5761154SFrançois Tigeot * decrease the height of rectangle @dst to compensate. 238b5761154SFrançois Tigeot * 239b5761154SFrançois Tigeot * If the calculated scaling factor is above @max_vscale, 240b5761154SFrançois Tigeot * decrease the height of rectangle @src to compensate. 241b5761154SFrançois Tigeot * 242b5761154SFrançois Tigeot * RETURNS: 243b5761154SFrançois Tigeot * The vertical scaling factor. 244b5761154SFrançois Tigeot */ 245b5761154SFrançois Tigeot int drm_rect_calc_vscale_relaxed(struct drm_rect *src, 246b5761154SFrançois Tigeot struct drm_rect *dst, 247b5761154SFrançois Tigeot int min_vscale, int max_vscale) 248b5761154SFrançois Tigeot { 249b5761154SFrançois Tigeot int src_h = drm_rect_height(src); 250b5761154SFrançois Tigeot int dst_h = drm_rect_height(dst); 251b5761154SFrançois Tigeot int vscale = drm_calc_scale(src_h, dst_h); 252b5761154SFrançois Tigeot 253b5761154SFrançois Tigeot if (vscale < 0 || dst_h == 0) 254b5761154SFrançois Tigeot return vscale; 255b5761154SFrançois Tigeot 256b5761154SFrançois Tigeot if (vscale < min_vscale) { 257b5761154SFrançois Tigeot int max_dst_h = src_h / min_vscale; 258b5761154SFrançois Tigeot 259b5761154SFrançois Tigeot drm_rect_adjust_size(dst, 0, max_dst_h - dst_h); 260b5761154SFrançois Tigeot 261b5761154SFrançois Tigeot return min_vscale; 262b5761154SFrançois Tigeot } 263b5761154SFrançois Tigeot 264b5761154SFrançois Tigeot if (vscale > max_vscale) { 265b5761154SFrançois Tigeot int max_src_h = dst_h * max_vscale; 266b5761154SFrançois Tigeot 267b5761154SFrançois Tigeot drm_rect_adjust_size(src, 0, max_src_h - src_h); 268b5761154SFrançois Tigeot 269b5761154SFrançois Tigeot return max_vscale; 270b5761154SFrançois Tigeot } 271b5761154SFrançois Tigeot 272b5761154SFrançois Tigeot return vscale; 273b5761154SFrançois Tigeot } 274b5761154SFrançois Tigeot EXPORT_SYMBOL(drm_rect_calc_vscale_relaxed); 275b5761154SFrançois Tigeot 276b5761154SFrançois Tigeot /** 277b5761154SFrançois Tigeot * drm_rect_debug_print - print the rectangle information 278b5761154SFrançois Tigeot * @r: rectangle to print 279b5761154SFrançois Tigeot * @fixed_point: rectangle is in 16.16 fixed point format 280b5761154SFrançois Tigeot */ 281b5761154SFrançois Tigeot void drm_rect_debug_print(const struct drm_rect *r, bool fixed_point) 282b5761154SFrançois Tigeot { 283b5761154SFrançois Tigeot int w = drm_rect_width(r); 284b5761154SFrançois Tigeot int h = drm_rect_height(r); 285b5761154SFrançois Tigeot 286b5761154SFrançois Tigeot if (fixed_point) 287b5761154SFrançois Tigeot DRM_DEBUG_KMS("%d.%06ux%d.%06u%+d.%06u%+d.%06u\n", 288b5761154SFrançois Tigeot w >> 16, ((w & 0xffff) * 15625) >> 10, 289b5761154SFrançois Tigeot h >> 16, ((h & 0xffff) * 15625) >> 10, 290b5761154SFrançois Tigeot r->x1 >> 16, ((r->x1 & 0xffff) * 15625) >> 10, 291b5761154SFrançois Tigeot r->y1 >> 16, ((r->y1 & 0xffff) * 15625) >> 10); 292b5761154SFrançois Tigeot else 293b5761154SFrançois Tigeot DRM_DEBUG_KMS("%dx%d%+d%+d\n", w, h, r->x1, r->y1); 294b5761154SFrançois Tigeot } 295b5761154SFrançois Tigeot EXPORT_SYMBOL(drm_rect_debug_print); 296*1b13d190SFrançois Tigeot 297*1b13d190SFrançois Tigeot /** 298*1b13d190SFrançois Tigeot * drm_rect_rotate - Rotate the rectangle 299*1b13d190SFrançois Tigeot * @r: rectangle to be rotated 300*1b13d190SFrançois Tigeot * @width: Width of the coordinate space 301*1b13d190SFrançois Tigeot * @height: Height of the coordinate space 302*1b13d190SFrançois Tigeot * @rotation: Transformation to be applied 303*1b13d190SFrançois Tigeot * 304*1b13d190SFrançois Tigeot * Apply @rotation to the coordinates of rectangle @r. 305*1b13d190SFrançois Tigeot * 306*1b13d190SFrançois Tigeot * @width and @height combined with @rotation define 307*1b13d190SFrançois Tigeot * the location of the new origin. 308*1b13d190SFrançois Tigeot * 309*1b13d190SFrançois Tigeot * @width correcsponds to the horizontal and @height 310*1b13d190SFrançois Tigeot * to the vertical axis of the untransformed coordinate 311*1b13d190SFrançois Tigeot * space. 312*1b13d190SFrançois Tigeot */ 313*1b13d190SFrançois Tigeot void drm_rect_rotate(struct drm_rect *r, 314*1b13d190SFrançois Tigeot int width, int height, 315*1b13d190SFrançois Tigeot unsigned int rotation) 316*1b13d190SFrançois Tigeot { 317*1b13d190SFrançois Tigeot struct drm_rect tmp; 318*1b13d190SFrançois Tigeot 319*1b13d190SFrançois Tigeot if (rotation & (BIT(DRM_REFLECT_X) | BIT(DRM_REFLECT_Y))) { 320*1b13d190SFrançois Tigeot tmp = *r; 321*1b13d190SFrançois Tigeot 322*1b13d190SFrançois Tigeot if (rotation & BIT(DRM_REFLECT_X)) { 323*1b13d190SFrançois Tigeot r->x1 = width - tmp.x2; 324*1b13d190SFrançois Tigeot r->x2 = width - tmp.x1; 325*1b13d190SFrançois Tigeot } 326*1b13d190SFrançois Tigeot 327*1b13d190SFrançois Tigeot if (rotation & BIT(DRM_REFLECT_Y)) { 328*1b13d190SFrançois Tigeot r->y1 = height - tmp.y2; 329*1b13d190SFrançois Tigeot r->y2 = height - tmp.y1; 330*1b13d190SFrançois Tigeot } 331*1b13d190SFrançois Tigeot } 332*1b13d190SFrançois Tigeot 333*1b13d190SFrançois Tigeot switch (rotation & 0xf) { 334*1b13d190SFrançois Tigeot case BIT(DRM_ROTATE_0): 335*1b13d190SFrançois Tigeot break; 336*1b13d190SFrançois Tigeot case BIT(DRM_ROTATE_90): 337*1b13d190SFrançois Tigeot tmp = *r; 338*1b13d190SFrançois Tigeot r->x1 = tmp.y1; 339*1b13d190SFrançois Tigeot r->x2 = tmp.y2; 340*1b13d190SFrançois Tigeot r->y1 = width - tmp.x2; 341*1b13d190SFrançois Tigeot r->y2 = width - tmp.x1; 342*1b13d190SFrançois Tigeot break; 343*1b13d190SFrançois Tigeot case BIT(DRM_ROTATE_180): 344*1b13d190SFrançois Tigeot tmp = *r; 345*1b13d190SFrançois Tigeot r->x1 = width - tmp.x2; 346*1b13d190SFrançois Tigeot r->x2 = width - tmp.x1; 347*1b13d190SFrançois Tigeot r->y1 = height - tmp.y2; 348*1b13d190SFrançois Tigeot r->y2 = height - tmp.y1; 349*1b13d190SFrançois Tigeot break; 350*1b13d190SFrançois Tigeot case BIT(DRM_ROTATE_270): 351*1b13d190SFrançois Tigeot tmp = *r; 352*1b13d190SFrançois Tigeot r->x1 = height - tmp.y2; 353*1b13d190SFrançois Tigeot r->x2 = height - tmp.y1; 354*1b13d190SFrançois Tigeot r->y1 = tmp.x1; 355*1b13d190SFrançois Tigeot r->y2 = tmp.x2; 356*1b13d190SFrançois Tigeot break; 357*1b13d190SFrançois Tigeot default: 358*1b13d190SFrançois Tigeot break; 359*1b13d190SFrançois Tigeot } 360*1b13d190SFrançois Tigeot } 361*1b13d190SFrançois Tigeot EXPORT_SYMBOL(drm_rect_rotate); 362*1b13d190SFrançois Tigeot 363*1b13d190SFrançois Tigeot /** 364*1b13d190SFrançois Tigeot * drm_rect_rotate_inv - Inverse rotate the rectangle 365*1b13d190SFrançois Tigeot * @r: rectangle to be rotated 366*1b13d190SFrançois Tigeot * @width: Width of the coordinate space 367*1b13d190SFrançois Tigeot * @height: Height of the coordinate space 368*1b13d190SFrançois Tigeot * @rotation: Transformation whose inverse is to be applied 369*1b13d190SFrançois Tigeot * 370*1b13d190SFrançois Tigeot * Apply the inverse of @rotation to the coordinates 371*1b13d190SFrançois Tigeot * of rectangle @r. 372*1b13d190SFrançois Tigeot * 373*1b13d190SFrançois Tigeot * @width and @height combined with @rotation define 374*1b13d190SFrançois Tigeot * the location of the new origin. 375*1b13d190SFrançois Tigeot * 376*1b13d190SFrançois Tigeot * @width correcsponds to the horizontal and @height 377*1b13d190SFrançois Tigeot * to the vertical axis of the original untransformed 378*1b13d190SFrançois Tigeot * coordinate space, so that you never have to flip 379*1b13d190SFrançois Tigeot * them when doing a rotatation and its inverse. 380*1b13d190SFrançois Tigeot * That is, if you do: 381*1b13d190SFrançois Tigeot * 382*1b13d190SFrançois Tigeot * drm_rotate(&r, width, height, rotation); 383*1b13d190SFrançois Tigeot * drm_rotate_inv(&r, width, height, rotation); 384*1b13d190SFrançois Tigeot * 385*1b13d190SFrançois Tigeot * you will always get back the original rectangle. 386*1b13d190SFrançois Tigeot */ 387*1b13d190SFrançois Tigeot void drm_rect_rotate_inv(struct drm_rect *r, 388*1b13d190SFrançois Tigeot int width, int height, 389*1b13d190SFrançois Tigeot unsigned int rotation) 390*1b13d190SFrançois Tigeot { 391*1b13d190SFrançois Tigeot struct drm_rect tmp; 392*1b13d190SFrançois Tigeot 393*1b13d190SFrançois Tigeot switch (rotation & 0xf) { 394*1b13d190SFrançois Tigeot case BIT(DRM_ROTATE_0): 395*1b13d190SFrançois Tigeot break; 396*1b13d190SFrançois Tigeot case BIT(DRM_ROTATE_90): 397*1b13d190SFrançois Tigeot tmp = *r; 398*1b13d190SFrançois Tigeot r->x1 = width - tmp.y2; 399*1b13d190SFrançois Tigeot r->x2 = width - tmp.y1; 400*1b13d190SFrançois Tigeot r->y1 = tmp.x1; 401*1b13d190SFrançois Tigeot r->y2 = tmp.x2; 402*1b13d190SFrançois Tigeot break; 403*1b13d190SFrançois Tigeot case BIT(DRM_ROTATE_180): 404*1b13d190SFrançois Tigeot tmp = *r; 405*1b13d190SFrançois Tigeot r->x1 = width - tmp.x2; 406*1b13d190SFrançois Tigeot r->x2 = width - tmp.x1; 407*1b13d190SFrançois Tigeot r->y1 = height - tmp.y2; 408*1b13d190SFrançois Tigeot r->y2 = height - tmp.y1; 409*1b13d190SFrançois Tigeot break; 410*1b13d190SFrançois Tigeot case BIT(DRM_ROTATE_270): 411*1b13d190SFrançois Tigeot tmp = *r; 412*1b13d190SFrançois Tigeot r->x1 = tmp.y1; 413*1b13d190SFrançois Tigeot r->x2 = tmp.y2; 414*1b13d190SFrançois Tigeot r->y1 = height - tmp.x2; 415*1b13d190SFrançois Tigeot r->y2 = height - tmp.x1; 416*1b13d190SFrançois Tigeot break; 417*1b13d190SFrançois Tigeot default: 418*1b13d190SFrançois Tigeot break; 419*1b13d190SFrançois Tigeot } 420*1b13d190SFrançois Tigeot 421*1b13d190SFrançois Tigeot if (rotation & (BIT(DRM_REFLECT_X) | BIT(DRM_REFLECT_Y))) { 422*1b13d190SFrançois Tigeot tmp = *r; 423*1b13d190SFrançois Tigeot 424*1b13d190SFrançois Tigeot if (rotation & BIT(DRM_REFLECT_X)) { 425*1b13d190SFrançois Tigeot r->x1 = width - tmp.x2; 426*1b13d190SFrançois Tigeot r->x2 = width - tmp.x1; 427*1b13d190SFrançois Tigeot } 428*1b13d190SFrançois Tigeot 429*1b13d190SFrançois Tigeot if (rotation & BIT(DRM_REFLECT_Y)) { 430*1b13d190SFrançois Tigeot r->y1 = height - tmp.y2; 431*1b13d190SFrançois Tigeot r->y2 = height - tmp.y1; 432*1b13d190SFrançois Tigeot } 433*1b13d190SFrançois Tigeot } 434*1b13d190SFrançois Tigeot } 435*1b13d190SFrançois Tigeot EXPORT_SYMBOL(drm_rect_rotate_inv); 436