eef2c1eb8769f0329d5e7ba91ddf739cd8d5e2dc
[profile/ivi/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 "paint.h"
33 #include "renderer.h"
34 #include "util_array.h"
35 #include "VG/openvg.h"
36
37 #include "pipe/p_context.h"
38 #include "pipe/p_defines.h"
39 #include "pipe/p_state.h"
40 #include "util/u_inlines.h"
41 #include "pipe/p_screen.h"
42
43 #include "util/u_draw_quad.h"
44 #include "util/u_math.h"
45
46 #include <string.h>
47 #include <stdlib.h>
48
49 #define DEBUG_POLYGON 0
50
51 #define COMPONENTS 2
52
53 struct polygon
54 {
55    VGfloat *data;
56    VGint    size;
57
58    VGint    num_verts;
59
60    VGboolean dirty;
61    struct pipe_buffer *vbuf;
62    struct pipe_screen *screen;
63 };
64
65 static float *ptr_to_vertex(float *data, int idx)
66 {
67    return data + (idx * COMPONENTS);
68 }
69
70 #if 0
71 static void polygon_print(struct polygon *poly)
72 {
73    int i;
74    float *vert;
75    debug_printf("Polygon %p, size = %d\n", poly, poly->num_verts);
76    for (i = 0; i < poly->num_verts; ++i) {
77       vert = ptr_to_vertex(poly->data, i);
78       debug_printf("%f, %f,  ", vert[0], vert[1]);
79    }
80    debug_printf("\nend\n");
81 }
82 #endif
83
84
85 struct polygon * polygon_create(int size)
86 {
87    struct polygon *poly = (struct polygon*)malloc(sizeof(struct polygon));
88
89    poly->data = malloc(sizeof(float) * COMPONENTS * size);
90    poly->size = size;
91    poly->num_verts = 0;
92    poly->dirty = VG_TRUE;
93    poly->vbuf = NULL;
94
95    return poly;
96 }
97
98 struct polygon * polygon_create_from_data(float *data, int size)
99 {
100    struct polygon *poly = polygon_create(size);
101
102    memcpy(poly->data, data, sizeof(float) * COMPONENTS * size);
103    poly->num_verts = size;
104    poly->dirty = VG_TRUE;
105    poly->vbuf = NULL;
106
107    return poly;
108 }
109
110 void polygon_destroy(struct polygon *poly)
111 {
112    if (poly->vbuf)
113       pipe_buffer_reference(&poly->vbuf, NULL);
114
115    free(poly->data);
116    free(poly);
117 }
118
119 void polygon_resize(struct polygon *poly, int new_size)
120 {
121    float *data = (float*)malloc(sizeof(float) * COMPONENTS * new_size);
122    int size = MIN2(sizeof(float) * COMPONENTS * new_size,
123                    sizeof(float) * COMPONENTS * poly->size);
124    memcpy(data, poly->data, size);
125    free(poly->data);
126    poly->data = data;
127    poly->size = new_size;
128    poly->dirty = VG_TRUE;
129 }
130
131 int polygon_size(struct polygon *poly)
132 {
133    return poly->size;
134 }
135
136 int polygon_vertex_count(struct polygon *poly)
137 {
138    return poly->num_verts;
139 }
140
141 float * polygon_data(struct polygon *poly)
142 {
143    return poly->data;
144 }
145
146 void polygon_vertex_append(struct polygon *p,
147                            float x, float y)
148 {
149    float *vert;
150 #if DEBUG_POLYGON
151    debug_printf("Append vertex [%f, %f]\n", x, y);
152 #endif
153    if (p->num_verts >= p->size) {
154       polygon_resize(p, p->size * 2);
155    }
156
157    vert = ptr_to_vertex(p->data, p->num_verts);
158    vert[0] = x;
159    vert[1] = y;
160    ++p->num_verts;
161    p->dirty = VG_TRUE;
162 }
163
164 void polygon_set_vertex(struct polygon *p, int idx,
165                         float x, float y)
166 {
167    float *vert;
168    if (idx >= p->num_verts) {
169       /*fixme: error reporting*/
170       abort();
171       return;
172    }
173
174    vert = ptr_to_vertex(p->data, idx);
175    vert[0] = x;
176    vert[1] = y;
177    p->dirty = VG_TRUE;
178 }
179
180 void polygon_vertex(struct polygon *p, int idx,
181                     float *vertex)
182 {
183    float *vert;
184    if (idx >= p->num_verts) {
185       /*fixme: error reporting*/
186       abort();
187       return;
188    }
189
190    vert = ptr_to_vertex(p->data, idx);
191    vertex[0] = vert[0];
192    vertex[1] = vert[1];
193 }
194
195 void polygon_bounding_rect(struct polygon *p,
196                            float *rect)
197 {
198    int i;
199    float minx, miny, maxx, maxy;
200    float *vert = ptr_to_vertex(p->data, 0);
201    minx = vert[0];
202    maxx = vert[0];
203    miny = vert[1];
204    maxy = vert[1];
205
206    for (i = 1; i < p->num_verts; ++i) {
207       vert = ptr_to_vertex(p->data, i);
208       minx = MIN2(vert[0], minx);
209       miny = MIN2(vert[1], miny);
210
211       maxx = MAX2(vert[0], maxx);
212       maxy = MAX2(vert[1], maxy);
213    }
214
215    rect[0] = minx;
216    rect[1] = miny;
217    rect[2] = maxx - minx;
218    rect[3] = maxy - miny;
219 }
220
221 int polygon_contains_point(struct polygon *p,
222                            float x, float y)
223 {
224    return 0;
225 }
226
227 void polygon_append_polygon(struct polygon *dst,
228                             struct polygon *src)
229 {
230    if (dst->num_verts + src->num_verts >= dst->size) {
231       polygon_resize(dst, dst->num_verts + src->num_verts * 1.5);
232    }
233    memcpy(ptr_to_vertex(dst->data, dst->num_verts),
234           src->data, src->num_verts * COMPONENTS * sizeof(VGfloat));
235    dst->num_verts += src->num_verts;
236 }
237
238 VGboolean polygon_is_closed(struct polygon *p)
239 {
240    VGfloat start[2], end[2];
241
242    polygon_vertex(p, 0, start);
243    polygon_vertex(p, p->num_verts - 1, end);
244
245    return floatsEqual(start[0], end[0]) && floatsEqual(start[1], end[1]);
246 }
247
248 static void set_blend_for_fill(struct pipe_blend_state *blend)
249 {
250    memset(blend, 0, sizeof(struct pipe_blend_state));
251    blend->rt[0].colormask = 0; /*disable colorwrites*/
252
253    blend->rt[0].rgb_src_factor = PIPE_BLENDFACTOR_ONE;
254    blend->rt[0].alpha_src_factor = PIPE_BLENDFACTOR_ONE;
255    blend->rt[0].rgb_dst_factor = PIPE_BLENDFACTOR_INV_SRC_ALPHA;
256    blend->rt[0].alpha_dst_factor = PIPE_BLENDFACTOR_INV_SRC_ALPHA;
257 }
258
259 static void draw_polygon(struct vg_context *ctx,
260                          struct polygon *poly)
261 {
262    int vert_size;
263    struct pipe_context *pipe;
264    struct pipe_vertex_buffer vbuffer;
265    struct pipe_vertex_element velement;
266
267    vert_size = poly->num_verts * COMPONENTS * sizeof(float);
268
269    /*polygon_print(poly);*/
270
271    pipe = ctx->pipe;
272
273    if (poly->vbuf == NULL || poly->dirty) {
274       if (poly->vbuf) {
275          pipe_buffer_reference(&poly->vbuf,
276                                NULL);
277       }
278       poly->screen = pipe->screen;
279       poly->vbuf= pipe_user_buffer_create(poly->screen,
280                                           poly->data,
281                                           vert_size);
282       poly->dirty = VG_FALSE;
283    }
284
285
286    /* tell pipe about the vertex buffer */
287    memset(&vbuffer, 0, sizeof(vbuffer));
288    vbuffer.buffer = poly->vbuf;
289    vbuffer.stride = COMPONENTS * sizeof(float);  /* vertex size */
290    vbuffer.buffer_offset = 0;
291    vbuffer.max_index = poly->num_verts - 1;
292    pipe->set_vertex_buffers(pipe, 1, &vbuffer);
293
294    /* tell pipe 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    cso_set_vertex_elements(ctx->cso_context, 1, &velement);
301
302    /* draw */
303    pipe->draw_arrays(pipe, PIPE_PRIM_TRIANGLE_FAN, 
304                      0, poly->num_verts);
305 }
306
307 void polygon_fill(struct polygon *poly, struct vg_context *ctx)
308 {
309    struct pipe_depth_stencil_alpha_state dsa;
310    struct pipe_stencil_ref sr;
311    struct pipe_blend_state blend;
312    VGfloat bounds[4];
313    VGfloat min_x, min_y, max_x, max_y;
314    assert(poly);
315    polygon_bounding_rect(poly, bounds);
316    min_x = bounds[0];
317    min_y = bounds[1];
318    max_x = bounds[0] + bounds[2];
319    max_y = bounds[1] + bounds[3];
320
321 #if DEBUG_POLYGON
322    debug_printf("Poly bounds are [%f, %f], [%f, %f]\n",
323                 min_x, min_y, max_x, max_y);
324 #endif
325
326    set_blend_for_fill(&blend);
327
328    memset(&dsa, 0, sizeof(struct pipe_depth_stencil_alpha_state));
329    memset(&sr, 0, sizeof(struct pipe_stencil_ref));
330    /* only need a fixed 0. Rely on default or move it out at least? */
331    cso_set_stencil_ref(ctx->cso_context, &sr);
332
333    cso_save_blend(ctx->cso_context);
334    cso_save_depth_stencil_alpha(ctx->cso_context);
335
336    dsa.stencil[0].enabled = 1;
337    if (ctx->state.vg.fill_rule == VG_EVEN_ODD) {
338       dsa.stencil[0].writemask = 1;
339       dsa.stencil[0].fail_op = PIPE_STENCIL_OP_KEEP;
340       dsa.stencil[0].zfail_op = PIPE_STENCIL_OP_KEEP;
341       dsa.stencil[0].zpass_op = PIPE_STENCIL_OP_INVERT;
342       dsa.stencil[0].func = PIPE_FUNC_ALWAYS;
343       dsa.stencil[0].valuemask = ~0;
344
345       cso_set_blend(ctx->cso_context, &blend);
346       cso_set_depth_stencil_alpha(ctx->cso_context, &dsa);
347       draw_polygon(ctx, poly);
348    } else if (ctx->state.vg.fill_rule == VG_NON_ZERO) {
349       struct pipe_screen *screen = ctx->pipe->screen;
350
351       if (screen->get_param(screen, PIPE_CAP_TWO_SIDED_STENCIL)) {
352          /* front */
353          dsa.stencil[0].writemask = ~0;
354          dsa.stencil[0].fail_op = PIPE_STENCIL_OP_KEEP;
355          dsa.stencil[0].zfail_op = PIPE_STENCIL_OP_KEEP;
356          dsa.stencil[0].zpass_op = PIPE_STENCIL_OP_INCR_WRAP;
357          dsa.stencil[0].func = PIPE_FUNC_ALWAYS;
358          dsa.stencil[0].valuemask = ~0;
359
360          /* back */
361          dsa.stencil[1].enabled = 1;
362          dsa.stencil[1].writemask = ~0;
363          dsa.stencil[1].fail_op = PIPE_STENCIL_OP_KEEP;
364          dsa.stencil[1].zfail_op = PIPE_STENCIL_OP_KEEP;
365          dsa.stencil[1].zpass_op = PIPE_STENCIL_OP_DECR_WRAP;
366          dsa.stencil[1].func = PIPE_FUNC_ALWAYS;
367          dsa.stencil[1].valuemask = ~0;
368
369          cso_set_blend(ctx->cso_context, &blend);
370          cso_set_depth_stencil_alpha(ctx->cso_context, &dsa);
371          draw_polygon(ctx, poly);
372       } else {
373          struct pipe_rasterizer_state raster;
374
375          memcpy(&raster, &ctx->state.g3d.rasterizer, sizeof(struct pipe_rasterizer_state));
376
377          cso_save_rasterizer(ctx->cso_context);
378          dsa.stencil[0].func = PIPE_FUNC_ALWAYS;
379          dsa.stencil[0].valuemask = ~0;
380
381          raster.cull_mode = raster.front_winding ^ PIPE_WINDING_BOTH;
382          dsa.stencil[0].fail_op = PIPE_STENCIL_OP_KEEP;
383          dsa.stencil[0].zfail_op = PIPE_STENCIL_OP_KEEP;
384          dsa.stencil[0].zpass_op = PIPE_STENCIL_OP_INCR_WRAP;
385
386          cso_set_blend(ctx->cso_context, &blend);
387          cso_set_depth_stencil_alpha(ctx->cso_context, &dsa);
388          cso_set_rasterizer(ctx->cso_context, &raster);
389          draw_polygon(ctx, poly);
390
391          raster.cull_mode = raster.front_winding;
392          dsa.stencil[0].fail_op = PIPE_STENCIL_OP_KEEP;
393          dsa.stencil[0].zfail_op = PIPE_STENCIL_OP_KEEP;
394          dsa.stencil[0].zpass_op = PIPE_STENCIL_OP_DECR_WRAP;
395          cso_set_depth_stencil_alpha(ctx->cso_context, &dsa);
396          cso_set_rasterizer(ctx->cso_context, &raster);
397          draw_polygon(ctx, poly);
398
399          cso_restore_rasterizer(ctx->cso_context);
400       }
401    }
402
403    /* restore color writes */
404    cso_restore_blend(ctx->cso_context);
405    /* setup stencil ops */
406    dsa.stencil[0].func = PIPE_FUNC_NOTEQUAL;
407    dsa.stencil[0].fail_op = PIPE_STENCIL_OP_REPLACE;
408    dsa.stencil[0].zfail_op = PIPE_STENCIL_OP_REPLACE;
409    dsa.stencil[0].zpass_op = PIPE_STENCIL_OP_REPLACE;
410    dsa.stencil[0].valuemask = dsa.stencil[0].writemask;
411    dsa.stencil[1].enabled = 0;
412    memcpy(&dsa.depth, &ctx->state.g3d.dsa.depth,
413           sizeof(struct pipe_depth_state));
414    cso_set_depth_stencil_alpha(ctx->cso_context, &dsa);
415
416    /* render the quad to propagate the rendering from stencil */
417    renderer_draw_quad(ctx->renderer, min_x, min_y,
418                       max_x, max_y, 0.0f/*depth should be disabled*/);
419
420    cso_restore_depth_stencil_alpha(ctx->cso_context);
421 }
422
423 void polygon_array_fill(struct polygon_array *polyarray, struct vg_context *ctx)
424 {
425    struct array *polys = polyarray->array;
426    struct pipe_depth_stencil_alpha_state dsa;
427    struct pipe_stencil_ref sr;
428    struct pipe_blend_state blend;
429    VGfloat min_x = polyarray->min_x;
430    VGfloat min_y = polyarray->min_y;
431    VGfloat max_x = polyarray->max_x;
432    VGfloat max_y = polyarray->max_y;
433    VGint i;
434
435
436 #if DEBUG_POLYGON
437    debug_printf("%s: Poly bounds are [%f, %f], [%f, %f]\n",
438                 __FUNCTION__,
439                 min_x, min_y, max_x, max_y);
440 #endif
441
442    set_blend_for_fill(&blend);
443
444    memset(&dsa, 0, sizeof(struct pipe_depth_stencil_alpha_state));
445    memset(&sr, 0, sizeof(struct pipe_stencil_ref));
446    /* only need a fixed 0. Rely on default or move it out at least? */
447    cso_set_stencil_ref(ctx->cso_context, &sr);
448
449    cso_save_blend(ctx->cso_context);
450    cso_save_depth_stencil_alpha(ctx->cso_context);
451
452    dsa.stencil[0].enabled = 1;
453    if (ctx->state.vg.fill_rule == VG_EVEN_ODD) {
454       dsa.stencil[0].writemask = 1;
455       dsa.stencil[0].fail_op = PIPE_STENCIL_OP_KEEP;
456       dsa.stencil[0].zfail_op = PIPE_STENCIL_OP_KEEP;
457       dsa.stencil[0].zpass_op = PIPE_STENCIL_OP_INVERT;
458       dsa.stencil[0].func = PIPE_FUNC_ALWAYS;
459       dsa.stencil[0].valuemask = ~0;
460
461       cso_set_blend(ctx->cso_context, &blend);
462       cso_set_depth_stencil_alpha(ctx->cso_context, &dsa);
463       for (i = 0; i < polys->num_elements; ++i) {
464          struct polygon *poly = (((struct polygon**)polys->data)[i]);
465          draw_polygon(ctx, poly);
466       }
467    } else if (ctx->state.vg.fill_rule == VG_NON_ZERO) {
468       struct pipe_screen *screen = ctx->pipe->screen;
469
470       if (screen->get_param(screen, PIPE_CAP_TWO_SIDED_STENCIL)) {
471          /* front */
472          dsa.stencil[0].writemask = ~0;
473          dsa.stencil[0].fail_op = PIPE_STENCIL_OP_KEEP;
474          dsa.stencil[0].zfail_op = PIPE_STENCIL_OP_KEEP;
475          dsa.stencil[0].zpass_op = PIPE_STENCIL_OP_INCR_WRAP;
476          dsa.stencil[0].func = PIPE_FUNC_ALWAYS;
477          dsa.stencil[0].valuemask = ~0;
478
479          /* back */
480          dsa.stencil[1].enabled = 1;
481          dsa.stencil[1].writemask = ~0;
482          dsa.stencil[1].fail_op = PIPE_STENCIL_OP_KEEP;
483          dsa.stencil[1].zfail_op = PIPE_STENCIL_OP_KEEP;
484          dsa.stencil[1].zpass_op = PIPE_STENCIL_OP_DECR_WRAP;
485          dsa.stencil[1].func = PIPE_FUNC_ALWAYS;
486          dsa.stencil[1].valuemask = ~0;
487
488          cso_set_blend(ctx->cso_context, &blend);
489          cso_set_depth_stencil_alpha(ctx->cso_context, &dsa);
490          for (i = 0; i < polys->num_elements; ++i) {
491             struct polygon *poly = (((struct polygon**)polys->data)[i]);
492             draw_polygon(ctx, poly);
493          }
494       } else {
495          struct pipe_rasterizer_state raster;
496
497          memcpy(&raster, &ctx->state.g3d.rasterizer, sizeof(struct pipe_rasterizer_state));
498
499          cso_save_rasterizer(ctx->cso_context);
500          dsa.stencil[0].func = PIPE_FUNC_ALWAYS;
501          dsa.stencil[0].valuemask = ~0;
502
503          raster.cull_mode = raster.front_winding ^ PIPE_WINDING_BOTH;
504          dsa.stencil[0].fail_op = PIPE_STENCIL_OP_KEEP;
505          dsa.stencil[0].zfail_op = PIPE_STENCIL_OP_KEEP;
506          dsa.stencil[0].zpass_op = PIPE_STENCIL_OP_INCR_WRAP;
507
508          cso_set_blend(ctx->cso_context, &blend);
509          cso_set_depth_stencil_alpha(ctx->cso_context, &dsa);
510          cso_set_rasterizer(ctx->cso_context, &raster);
511          for (i = 0; i < polys->num_elements; ++i) {
512             struct polygon *poly = (((struct polygon**)polys->data)[i]);
513             draw_polygon(ctx, poly);
514          }
515
516          raster.cull_mode = raster.front_winding;
517          dsa.stencil[0].fail_op = PIPE_STENCIL_OP_KEEP;
518          dsa.stencil[0].zfail_op = PIPE_STENCIL_OP_KEEP;
519          dsa.stencil[0].zpass_op = PIPE_STENCIL_OP_DECR_WRAP;
520          cso_set_depth_stencil_alpha(ctx->cso_context, &dsa);
521          cso_set_rasterizer(ctx->cso_context, &raster);
522          for (i = 0; i < polys->num_elements; ++i) {
523             struct polygon *poly = (((struct polygon**)polys->data)[i]);
524             draw_polygon(ctx, poly);
525          }
526
527          cso_restore_rasterizer(ctx->cso_context);
528       }
529    }
530
531    /* restore color writes */
532    cso_restore_blend(ctx->cso_context);
533    /* setup stencil ops */
534    dsa.stencil[0].func = PIPE_FUNC_NOTEQUAL;
535    dsa.stencil[0].fail_op = PIPE_STENCIL_OP_REPLACE;
536    dsa.stencil[0].zfail_op = PIPE_STENCIL_OP_REPLACE;
537    dsa.stencil[0].zpass_op = PIPE_STENCIL_OP_REPLACE;
538    dsa.stencil[0].valuemask = dsa.stencil[0].writemask;
539    dsa.stencil[1].enabled = 0;
540    memcpy(&dsa.depth, &ctx->state.g3d.dsa.depth,
541           sizeof(struct pipe_depth_state));
542    cso_set_depth_stencil_alpha(ctx->cso_context, &dsa);
543
544    /* render the quad to propagate the rendering from stencil */
545    renderer_draw_quad(ctx->renderer, min_x, min_y,
546                       max_x, max_y, 0.0f/*depth should be disabled*/);
547
548    cso_restore_depth_stencil_alpha(ctx->cso_context);
549 }