0001
0002
0003
0004
0005
0006
0007
0008
0009
0010
0011
0012
0013
0014
0015
0016
0017
0018
0019
0020
0021
0022
0023
0024 #include <linux/errno.h>
0025 #include <linux/export.h>
0026 #include <linux/kernel.h>
0027
0028 #include <drm/drm_mode.h>
0029 #include <drm/drm_print.h>
0030 #include <drm/drm_rect.h>
0031
0032
0033
0034
0035
0036
0037
0038
0039
0040
0041
0042
0043
0044 bool drm_rect_intersect(struct drm_rect *r1, const struct drm_rect *r2)
0045 {
0046 r1->x1 = max(r1->x1, r2->x1);
0047 r1->y1 = max(r1->y1, r2->y1);
0048 r1->x2 = min(r1->x2, r2->x2);
0049 r1->y2 = min(r1->y2, r2->y2);
0050
0051 return drm_rect_visible(r1);
0052 }
0053 EXPORT_SYMBOL(drm_rect_intersect);
0054
0055 static u32 clip_scaled(int src, int dst, int *clip)
0056 {
0057 u64 tmp;
0058
0059 if (dst == 0)
0060 return 0;
0061
0062
0063 *clip = min(*clip, dst);
0064
0065 tmp = mul_u32_u32(src, dst - *clip);
0066
0067
0068
0069
0070
0071 if (src < (dst << 16))
0072 return DIV_ROUND_UP_ULL(tmp, dst);
0073 else
0074 return DIV_ROUND_DOWN_ULL(tmp, dst);
0075 }
0076
0077
0078
0079
0080
0081
0082
0083
0084
0085
0086
0087
0088
0089
0090
0091
0092 bool drm_rect_clip_scaled(struct drm_rect *src, struct drm_rect *dst,
0093 const struct drm_rect *clip)
0094 {
0095 int diff;
0096
0097 diff = clip->x1 - dst->x1;
0098 if (diff > 0) {
0099 u32 new_src_w = clip_scaled(drm_rect_width(src),
0100 drm_rect_width(dst), &diff);
0101
0102 src->x1 = src->x2 - new_src_w;
0103 dst->x1 += diff;
0104 }
0105 diff = clip->y1 - dst->y1;
0106 if (diff > 0) {
0107 u32 new_src_h = clip_scaled(drm_rect_height(src),
0108 drm_rect_height(dst), &diff);
0109
0110 src->y1 = src->y2 - new_src_h;
0111 dst->y1 += diff;
0112 }
0113 diff = dst->x2 - clip->x2;
0114 if (diff > 0) {
0115 u32 new_src_w = clip_scaled(drm_rect_width(src),
0116 drm_rect_width(dst), &diff);
0117
0118 src->x2 = src->x1 + new_src_w;
0119 dst->x2 -= diff;
0120 }
0121 diff = dst->y2 - clip->y2;
0122 if (diff > 0) {
0123 u32 new_src_h = clip_scaled(drm_rect_height(src),
0124 drm_rect_height(dst), &diff);
0125
0126 src->y2 = src->y1 + new_src_h;
0127 dst->y2 -= diff;
0128 }
0129
0130 return drm_rect_visible(dst);
0131 }
0132 EXPORT_SYMBOL(drm_rect_clip_scaled);
0133
0134 static int drm_calc_scale(int src, int dst)
0135 {
0136 int scale = 0;
0137
0138 if (WARN_ON(src < 0 || dst < 0))
0139 return -EINVAL;
0140
0141 if (dst == 0)
0142 return 0;
0143
0144 if (src > (dst << 16))
0145 return DIV_ROUND_UP(src, dst);
0146 else
0147 scale = src / dst;
0148
0149 return scale;
0150 }
0151
0152
0153
0154
0155
0156
0157
0158
0159
0160
0161
0162
0163
0164
0165
0166
0167
0168
0169 int drm_rect_calc_hscale(const struct drm_rect *src,
0170 const struct drm_rect *dst,
0171 int min_hscale, int max_hscale)
0172 {
0173 int src_w = drm_rect_width(src);
0174 int dst_w = drm_rect_width(dst);
0175 int hscale = drm_calc_scale(src_w, dst_w);
0176
0177 if (hscale < 0 || dst_w == 0)
0178 return hscale;
0179
0180 if (hscale < min_hscale || hscale > max_hscale)
0181 return -ERANGE;
0182
0183 return hscale;
0184 }
0185 EXPORT_SYMBOL(drm_rect_calc_hscale);
0186
0187
0188
0189
0190
0191
0192
0193
0194
0195
0196
0197
0198
0199
0200
0201
0202
0203
0204 int drm_rect_calc_vscale(const struct drm_rect *src,
0205 const struct drm_rect *dst,
0206 int min_vscale, int max_vscale)
0207 {
0208 int src_h = drm_rect_height(src);
0209 int dst_h = drm_rect_height(dst);
0210 int vscale = drm_calc_scale(src_h, dst_h);
0211
0212 if (vscale < 0 || dst_h == 0)
0213 return vscale;
0214
0215 if (vscale < min_vscale || vscale > max_vscale)
0216 return -ERANGE;
0217
0218 return vscale;
0219 }
0220 EXPORT_SYMBOL(drm_rect_calc_vscale);
0221
0222
0223
0224
0225
0226
0227
0228 void drm_rect_debug_print(const char *prefix, const struct drm_rect *r, bool fixed_point)
0229 {
0230 if (fixed_point)
0231 DRM_DEBUG_KMS("%s" DRM_RECT_FP_FMT "\n", prefix, DRM_RECT_FP_ARG(r));
0232 else
0233 DRM_DEBUG_KMS("%s" DRM_RECT_FMT "\n", prefix, DRM_RECT_ARG(r));
0234 }
0235 EXPORT_SYMBOL(drm_rect_debug_print);
0236
0237
0238
0239
0240
0241
0242
0243
0244
0245
0246
0247
0248
0249
0250
0251
0252
0253 void drm_rect_rotate(struct drm_rect *r,
0254 int width, int height,
0255 unsigned int rotation)
0256 {
0257 struct drm_rect tmp;
0258
0259 if (rotation & (DRM_MODE_REFLECT_X | DRM_MODE_REFLECT_Y)) {
0260 tmp = *r;
0261
0262 if (rotation & DRM_MODE_REFLECT_X) {
0263 r->x1 = width - tmp.x2;
0264 r->x2 = width - tmp.x1;
0265 }
0266
0267 if (rotation & DRM_MODE_REFLECT_Y) {
0268 r->y1 = height - tmp.y2;
0269 r->y2 = height - tmp.y1;
0270 }
0271 }
0272
0273 switch (rotation & DRM_MODE_ROTATE_MASK) {
0274 case DRM_MODE_ROTATE_0:
0275 break;
0276 case DRM_MODE_ROTATE_90:
0277 tmp = *r;
0278 r->x1 = tmp.y1;
0279 r->x2 = tmp.y2;
0280 r->y1 = width - tmp.x2;
0281 r->y2 = width - tmp.x1;
0282 break;
0283 case DRM_MODE_ROTATE_180:
0284 tmp = *r;
0285 r->x1 = width - tmp.x2;
0286 r->x2 = width - tmp.x1;
0287 r->y1 = height - tmp.y2;
0288 r->y2 = height - tmp.y1;
0289 break;
0290 case DRM_MODE_ROTATE_270:
0291 tmp = *r;
0292 r->x1 = height - tmp.y2;
0293 r->x2 = height - tmp.y1;
0294 r->y1 = tmp.x1;
0295 r->y2 = tmp.x2;
0296 break;
0297 default:
0298 break;
0299 }
0300 }
0301 EXPORT_SYMBOL(drm_rect_rotate);
0302
0303
0304
0305
0306
0307
0308
0309
0310
0311
0312
0313
0314
0315
0316
0317
0318
0319
0320
0321
0322
0323
0324
0325
0326
0327 void drm_rect_rotate_inv(struct drm_rect *r,
0328 int width, int height,
0329 unsigned int rotation)
0330 {
0331 struct drm_rect tmp;
0332
0333 switch (rotation & DRM_MODE_ROTATE_MASK) {
0334 case DRM_MODE_ROTATE_0:
0335 break;
0336 case DRM_MODE_ROTATE_90:
0337 tmp = *r;
0338 r->x1 = width - tmp.y2;
0339 r->x2 = width - tmp.y1;
0340 r->y1 = tmp.x1;
0341 r->y2 = tmp.x2;
0342 break;
0343 case DRM_MODE_ROTATE_180:
0344 tmp = *r;
0345 r->x1 = width - tmp.x2;
0346 r->x2 = width - tmp.x1;
0347 r->y1 = height - tmp.y2;
0348 r->y2 = height - tmp.y1;
0349 break;
0350 case DRM_MODE_ROTATE_270:
0351 tmp = *r;
0352 r->x1 = tmp.y1;
0353 r->x2 = tmp.y2;
0354 r->y1 = height - tmp.x2;
0355 r->y2 = height - tmp.x1;
0356 break;
0357 default:
0358 break;
0359 }
0360
0361 if (rotation & (DRM_MODE_REFLECT_X | DRM_MODE_REFLECT_Y)) {
0362 tmp = *r;
0363
0364 if (rotation & DRM_MODE_REFLECT_X) {
0365 r->x1 = width - tmp.x2;
0366 r->x2 = width - tmp.x1;
0367 }
0368
0369 if (rotation & DRM_MODE_REFLECT_Y) {
0370 r->y1 = height - tmp.y2;
0371 r->y2 = height - tmp.y1;
0372 }
0373 }
0374 }
0375 EXPORT_SYMBOL(drm_rect_rotate_inv);