1 /* $OpenBSD: drm_rect.c,v 1.1 2015/09/23 23:12:11 kettenis Exp $ */ 2 /* 3 * Copyright (C) 2011-2013 Intel Corporation 4 * 5 * Permission is hereby granted, free of charge, to any person obtaining a 6 * copy of this software and associated documentation files (the "Software"), 7 * to deal in the Software without restriction, including without limitation 8 * the rights to use, copy, modify, merge, publish, distribute, sublicense, 9 * and/or sell copies of the Software, and to permit persons to whom the 10 * Software is furnished to do so, subject to the following conditions: 11 * 12 * The above copyright notice and this permission notice (including the next 13 * paragraph) shall be included in all copies or substantial portions of the 14 * Software. 15 * 16 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 17 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 18 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL 19 * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 20 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 21 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 22 * SOFTWARE. 23 */ 24 25 #include <dev/pci/drm/drmP.h> 26 #include <dev/pci/drm/drm_rect.h> 27 28 /** 29 * drm_rect_intersect - intersect two rectangles 30 * @r1: first rectangle 31 * @r2: second rectangle 32 * 33 * Calculate the intersection of rectangles @r1 and @r2. 34 * @r1 will be overwritten with the intersection. 35 * 36 * RETURNS: 37 * %true if rectangle @r1 is still visible after the operation, 38 * %false otherwise. 39 */ 40 bool drm_rect_intersect(struct drm_rect *r1, const struct drm_rect *r2) 41 { 42 r1->x1 = max(r1->x1, r2->x1); 43 r1->y1 = max(r1->y1, r2->y1); 44 r1->x2 = min(r1->x2, r2->x2); 45 r1->y2 = min(r1->y2, r2->y2); 46 47 return drm_rect_visible(r1); 48 } 49 EXPORT_SYMBOL(drm_rect_intersect); 50 51 /** 52 * drm_rect_clip_scaled - perform a scaled clip operation 53 * @src: source window rectangle 54 * @dst: destination window rectangle 55 * @clip: clip rectangle 56 * @hscale: horizontal scaling factor 57 * @vscale: vertical scaling factor 58 * 59 * Clip rectangle @dst by rectangle @clip. Clip rectangle @src by the 60 * same amounts multiplied by @hscale and @vscale. 61 * 62 * RETURNS: 63 * %true if rectangle @dst is still visible after being clipped, 64 * %false otherwise 65 */ 66 bool drm_rect_clip_scaled(struct drm_rect *src, struct drm_rect *dst, 67 const struct drm_rect *clip, 68 int hscale, int vscale) 69 { 70 int diff; 71 72 diff = clip->x1 - dst->x1; 73 if (diff > 0) { 74 int64_t tmp = src->x1 + (int64_t) diff * hscale; 75 src->x1 = clamp_t(int64_t, tmp, INT_MIN, INT_MAX); 76 } 77 diff = clip->y1 - dst->y1; 78 if (diff > 0) { 79 int64_t tmp = src->y1 + (int64_t) diff * vscale; 80 src->y1 = clamp_t(int64_t, tmp, INT_MIN, INT_MAX); 81 } 82 diff = dst->x2 - clip->x2; 83 if (diff > 0) { 84 int64_t tmp = src->x2 - (int64_t) diff * hscale; 85 src->x2 = clamp_t(int64_t, tmp, INT_MIN, INT_MAX); 86 } 87 diff = dst->y2 - clip->y2; 88 if (diff > 0) { 89 int64_t tmp = src->y2 - (int64_t) diff * vscale; 90 src->y2 = clamp_t(int64_t, tmp, INT_MIN, INT_MAX); 91 } 92 93 return drm_rect_intersect(dst, clip); 94 } 95 EXPORT_SYMBOL(drm_rect_clip_scaled); 96 97 static int drm_calc_scale(int src, int dst) 98 { 99 int scale = 0; 100 101 if (src < 0 || dst < 0) 102 return -EINVAL; 103 104 if (dst == 0) 105 return 0; 106 107 scale = src / dst; 108 109 return scale; 110 } 111 112 /** 113 * drm_rect_calc_hscale - calculate the horizontal scaling factor 114 * @src: source window rectangle 115 * @dst: destination window rectangle 116 * @min_hscale: minimum allowed horizontal scaling factor 117 * @max_hscale: maximum allowed horizontal scaling factor 118 * 119 * Calculate the horizontal scaling factor as 120 * (@src width) / (@dst width). 121 * 122 * RETURNS: 123 * The horizontal scaling factor, or errno of out of limits. 124 */ 125 int drm_rect_calc_hscale(const struct drm_rect *src, 126 const struct drm_rect *dst, 127 int min_hscale, int max_hscale) 128 { 129 int src_w = drm_rect_width(src); 130 int dst_w = drm_rect_width(dst); 131 int hscale = drm_calc_scale(src_w, dst_w); 132 133 if (hscale < 0 || dst_w == 0) 134 return hscale; 135 136 if (hscale < min_hscale || hscale > max_hscale) 137 return -ERANGE; 138 139 return hscale; 140 } 141 EXPORT_SYMBOL(drm_rect_calc_hscale); 142 143 /** 144 * drm_rect_calc_vscale - calculate the vertical scaling factor 145 * @src: source window rectangle 146 * @dst: destination window rectangle 147 * @min_vscale: minimum allowed vertical scaling factor 148 * @max_vscale: maximum allowed vertical scaling factor 149 * 150 * Calculate the vertical scaling factor as 151 * (@src height) / (@dst height). 152 * 153 * RETURNS: 154 * The vertical scaling factor, or errno of out of limits. 155 */ 156 int drm_rect_calc_vscale(const struct drm_rect *src, 157 const struct drm_rect *dst, 158 int min_vscale, int max_vscale) 159 { 160 int src_h = drm_rect_height(src); 161 int dst_h = drm_rect_height(dst); 162 int vscale = drm_calc_scale(src_h, dst_h); 163 164 if (vscale < 0 || dst_h == 0) 165 return vscale; 166 167 if (vscale < min_vscale || vscale > max_vscale) 168 return -ERANGE; 169 170 return vscale; 171 } 172 EXPORT_SYMBOL(drm_rect_calc_vscale); 173 174 /** 175 * drm_calc_hscale_relaxed - calculate the horizontal scaling factor 176 * @src: source window rectangle 177 * @dst: destination window rectangle 178 * @min_hscale: minimum allowed horizontal scaling factor 179 * @max_hscale: maximum allowed horizontal scaling factor 180 * 181 * Calculate the horizontal scaling factor as 182 * (@src width) / (@dst width). 183 * 184 * If the calculated scaling factor is below @min_vscale, 185 * decrease the height of rectangle @dst to compensate. 186 * 187 * If the calculated scaling factor is above @max_vscale, 188 * decrease the height of rectangle @src to compensate. 189 * 190 * RETURNS: 191 * The horizontal scaling factor. 192 */ 193 int drm_rect_calc_hscale_relaxed(struct drm_rect *src, 194 struct drm_rect *dst, 195 int min_hscale, int max_hscale) 196 { 197 int src_w = drm_rect_width(src); 198 int dst_w = drm_rect_width(dst); 199 int hscale = drm_calc_scale(src_w, dst_w); 200 201 if (hscale < 0 || dst_w == 0) 202 return hscale; 203 204 if (hscale < min_hscale) { 205 int max_dst_w = src_w / min_hscale; 206 207 drm_rect_adjust_size(dst, max_dst_w - dst_w, 0); 208 209 return min_hscale; 210 } 211 212 if (hscale > max_hscale) { 213 int max_src_w = dst_w * max_hscale; 214 215 drm_rect_adjust_size(src, max_src_w - src_w, 0); 216 217 return max_hscale; 218 } 219 220 return hscale; 221 } 222 EXPORT_SYMBOL(drm_rect_calc_hscale_relaxed); 223 224 /** 225 * drm_rect_calc_vscale_relaxed - calculate the vertical scaling factor 226 * @src: source window rectangle 227 * @dst: destination window rectangle 228 * @min_vscale: minimum allowed vertical scaling factor 229 * @max_vscale: maximum allowed vertical scaling factor 230 * 231 * Calculate the vertical scaling factor as 232 * (@src height) / (@dst height). 233 * 234 * If the calculated scaling factor is below @min_vscale, 235 * decrease the height of rectangle @dst to compensate. 236 * 237 * If the calculated scaling factor is above @max_vscale, 238 * decrease the height of rectangle @src to compensate. 239 * 240 * RETURNS: 241 * The vertical scaling factor. 242 */ 243 int drm_rect_calc_vscale_relaxed(struct drm_rect *src, 244 struct drm_rect *dst, 245 int min_vscale, int max_vscale) 246 { 247 int src_h = drm_rect_height(src); 248 int dst_h = drm_rect_height(dst); 249 int vscale = drm_calc_scale(src_h, dst_h); 250 251 if (vscale < 0 || dst_h == 0) 252 return vscale; 253 254 if (vscale < min_vscale) { 255 int max_dst_h = src_h / min_vscale; 256 257 drm_rect_adjust_size(dst, 0, max_dst_h - dst_h); 258 259 return min_vscale; 260 } 261 262 if (vscale > max_vscale) { 263 int max_src_h = dst_h * max_vscale; 264 265 drm_rect_adjust_size(src, 0, max_src_h - src_h); 266 267 return max_vscale; 268 } 269 270 return vscale; 271 } 272 EXPORT_SYMBOL(drm_rect_calc_vscale_relaxed); 273 274 /** 275 * drm_rect_debug_print - print the rectangle information 276 * @r: rectangle to print 277 * @fixed_point: rectangle is in 16.16 fixed point format 278 */ 279 void drm_rect_debug_print(const struct drm_rect *r, bool fixed_point) 280 { 281 #ifdef DRMDEBUG 282 int w = drm_rect_width(r); 283 int h = drm_rect_height(r); 284 #endif 285 286 if (fixed_point) 287 DRM_DEBUG_KMS("%d.%06ux%d.%06u%+d.%06u%+d.%06u\n", 288 w >> 16, ((w & 0xffff) * 15625) >> 10, 289 h >> 16, ((h & 0xffff) * 15625) >> 10, 290 r->x1 >> 16, ((r->x1 & 0xffff) * 15625) >> 10, 291 r->y1 >> 16, ((r->y1 & 0xffff) * 15625) >> 10); 292 else 293 DRM_DEBUG_KMS("%dx%d%+d%+d\n", w, h, r->x1, r->y1); 294 } 295 EXPORT_SYMBOL(drm_rect_debug_print); 296