1/* 2 * Copyright © 2011,2012,2013 Intel Corporation 3 * 4 * Permission is hereby granted, free of charge, to any person obtaining a 5 * copy of this software and associated documentation files (the "Software"), 6 * to deal in the Software without restriction, including without limitation 7 * the rights to use, copy, modify, merge, publish, distribute, sublicense, 8 * and/or sell copies of the Software, and to permit persons to whom the 9 * Software is furnished to do so, subject to the following conditions: 10 * 11 * The above copyright notice and this permission notice (including the next 12 * paragraph) shall be included in all copies or substantial portions of the 13 * Software. 14 * 15 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL 18 * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 * SOFTWARE. 22 * 23 * Authors: 24 * Chris Wilson <chris@chris-wilson.co.uk> 25 * 26 */ 27 28#ifdef HAVE_CONFIG_H 29#include "config.h" 30#endif 31 32#include "sna.h" 33#include "sna_render.h" 34#include "sna_render_inline.h" 35#include "gen4_source.h" 36#include "gen4_render.h" 37 38bool 39gen4_channel_init_solid(struct sna *sna, 40 struct sna_composite_channel *channel, 41 uint32_t color) 42{ 43 channel->filter = PictFilterNearest; 44 channel->repeat = RepeatNormal; 45 channel->is_affine = true; 46 channel->is_solid = true; 47 channel->is_opaque = (color >> 24) == 0xff; 48 channel->transform = NULL; 49 channel->width = 1; 50 channel->height = 1; 51 channel->pict_format = PICT_a8r8g8b8; 52 channel->card_format = GEN4_SURFACEFORMAT_B8G8R8A8_UNORM; 53 54 channel->bo = sna_render_get_solid(sna, color); 55 56 channel->scale[0] = channel->scale[1] = 1; 57 channel->offset[0] = channel->offset[1] = 0; 58 return channel->bo != NULL; 59} 60 61bool 62gen4_channel_init_linear(struct sna *sna, 63 PicturePtr picture, 64 struct sna_composite_channel *channel, 65 int x, int y, 66 int w, int h, 67 int dst_x, int dst_y) 68{ 69 PictLinearGradient *linear = 70 (PictLinearGradient *)picture->pSourcePict; 71 pixman_fixed_t tx, ty; 72 float x0, y0, sf; 73 float dx, dy; 74 75 DBG(("%s: p1=(%f, %f), p2=(%f, %f), src=(%d, %d), dst=(%d, %d), size=(%d, %d)\n", 76 __FUNCTION__, 77 pixman_fixed_to_double(linear->p1.x), pixman_fixed_to_double(linear->p1.y), 78 pixman_fixed_to_double(linear->p2.x), pixman_fixed_to_double(linear->p2.y), 79 x, y, dst_x, dst_y, w, h)); 80 81 if (linear->p2.x == linear->p1.x && linear->p2.y == linear->p1.y) 82 return 0; 83 84 if (!sna_transform_is_affine(picture->transform)) { 85 DBG(("%s: fallback due to projective transform\n", 86 __FUNCTION__)); 87 return sna_render_picture_fixup(sna, picture, channel, 88 x, y, w, h, dst_x, dst_y); 89 } 90 91 channel->bo = sna_render_get_gradient(sna, (PictGradient *)linear); 92 if (!channel->bo) 93 return 0; 94 95 channel->filter = PictFilterNearest; 96 channel->repeat = picture->repeat ? picture->repeatType : RepeatNone; 97 channel->width = channel->bo->pitch / 4; 98 channel->height = 1; 99 channel->pict_format = PICT_a8r8g8b8; 100 channel->card_format = GEN4_SURFACEFORMAT_B8G8R8A8_UNORM; 101 channel->is_linear = 1; 102 channel->is_affine = 1; 103 104 channel->scale[0] = channel->scale[1] = 1; 105 channel->offset[0] = channel->offset[1] = 0; 106 107 if (sna_transform_is_translation(picture->transform, &tx, &ty)) { 108 dx = pixman_fixed_to_double(linear->p2.x - linear->p1.x); 109 dy = pixman_fixed_to_double(linear->p2.y - linear->p1.y); 110 111 x0 = pixman_fixed_to_double(linear->p1.x); 112 y0 = pixman_fixed_to_double(linear->p1.y); 113 114 if (tx | ty) { 115 x0 -= pixman_fixed_to_double(tx); 116 y0 -= pixman_fixed_to_double(ty); 117 } 118 } else { 119 struct pixman_f_vector p1, p2; 120 struct pixman_f_transform m, inv; 121 122 pixman_f_transform_from_pixman_transform(&m, picture->transform); 123 DBG(("%s: transform = [%f %f %f, %f %f %f, %f %f %f]\n", 124 __FUNCTION__, 125 m.m[0][0], m.m[0][1], m.m[0][2], 126 m.m[1][0], m.m[1][1], m.m[1][2], 127 m.m[2][0], m.m[2][1], m.m[2][2])); 128 if (!pixman_f_transform_invert(&inv, &m)) 129 return 0; 130 131 p1.v[0] = pixman_fixed_to_double(linear->p1.x); 132 p1.v[1] = pixman_fixed_to_double(linear->p1.y); 133 p1.v[2] = 1.; 134 pixman_f_transform_point(&inv, &p1); 135 136 p2.v[0] = pixman_fixed_to_double(linear->p2.x); 137 p2.v[1] = pixman_fixed_to_double(linear->p2.y); 138 p2.v[2] = 1.; 139 pixman_f_transform_point(&inv, &p2); 140 141 DBG(("%s: untransformed: p1=(%f, %f, %f), p2=(%f, %f, %f)\n", 142 __FUNCTION__, 143 p1.v[0], p1.v[1], p1.v[2], 144 p2.v[0], p2.v[1], p2.v[2])); 145 146 dx = p2.v[0] - p1.v[0]; 147 dy = p2.v[1] - p1.v[1]; 148 149 x0 = p1.v[0]; 150 y0 = p1.v[1]; 151 } 152 153 sf = dx*dx + dy*dy; 154 dx /= sf; 155 dy /= sf; 156 157 channel->u.linear.dx = dx; 158 channel->u.linear.dy = dy; 159 channel->u.linear.offset = -dx*(x0+dst_x-x) + -dy*(y0+dst_y-y); 160 161 channel->embedded_transform.matrix[0][0] = pixman_double_to_fixed(dx); 162 channel->embedded_transform.matrix[0][1] = pixman_double_to_fixed(dy); 163 channel->embedded_transform.matrix[0][2] = pixman_double_to_fixed(channel->u.linear.offset); 164 165 channel->embedded_transform.matrix[1][0] = 0; 166 channel->embedded_transform.matrix[1][1] = 0; 167 channel->embedded_transform.matrix[1][2] = pixman_double_to_fixed(.5); 168 169 channel->embedded_transform.matrix[2][0] = 0; 170 channel->embedded_transform.matrix[2][1] = 0; 171 channel->embedded_transform.matrix[2][2] = pixman_fixed_1; 172 173 channel->transform = &channel->embedded_transform; 174 175 DBG(("%s: dx=%f, dy=%f, offset=%f\n", 176 __FUNCTION__, dx, dy, channel->u.linear.offset)); 177 178 return channel->bo != NULL; 179} 180