Tizen 2.0 Release
[profile/ivi/osmesa.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    struct pipe_resource *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->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->vbuf = NULL;
105
106    return poly;
107 }
108
109 void polygon_destroy(struct polygon *poly)
110 {
111    if (poly->vbuf)
112       pipe_resource_reference(&poly->vbuf, NULL);
113
114    free(poly->data);
115    free(poly);
116 }
117
118 void polygon_resize(struct polygon *poly, int new_size)
119 {
120    float *data = (float*)malloc(sizeof(float) * COMPONENTS * new_size);
121    int size = MIN2(sizeof(float) * COMPONENTS * new_size,
122                    sizeof(float) * COMPONENTS * poly->size);
123    memcpy(data, poly->data, size);
124    free(poly->data);
125    poly->data = data;
126    poly->size = new_size;
127    poly->dirty = VG_TRUE;
128 }
129
130 int polygon_size(struct polygon *poly)
131 {
132    return poly->size;
133 }
134
135 int polygon_vertex_count(struct polygon *poly)
136 {
137    return poly->num_verts;
138 }
139
140 float * polygon_data(struct polygon *poly)
141 {
142    return poly->data;
143 }
144
145 void polygon_vertex_append(struct polygon *p,
146                            float x, float y)
147 {
148    float *vert;
149 #if DEBUG_POLYGON
150    debug_printf("Append vertex [%f, %f]\n", x, y);
151 #endif
152    if (p->num_verts >= p->size) {
153       polygon_resize(p, p->size * 2);
154    }
155
156    vert = ptr_to_vertex(p->data, p->num_verts);
157    vert[0] = x;
158    vert[1] = y;
159    ++p->num_verts;
160    p->dirty = VG_TRUE;
161 }
162
163 void polygon_set_vertex(struct polygon *p, int idx,
164                         float x, float y)
165 {
166    float *vert;
167    if (idx >= p->num_verts) {
168       /*fixme: error reporting*/
169       abort();
170       return;
171    }
172
173    vert = ptr_to_vertex(p->data, idx);
174    vert[0] = x;
175    vert[1] = y;
176    p->dirty = VG_TRUE;
177 }
178
179 void polygon_vertex(struct polygon *p, int idx,
180                     float *vertex)
181 {
182    float *vert;
183    if (idx >= p->num_verts) {
184       /*fixme: error reporting*/
185       abort();
186       return;
187    }
188
189    vert = ptr_to_vertex(p->data, idx);
190    vertex[0] = vert[0];
191    vertex[1] = vert[1];
192 }
193
194 void polygon_bounding_rect(struct polygon *p,
195                            float *rect)
196 {
197    int i;
198    float minx, miny, maxx, maxy;
199    float *vert = ptr_to_vertex(p->data, 0);
200    minx = vert[0];
201    maxx = vert[0];
202    miny = vert[1];
203    maxy = vert[1];
204
205    for (i = 1; i < p->num_verts; ++i) {
206       vert = ptr_to_vertex(p->data, i);
207       minx = MIN2(vert[0], minx);
208       miny = MIN2(vert[1], miny);
209
210       maxx = MAX2(vert[0], maxx);
211       maxy = MAX2(vert[1], maxy);
212    }
213
214    rect[0] = minx;
215    rect[1] = miny;
216    rect[2] = maxx - minx;
217    rect[3] = maxy - miny;
218 }
219
220 int polygon_contains_point(struct polygon *p,
221                            float x, float y)
222 {
223    return 0;
224 }
225
226 void polygon_append_polygon(struct polygon *dst,
227                             struct polygon *src)
228 {
229    if (dst->num_verts + src->num_verts >= dst->size) {
230       polygon_resize(dst, dst->num_verts + src->num_verts * 1.5);
231    }
232    memcpy(ptr_to_vertex(dst->data, dst->num_verts),
233           src->data, src->num_verts * COMPONENTS * sizeof(VGfloat));
234    dst->num_verts += src->num_verts;
235 }
236
237 VGboolean polygon_is_closed(struct polygon *p)
238 {
239    VGfloat start[2], end[2];
240
241    polygon_vertex(p, 0, start);
242    polygon_vertex(p, p->num_verts - 1, end);
243
244    return floatsEqual(start[0], end[0]) && floatsEqual(start[1], end[1]);
245 }
246
247 static void polygon_prepare_buffer(struct vg_context *ctx,
248                                    struct polygon *poly)
249 {
250    int vert_size;
251    struct pipe_context *pipe;
252
253    vert_size = poly->num_verts * COMPONENTS * sizeof(float);
254
255    /*polygon_print(poly);*/
256
257    pipe = ctx->pipe;
258
259    if (poly->vbuf == NULL || poly->dirty) {
260       if (poly->vbuf) {
261          pipe_resource_reference(&poly->vbuf,
262                                NULL);
263       }
264       poly->screen = pipe->screen;
265       poly->vbuf= pipe_user_buffer_create(poly->screen,
266                                           poly->data,
267                                           vert_size,
268                                           PIPE_BIND_VERTEX_BUFFER);
269       poly->dirty = VG_FALSE;
270    }
271 }
272
273 void polygon_fill(struct polygon *poly, struct vg_context *ctx)
274 {
275    struct pipe_vertex_element velement;
276    struct pipe_vertex_buffer vbuffer;
277    VGfloat bounds[4];
278    VGfloat min_x, min_y, max_x, max_y;
279
280    assert(poly);
281    polygon_bounding_rect(poly, bounds);
282    min_x = bounds[0];
283    min_y = bounds[1];
284    max_x = bounds[0] + bounds[2];
285    max_y = bounds[1] + bounds[3];
286
287 #if DEBUG_POLYGON
288    debug_printf("Poly bounds are [%f, %f], [%f, %f]\n",
289                 min_x, min_y, max_x, max_y);
290 #endif
291
292    polygon_prepare_buffer(ctx, poly);
293
294    /* tell renderer about the vertex attributes */
295    memset(&velement, 0, sizeof(velement));
296    velement.src_offset = 0;
297    velement.instance_divisor = 0;
298    velement.vertex_buffer_index = 0;
299    velement.src_format = PIPE_FORMAT_R32G32_FLOAT;
300
301    /* tell renderer about the vertex buffer */
302    memset(&vbuffer, 0, sizeof(vbuffer));
303    vbuffer.buffer = poly->vbuf;
304    vbuffer.stride = COMPONENTS * sizeof(float);  /* vertex size */
305    vbuffer.buffer_offset = 0;
306
307    renderer_polygon_stencil_begin(ctx->renderer,
308          &velement, ctx->state.vg.fill_rule, VG_FALSE);
309    renderer_polygon_stencil(ctx->renderer, &vbuffer,
310          PIPE_PRIM_TRIANGLE_FAN, 0, (VGuint) poly->num_verts);
311    renderer_polygon_stencil_end(ctx->renderer);
312
313    renderer_polygon_fill_begin(ctx->renderer, VG_FALSE);
314    renderer_polygon_fill(ctx->renderer, min_x, min_y, max_x, max_y);
315    renderer_polygon_fill_end(ctx->renderer);
316 }
317
318 void polygon_array_fill(struct polygon_array *polyarray, struct vg_context *ctx)
319 {
320    struct array *polys = polyarray->array;
321    VGfloat min_x = polyarray->min_x;
322    VGfloat min_y = polyarray->min_y;
323    VGfloat max_x = polyarray->max_x;
324    VGfloat max_y = polyarray->max_y;
325    struct pipe_vertex_element velement;
326    struct pipe_vertex_buffer vbuffer;
327    VGint i;
328
329
330 #if DEBUG_POLYGON
331    debug_printf("%s: Poly bounds are [%f, %f], [%f, %f]\n",
332                 __FUNCTION__,
333                 min_x, min_y, max_x, max_y);
334 #endif
335
336    /* tell renderer about the vertex attributes */
337    memset(&velement, 0, sizeof(velement));
338    velement.src_offset = 0;
339    velement.instance_divisor = 0;
340    velement.vertex_buffer_index = 0;
341    velement.src_format = PIPE_FORMAT_R32G32_FLOAT;
342
343    /* tell renderer about the vertex buffer */
344    memset(&vbuffer, 0, sizeof(vbuffer));
345    vbuffer.stride = COMPONENTS * sizeof(float);  /* vertex size */
346    vbuffer.buffer_offset = 0;
347
348    /* prepare the stencil buffer */
349    renderer_polygon_stencil_begin(ctx->renderer,
350          &velement, ctx->state.vg.fill_rule, VG_FALSE);
351    for (i = 0; i < polys->num_elements; ++i) {
352       struct polygon *poly = (((struct polygon**)polys->data)[i]);
353
354       polygon_prepare_buffer(ctx, poly);
355       vbuffer.buffer = poly->vbuf;
356
357       renderer_polygon_stencil(ctx->renderer, &vbuffer,
358             PIPE_PRIM_TRIANGLE_FAN, 0, (VGuint) poly->num_verts);
359    }
360    renderer_polygon_stencil_end(ctx->renderer);
361
362    /* fill it */
363    renderer_polygon_fill_begin(ctx->renderer, VG_FALSE);
364    renderer_polygon_fill(ctx->renderer, min_x, min_y, max_x, max_y);
365    renderer_polygon_fill_end(ctx->renderer);
366 }