| .. | .. |
|---|
| 24 | 24 | #include <linux/errno.h> |
|---|
| 25 | 25 | #include <linux/export.h> |
|---|
| 26 | 26 | #include <linux/kernel.h> |
|---|
| 27 | | -#include <drm/drmP.h> |
|---|
| 27 | + |
|---|
| 28 | +#include <drm/drm_mode.h> |
|---|
| 29 | +#include <drm/drm_print.h> |
|---|
| 28 | 30 | #include <drm/drm_rect.h> |
|---|
| 29 | 31 | |
|---|
| 30 | 32 | /** |
|---|
| .. | .. |
|---|
| 50 | 52 | } |
|---|
| 51 | 53 | EXPORT_SYMBOL(drm_rect_intersect); |
|---|
| 52 | 54 | |
|---|
| 53 | | -static u32 clip_scaled(u32 src, u32 dst, u32 clip) |
|---|
| 55 | +static u32 clip_scaled(int src, int dst, int *clip) |
|---|
| 54 | 56 | { |
|---|
| 55 | 57 | u64 tmp; |
|---|
| 56 | 58 | |
|---|
| 57 | 59 | if (dst == 0) |
|---|
| 58 | 60 | return 0; |
|---|
| 59 | 61 | |
|---|
| 60 | | - tmp = mul_u32_u32(src, dst - clip); |
|---|
| 62 | + /* Only clip what we have. Keeps the result bounded. */ |
|---|
| 63 | + *clip = min(*clip, dst); |
|---|
| 64 | + |
|---|
| 65 | + tmp = mul_u32_u32(src, dst - *clip); |
|---|
| 61 | 66 | |
|---|
| 62 | 67 | /* |
|---|
| 63 | 68 | * Round toward 1.0 when clipping so that we don't accidentally |
|---|
| .. | .. |
|---|
| 76 | 81 | * @clip: clip rectangle |
|---|
| 77 | 82 | * |
|---|
| 78 | 83 | * Clip rectangle @dst by rectangle @clip. Clip rectangle @src by the |
|---|
| 79 | | - * same amounts multiplied by @hscale and @vscale. |
|---|
| 84 | + * the corresponding amounts, retaining the vertical and horizontal scaling |
|---|
| 85 | + * factors from @src to @dst. |
|---|
| 80 | 86 | * |
|---|
| 81 | 87 | * RETURNS: |
|---|
| 88 | + * |
|---|
| 82 | 89 | * %true if rectangle @dst is still visible after being clipped, |
|---|
| 83 | | - * %false otherwise |
|---|
| 90 | + * %false otherwise. |
|---|
| 84 | 91 | */ |
|---|
| 85 | 92 | bool drm_rect_clip_scaled(struct drm_rect *src, struct drm_rect *dst, |
|---|
| 86 | 93 | const struct drm_rect *clip) |
|---|
| .. | .. |
|---|
| 90 | 97 | diff = clip->x1 - dst->x1; |
|---|
| 91 | 98 | if (diff > 0) { |
|---|
| 92 | 99 | u32 new_src_w = clip_scaled(drm_rect_width(src), |
|---|
| 93 | | - drm_rect_width(dst), diff); |
|---|
| 100 | + drm_rect_width(dst), &diff); |
|---|
| 94 | 101 | |
|---|
| 95 | | - src->x1 = clamp_t(int64_t, src->x2 - new_src_w, INT_MIN, INT_MAX); |
|---|
| 96 | | - dst->x1 = clip->x1; |
|---|
| 102 | + src->x1 = src->x2 - new_src_w; |
|---|
| 103 | + dst->x1 += diff; |
|---|
| 97 | 104 | } |
|---|
| 98 | 105 | diff = clip->y1 - dst->y1; |
|---|
| 99 | 106 | if (diff > 0) { |
|---|
| 100 | 107 | u32 new_src_h = clip_scaled(drm_rect_height(src), |
|---|
| 101 | | - drm_rect_height(dst), diff); |
|---|
| 108 | + drm_rect_height(dst), &diff); |
|---|
| 102 | 109 | |
|---|
| 103 | | - src->y1 = clamp_t(int64_t, src->y2 - new_src_h, INT_MIN, INT_MAX); |
|---|
| 104 | | - dst->y1 = clip->y1; |
|---|
| 110 | + src->y1 = src->y2 - new_src_h; |
|---|
| 111 | + dst->y1 += diff; |
|---|
| 105 | 112 | } |
|---|
| 106 | 113 | diff = dst->x2 - clip->x2; |
|---|
| 107 | 114 | if (diff > 0) { |
|---|
| 108 | 115 | u32 new_src_w = clip_scaled(drm_rect_width(src), |
|---|
| 109 | | - drm_rect_width(dst), diff); |
|---|
| 116 | + drm_rect_width(dst), &diff); |
|---|
| 110 | 117 | |
|---|
| 111 | | - src->x2 = clamp_t(int64_t, src->x1 + new_src_w, INT_MIN, INT_MAX); |
|---|
| 112 | | - dst->x2 = clip->x2; |
|---|
| 118 | + src->x2 = src->x1 + new_src_w; |
|---|
| 119 | + dst->x2 -= diff; |
|---|
| 113 | 120 | } |
|---|
| 114 | 121 | diff = dst->y2 - clip->y2; |
|---|
| 115 | 122 | if (diff > 0) { |
|---|
| 116 | 123 | u32 new_src_h = clip_scaled(drm_rect_height(src), |
|---|
| 117 | | - drm_rect_height(dst), diff); |
|---|
| 124 | + drm_rect_height(dst), &diff); |
|---|
| 118 | 125 | |
|---|
| 119 | | - src->y2 = clamp_t(int64_t, src->y1 + new_src_h, INT_MIN, INT_MAX); |
|---|
| 120 | | - dst->y2 = clip->y2; |
|---|
| 126 | + src->y2 = src->y1 + new_src_h; |
|---|
| 127 | + dst->y2 -= diff; |
|---|
| 121 | 128 | } |
|---|
| 122 | 129 | |
|---|
| 123 | 130 | return drm_rect_visible(dst); |
|---|
| .. | .. |
|---|
| 211 | 218 | return vscale; |
|---|
| 212 | 219 | } |
|---|
| 213 | 220 | EXPORT_SYMBOL(drm_rect_calc_vscale); |
|---|
| 214 | | - |
|---|
| 215 | | -/** |
|---|
| 216 | | - * drm_calc_hscale_relaxed - calculate the horizontal scaling factor |
|---|
| 217 | | - * @src: source window rectangle |
|---|
| 218 | | - * @dst: destination window rectangle |
|---|
| 219 | | - * @min_hscale: minimum allowed horizontal scaling factor |
|---|
| 220 | | - * @max_hscale: maximum allowed horizontal scaling factor |
|---|
| 221 | | - * |
|---|
| 222 | | - * Calculate the horizontal scaling factor as |
|---|
| 223 | | - * (@src width) / (@dst width). |
|---|
| 224 | | - * |
|---|
| 225 | | - * If the calculated scaling factor is below @min_vscale, |
|---|
| 226 | | - * decrease the height of rectangle @dst to compensate. |
|---|
| 227 | | - * |
|---|
| 228 | | - * If the calculated scaling factor is above @max_vscale, |
|---|
| 229 | | - * decrease the height of rectangle @src to compensate. |
|---|
| 230 | | - * |
|---|
| 231 | | - * If the scale is below 1 << 16, round down. If the scale is above |
|---|
| 232 | | - * 1 << 16, round up. This will calculate the scale with the most |
|---|
| 233 | | - * pessimistic limit calculation. |
|---|
| 234 | | - * |
|---|
| 235 | | - * RETURNS: |
|---|
| 236 | | - * The horizontal scaling factor. |
|---|
| 237 | | - */ |
|---|
| 238 | | -int drm_rect_calc_hscale_relaxed(struct drm_rect *src, |
|---|
| 239 | | - struct drm_rect *dst, |
|---|
| 240 | | - int min_hscale, int max_hscale) |
|---|
| 241 | | -{ |
|---|
| 242 | | - int src_w = drm_rect_width(src); |
|---|
| 243 | | - int dst_w = drm_rect_width(dst); |
|---|
| 244 | | - int hscale = drm_calc_scale(src_w, dst_w); |
|---|
| 245 | | - |
|---|
| 246 | | - if (hscale < 0 || dst_w == 0) |
|---|
| 247 | | - return hscale; |
|---|
| 248 | | - |
|---|
| 249 | | - if (hscale < min_hscale) { |
|---|
| 250 | | - int max_dst_w = src_w / min_hscale; |
|---|
| 251 | | - |
|---|
| 252 | | - drm_rect_adjust_size(dst, max_dst_w - dst_w, 0); |
|---|
| 253 | | - |
|---|
| 254 | | - return min_hscale; |
|---|
| 255 | | - } |
|---|
| 256 | | - |
|---|
| 257 | | - if (hscale > max_hscale) { |
|---|
| 258 | | - int max_src_w = dst_w * max_hscale; |
|---|
| 259 | | - |
|---|
| 260 | | - drm_rect_adjust_size(src, max_src_w - src_w, 0); |
|---|
| 261 | | - |
|---|
| 262 | | - return max_hscale; |
|---|
| 263 | | - } |
|---|
| 264 | | - |
|---|
| 265 | | - return hscale; |
|---|
| 266 | | -} |
|---|
| 267 | | -EXPORT_SYMBOL(drm_rect_calc_hscale_relaxed); |
|---|
| 268 | | - |
|---|
| 269 | | -/** |
|---|
| 270 | | - * drm_rect_calc_vscale_relaxed - calculate the vertical scaling factor |
|---|
| 271 | | - * @src: source window rectangle |
|---|
| 272 | | - * @dst: destination window rectangle |
|---|
| 273 | | - * @min_vscale: minimum allowed vertical scaling factor |
|---|
| 274 | | - * @max_vscale: maximum allowed vertical scaling factor |
|---|
| 275 | | - * |
|---|
| 276 | | - * Calculate the vertical scaling factor as |
|---|
| 277 | | - * (@src height) / (@dst height). |
|---|
| 278 | | - * |
|---|
| 279 | | - * If the calculated scaling factor is below @min_vscale, |
|---|
| 280 | | - * decrease the height of rectangle @dst to compensate. |
|---|
| 281 | | - * |
|---|
| 282 | | - * If the calculated scaling factor is above @max_vscale, |
|---|
| 283 | | - * decrease the height of rectangle @src to compensate. |
|---|
| 284 | | - * |
|---|
| 285 | | - * If the scale is below 1 << 16, round down. If the scale is above |
|---|
| 286 | | - * 1 << 16, round up. This will calculate the scale with the most |
|---|
| 287 | | - * pessimistic limit calculation. |
|---|
| 288 | | - * |
|---|
| 289 | | - * RETURNS: |
|---|
| 290 | | - * The vertical scaling factor. |
|---|
| 291 | | - */ |
|---|
| 292 | | -int drm_rect_calc_vscale_relaxed(struct drm_rect *src, |
|---|
| 293 | | - struct drm_rect *dst, |
|---|
| 294 | | - int min_vscale, int max_vscale) |
|---|
| 295 | | -{ |
|---|
| 296 | | - int src_h = drm_rect_height(src); |
|---|
| 297 | | - int dst_h = drm_rect_height(dst); |
|---|
| 298 | | - int vscale = drm_calc_scale(src_h, dst_h); |
|---|
| 299 | | - |
|---|
| 300 | | - if (vscale < 0 || dst_h == 0) |
|---|
| 301 | | - return vscale; |
|---|
| 302 | | - |
|---|
| 303 | | - if (vscale < min_vscale) { |
|---|
| 304 | | - int max_dst_h = src_h / min_vscale; |
|---|
| 305 | | - |
|---|
| 306 | | - drm_rect_adjust_size(dst, 0, max_dst_h - dst_h); |
|---|
| 307 | | - |
|---|
| 308 | | - return min_vscale; |
|---|
| 309 | | - } |
|---|
| 310 | | - |
|---|
| 311 | | - if (vscale > max_vscale) { |
|---|
| 312 | | - int max_src_h = dst_h * max_vscale; |
|---|
| 313 | | - |
|---|
| 314 | | - drm_rect_adjust_size(src, 0, max_src_h - src_h); |
|---|
| 315 | | - |
|---|
| 316 | | - return max_vscale; |
|---|
| 317 | | - } |
|---|
| 318 | | - |
|---|
| 319 | | - return vscale; |
|---|
| 320 | | -} |
|---|
| 321 | | -EXPORT_SYMBOL(drm_rect_calc_vscale_relaxed); |
|---|
| 322 | 221 | |
|---|
| 323 | 222 | /** |
|---|
| 324 | 223 | * drm_rect_debug_print - print the rectangle information |
|---|