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 
ptr_to_vertex(float * data,int idx)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 
polygon_create(int size)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 
polygon_create_from_data(float * data,int size)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 
polygon_destroy(struct polygon * poly)109 void polygon_destroy(struct polygon *poly)
110 {
111    free(poly->data);
112    free(poly);
113 }
114 
polygon_resize(struct polygon * poly,int new_size)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 
polygon_size(struct polygon * poly)127 int polygon_size(struct polygon *poly)
128 {
129    return poly->size;
130 }
131 
polygon_vertex_count(struct polygon * poly)132 int polygon_vertex_count(struct polygon *poly)
133 {
134    return poly->num_verts;
135 }
136 
polygon_data(struct polygon * poly)137 float * polygon_data(struct polygon *poly)
138 {
139    return poly->data;
140 }
141 
polygon_vertex_append(struct polygon * p,float x,float y)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 
polygon_set_vertex(struct polygon * p,int idx,float x,float y)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 
polygon_vertex(struct polygon * p,int idx,float * vertex)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 
polygon_bounding_rect(struct polygon * p,float * rect)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 
polygon_contains_point(struct polygon * p,float x,float y)217 int polygon_contains_point(struct polygon *p,
218                            float x, float y)
219 {
220    return 0;
221 }
222 
polygon_append_polygon(struct polygon * dst,struct polygon * src)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 
polygon_is_closed(struct polygon * p)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 
polygon_prepare_buffer(struct vg_context * ctx,struct polygon * poly)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 
polygon_fill(struct polygon * poly,struct vg_context * ctx)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 
polygon_array_fill(struct polygon_array * polyarray,struct vg_context * ctx)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 }
352