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