cachepc-linux

Fork of AMDESE/linux with modifications for CachePC side-channel attack
git clone https://git.sinitax.com/sinitax/cachepc-linux
Log | Files | Refs | README | LICENSE | sfeed.txt

drm_rect.c (9674B)


      1/*
      2 * Copyright (C) 2011-2013 Intel Corporation
      3 *
      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:
     10 *
     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
     13 * Software.
     14 *
     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
     21 * SOFTWARE.
     22 */
     23
     24#include <linux/errno.h>
     25#include <linux/export.h>
     26#include <linux/kernel.h>
     27
     28#include <drm/drm_mode.h>
     29#include <drm/drm_print.h>
     30#include <drm/drm_rect.h>
     31
     32/**
     33 * drm_rect_intersect - intersect two rectangles
     34 * @r1: first rectangle
     35 * @r2: second rectangle
     36 *
     37 * Calculate the intersection of rectangles @r1 and @r2.
     38 * @r1 will be overwritten with the intersection.
     39 *
     40 * RETURNS:
     41 * %true if rectangle @r1 is still visible after the operation,
     42 * %false otherwise.
     43 */
     44bool drm_rect_intersect(struct drm_rect *r1, const struct drm_rect *r2)
     45{
     46	r1->x1 = max(r1->x1, r2->x1);
     47	r1->y1 = max(r1->y1, r2->y1);
     48	r1->x2 = min(r1->x2, r2->x2);
     49	r1->y2 = min(r1->y2, r2->y2);
     50
     51	return drm_rect_visible(r1);
     52}
     53EXPORT_SYMBOL(drm_rect_intersect);
     54
     55static u32 clip_scaled(int src, int dst, int *clip)
     56{
     57	u64 tmp;
     58
     59	if (dst == 0)
     60		return 0;
     61
     62	/* Only clip what we have. Keeps the result bounded. */
     63	*clip = min(*clip, dst);
     64
     65	tmp = mul_u32_u32(src, dst - *clip);
     66
     67	/*
     68	 * Round toward 1.0 when clipping so that we don't accidentally
     69	 * change upscaling to downscaling or vice versa.
     70	 */
     71	if (src < (dst << 16))
     72		return DIV_ROUND_UP_ULL(tmp, dst);
     73	else
     74		return DIV_ROUND_DOWN_ULL(tmp, dst);
     75}
     76
     77/**
     78 * drm_rect_clip_scaled - perform a scaled clip operation
     79 * @src: source window rectangle
     80 * @dst: destination window rectangle
     81 * @clip: clip rectangle
     82 *
     83 * Clip rectangle @dst by rectangle @clip. Clip rectangle @src by the
     84 * the corresponding amounts, retaining the vertical and horizontal scaling
     85 * factors from @src to @dst.
     86 *
     87 * RETURNS:
     88 *
     89 * %true if rectangle @dst is still visible after being clipped,
     90 * %false otherwise.
     91 */
     92bool drm_rect_clip_scaled(struct drm_rect *src, struct drm_rect *dst,
     93			  const struct drm_rect *clip)
     94{
     95	int diff;
     96
     97	diff = clip->x1 - dst->x1;
     98	if (diff > 0) {
     99		u32 new_src_w = clip_scaled(drm_rect_width(src),
    100					    drm_rect_width(dst), &diff);
    101
    102		src->x1 = src->x2 - new_src_w;
    103		dst->x1 += diff;
    104	}
    105	diff = clip->y1 - dst->y1;
    106	if (diff > 0) {
    107		u32 new_src_h = clip_scaled(drm_rect_height(src),
    108					    drm_rect_height(dst), &diff);
    109
    110		src->y1 = src->y2 - new_src_h;
    111		dst->y1 += diff;
    112	}
    113	diff = dst->x2 - clip->x2;
    114	if (diff > 0) {
    115		u32 new_src_w = clip_scaled(drm_rect_width(src),
    116					    drm_rect_width(dst), &diff);
    117
    118		src->x2 = src->x1 + new_src_w;
    119		dst->x2 -= diff;
    120	}
    121	diff = dst->y2 - clip->y2;
    122	if (diff > 0) {
    123		u32 new_src_h = clip_scaled(drm_rect_height(src),
    124					    drm_rect_height(dst), &diff);
    125
    126		src->y2 = src->y1 + new_src_h;
    127		dst->y2 -= diff;
    128	}
    129
    130	return drm_rect_visible(dst);
    131}
    132EXPORT_SYMBOL(drm_rect_clip_scaled);
    133
    134static int drm_calc_scale(int src, int dst)
    135{
    136	int scale = 0;
    137
    138	if (WARN_ON(src < 0 || dst < 0))
    139		return -EINVAL;
    140
    141	if (dst == 0)
    142		return 0;
    143
    144	if (src > (dst << 16))
    145		return DIV_ROUND_UP(src, dst);
    146	else
    147		scale = src / dst;
    148
    149	return scale;
    150}
    151
    152/**
    153 * drm_rect_calc_hscale - calculate the horizontal scaling factor
    154 * @src: source window rectangle
    155 * @dst: destination window rectangle
    156 * @min_hscale: minimum allowed horizontal scaling factor
    157 * @max_hscale: maximum allowed horizontal scaling factor
    158 *
    159 * Calculate the horizontal scaling factor as
    160 * (@src width) / (@dst width).
    161 *
    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.
    165 *
    166 * RETURNS:
    167 * The horizontal scaling factor, or errno of out of limits.
    168 */
    169int drm_rect_calc_hscale(const struct drm_rect *src,
    170			 const struct drm_rect *dst,
    171			 int min_hscale, int max_hscale)
    172{
    173	int src_w = drm_rect_width(src);
    174	int dst_w = drm_rect_width(dst);
    175	int hscale = drm_calc_scale(src_w, dst_w);
    176
    177	if (hscale < 0 || dst_w == 0)
    178		return hscale;
    179
    180	if (hscale < min_hscale || hscale > max_hscale)
    181		return -ERANGE;
    182
    183	return hscale;
    184}
    185EXPORT_SYMBOL(drm_rect_calc_hscale);
    186
    187/**
    188 * drm_rect_calc_vscale - calculate the vertical scaling factor
    189 * @src: source window rectangle
    190 * @dst: destination window rectangle
    191 * @min_vscale: minimum allowed vertical scaling factor
    192 * @max_vscale: maximum allowed vertical scaling factor
    193 *
    194 * Calculate the vertical scaling factor as
    195 * (@src height) / (@dst height).
    196 *
    197 * If the scale is below 1 << 16, round down. If the scale is above
    198 * 1 << 16, round up. This will calculate the scale with the most
    199 * pessimistic limit calculation.
    200 *
    201 * RETURNS:
    202 * The vertical scaling factor, or errno of out of limits.
    203 */
    204int drm_rect_calc_vscale(const struct drm_rect *src,
    205			 const struct drm_rect *dst,
    206			 int min_vscale, int max_vscale)
    207{
    208	int src_h = drm_rect_height(src);
    209	int dst_h = drm_rect_height(dst);
    210	int vscale = drm_calc_scale(src_h, dst_h);
    211
    212	if (vscale < 0 || dst_h == 0)
    213		return vscale;
    214
    215	if (vscale < min_vscale || vscale > max_vscale)
    216		return -ERANGE;
    217
    218	return vscale;
    219}
    220EXPORT_SYMBOL(drm_rect_calc_vscale);
    221
    222/**
    223 * drm_rect_debug_print - print the rectangle information
    224 * @prefix: prefix string
    225 * @r: rectangle to print
    226 * @fixed_point: rectangle is in 16.16 fixed point format
    227 */
    228void drm_rect_debug_print(const char *prefix, const struct drm_rect *r, bool fixed_point)
    229{
    230	if (fixed_point)
    231		DRM_DEBUG_KMS("%s" DRM_RECT_FP_FMT "\n", prefix, DRM_RECT_FP_ARG(r));
    232	else
    233		DRM_DEBUG_KMS("%s" DRM_RECT_FMT "\n", prefix, DRM_RECT_ARG(r));
    234}
    235EXPORT_SYMBOL(drm_rect_debug_print);
    236
    237/**
    238 * drm_rect_rotate - Rotate the rectangle
    239 * @r: rectangle to be rotated
    240 * @width: Width of the coordinate space
    241 * @height: Height of the coordinate space
    242 * @rotation: Transformation to be applied
    243 *
    244 * Apply @rotation to the coordinates of rectangle @r.
    245 *
    246 * @width and @height combined with @rotation define
    247 * the location of the new origin.
    248 *
    249 * @width correcsponds to the horizontal and @height
    250 * to the vertical axis of the untransformed coordinate
    251 * space.
    252 */
    253void drm_rect_rotate(struct drm_rect *r,
    254		     int width, int height,
    255		     unsigned int rotation)
    256{
    257	struct drm_rect tmp;
    258
    259	if (rotation & (DRM_MODE_REFLECT_X | DRM_MODE_REFLECT_Y)) {
    260		tmp = *r;
    261
    262		if (rotation & DRM_MODE_REFLECT_X) {
    263			r->x1 = width - tmp.x2;
    264			r->x2 = width - tmp.x1;
    265		}
    266
    267		if (rotation & DRM_MODE_REFLECT_Y) {
    268			r->y1 = height - tmp.y2;
    269			r->y2 = height - tmp.y1;
    270		}
    271	}
    272
    273	switch (rotation & DRM_MODE_ROTATE_MASK) {
    274	case DRM_MODE_ROTATE_0:
    275		break;
    276	case DRM_MODE_ROTATE_90:
    277		tmp = *r;
    278		r->x1 = tmp.y1;
    279		r->x2 = tmp.y2;
    280		r->y1 = width - tmp.x2;
    281		r->y2 = width - tmp.x1;
    282		break;
    283	case DRM_MODE_ROTATE_180:
    284		tmp = *r;
    285		r->x1 = width - tmp.x2;
    286		r->x2 = width - tmp.x1;
    287		r->y1 = height - tmp.y2;
    288		r->y2 = height - tmp.y1;
    289		break;
    290	case DRM_MODE_ROTATE_270:
    291		tmp = *r;
    292		r->x1 = height - tmp.y2;
    293		r->x2 = height - tmp.y1;
    294		r->y1 = tmp.x1;
    295		r->y2 = tmp.x2;
    296		break;
    297	default:
    298		break;
    299	}
    300}
    301EXPORT_SYMBOL(drm_rect_rotate);
    302
    303/**
    304 * drm_rect_rotate_inv - Inverse rotate the rectangle
    305 * @r: rectangle to be rotated
    306 * @width: Width of the coordinate space
    307 * @height: Height of the coordinate space
    308 * @rotation: Transformation whose inverse is to be applied
    309 *
    310 * Apply the inverse of @rotation to the coordinates
    311 * of rectangle @r.
    312 *
    313 * @width and @height combined with @rotation define
    314 * the location of the new origin.
    315 *
    316 * @width correcsponds to the horizontal and @height
    317 * to the vertical axis of the original untransformed
    318 * coordinate space, so that you never have to flip
    319 * them when doing a rotatation and its inverse.
    320 * That is, if you do ::
    321 *
    322 *     drm_rect_rotate(&r, width, height, rotation);
    323 *     drm_rect_rotate_inv(&r, width, height, rotation);
    324 *
    325 * you will always get back the original rectangle.
    326 */
    327void drm_rect_rotate_inv(struct drm_rect *r,
    328			 int width, int height,
    329			 unsigned int rotation)
    330{
    331	struct drm_rect tmp;
    332
    333	switch (rotation & DRM_MODE_ROTATE_MASK) {
    334	case DRM_MODE_ROTATE_0:
    335		break;
    336	case DRM_MODE_ROTATE_90:
    337		tmp = *r;
    338		r->x1 = width - tmp.y2;
    339		r->x2 = width - tmp.y1;
    340		r->y1 = tmp.x1;
    341		r->y2 = tmp.x2;
    342		break;
    343	case DRM_MODE_ROTATE_180:
    344		tmp = *r;
    345		r->x1 = width - tmp.x2;
    346		r->x2 = width - tmp.x1;
    347		r->y1 = height - tmp.y2;
    348		r->y2 = height - tmp.y1;
    349		break;
    350	case DRM_MODE_ROTATE_270:
    351		tmp = *r;
    352		r->x1 = tmp.y1;
    353		r->x2 = tmp.y2;
    354		r->y1 = height - tmp.x2;
    355		r->y2 = height - tmp.x1;
    356		break;
    357	default:
    358		break;
    359	}
    360
    361	if (rotation & (DRM_MODE_REFLECT_X | DRM_MODE_REFLECT_Y)) {
    362		tmp = *r;
    363
    364		if (rotation & DRM_MODE_REFLECT_X) {
    365			r->x1 = width - tmp.x2;
    366			r->x2 = width - tmp.x1;
    367		}
    368
    369		if (rotation & DRM_MODE_REFLECT_Y) {
    370			r->y1 = height - tmp.y2;
    371			r->y2 = height - tmp.y1;
    372		}
    373	}
    374}
    375EXPORT_SYMBOL(drm_rect_rotate_inv);