103b705cfSriastradh/* 203b705cfSriastradh * Copyright 1998-1999 Precision Insight, Inc., Cedar Park, Texas. All Rights Reserved. 303b705cfSriastradh * Copyright (c) 2005 Jesse Barnes <jbarnes@virtuousgeek.org> 403b705cfSriastradh * Copyright © 2010 Intel Corporation 503b705cfSriastradh * 603b705cfSriastradh * Permission is hereby granted, free of charge, to any person obtaining a 703b705cfSriastradh * copy of this software and associated documentation files (the "Software"), 803b705cfSriastradh * to deal in the Software without restriction, including without limitation 903b705cfSriastradh * the rights to use, copy, modify, merge, publish, distribute, sublicense, 1003b705cfSriastradh * and/or sell copies of the Software, and to permit persons to whom the 1103b705cfSriastradh * Software is furnished to do so, subject to the following conditions: 1203b705cfSriastradh * 1303b705cfSriastradh * The above copyright notice and this permission notice (including the next 1403b705cfSriastradh * paragraph) shall be included in all copies or substantial portions of the 1503b705cfSriastradh * Software. 1603b705cfSriastradh * 1703b705cfSriastradh * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 1803b705cfSriastradh * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 1903b705cfSriastradh * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL 2003b705cfSriastradh * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 2103b705cfSriastradh * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 2203b705cfSriastradh * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 2303b705cfSriastradh * SOFTWARE. 2403b705cfSriastradh * 2503b705cfSriastradh * Authors: 2603b705cfSriastradh * Jesse Barns <jbarnes@virtuousgeek.org> 2703b705cfSriastradh * Chris Wilson <chris@chris-wilson.co.uk> 2803b705cfSriastradh */ 2903b705cfSriastradh 3003b705cfSriastradh#ifdef HAVE_CONFIG_H 3103b705cfSriastradh#include "config.h" 3203b705cfSriastradh#endif 3303b705cfSriastradh 3403b705cfSriastradh#include "sna.h" 3503b705cfSriastradh 3603b705cfSriastradh/** 3703b705cfSriastradh * Returns whether the provided transform is affine. 3803b705cfSriastradh * 3903b705cfSriastradh * transform may be null. 4003b705cfSriastradh */ 4103b705cfSriastradhbool sna_transform_is_affine(const PictTransform *t) 4203b705cfSriastradh{ 4303b705cfSriastradh if (t == NULL) 4403b705cfSriastradh return true; 4503b705cfSriastradh 4603b705cfSriastradh return t->matrix[2][0] == 0 && t->matrix[2][1] == 0; 4703b705cfSriastradh} 4803b705cfSriastradh 4903b705cfSriastradhbool 5003b705cfSriastradhsna_transform_is_translation(const PictTransform *t, 5103b705cfSriastradh pixman_fixed_t *tx, 5203b705cfSriastradh pixman_fixed_t *ty) 5303b705cfSriastradh{ 5403b705cfSriastradh if (t == NULL) { 5503b705cfSriastradh *tx = *ty = 0; 5603b705cfSriastradh return true; 5703b705cfSriastradh } 5803b705cfSriastradh 5903b705cfSriastradh if (t->matrix[0][0] != IntToxFixed(1) || 6003b705cfSriastradh t->matrix[0][1] != 0 || 6103b705cfSriastradh t->matrix[1][0] != 0 || 6203b705cfSriastradh t->matrix[1][1] != IntToxFixed(1) || 6303b705cfSriastradh t->matrix[2][0] != 0 || 6403b705cfSriastradh t->matrix[2][1] != 0 || 6503b705cfSriastradh t->matrix[2][2] != IntToxFixed(1)) 6603b705cfSriastradh return false; 6703b705cfSriastradh 6803b705cfSriastradh *tx = t->matrix[0][2]; 6903b705cfSriastradh *ty = t->matrix[1][2]; 7003b705cfSriastradh return true; 7103b705cfSriastradh} 7203b705cfSriastradh 7303b705cfSriastradhbool 7403b705cfSriastradhsna_transform_is_integer_translation(const PictTransform *t, int16_t *tx, int16_t *ty) 7503b705cfSriastradh{ 7603b705cfSriastradh if (t == NULL) { 7703b705cfSriastradh *tx = *ty = 0; 7803b705cfSriastradh return true; 7903b705cfSriastradh } 8003b705cfSriastradh 8103b705cfSriastradh if (t->matrix[0][0] != IntToxFixed(1) || 8203b705cfSriastradh t->matrix[0][1] != 0 || 8303b705cfSriastradh t->matrix[1][0] != 0 || 8403b705cfSriastradh t->matrix[1][1] != IntToxFixed(1) || 8503b705cfSriastradh t->matrix[2][0] != 0 || 8603b705cfSriastradh t->matrix[2][1] != 0 || 8703b705cfSriastradh t->matrix[2][2] != IntToxFixed(1)) 8803b705cfSriastradh return false; 8903b705cfSriastradh 9003b705cfSriastradh if (pixman_fixed_fraction(t->matrix[0][2]) || 9103b705cfSriastradh pixman_fixed_fraction(t->matrix[1][2])) 9203b705cfSriastradh return false; 9303b705cfSriastradh 9403b705cfSriastradh *tx = pixman_fixed_to_int(t->matrix[0][2]); 9503b705cfSriastradh *ty = pixman_fixed_to_int(t->matrix[1][2]); 9603b705cfSriastradh return true; 9703b705cfSriastradh} 9803b705cfSriastradh 9942542f5fSchristosbool 10042542f5fSchristossna_transform_is_imprecise_integer_translation(const PictTransform *t, 10142542f5fSchristos int filter, bool precise, 10242542f5fSchristos int16_t *tx, int16_t *ty) 10342542f5fSchristos{ 10442542f5fSchristos if (t == NULL) { 10542542f5fSchristos DBG(("%s: no transform\n", __FUNCTION__)); 10642542f5fSchristos *tx = *ty = 0; 10742542f5fSchristos return true; 10842542f5fSchristos } 10942542f5fSchristos 11042542f5fSchristos DBG(("%s: FilterNearest?=%d, precise?=%d, transform=[%f %f %f, %f %f %f, %f %f %f]\n", 11142542f5fSchristos __FUNCTION__, filter==PictFilterNearest, precise, 11242542f5fSchristos t->matrix[0][0]/65536., t->matrix[0][1]/65536., t->matrix[0][2]/65536., 11342542f5fSchristos t->matrix[1][0]/65536., t->matrix[1][1]/65536., t->matrix[1][2]/65536., 11442542f5fSchristos t->matrix[2][0]/65536., t->matrix[2][1]/65536., t->matrix[2][2]/65536.)); 11542542f5fSchristos 11642542f5fSchristos if (t->matrix[0][0] != IntToxFixed(1) || 11742542f5fSchristos t->matrix[0][1] != 0 || 11842542f5fSchristos t->matrix[1][0] != 0 || 11942542f5fSchristos t->matrix[1][1] != IntToxFixed(1) || 12042542f5fSchristos t->matrix[2][0] != 0 || 12142542f5fSchristos t->matrix[2][1] != 0 || 12242542f5fSchristos t->matrix[2][2] != IntToxFixed(1)) { 12342542f5fSchristos DBG(("%s: not unity scaling\n", __FUNCTION__)); 12442542f5fSchristos return false; 12542542f5fSchristos } 12642542f5fSchristos 12742542f5fSchristos if (filter != PictFilterNearest) { 12842542f5fSchristos if (precise) { 12942542f5fSchristos if (pixman_fixed_fraction(t->matrix[0][2]) || 13042542f5fSchristos pixman_fixed_fraction(t->matrix[1][2])) { 13142542f5fSchristos DBG(("%s: precise, fractional translation\n", __FUNCTION__)); 13242542f5fSchristos return false; 13342542f5fSchristos } 13442542f5fSchristos } else { 13542542f5fSchristos int f; 13642542f5fSchristos 13742542f5fSchristos f = pixman_fixed_fraction(t->matrix[0][2]); 13813496ba1Ssnj if (f > IntToxFixed(1)/4 && f < IntToxFixed(3)/4) { 13913496ba1Ssnj DBG(("%s: imprecise, fractional translation X: %x\n", __FUNCTION__, f)); 14042542f5fSchristos return false; 14142542f5fSchristos } 14242542f5fSchristos 14342542f5fSchristos f = pixman_fixed_fraction(t->matrix[1][2]); 14413496ba1Ssnj if (f > IntToxFixed(1)/4 && f < IntToxFixed(3)/4) { 14513496ba1Ssnj DBG(("%s: imprecise, fractional translation Y: %x\n", __FUNCTION__, f)); 14642542f5fSchristos return false; 14742542f5fSchristos } 14842542f5fSchristos } 14942542f5fSchristos } 15042542f5fSchristos 15142542f5fSchristos *tx = pixman_fixed_to_int(t->matrix[0][2] + IntToxFixed(1)/2); 15242542f5fSchristos *ty = pixman_fixed_to_int(t->matrix[1][2] + IntToxFixed(1)/2); 15342542f5fSchristos return true; 15442542f5fSchristos} 15542542f5fSchristos 15603b705cfSriastradh/** 15703b705cfSriastradh * Returns the floating-point coordinates transformed by the given transform. 15803b705cfSriastradh */ 15903b705cfSriastradhvoid 16003b705cfSriastradhsna_get_transformed_coordinates(int x, int y, 16103b705cfSriastradh const PictTransform *transform, 16203b705cfSriastradh float *x_out, float *y_out) 16303b705cfSriastradh{ 16403b705cfSriastradh if (transform == NULL) { 16503b705cfSriastradh *x_out = x; 16603b705cfSriastradh *y_out = y; 16703b705cfSriastradh } else 16803b705cfSriastradh _sna_get_transformed_coordinates(x, y, transform, x_out, y_out); 16903b705cfSriastradh} 17003b705cfSriastradh 17103b705cfSriastradh/** 17203b705cfSriastradh * Returns the un-normalized floating-point coordinates transformed by the given transform. 17303b705cfSriastradh */ 17403b705cfSriastradhvoid 17503b705cfSriastradhsna_get_transformed_coordinates_3d(int x, int y, 17603b705cfSriastradh const PictTransform *transform, 17703b705cfSriastradh float *x_out, float *y_out, float *w_out) 17803b705cfSriastradh{ 17903b705cfSriastradh if (transform == NULL) { 18003b705cfSriastradh *x_out = x; 18103b705cfSriastradh *y_out = y; 18203b705cfSriastradh *w_out = 1; 18303b705cfSriastradh } else { 18403b705cfSriastradh int64_t result[3]; 18503b705cfSriastradh 18603b705cfSriastradh if (_sna_transform_point(transform, x, y, result)) { 18703b705cfSriastradh *x_out = result[0] / 65536.; 18803b705cfSriastradh *y_out = result[1] / 65536.; 18903b705cfSriastradh *w_out = result[2] / 65536.; 19003b705cfSriastradh } else { 19103b705cfSriastradh *x_out = *y_out = 0; 19203b705cfSriastradh *w_out = 1.; 19303b705cfSriastradh } 19403b705cfSriastradh } 19503b705cfSriastradh} 196