LCOV - code coverage report
Current view: top level - drivers/gpu/drm - drm_rect.c (source / functions) Hit Total Coverage
Test: coverage.info Lines: 119 119 100.0 %
Date: 2023-07-19 18:55:55 Functions: 8 8 100.0 %

          Line data    Source code
       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             :  */
      44          28 : bool drm_rect_intersect(struct drm_rect *r1, const struct drm_rect *r2)
      45             : {
      46          28 :         r1->x1 = max(r1->x1, r2->x1);
      47          28 :         r1->y1 = max(r1->y1, r2->y1);
      48          28 :         r1->x2 = min(r1->x2, r2->x2);
      49          28 :         r1->y2 = min(r1->y2, r2->y2);
      50             : 
      51          28 :         return drm_rect_visible(r1);
      52             : }
      53             : EXPORT_SYMBOL(drm_rect_intersect);
      54             : 
      55             : static u32 clip_scaled(int src, int dst, int *clip)
      56             : {
      57             :         u64 tmp;
      58             : 
      59          34 :         if (dst == 0)
      60             :                 return 0;
      61             : 
      62             :         /* Only clip what we have. Keeps the result bounded. */
      63          30 :         *clip = min(*clip, dst);
      64             : 
      65          60 :         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          30 :         if (src < (dst << 16))
      72           8 :                 return DIV_ROUND_UP_ULL(tmp, dst);
      73             :         else
      74          22 :                 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
      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             :  */
      92          22 : bool drm_rect_clip_scaled(struct drm_rect *src, struct drm_rect *dst,
      93             :                           const struct drm_rect *clip)
      94             : {
      95             :         int diff;
      96             : 
      97          22 :         diff = clip->x1 - dst->x1;
      98          22 :         if (diff > 0) {
      99          28 :                 u32 new_src_w = clip_scaled(drm_rect_width(src),
     100             :                                             drm_rect_width(dst), &diff);
     101             : 
     102           7 :                 src->x1 = src->x2 - new_src_w;
     103           7 :                 dst->x1 += diff;
     104             :         }
     105          22 :         diff = clip->y1 - dst->y1;
     106          22 :         if (diff > 0) {
     107          28 :                 u32 new_src_h = clip_scaled(drm_rect_height(src),
     108             :                                             drm_rect_height(dst), &diff);
     109             : 
     110           7 :                 src->y1 = src->y2 - new_src_h;
     111           7 :                 dst->y1 += diff;
     112             :         }
     113          22 :         diff = dst->x2 - clip->x2;
     114          22 :         if (diff > 0) {
     115          40 :                 u32 new_src_w = clip_scaled(drm_rect_width(src),
     116             :                                             drm_rect_width(dst), &diff);
     117             : 
     118          10 :                 src->x2 = src->x1 + new_src_w;
     119          10 :                 dst->x2 -= diff;
     120             :         }
     121          22 :         diff = dst->y2 - clip->y2;
     122          22 :         if (diff > 0) {
     123          40 :                 u32 new_src_h = clip_scaled(drm_rect_height(src),
     124             :                                             drm_rect_height(dst), &diff);
     125             : 
     126          10 :                 src->y2 = src->y1 + new_src_h;
     127          10 :                 dst->y2 -= diff;
     128             :         }
     129             : 
     130          22 :         return drm_rect_visible(dst);
     131             : }
     132             : EXPORT_SYMBOL(drm_rect_clip_scaled);
     133             : 
     134          36 : static int drm_calc_scale(int src, int dst)
     135             : {
     136          36 :         int scale = 0;
     137             : 
     138          36 :         if (WARN_ON(src < 0 || dst < 0))
     139             :                 return -EINVAL;
     140             : 
     141          32 :         if (dst == 0)
     142             :                 return 0;
     143             : 
     144          30 :         if (src > (dst << 16))
     145          14 :                 return DIV_ROUND_UP(src, dst);
     146             :         else
     147          16 :                 scale = src / dst;
     148             : 
     149          16 :         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             :  */
     169          18 : int drm_rect_calc_hscale(const struct drm_rect *src,
     170             :                          const struct drm_rect *dst,
     171             :                          int min_hscale, int max_hscale)
     172             : {
     173          36 :         int src_w = drm_rect_width(src);
     174          36 :         int dst_w = drm_rect_width(dst);
     175          18 :         int hscale = drm_calc_scale(src_w, dst_w);
     176             : 
     177          18 :         if (hscale < 0 || dst_w == 0)
     178             :                 return hscale;
     179             : 
     180          15 :         if (hscale < min_hscale || hscale > max_hscale)
     181             :                 return -ERANGE;
     182             : 
     183          11 :         return hscale;
     184             : }
     185             : EXPORT_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             :  */
     204          18 : int drm_rect_calc_vscale(const struct drm_rect *src,
     205             :                          const struct drm_rect *dst,
     206             :                          int min_vscale, int max_vscale)
     207             : {
     208          36 :         int src_h = drm_rect_height(src);
     209          36 :         int dst_h = drm_rect_height(dst);
     210          18 :         int vscale = drm_calc_scale(src_h, dst_h);
     211             : 
     212          18 :         if (vscale < 0 || dst_h == 0)
     213             :                 return vscale;
     214             : 
     215          15 :         if (vscale < min_vscale || vscale > max_vscale)
     216             :                 return -ERANGE;
     217             : 
     218          11 :         return vscale;
     219             : }
     220             : EXPORT_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             :  */
     228           6 : void drm_rect_debug_print(const char *prefix, const struct drm_rect *r, bool fixed_point)
     229             : {
     230           6 :         if (fixed_point)
     231           6 :                 DRM_DEBUG_KMS("%s" DRM_RECT_FP_FMT "\n", prefix, DRM_RECT_FP_ARG(r));
     232             :         else
     233          12 :                 DRM_DEBUG_KMS("%s" DRM_RECT_FMT "\n", prefix, DRM_RECT_ARG(r));
     234           6 : }
     235             : EXPORT_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             :  */
     253          18 : void drm_rect_rotate(struct drm_rect *r,
     254             :                      int width, int height,
     255             :                      unsigned int rotation)
     256             : {
     257             :         struct drm_rect tmp;
     258             : 
     259          18 :         if (rotation & (DRM_MODE_REFLECT_X | DRM_MODE_REFLECT_Y)) {
     260           3 :                 tmp = *r;
     261             : 
     262           3 :                 if (rotation & DRM_MODE_REFLECT_X) {
     263           2 :                         r->x1 = width - tmp.x2;
     264           2 :                         r->x2 = width - tmp.x1;
     265             :                 }
     266             : 
     267           3 :                 if (rotation & DRM_MODE_REFLECT_Y) {
     268           1 :                         r->y1 = height - tmp.y2;
     269           1 :                         r->y2 = height - tmp.y1;
     270             :                 }
     271             :         }
     272             : 
     273          18 :         switch (rotation & DRM_MODE_ROTATE_MASK) {
     274             :         case DRM_MODE_ROTATE_0:
     275             :                 break;
     276             :         case DRM_MODE_ROTATE_90:
     277           2 :                 tmp = *r;
     278           2 :                 r->x1 = tmp.y1;
     279           2 :                 r->x2 = tmp.y2;
     280           2 :                 r->y1 = width - tmp.x2;
     281           2 :                 r->y2 = width - tmp.x1;
     282           2 :                 break;
     283             :         case DRM_MODE_ROTATE_180:
     284           1 :                 tmp = *r;
     285           1 :                 r->x1 = width - tmp.x2;
     286           1 :                 r->x2 = width - tmp.x1;
     287           1 :                 r->y1 = height - tmp.y2;
     288           1 :                 r->y2 = height - tmp.y1;
     289           1 :                 break;
     290             :         case DRM_MODE_ROTATE_270:
     291           1 :                 tmp = *r;
     292           1 :                 r->x1 = height - tmp.y2;
     293           1 :                 r->x2 = height - tmp.y1;
     294           1 :                 r->y1 = tmp.x1;
     295           1 :                 r->y2 = tmp.x2;
     296           1 :                 break;
     297             :         default:
     298             :                 break;
     299             :         }
     300          18 : }
     301             : EXPORT_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             :  */
     327          16 : void 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          16 :         switch (rotation & DRM_MODE_ROTATE_MASK) {
     334             :         case DRM_MODE_ROTATE_0:
     335             :                 break;
     336             :         case DRM_MODE_ROTATE_90:
     337           2 :                 tmp = *r;
     338           2 :                 r->x1 = width - tmp.y2;
     339           2 :                 r->x2 = width - tmp.y1;
     340           2 :                 r->y1 = tmp.x1;
     341           2 :                 r->y2 = tmp.x2;
     342           2 :                 break;
     343             :         case DRM_MODE_ROTATE_180:
     344           1 :                 tmp = *r;
     345           1 :                 r->x1 = width - tmp.x2;
     346           1 :                 r->x2 = width - tmp.x1;
     347           1 :                 r->y1 = height - tmp.y2;
     348           1 :                 r->y2 = height - tmp.y1;
     349           1 :                 break;
     350             :         case DRM_MODE_ROTATE_270:
     351           1 :                 tmp = *r;
     352           1 :                 r->x1 = tmp.y1;
     353           1 :                 r->x2 = tmp.y2;
     354           1 :                 r->y1 = height - tmp.x2;
     355           1 :                 r->y2 = height - tmp.x1;
     356           1 :                 break;
     357             :         default:
     358             :                 break;
     359             :         }
     360             : 
     361          16 :         if (rotation & (DRM_MODE_REFLECT_X | DRM_MODE_REFLECT_Y)) {
     362           3 :                 tmp = *r;
     363             : 
     364           3 :                 if (rotation & DRM_MODE_REFLECT_X) {
     365           2 :                         r->x1 = width - tmp.x2;
     366           2 :                         r->x2 = width - tmp.x1;
     367             :                 }
     368             : 
     369           3 :                 if (rotation & DRM_MODE_REFLECT_Y) {
     370           1 :                         r->y1 = height - tmp.y2;
     371           1 :                         r->y2 = height - tmp.y1;
     372             :                 }
     373             :         }
     374          16 : }
     375             : EXPORT_SYMBOL(drm_rect_rotate_inv);

Generated by: LCOV version 1.14