1428d7b3dSmrg/*
2428d7b3dSmrg * Copyright 1998-1999 Precision Insight, Inc., Cedar Park, Texas.  All Rights Reserved.
3428d7b3dSmrg * Copyright (c) 2005 Jesse Barnes <jbarnes@virtuousgeek.org>
4428d7b3dSmrg * Copyright © 2010 Intel Corporation
5428d7b3dSmrg *
6428d7b3dSmrg * Permission is hereby granted, free of charge, to any person obtaining a
7428d7b3dSmrg * copy of this software and associated documentation files (the "Software"),
8428d7b3dSmrg * to deal in the Software without restriction, including without limitation
9428d7b3dSmrg * the rights to use, copy, modify, merge, publish, distribute, sublicense,
10428d7b3dSmrg * and/or sell copies of the Software, and to permit persons to whom the
11428d7b3dSmrg * Software is furnished to do so, subject to the following conditions:
12428d7b3dSmrg *
13428d7b3dSmrg * The above copyright notice and this permission notice (including the next
14428d7b3dSmrg * paragraph) shall be included in all copies or substantial portions of the
15428d7b3dSmrg * Software.
16428d7b3dSmrg *
17428d7b3dSmrg * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
18428d7b3dSmrg * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
19428d7b3dSmrg * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
20428d7b3dSmrg * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
21428d7b3dSmrg * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
22428d7b3dSmrg * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
23428d7b3dSmrg * SOFTWARE.
24428d7b3dSmrg *
25428d7b3dSmrg * Authors:
26428d7b3dSmrg *    Jesse Barns <jbarnes@virtuousgeek.org>
27428d7b3dSmrg *    Chris Wilson <chris@chris-wilson.co.uk>
28428d7b3dSmrg */
29428d7b3dSmrg
30428d7b3dSmrg#ifdef HAVE_CONFIG_H
31428d7b3dSmrg#include "config.h"
32428d7b3dSmrg#endif
33428d7b3dSmrg
34428d7b3dSmrg#include "sna.h"
35428d7b3dSmrg
36428d7b3dSmrg/**
37428d7b3dSmrg * Returns whether the provided transform is affine.
38428d7b3dSmrg *
39428d7b3dSmrg * transform may be null.
40428d7b3dSmrg */
41428d7b3dSmrgbool sna_transform_is_affine(const PictTransform *t)
42428d7b3dSmrg{
43428d7b3dSmrg	if (t == NULL)
44428d7b3dSmrg		return true;
45428d7b3dSmrg
46428d7b3dSmrg	return t->matrix[2][0] == 0 && t->matrix[2][1] == 0;
47428d7b3dSmrg}
48428d7b3dSmrg
49428d7b3dSmrgbool
50428d7b3dSmrgsna_transform_is_translation(const PictTransform *t,
51428d7b3dSmrg			     pixman_fixed_t *tx,
52428d7b3dSmrg			     pixman_fixed_t *ty)
53428d7b3dSmrg{
54428d7b3dSmrg	if (t == NULL) {
55428d7b3dSmrg		*tx = *ty = 0;
56428d7b3dSmrg		return true;
57428d7b3dSmrg	}
58428d7b3dSmrg
59428d7b3dSmrg	if (t->matrix[0][0] != IntToxFixed(1) ||
60428d7b3dSmrg	    t->matrix[0][1] != 0 ||
61428d7b3dSmrg	    t->matrix[1][0] != 0 ||
62428d7b3dSmrg	    t->matrix[1][1] != IntToxFixed(1) ||
63428d7b3dSmrg	    t->matrix[2][0] != 0 ||
64428d7b3dSmrg	    t->matrix[2][1] != 0 ||
65428d7b3dSmrg	    t->matrix[2][2] != IntToxFixed(1))
66428d7b3dSmrg		return false;
67428d7b3dSmrg
68428d7b3dSmrg	*tx = t->matrix[0][2];
69428d7b3dSmrg	*ty = t->matrix[1][2];
70428d7b3dSmrg	return true;
71428d7b3dSmrg}
72428d7b3dSmrg
73428d7b3dSmrgbool
74428d7b3dSmrgsna_transform_is_integer_translation(const PictTransform *t, int16_t *tx, int16_t *ty)
75428d7b3dSmrg{
76428d7b3dSmrg	if (t == NULL) {
77428d7b3dSmrg		*tx = *ty = 0;
78428d7b3dSmrg		return true;
79428d7b3dSmrg	}
80428d7b3dSmrg
81428d7b3dSmrg	if (t->matrix[0][0] != IntToxFixed(1) ||
82428d7b3dSmrg	    t->matrix[0][1] != 0 ||
83428d7b3dSmrg	    t->matrix[1][0] != 0 ||
84428d7b3dSmrg	    t->matrix[1][1] != IntToxFixed(1) ||
85428d7b3dSmrg	    t->matrix[2][0] != 0 ||
86428d7b3dSmrg	    t->matrix[2][1] != 0 ||
87428d7b3dSmrg	    t->matrix[2][2] != IntToxFixed(1))
88428d7b3dSmrg		return false;
89428d7b3dSmrg
90428d7b3dSmrg	if (pixman_fixed_fraction(t->matrix[0][2]) ||
91428d7b3dSmrg	    pixman_fixed_fraction(t->matrix[1][2]))
92428d7b3dSmrg		return false;
93428d7b3dSmrg
94428d7b3dSmrg	*tx = pixman_fixed_to_int(t->matrix[0][2]);
95428d7b3dSmrg	*ty = pixman_fixed_to_int(t->matrix[1][2]);
96428d7b3dSmrg	return true;
97428d7b3dSmrg}
98428d7b3dSmrg
99428d7b3dSmrgbool
100428d7b3dSmrgsna_transform_is_imprecise_integer_translation(const PictTransform *t,
101428d7b3dSmrg					       int filter, bool precise,
102428d7b3dSmrg					       int16_t *tx, int16_t *ty)
103428d7b3dSmrg{
104428d7b3dSmrg	if (t == NULL) {
105428d7b3dSmrg		DBG(("%s: no transform\n", __FUNCTION__));
106428d7b3dSmrg		*tx = *ty = 0;
107428d7b3dSmrg		return true;
108428d7b3dSmrg	}
109428d7b3dSmrg
110428d7b3dSmrg	DBG(("%s: FilterNearest?=%d, precise?=%d, transform=[%f %f %f, %f %f %f, %f %f %f]\n",
111428d7b3dSmrg	     __FUNCTION__, filter==PictFilterNearest, precise,
112428d7b3dSmrg	     t->matrix[0][0]/65536., t->matrix[0][1]/65536., t->matrix[0][2]/65536.,
113428d7b3dSmrg	     t->matrix[1][0]/65536., t->matrix[1][1]/65536., t->matrix[1][2]/65536.,
114428d7b3dSmrg	     t->matrix[2][0]/65536., t->matrix[2][1]/65536., t->matrix[2][2]/65536.));
115428d7b3dSmrg
116428d7b3dSmrg	if (t->matrix[0][0] != IntToxFixed(1) ||
117428d7b3dSmrg	    t->matrix[0][1] != 0 ||
118428d7b3dSmrg	    t->matrix[1][0] != 0 ||
119428d7b3dSmrg	    t->matrix[1][1] != IntToxFixed(1) ||
120428d7b3dSmrg	    t->matrix[2][0] != 0 ||
121428d7b3dSmrg	    t->matrix[2][1] != 0 ||
122428d7b3dSmrg	    t->matrix[2][2] != IntToxFixed(1)) {
123428d7b3dSmrg		DBG(("%s: not unity scaling\n", __FUNCTION__));
124428d7b3dSmrg		return false;
125428d7b3dSmrg	}
126428d7b3dSmrg
127428d7b3dSmrg	if (filter != PictFilterNearest) {
128428d7b3dSmrg		if (precise) {
129428d7b3dSmrg			if (pixman_fixed_fraction(t->matrix[0][2]) ||
130428d7b3dSmrg			    pixman_fixed_fraction(t->matrix[1][2])) {
131428d7b3dSmrg				DBG(("%s: precise, fractional translation\n", __FUNCTION__));
132428d7b3dSmrg				return false;
133428d7b3dSmrg			}
134428d7b3dSmrg		} else {
135428d7b3dSmrg			int f;
136428d7b3dSmrg
137428d7b3dSmrg			f = pixman_fixed_fraction(t->matrix[0][2]);
138428d7b3dSmrg			if (f > IntToxFixed(1)/4 && f < IntToxFixed(3)/4) {
139428d7b3dSmrg				DBG(("%s: imprecise, fractional translation X: %x\n", __FUNCTION__, f));
140428d7b3dSmrg				return false;
141428d7b3dSmrg			}
142428d7b3dSmrg
143428d7b3dSmrg			f = pixman_fixed_fraction(t->matrix[1][2]);
144428d7b3dSmrg			if (f > IntToxFixed(1)/4 && f < IntToxFixed(3)/4) {
145428d7b3dSmrg				DBG(("%s: imprecise, fractional translation Y: %x\n", __FUNCTION__, f));
146428d7b3dSmrg				return false;
147428d7b3dSmrg			}
148428d7b3dSmrg		}
149428d7b3dSmrg	}
150428d7b3dSmrg
151428d7b3dSmrg	*tx = pixman_fixed_to_int(t->matrix[0][2] + IntToxFixed(1)/2);
152428d7b3dSmrg	*ty = pixman_fixed_to_int(t->matrix[1][2] + IntToxFixed(1)/2);
153428d7b3dSmrg	return true;
154428d7b3dSmrg}
155428d7b3dSmrg
156428d7b3dSmrg/**
157428d7b3dSmrg * Returns the floating-point coordinates transformed by the given transform.
158428d7b3dSmrg */
159428d7b3dSmrgvoid
160428d7b3dSmrgsna_get_transformed_coordinates(int x, int y,
161428d7b3dSmrg			       	const PictTransform *transform,
162428d7b3dSmrg				float *x_out, float *y_out)
163428d7b3dSmrg{
164428d7b3dSmrg	if (transform == NULL) {
165428d7b3dSmrg		*x_out = x;
166428d7b3dSmrg		*y_out = y;
167428d7b3dSmrg	} else
168428d7b3dSmrg		_sna_get_transformed_coordinates(x, y, transform, x_out, y_out);
169428d7b3dSmrg}
170428d7b3dSmrg
171428d7b3dSmrg/**
172428d7b3dSmrg * Returns the un-normalized floating-point coordinates transformed by the given transform.
173428d7b3dSmrg */
174428d7b3dSmrgvoid
175428d7b3dSmrgsna_get_transformed_coordinates_3d(int x, int y,
176428d7b3dSmrg				   const PictTransform *transform,
177428d7b3dSmrg				   float *x_out, float *y_out, float *w_out)
178428d7b3dSmrg{
179428d7b3dSmrg	if (transform == NULL) {
180428d7b3dSmrg		*x_out = x;
181428d7b3dSmrg		*y_out = y;
182428d7b3dSmrg		*w_out = 1;
183428d7b3dSmrg	} else {
184428d7b3dSmrg		int64_t result[3];
185428d7b3dSmrg
186428d7b3dSmrg		if (_sna_transform_point(transform, x, y, result)) {
187428d7b3dSmrg			*x_out = result[0] / 65536.;
188428d7b3dSmrg			*y_out = result[1] / 65536.;
189428d7b3dSmrg			*w_out = result[2] / 65536.;
190428d7b3dSmrg		} else {
191428d7b3dSmrg			*x_out = *y_out = 0;
192428d7b3dSmrg			*w_out = 1.;
193428d7b3dSmrg		}
194428d7b3dSmrg	}
195428d7b3dSmrg}
196