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
52struct 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
64static float *ptr_to_vertex(float *data, int idx)
65{
66   return data + (idx * COMPONENTS);
67}
68
69#if 0
70static 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
84struct 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
97struct 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
109void polygon_destroy(struct polygon *poly)
110{
111   free(poly->data);
112   free(poly);
113}
114
115void 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
127int polygon_size(struct polygon *poly)
128{
129   return poly->size;
130}
131
132int polygon_vertex_count(struct polygon *poly)
133{
134   return poly->num_verts;
135}
136
137float * polygon_data(struct polygon *poly)
138{
139   return poly->data;
140}
141
142void 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
160void 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
176void 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
191void 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
217int polygon_contains_point(struct polygon *p,
218                           float x, float y)
219{
220   return 0;
221}
222
223void 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
234VGboolean 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
244static 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
260void 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
304void 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}
352