Details | Last modification | View Log | RSS feed
Rev | Author | Line No. | Line |
---|---|---|---|
5563 | serge | 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 |
||
46 | #include |
||
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 = 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 = 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 | }>>> |