3faec749e12bd4516e204e4cb7d9d68cef3de428
[mesa.git] / src / gallium / state_trackers / vega / polygon.c
1 /**************************************************************************
2 *
3 * Copyright 2009 VMware, Inc. All Rights Reserved.
4 *
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:
12 *
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.
16 *
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.
24 *
25 **************************************************************************/
26
27 #include "polygon.h"
28
29 #include "matrix.h" /*for floatsEqual*/
30 #include "vg_context.h"
31 #include "vg_state.h"
32 #include "renderer.h"
33 #include "util_array.h"
34 #include "VG/openvg.h"
35
36 #include "pipe/p_context.h"
37 #include "pipe/p_defines.h"
38 #include "pipe/p_state.h"
39 #include "util/u_inlines.h"
40 #include "pipe/p_screen.h"
41
42 #include "util/u_draw_quad.h"
43 #include "util/u_math.h"
44
45 #include <string.h>
46 #include <stdlib.h>
47
48 #define DEBUG_POLYGON 0
49
50 #define COMPONENTS 2
51
52 struct polygon
53 {
54 VGfloat *data;
55 VGint size;
56
57 VGint num_verts;
58
59 VGboolean dirty;
60 void *user_vbuf;
61 struct pipe_screen *screen;
62 };
63
64 static float *ptr_to_vertex(float *data, int idx)
65 {
66 return data + (idx * COMPONENTS);
67 }
68
69 #if 0
70 static void polygon_print(struct polygon *poly)
71 {
72 int i;
73 float *vert;
74 debug_printf("Polygon %p, size = %d\n", poly, poly->num_verts);
75 for (i = 0; i < poly->num_verts; ++i) {
76 vert = ptr_to_vertex(poly->data, i);
77 debug_printf("%f, %f, ", vert[0], vert[1]);
78 }
79 debug_printf("\nend\n");
80 }
81 #endif
82
83
84 struct polygon * polygon_create(int size)
85 {
86 struct polygon *poly = (struct polygon*)malloc(sizeof(struct polygon));
87
88 poly->data = malloc(sizeof(float) * COMPONENTS * size);
89 poly->size = size;
90 poly->num_verts = 0;
91 poly->dirty = VG_TRUE;
92 poly->user_vbuf = NULL;
93
94 return poly;
95 }
96
97 struct polygon * polygon_create_from_data(float *data, int size)
98 {
99 struct polygon *poly = polygon_create(size);
100
101 memcpy(poly->data, data, sizeof(float) * COMPONENTS * size);
102 poly->num_verts = size;
103 poly->dirty = VG_TRUE;
104 poly->user_vbuf = NULL;
105
106 return poly;
107 }
108
109 void polygon_destroy(struct polygon *poly)
110 {
111 free(poly->data);
112 free(poly);
113 }
114
115 void polygon_resize(struct polygon *poly, int new_size)
116 {
117 float *data = (float*)malloc(sizeof(float) * COMPONENTS * new_size);
118 int size = MIN2(sizeof(float) * COMPONENTS * new_size,
119 sizeof(float) * COMPONENTS * poly->size);
120 memcpy(data, poly->data, size);
121 free(poly->data);
122 poly->data = data;
123 poly->size = new_size;
124 poly->dirty = VG_TRUE;
125 }
126
127 int polygon_size(struct polygon *poly)
128 {
129 return poly->size;
130 }
131
132 int polygon_vertex_count(struct polygon *poly)
133 {
134 return poly->num_verts;
135 }
136
137 float * polygon_data(struct polygon *poly)
138 {
139 return poly->data;
140 }
141
142 void polygon_vertex_append(struct polygon *p,
143 float x, float y)
144 {
145 float *vert;
146 #if DEBUG_POLYGON
147 debug_printf("Append vertex [%f, %f]\n", x, y);
148 #endif
149 if (p->num_verts >= p->size) {
150 polygon_resize(p, p->size * 2);
151 }
152
153 vert = ptr_to_vertex(p->data, p->num_verts);
154 vert[0] = x;
155 vert[1] = y;
156 ++p->num_verts;
157 p->dirty = VG_TRUE;
158 }
159
160 void polygon_set_vertex(struct polygon *p, int idx,
161 float x, float y)
162 {
163 float *vert;
164 if (idx >= p->num_verts) {
165 /*fixme: error reporting*/
166 abort();
167 return;
168 }
169
170 vert = ptr_to_vertex(p->data, idx);
171 vert[0] = x;
172 vert[1] = y;
173 p->dirty = VG_TRUE;
174 }
175
176 void polygon_vertex(struct polygon *p, int idx,
177 float *vertex)
178 {
179 float *vert;
180 if (idx >= p->num_verts) {
181 /*fixme: error reporting*/
182 abort();
183 return;
184 }
185
186 vert = ptr_to_vertex(p->data, idx);
187 vertex[0] = vert[0];
188 vertex[1] = vert[1];
189 }
190
191 void polygon_bounding_rect(struct polygon *p,
192 float *rect)
193 {
194 int i;
195 float minx, miny, maxx, maxy;
196 float *vert = ptr_to_vertex(p->data, 0);
197 minx = vert[0];
198 maxx = vert[0];
199 miny = vert[1];
200 maxy = vert[1];
201
202 for (i = 1; i < p->num_verts; ++i) {
203 vert = ptr_to_vertex(p->data, i);
204 minx = MIN2(vert[0], minx);
205 miny = MIN2(vert[1], miny);
206
207 maxx = MAX2(vert[0], maxx);
208 maxy = MAX2(vert[1], maxy);
209 }
210
211 rect[0] = minx;
212 rect[1] = miny;
213 rect[2] = maxx - minx;
214 rect[3] = maxy - miny;
215 }
216
217 int polygon_contains_point(struct polygon *p,
218 float x, float y)
219 {
220 return 0;
221 }
222
223 void polygon_append_polygon(struct polygon *dst,
224 struct polygon *src)
225 {
226 if (dst->num_verts + src->num_verts >= dst->size) {
227 polygon_resize(dst, dst->num_verts + src->num_verts * 1.5);
228 }
229 memcpy(ptr_to_vertex(dst->data, dst->num_verts),
230 src->data, src->num_verts * COMPONENTS * sizeof(VGfloat));
231 dst->num_verts += src->num_verts;
232 }
233
234 VGboolean polygon_is_closed(struct polygon *p)
235 {
236 VGfloat start[2], end[2];
237
238 polygon_vertex(p, 0, start);
239 polygon_vertex(p, p->num_verts - 1, end);
240
241 return floatsEqual(start[0], end[0]) && floatsEqual(start[1], end[1]);
242 }
243
244 static void polygon_prepare_buffer(struct vg_context *ctx,
245 struct polygon *poly)
246 {
247 struct pipe_context *pipe;
248
249 /*polygon_print(poly);*/
250
251 pipe = ctx->pipe;
252
253 if (poly->user_vbuf == NULL || poly->dirty) {
254 poly->screen = pipe->screen;
255 poly->user_vbuf = poly->data;
256 poly->dirty = VG_FALSE;
257 }
258 }
259
260 void polygon_fill(struct polygon *poly, struct vg_context *ctx)
261 {
262 struct pipe_vertex_element velement;
263 struct pipe_vertex_buffer vbuffer;
264 VGfloat bounds[4];
265 VGfloat min_x, min_y, max_x, max_y;
266
267 assert(poly);
268 polygon_bounding_rect(poly, bounds);
269 min_x = bounds[0];
270 min_y = bounds[1];
271 max_x = bounds[0] + bounds[2];
272 max_y = bounds[1] + bounds[3];
273
274 #if DEBUG_POLYGON
275 debug_printf("Poly bounds are [%f, %f], [%f, %f]\n",
276 min_x, min_y, max_x, max_y);
277 #endif
278
279 polygon_prepare_buffer(ctx, poly);
280
281 /* tell renderer about the vertex attributes */
282 memset(&velement, 0, sizeof(velement));
283 velement.src_offset = 0;
284 velement.instance_divisor = 0;
285 velement.vertex_buffer_index = 0;
286 velement.src_format = PIPE_FORMAT_R32G32_FLOAT;
287
288 /* tell renderer about the vertex buffer */
289 memset(&vbuffer, 0, sizeof(vbuffer));
290 vbuffer.user_buffer = poly->user_vbuf;
291 vbuffer.stride = COMPONENTS * sizeof(float); /* vertex size */
292
293 renderer_polygon_stencil_begin(ctx->renderer,
294 &velement, ctx->state.vg.fill_rule, VG_FALSE);
295 renderer_polygon_stencil(ctx->renderer, &vbuffer,
296 PIPE_PRIM_TRIANGLE_FAN, 0, (VGuint) poly->num_verts);
297 renderer_polygon_stencil_end(ctx->renderer);
298
299 renderer_polygon_fill_begin(ctx->renderer, VG_FALSE);
300 renderer_polygon_fill(ctx->renderer, min_x, min_y, max_x, max_y);
301 renderer_polygon_fill_end(ctx->renderer);
302 }
303
304 void polygon_array_fill(struct polygon_array *polyarray, struct vg_context *ctx)
305 {
306 struct array *polys = polyarray->array;
307 VGfloat min_x = polyarray->min_x;
308 VGfloat min_y = polyarray->min_y;
309 VGfloat max_x = polyarray->max_x;
310 VGfloat max_y = polyarray->max_y;
311 struct pipe_vertex_element velement;
312 struct pipe_vertex_buffer vbuffer;
313 VGint i;
314
315
316 #if DEBUG_POLYGON
317 debug_printf("%s: Poly bounds are [%f, %f], [%f, %f]\n",
318 __FUNCTION__,
319 min_x, min_y, max_x, max_y);
320 #endif
321
322 /* tell renderer about the vertex attributes */
323 memset(&velement, 0, sizeof(velement));
324 velement.src_offset = 0;
325 velement.instance_divisor = 0;
326 velement.vertex_buffer_index = 0;
327 velement.src_format = PIPE_FORMAT_R32G32_FLOAT;
328
329 /* tell renderer about the vertex buffer */
330 memset(&vbuffer, 0, sizeof(vbuffer));
331 vbuffer.stride = COMPONENTS * sizeof(float); /* vertex size */
332
333 /* prepare the stencil buffer */
334 renderer_polygon_stencil_begin(ctx->renderer,
335 &velement, ctx->state.vg.fill_rule, VG_FALSE);
336 for (i = 0; i < polys->num_elements; ++i) {
337 struct polygon *poly = (((struct polygon**)polys->data)[i]);
338
339 polygon_prepare_buffer(ctx, poly);
340 vbuffer.user_buffer = poly->user_vbuf;
341
342 renderer_polygon_stencil(ctx->renderer, &vbuffer,
343 PIPE_PRIM_TRIANGLE_FAN, 0, (VGuint) poly->num_verts);
344 }
345 renderer_polygon_stencil_end(ctx->renderer);
346
347 /* fill it */
348 renderer_polygon_fill_begin(ctx->renderer, VG_FALSE);
349 renderer_polygon_fill(ctx->renderer, min_x, min_y, max_x, max_y);
350 renderer_polygon_fill_end(ctx->renderer);
351 }