xserver

xserver with xephyr scale patch
git clone https://git.neptards.moe/u3shit/xserver.git
Log | Files | Refs | README | LICENSE

rrtransform.c (9500B)


      1 /*
      2  * Copyright © 2007 Keith Packard
      3  *
      4  * Permission to use, copy, modify, distribute, and sell this software and its
      5  * documentation for any purpose is hereby granted without fee, provided that
      6  * the above copyright notice appear in all copies and that both that copyright
      7  * notice and this permission notice appear in supporting documentation, and
      8  * that the name of the copyright holders not be used in advertising or
      9  * publicity pertaining to distribution of the software without specific,
     10  * written prior permission.  The copyright holders make no representations
     11  * about the suitability of this software for any purpose.  It is provided "as
     12  * is" without express or implied warranty.
     13  *
     14  * THE COPYRIGHT HOLDERS DISCLAIM ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
     15  * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO
     16  * EVENT SHALL THE COPYRIGHT HOLDERS BE LIABLE FOR ANY SPECIAL, INDIRECT OR
     17  * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE,
     18  * DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
     19  * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE
     20  * OF THIS SOFTWARE.
     21  */
     22 
     23 #include "randrstr.h"
     24 #include "rrtransform.h"
     25 
     26 void
     27 RRTransformInit(RRTransformPtr transform)
     28 {
     29     pixman_transform_init_identity(&transform->transform);
     30     pixman_f_transform_init_identity(&transform->f_transform);
     31     pixman_f_transform_init_identity(&transform->f_inverse);
     32     transform->filter = NULL;
     33     transform->params = NULL;
     34     transform->nparams = 0;
     35 }
     36 
     37 void
     38 RRTransformFini(RRTransformPtr transform)
     39 {
     40     free(transform->params);
     41 }
     42 
     43 Bool
     44 RRTransformEqual(RRTransformPtr a, RRTransformPtr b)
     45 {
     46     if (a && pixman_transform_is_identity(&a->transform))
     47         a = NULL;
     48     if (b && pixman_transform_is_identity(&b->transform))
     49         b = NULL;
     50     if (a == NULL && b == NULL)
     51         return TRUE;
     52     if (a == NULL || b == NULL)
     53         return FALSE;
     54     if (memcmp(&a->transform, &b->transform, sizeof(a->transform)) != 0)
     55         return FALSE;
     56     if (a->filter != b->filter)
     57         return FALSE;
     58     if (a->nparams != b->nparams)
     59         return FALSE;
     60     if (memcmp(a->params, b->params, a->nparams * sizeof(xFixed)) != 0)
     61         return FALSE;
     62     return TRUE;
     63 }
     64 
     65 Bool
     66 RRTransformSetFilter(RRTransformPtr dst,
     67                      PictFilterPtr filter,
     68                      xFixed * params, int nparams, int width, int height)
     69 {
     70     xFixed *new_params;
     71 
     72     if (nparams) {
     73         new_params = xallocarray(nparams, sizeof(xFixed));
     74         if (!new_params)
     75             return FALSE;
     76         memcpy(new_params, params, nparams * sizeof(xFixed));
     77     }
     78     else
     79         new_params = NULL;
     80     free(dst->params);
     81     dst->filter = filter;
     82     dst->params = new_params;
     83     dst->nparams = nparams;
     84     dst->width = width;
     85     dst->height = height;
     86     return TRUE;
     87 }
     88 
     89 Bool
     90 RRTransformCopy(RRTransformPtr dst, RRTransformPtr src)
     91 {
     92     if (src && pixman_transform_is_identity(&src->transform))
     93         src = NULL;
     94 
     95     if (src) {
     96         if (!RRTransformSetFilter(dst, src->filter,
     97                                   src->params, src->nparams, src->width,
     98                                   src->height))
     99             return FALSE;
    100         dst->transform = src->transform;
    101         dst->f_transform = src->f_transform;
    102         dst->f_inverse = src->f_inverse;
    103     }
    104     else {
    105         if (!RRTransformSetFilter(dst, NULL, NULL, 0, 0, 0))
    106             return FALSE;
    107         pixman_transform_init_identity(&dst->transform);
    108         pixman_f_transform_init_identity(&dst->f_transform);
    109         pixman_f_transform_init_identity(&dst->f_inverse);
    110     }
    111     return TRUE;
    112 }
    113 
    114 #define F(x)	IntToxFixed(x)
    115 
    116 static void
    117 RRTransformRescale(struct pixman_f_transform *f_transform, double limit)
    118 {
    119     double max = 0, v, scale;
    120     int i, j;
    121 
    122     for (j = 0; j < 3; j++)
    123         for (i = 0; i < 3; i++)
    124             if ((v = fabs(f_transform->m[j][i])) > max)
    125                 max = v;
    126     scale = limit / max;
    127     for (j = 0; j < 3; j++)
    128         for (i = 0; i < 3; i++)
    129             f_transform->m[j][i] *= scale;
    130 }
    131 
    132 /*
    133  * Compute the complete transformation matrix including
    134  * client-specified transform, rotation/reflection values and the crtc
    135  * offset.
    136  *
    137  * Return TRUE if the resulting transform is not a simple translation.
    138  */
    139 Bool
    140 RRTransformCompute(int x,
    141                    int y,
    142                    int width,
    143                    int height,
    144                    Rotation rotation,
    145                    RRTransformPtr rr_transform,
    146                    PictTransformPtr transform,
    147                    struct pixman_f_transform *f_transform,
    148                    struct pixman_f_transform *f_inverse)
    149 {
    150     PictTransform t_transform, inverse;
    151     struct pixman_f_transform tf_transform, tf_inverse;
    152     Bool overflow = FALSE;
    153 
    154     if (!transform)
    155         transform = &t_transform;
    156     if (!f_transform)
    157         f_transform = &tf_transform;
    158     if (!f_inverse)
    159         f_inverse = &tf_inverse;
    160 
    161     pixman_transform_init_identity(transform);
    162     pixman_transform_init_identity(&inverse);
    163     pixman_f_transform_init_identity(f_transform);
    164     pixman_f_transform_init_identity(f_inverse);
    165     if (rotation != RR_Rotate_0) {
    166         double f_rot_cos, f_rot_sin, f_rot_dx, f_rot_dy;
    167         double f_scale_x, f_scale_y, f_scale_dx, f_scale_dy;
    168         xFixed rot_cos, rot_sin, rot_dx, rot_dy;
    169         xFixed scale_x, scale_y, scale_dx, scale_dy;
    170 
    171         /* rotation */
    172         switch (rotation & 0xf) {
    173         default:
    174         case RR_Rotate_0:
    175             f_rot_cos = 1;
    176             f_rot_sin = 0;
    177             f_rot_dx = 0;
    178             f_rot_dy = 0;
    179             rot_cos = F(1);
    180             rot_sin = F(0);
    181             rot_dx = F(0);
    182             rot_dy = F(0);
    183             break;
    184         case RR_Rotate_90:
    185             f_rot_cos = 0;
    186             f_rot_sin = 1;
    187             f_rot_dx = height;
    188             f_rot_dy = 0;
    189             rot_cos = F(0);
    190             rot_sin = F(1);
    191             rot_dx = F(height);
    192             rot_dy = F(0);
    193             break;
    194         case RR_Rotate_180:
    195             f_rot_cos = -1;
    196             f_rot_sin = 0;
    197             f_rot_dx = width;
    198             f_rot_dy = height;
    199             rot_cos = F(~0u);
    200             rot_sin = F(0);
    201             rot_dx = F(width);
    202             rot_dy = F(height);
    203             break;
    204         case RR_Rotate_270:
    205             f_rot_cos = 0;
    206             f_rot_sin = -1;
    207             f_rot_dx = 0;
    208             f_rot_dy = width;
    209             rot_cos = F(0);
    210             rot_sin = F(~0u);
    211             rot_dx = F(0);
    212             rot_dy = F(width);
    213             break;
    214         }
    215 
    216         pixman_transform_rotate(transform, &inverse, rot_cos, rot_sin);
    217         pixman_transform_translate(transform, &inverse, rot_dx, rot_dy);
    218         pixman_f_transform_rotate(f_transform, f_inverse, f_rot_cos, f_rot_sin);
    219         pixman_f_transform_translate(f_transform, f_inverse, f_rot_dx,
    220                                      f_rot_dy);
    221 
    222         /* reflection */
    223         f_scale_x = 1;
    224         f_scale_dx = 0;
    225         f_scale_y = 1;
    226         f_scale_dy = 0;
    227         scale_x = F(1);
    228         scale_dx = 0;
    229         scale_y = F(1);
    230         scale_dy = 0;
    231         if (rotation & RR_Reflect_X) {
    232             f_scale_x = -1;
    233             scale_x = F(~0u);
    234             if (rotation & (RR_Rotate_0 | RR_Rotate_180)) {
    235                 f_scale_dx = width;
    236                 scale_dx = F(width);
    237             }
    238             else {
    239                 f_scale_dx = height;
    240                 scale_dx = F(height);
    241             }
    242         }
    243         if (rotation & RR_Reflect_Y) {
    244             f_scale_y = -1;
    245             scale_y = F(~0u);
    246             if (rotation & (RR_Rotate_0 | RR_Rotate_180)) {
    247                 f_scale_dy = height;
    248                 scale_dy = F(height);
    249             }
    250             else {
    251                 f_scale_dy = width;
    252                 scale_dy = F(width);
    253             }
    254         }
    255 
    256         pixman_transform_scale(transform, &inverse, scale_x, scale_y);
    257         pixman_f_transform_scale(f_transform, f_inverse, f_scale_x, f_scale_y);
    258         pixman_transform_translate(transform, &inverse, scale_dx, scale_dy);
    259         pixman_f_transform_translate(f_transform, f_inverse, f_scale_dx,
    260                                      f_scale_dy);
    261     }
    262 
    263 #ifdef RANDR_12_INTERFACE
    264     if (rr_transform) {
    265         if (!pixman_transform_multiply
    266             (transform, &rr_transform->transform, transform))
    267             overflow = TRUE;
    268         pixman_f_transform_multiply(f_transform, &rr_transform->f_transform,
    269                                     f_transform);
    270         pixman_f_transform_multiply(f_inverse, f_inverse,
    271                                     &rr_transform->f_inverse);
    272     }
    273 #endif
    274     /*
    275      * Compute the class of the resulting transform
    276      */
    277     if (!overflow && pixman_transform_is_identity(transform)) {
    278         pixman_transform_init_translate(transform, F(x), F(y));
    279 
    280         pixman_f_transform_init_translate(f_transform, x, y);
    281         pixman_f_transform_init_translate(f_inverse, -x, -y);
    282         return FALSE;
    283     }
    284     else {
    285         pixman_f_transform_translate(f_transform, f_inverse, x, y);
    286         if (!pixman_transform_translate(transform, &inverse, F(x), F(y)))
    287             overflow = TRUE;
    288         if (overflow) {
    289             struct pixman_f_transform f_scaled;
    290 
    291             f_scaled = *f_transform;
    292             RRTransformRescale(&f_scaled, 16384.0);
    293             pixman_transform_from_pixman_f_transform(transform, &f_scaled);
    294         }
    295         return TRUE;
    296     }
    297 }