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