glsl2: Add and use new variable mode ir_var_temporary
[mesa/nouveau-pmpeg.git] / src / gallium / state_trackers / vega / vgu.c
blob7dc51c5599cd575801ebee36fb664e3eee411d24
1 /**************************************************************************
3 * Copyright 2009 VMware, Inc. All Rights Reserved.
5 * Permission is hereby granted, free of charge, to any person obtaining a
6 * copy of this software and associated documentation files (the
7 * "Software"), to deal in the Software without restriction, including
8 * without limitation the rights to use, copy, modify, merge, publish,
9 * distribute, sub license, and/or sell copies of the Software, and to
10 * permit persons to whom the Software is furnished to do so, subject to
11 * the following conditions:
13 * The above copyright notice and this permission notice (including the
14 * next paragraph) shall be included in all copies or substantial portions
15 * of the Software.
17 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
18 * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
19 * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.
20 * IN NO EVENT SHALL VMWARE AND/OR ITS SUPPLIERS BE LIABLE FOR
21 * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
22 * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
23 * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
25 **************************************************************************/
27 #include "VG/openvg.h"
28 #include "VG/vgu.h"
30 #include "matrix.h"
31 #include "path.h"
33 #include "util/u_debug.h"
34 #include "util/u_pointer.h"
36 #include <math.h>
37 #include <assert.h>
39 static VGboolean is_aligned_to(const void *ptr, VGbyte alignment)
41 void *aligned = align_pointer(ptr, alignment);
42 return (ptr == aligned) ? VG_TRUE : VG_FALSE;
45 static VGboolean is_aligned(const void *ptr)
47 return is_aligned_to(ptr, 4);
50 static void vgu_append_float_coords(VGPath path,
51 const VGubyte *cmds,
52 VGint num_cmds,
53 const VGfloat *coords,
54 VGint num_coords)
56 VGubyte common_data[40 * sizeof(VGfloat)];
57 struct path *p = (struct path *)path;
59 vg_float_to_datatype(path_datatype(p), common_data, coords, num_coords);
60 vgAppendPathData(path, num_cmds, cmds, common_data);
63 VGUErrorCode vguLine(VGPath path,
64 VGfloat x0, VGfloat y0,
65 VGfloat x1, VGfloat y1)
67 static const VGubyte cmds[] = {VG_MOVE_TO_ABS, VG_LINE_TO_ABS};
68 VGfloat coords[4];
69 VGbitfield caps;
71 if (path == VG_INVALID_HANDLE) {
72 return VGU_BAD_HANDLE_ERROR;
74 caps = vgGetPathCapabilities(path);
75 if (!(caps & VG_PATH_CAPABILITY_APPEND_TO)) {
76 return VGU_PATH_CAPABILITY_ERROR;
79 coords[0] = x0;
80 coords[1] = y0;
81 coords[2] = x1;
82 coords[3] = y1;
84 vgu_append_float_coords(path, cmds, 2, coords, 4);
86 return VGU_NO_ERROR;
89 VGUErrorCode vguPolygon(VGPath path,
90 const VGfloat * points,
91 VGint count,
92 VGboolean closed)
94 VGubyte *cmds;
95 VGfloat *coords;
96 VGbitfield caps;
97 VGint i;
99 if (path == VG_INVALID_HANDLE) {
100 return VGU_BAD_HANDLE_ERROR;
103 if (!points || count <= 0 || !is_aligned(points)) {
104 return VGU_ILLEGAL_ARGUMENT_ERROR;
107 caps = vgGetPathCapabilities(path);
108 if (!(caps & VG_PATH_CAPABILITY_APPEND_TO)) {
109 return VGU_PATH_CAPABILITY_ERROR;
112 cmds = malloc(sizeof(VGubyte) * count + 1);
113 coords = malloc(sizeof(VGfloat) * count * 2);
115 cmds[0] = VG_MOVE_TO_ABS;
116 coords[0] = points[0];
117 coords[1] = points[1];
118 for (i = 1; i < count; ++i) {
119 cmds[i] = VG_LINE_TO_ABS;
120 coords[2*i + 0] = points[2*i + 0];
121 coords[2*i + 1] = points[2*i + 1];
124 if (closed) {
125 cmds[i] = VG_CLOSE_PATH;
126 ++i;
129 vgu_append_float_coords(path, cmds, i, coords, 2*i);
131 free(cmds);
132 free(coords);
134 return VGU_NO_ERROR;
137 VGUErrorCode vguRect(VGPath path,
138 VGfloat x, VGfloat y,
139 VGfloat width, VGfloat height)
141 static const VGubyte cmds[] = {VG_MOVE_TO_ABS,
142 VG_HLINE_TO_REL,
143 VG_VLINE_TO_REL,
144 VG_HLINE_TO_REL,
145 VG_CLOSE_PATH
147 VGfloat coords[5];
148 VGbitfield caps;
150 if (path == VG_INVALID_HANDLE) {
151 return VGU_BAD_HANDLE_ERROR;
153 caps = vgGetPathCapabilities(path);
154 if (!(caps & VG_PATH_CAPABILITY_APPEND_TO)) {
155 return VGU_PATH_CAPABILITY_ERROR;
157 if (width <= 0 || height <= 0) {
158 return VGU_ILLEGAL_ARGUMENT_ERROR;
161 coords[0] = x;
162 coords[1] = y;
163 coords[2] = width;
164 coords[3] = height;
165 coords[4] = -width;
167 vgu_append_float_coords(path, cmds, 5, coords, 5);
169 return VGU_NO_ERROR;
172 VGUErrorCode vguRoundRect(VGPath path,
173 VGfloat x, VGfloat y,
174 VGfloat width,
175 VGfloat height,
176 VGfloat arcWidth,
177 VGfloat arcHeight)
179 static const VGubyte cmds[] = {VG_MOVE_TO_ABS,
180 VG_HLINE_TO_REL,
181 VG_SCCWARC_TO_REL,
182 VG_VLINE_TO_REL,
183 VG_SCCWARC_TO_REL,
184 VG_HLINE_TO_REL,
185 VG_SCCWARC_TO_REL,
186 VG_VLINE_TO_REL,
187 VG_SCCWARC_TO_REL,
188 VG_CLOSE_PATH
190 VGfloat c[26];
191 VGbitfield caps;
193 if (path == VG_INVALID_HANDLE) {
194 return VGU_BAD_HANDLE_ERROR;
196 caps = vgGetPathCapabilities(path);
197 if (!(caps & VG_PATH_CAPABILITY_APPEND_TO)) {
198 return VGU_PATH_CAPABILITY_ERROR;
200 if (width <= 0 || height <= 0) {
201 return VGU_ILLEGAL_ARGUMENT_ERROR;
204 c[0] = x + arcWidth/2; c[1] = y;
206 c[2] = width - arcWidth;
208 c[3] = arcWidth/2; c[4] = arcHeight/2; c[5] = 0;
209 c[6] = arcWidth/2; c[7] = arcHeight/2;
211 c[8] = height - arcHeight;
213 c[9] = arcWidth/2; c[10] = arcHeight/2; c[11] = 0;
214 c[12] = -arcWidth/2; c[13] = arcHeight/2;
216 c[14] = -(width - arcWidth);
218 c[15] = arcWidth/2; c[16] = arcHeight/2; c[17] = 0;
219 c[18] = -arcWidth/2; c[19] = -arcHeight/2;
221 c[20] = -(height - arcHeight);
223 c[21] = arcWidth/2; c[22] = arcHeight/2; c[23] = 0;
224 c[24] = arcWidth/2; c[25] = -arcHeight/2;
226 vgu_append_float_coords(path, cmds, 10, c, 26);
228 return VGU_NO_ERROR;
231 VGUErrorCode vguEllipse(VGPath path,
232 VGfloat cx, VGfloat cy,
233 VGfloat width,
234 VGfloat height)
236 static const VGubyte cmds[] = {VG_MOVE_TO_ABS,
237 VG_SCCWARC_TO_REL,
238 VG_SCCWARC_TO_REL,
239 VG_CLOSE_PATH
241 VGfloat coords[12];
242 VGbitfield caps;
244 if (path == VG_INVALID_HANDLE) {
245 return VGU_BAD_HANDLE_ERROR;
247 caps = vgGetPathCapabilities(path);
248 if (!(caps & VG_PATH_CAPABILITY_APPEND_TO)) {
249 return VGU_PATH_CAPABILITY_ERROR;
251 if (width <= 0 || height <= 0) {
252 return VGU_ILLEGAL_ARGUMENT_ERROR;
255 coords[0] = cx + width/2; coords[1] = cy;
257 coords[2] = width/2; coords[3] = height/2; coords[4] = 0;
258 coords[5] = -width; coords[6] = 0;
260 coords[7] = width/2; coords[8] = height/2; coords[9] = 0;
261 coords[10] = width; coords[11] = 0;
263 vgu_append_float_coords(path, cmds, 4, coords, 11);
265 return VGU_NO_ERROR;
268 VGUErrorCode vguArc(VGPath path,
269 VGfloat x, VGfloat y,
270 VGfloat width, VGfloat height,
271 VGfloat startAngle,
272 VGfloat angleExtent,
273 VGUArcType arcType)
275 VGubyte cmds[11];
276 VGfloat coords[40];
277 VGbitfield caps;
278 VGfloat last = startAngle + angleExtent;
279 VGint i, c = 0;
281 if (path == VG_INVALID_HANDLE) {
282 return VGU_BAD_HANDLE_ERROR;
284 caps = vgGetPathCapabilities(path);
285 if (!(caps & VG_PATH_CAPABILITY_APPEND_TO)) {
286 return VGU_PATH_CAPABILITY_ERROR;
288 if (width <= 0 || height <= 0) {
289 return VGU_ILLEGAL_ARGUMENT_ERROR;
291 if (arcType != VGU_ARC_OPEN &&
292 arcType != VGU_ARC_CHORD &&
293 arcType != VGU_ARC_PIE) {
294 return VGU_ILLEGAL_ARGUMENT_ERROR;
297 cmds[c] = VG_MOVE_TO_ABS; ++c;
298 coords[0] = x+cos(DEGREES_TO_RADIANS(startAngle))*width/2;
299 coords[1] = y+sin(DEGREES_TO_RADIANS(startAngle))*height/2;
300 #ifdef DEBUG_VGUARC
301 debug_printf("start [%f, %f]\n", coords[0], coords[1]);
302 #endif
303 i = 2;
304 if (angleExtent > 0) {
305 VGfloat angle = startAngle + 180;
306 while (angle < last) {
307 cmds[c] = VG_SCCWARC_TO_ABS; ++c;
308 coords[i] = width/2; coords[i+1] = height/2; coords[i+2] = 0;
309 coords[i+3] = x + cos(DEGREES_TO_RADIANS(angle))*width/2;
310 coords[i+4] = y + sin(DEGREES_TO_RADIANS(angle))*height/2;
311 #ifdef DEBUG_VGUARC
312 debug_printf("1 [%f, %f]\n", coords[i+3],
313 coords[i+4]);
314 #endif
315 i += 5;
316 angle += 180;
318 cmds[c] = VG_SCCWARC_TO_ABS; ++c;
319 coords[i] = width/2; coords[i+1] = height/2; coords[i+2] = 0;
320 coords[i+3] = x+cos(DEGREES_TO_RADIANS(last))*width/2;
321 coords[i+4] = y+sin(DEGREES_TO_RADIANS(last))*height/2;
322 #ifdef DEBUG_VGUARC
323 debug_printf("2 [%f, %f]\n", coords[i+3],
324 coords[i+4]);
325 #endif
326 i += 5;
327 } else {
328 VGfloat angle = startAngle - 180;
329 while (angle > last) {
330 cmds[c] = VG_SCWARC_TO_ABS; ++c;
331 coords[i] = width/2; coords[i+1] = height/2; coords[i+2] = 0;
332 coords[i+3] = x + cos(DEGREES_TO_RADIANS(angle)) * width/2;
333 coords[i+4] = y + sin(DEGREES_TO_RADIANS(angle)) * height/2;
334 #ifdef DEBUG_VGUARC
335 debug_printf("3 [%f, %f]\n", coords[i+3],
336 coords[i+4]);
337 #endif
338 angle -= 180;
339 i += 5;
341 cmds[c] = VG_SCWARC_TO_ABS; ++c;
342 coords[i] = width/2; coords[i+1] = height/2; coords[i+2] = 0;
343 coords[i+3] = x + cos(DEGREES_TO_RADIANS(last)) * width/2;
344 coords[i+4] = y + sin(DEGREES_TO_RADIANS(last)) * height/2;
345 #ifdef DEBUG_VGUARC
346 debug_printf("4 [%f, %f]\n", coords[i+3],
347 coords[i+4]);
348 #endif
349 i += 5;
352 if (arcType == VGU_ARC_PIE) {
353 cmds[c] = VG_LINE_TO_ABS; ++c;
354 coords[i] = x; coords[i + 1] = y;
355 i += 2;
357 if (arcType == VGU_ARC_PIE || arcType == VGU_ARC_CHORD) {
358 cmds[c] = VG_CLOSE_PATH;
359 ++c;
362 assert(c < 11);
364 vgu_append_float_coords(path, cmds, c, coords, i);
366 return VGU_NO_ERROR;
369 VGUErrorCode vguComputeWarpQuadToSquare(VGfloat sx0, VGfloat sy0,
370 VGfloat sx1, VGfloat sy1,
371 VGfloat sx2, VGfloat sy2,
372 VGfloat sx3, VGfloat sy3,
373 VGfloat * matrix)
375 struct matrix mat;
377 if (!matrix || !is_aligned(matrix))
378 return VGU_ILLEGAL_ARGUMENT_ERROR;
380 if (!matrix_quad_to_square(sx0, sy0,
381 sx1, sy1,
382 sx2, sy2,
383 sx3, sy3,
384 &mat))
385 return VGU_BAD_WARP_ERROR;
387 if (!matrix_is_invertible(&mat))
388 return VGU_BAD_WARP_ERROR;
390 memcpy(matrix, mat.m, sizeof(VGfloat) * 9);
392 return VGU_NO_ERROR;
395 VGUErrorCode vguComputeWarpSquareToQuad(VGfloat dx0, VGfloat dy0,
396 VGfloat dx1, VGfloat dy1,
397 VGfloat dx2, VGfloat dy2,
398 VGfloat dx3, VGfloat dy3,
399 VGfloat * matrix)
401 struct matrix mat;
403 if (!matrix || !is_aligned(matrix))
404 return VGU_ILLEGAL_ARGUMENT_ERROR;
406 if (!matrix_square_to_quad(dx0, dy0,
407 dx1, dy1,
408 dx2, dy2,
409 dx3, dy3,
410 &mat))
411 return VGU_BAD_WARP_ERROR;
413 if (!matrix_is_invertible(&mat))
414 return VGU_BAD_WARP_ERROR;
416 memcpy(matrix, mat.m, sizeof(VGfloat) * 9);
418 return VGU_NO_ERROR;
421 VGUErrorCode vguComputeWarpQuadToQuad(VGfloat dx0, VGfloat dy0,
422 VGfloat dx1, VGfloat dy1,
423 VGfloat dx2, VGfloat dy2,
424 VGfloat dx3, VGfloat dy3,
425 VGfloat sx0, VGfloat sy0,
426 VGfloat sx1, VGfloat sy1,
427 VGfloat sx2, VGfloat sy2,
428 VGfloat sx3, VGfloat sy3,
429 VGfloat * matrix)
431 struct matrix mat;
433 if (!matrix || !is_aligned(matrix))
434 return VGU_ILLEGAL_ARGUMENT_ERROR;
436 if (!matrix_quad_to_quad(dx0, dy0,
437 dx1, dy1,
438 dx2, dy2,
439 dx3, dy3,
440 sx0, sy0,
441 sx1, sy1,
442 sx2, sy2,
443 sx3, sy3,
444 &mat))
445 return VGU_BAD_WARP_ERROR;
447 memcpy(matrix, mat.m, sizeof(VGfloat) * 9);
449 return VGU_NO_ERROR;