Merge branch 'lp-offset-twoside'
[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 "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 set_blend_for_fill(struct pipe_blend_state *blend)
248 {
249 memset(blend, 0, sizeof(struct pipe_blend_state));
250 blend->rt[0].colormask = 0; /*disable colorwrites*/
251
252 blend->rt[0].rgb_src_factor = PIPE_BLENDFACTOR_ONE;
253 blend->rt[0].alpha_src_factor = PIPE_BLENDFACTOR_ONE;
254 blend->rt[0].rgb_dst_factor = PIPE_BLENDFACTOR_INV_SRC_ALPHA;
255 blend->rt[0].alpha_dst_factor = PIPE_BLENDFACTOR_INV_SRC_ALPHA;
256 }
257
258 static void draw_polygon(struct vg_context *ctx,
259 struct polygon *poly)
260 {
261 int vert_size;
262 struct pipe_context *pipe;
263 struct pipe_vertex_buffer vbuffer;
264 struct pipe_vertex_element velement;
265
266 vert_size = poly->num_verts * COMPONENTS * sizeof(float);
267
268 /*polygon_print(poly);*/
269
270 pipe = ctx->pipe;
271
272 if (poly->vbuf == NULL || poly->dirty) {
273 if (poly->vbuf) {
274 pipe_resource_reference(&poly->vbuf,
275 NULL);
276 }
277 poly->screen = pipe->screen;
278 poly->vbuf= pipe_user_buffer_create(poly->screen,
279 poly->data,
280 vert_size,
281 PIPE_BIND_VERTEX_BUFFER);
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 util_draw_arrays(pipe, PIPE_PRIM_TRIANGLE_FAN, 0, (uint) poly->num_verts);
304 }
305
306 void polygon_fill(struct polygon *poly, struct vg_context *ctx)
307 {
308 struct pipe_depth_stencil_alpha_state dsa;
309 struct pipe_stencil_ref sr;
310 struct pipe_blend_state blend;
311 VGfloat bounds[4];
312 VGfloat min_x, min_y, max_x, max_y;
313 assert(poly);
314 polygon_bounding_rect(poly, bounds);
315 min_x = bounds[0];
316 min_y = bounds[1];
317 max_x = bounds[0] + bounds[2];
318 max_y = bounds[1] + bounds[3];
319
320 #if DEBUG_POLYGON
321 debug_printf("Poly bounds are [%f, %f], [%f, %f]\n",
322 min_x, min_y, max_x, max_y);
323 #endif
324
325 set_blend_for_fill(&blend);
326
327 memset(&dsa, 0, sizeof(struct pipe_depth_stencil_alpha_state));
328 memset(&sr, 0, sizeof(struct pipe_stencil_ref));
329 /* only need a fixed 0. Rely on default or move it out at least? */
330 cso_set_stencil_ref(ctx->cso_context, &sr);
331
332 cso_save_blend(ctx->cso_context);
333 cso_save_depth_stencil_alpha(ctx->cso_context);
334
335 dsa.stencil[0].enabled = 1;
336 if (ctx->state.vg.fill_rule == VG_EVEN_ODD) {
337 dsa.stencil[0].writemask = 1;
338 dsa.stencil[0].fail_op = PIPE_STENCIL_OP_KEEP;
339 dsa.stencil[0].zfail_op = PIPE_STENCIL_OP_KEEP;
340 dsa.stencil[0].zpass_op = PIPE_STENCIL_OP_INVERT;
341 dsa.stencil[0].func = PIPE_FUNC_ALWAYS;
342 dsa.stencil[0].valuemask = ~0;
343
344 cso_set_blend(ctx->cso_context, &blend);
345 cso_set_depth_stencil_alpha(ctx->cso_context, &dsa);
346 draw_polygon(ctx, poly);
347 } else if (ctx->state.vg.fill_rule == VG_NON_ZERO) {
348 struct pipe_screen *screen = ctx->pipe->screen;
349
350 if (screen->get_param(screen, PIPE_CAP_TWO_SIDED_STENCIL)) {
351 /* front */
352 dsa.stencil[0].writemask = ~0;
353 dsa.stencil[0].fail_op = PIPE_STENCIL_OP_KEEP;
354 dsa.stencil[0].zfail_op = PIPE_STENCIL_OP_KEEP;
355 dsa.stencil[0].zpass_op = PIPE_STENCIL_OP_INCR_WRAP;
356 dsa.stencil[0].func = PIPE_FUNC_ALWAYS;
357 dsa.stencil[0].valuemask = ~0;
358
359 /* back */
360 dsa.stencil[1].enabled = 1;
361 dsa.stencil[1].writemask = ~0;
362 dsa.stencil[1].fail_op = PIPE_STENCIL_OP_KEEP;
363 dsa.stencil[1].zfail_op = PIPE_STENCIL_OP_KEEP;
364 dsa.stencil[1].zpass_op = PIPE_STENCIL_OP_DECR_WRAP;
365 dsa.stencil[1].func = PIPE_FUNC_ALWAYS;
366 dsa.stencil[1].valuemask = ~0;
367
368 cso_set_blend(ctx->cso_context, &blend);
369 cso_set_depth_stencil_alpha(ctx->cso_context, &dsa);
370 draw_polygon(ctx, poly);
371 } else {
372 struct pipe_rasterizer_state raster;
373
374 memcpy(&raster, &ctx->state.g3d.rasterizer, sizeof(struct pipe_rasterizer_state));
375
376 cso_save_rasterizer(ctx->cso_context);
377 dsa.stencil[0].func = PIPE_FUNC_ALWAYS;
378 dsa.stencil[0].valuemask = ~0;
379
380 raster.cull_face = PIPE_FACE_BACK;
381 dsa.stencil[0].fail_op = PIPE_STENCIL_OP_KEEP;
382 dsa.stencil[0].zfail_op = PIPE_STENCIL_OP_KEEP;
383 dsa.stencil[0].zpass_op = PIPE_STENCIL_OP_INCR_WRAP;
384
385 cso_set_blend(ctx->cso_context, &blend);
386 cso_set_depth_stencil_alpha(ctx->cso_context, &dsa);
387 cso_set_rasterizer(ctx->cso_context, &raster);
388 draw_polygon(ctx, poly);
389
390 raster.cull_face = PIPE_FACE_FRONT;
391 dsa.stencil[0].fail_op = PIPE_STENCIL_OP_KEEP;
392 dsa.stencil[0].zfail_op = PIPE_STENCIL_OP_KEEP;
393 dsa.stencil[0].zpass_op = PIPE_STENCIL_OP_DECR_WRAP;
394 cso_set_depth_stencil_alpha(ctx->cso_context, &dsa);
395 cso_set_rasterizer(ctx->cso_context, &raster);
396 draw_polygon(ctx, poly);
397
398 cso_restore_rasterizer(ctx->cso_context);
399 }
400 }
401
402 /* restore color writes */
403 cso_restore_blend(ctx->cso_context);
404 /* setup stencil ops */
405 dsa.stencil[0].func = PIPE_FUNC_NOTEQUAL;
406 dsa.stencil[0].fail_op = PIPE_STENCIL_OP_REPLACE;
407 dsa.stencil[0].zfail_op = PIPE_STENCIL_OP_REPLACE;
408 dsa.stencil[0].zpass_op = PIPE_STENCIL_OP_REPLACE;
409 dsa.stencil[0].valuemask = dsa.stencil[0].writemask;
410 dsa.stencil[1].enabled = 0;
411 memcpy(&dsa.depth, &ctx->state.g3d.dsa.depth,
412 sizeof(struct pipe_depth_state));
413 cso_set_depth_stencil_alpha(ctx->cso_context, &dsa);
414
415 /* render the quad to propagate the rendering from stencil */
416 renderer_draw_quad(ctx->renderer, min_x, min_y,
417 max_x, max_y, 0.0f/*depth should be disabled*/);
418
419 cso_restore_depth_stencil_alpha(ctx->cso_context);
420 }
421
422 void polygon_array_fill(struct polygon_array *polyarray, struct vg_context *ctx)
423 {
424 struct array *polys = polyarray->array;
425 struct pipe_depth_stencil_alpha_state dsa;
426 struct pipe_stencil_ref sr;
427 struct pipe_blend_state blend;
428 VGfloat min_x = polyarray->min_x;
429 VGfloat min_y = polyarray->min_y;
430 VGfloat max_x = polyarray->max_x;
431 VGfloat max_y = polyarray->max_y;
432 VGint i;
433
434
435 #if DEBUG_POLYGON
436 debug_printf("%s: Poly bounds are [%f, %f], [%f, %f]\n",
437 __FUNCTION__,
438 min_x, min_y, max_x, max_y);
439 #endif
440
441 set_blend_for_fill(&blend);
442
443 memset(&dsa, 0, sizeof(struct pipe_depth_stencil_alpha_state));
444 memset(&sr, 0, sizeof(struct pipe_stencil_ref));
445 /* only need a fixed 0. Rely on default or move it out at least? */
446 cso_set_stencil_ref(ctx->cso_context, &sr);
447
448 cso_save_blend(ctx->cso_context);
449 cso_save_depth_stencil_alpha(ctx->cso_context);
450
451 dsa.stencil[0].enabled = 1;
452 if (ctx->state.vg.fill_rule == VG_EVEN_ODD) {
453 dsa.stencil[0].writemask = 1;
454 dsa.stencil[0].fail_op = PIPE_STENCIL_OP_KEEP;
455 dsa.stencil[0].zfail_op = PIPE_STENCIL_OP_KEEP;
456 dsa.stencil[0].zpass_op = PIPE_STENCIL_OP_INVERT;
457 dsa.stencil[0].func = PIPE_FUNC_ALWAYS;
458 dsa.stencil[0].valuemask = ~0;
459
460 cso_set_blend(ctx->cso_context, &blend);
461 cso_set_depth_stencil_alpha(ctx->cso_context, &dsa);
462 for (i = 0; i < polys->num_elements; ++i) {
463 struct polygon *poly = (((struct polygon**)polys->data)[i]);
464 draw_polygon(ctx, poly);
465 }
466 } else if (ctx->state.vg.fill_rule == VG_NON_ZERO) {
467 struct pipe_screen *screen = ctx->pipe->screen;
468
469 if (screen->get_param(screen, PIPE_CAP_TWO_SIDED_STENCIL)) {
470 /* front */
471 dsa.stencil[0].writemask = ~0;
472 dsa.stencil[0].fail_op = PIPE_STENCIL_OP_KEEP;
473 dsa.stencil[0].zfail_op = PIPE_STENCIL_OP_KEEP;
474 dsa.stencil[0].zpass_op = PIPE_STENCIL_OP_INCR_WRAP;
475 dsa.stencil[0].func = PIPE_FUNC_ALWAYS;
476 dsa.stencil[0].valuemask = ~0;
477
478 /* back */
479 dsa.stencil[1].enabled = 1;
480 dsa.stencil[1].writemask = ~0;
481 dsa.stencil[1].fail_op = PIPE_STENCIL_OP_KEEP;
482 dsa.stencil[1].zfail_op = PIPE_STENCIL_OP_KEEP;
483 dsa.stencil[1].zpass_op = PIPE_STENCIL_OP_DECR_WRAP;
484 dsa.stencil[1].func = PIPE_FUNC_ALWAYS;
485 dsa.stencil[1].valuemask = ~0;
486
487 cso_set_blend(ctx->cso_context, &blend);
488 cso_set_depth_stencil_alpha(ctx->cso_context, &dsa);
489 for (i = 0; i < polys->num_elements; ++i) {
490 struct polygon *poly = (((struct polygon**)polys->data)[i]);
491 draw_polygon(ctx, poly);
492 }
493 } else {
494 struct pipe_rasterizer_state raster;
495
496 memcpy(&raster, &ctx->state.g3d.rasterizer, sizeof(struct pipe_rasterizer_state));
497
498 cso_save_rasterizer(ctx->cso_context);
499 dsa.stencil[0].func = PIPE_FUNC_ALWAYS;
500 dsa.stencil[0].valuemask = ~0;
501
502 raster.cull_face = PIPE_FACE_BACK;
503 dsa.stencil[0].fail_op = PIPE_STENCIL_OP_KEEP;
504 dsa.stencil[0].zfail_op = PIPE_STENCIL_OP_KEEP;
505 dsa.stencil[0].zpass_op = PIPE_STENCIL_OP_INCR_WRAP;
506
507 cso_set_blend(ctx->cso_context, &blend);
508 cso_set_depth_stencil_alpha(ctx->cso_context, &dsa);
509 cso_set_rasterizer(ctx->cso_context, &raster);
510 for (i = 0; i < polys->num_elements; ++i) {
511 struct polygon *poly = (((struct polygon**)polys->data)[i]);
512 draw_polygon(ctx, poly);
513 }
514
515 raster.cull_face = PIPE_FACE_FRONT;
516 dsa.stencil[0].fail_op = PIPE_STENCIL_OP_KEEP;
517 dsa.stencil[0].zfail_op = PIPE_STENCIL_OP_KEEP;
518 dsa.stencil[0].zpass_op = PIPE_STENCIL_OP_DECR_WRAP;
519 cso_set_depth_stencil_alpha(ctx->cso_context, &dsa);
520 cso_set_rasterizer(ctx->cso_context, &raster);
521 for (i = 0; i < polys->num_elements; ++i) {
522 struct polygon *poly = (((struct polygon**)polys->data)[i]);
523 draw_polygon(ctx, poly);
524 }
525
526 cso_restore_rasterizer(ctx->cso_context);
527 }
528 }
529
530 /* restore color writes */
531 cso_restore_blend(ctx->cso_context);
532 /* setup stencil ops */
533 dsa.stencil[0].func = PIPE_FUNC_NOTEQUAL;
534 dsa.stencil[0].fail_op = PIPE_STENCIL_OP_REPLACE;
535 dsa.stencil[0].zfail_op = PIPE_STENCIL_OP_REPLACE;
536 dsa.stencil[0].zpass_op = PIPE_STENCIL_OP_REPLACE;
537 dsa.stencil[0].valuemask = dsa.stencil[0].writemask;
538 dsa.stencil[1].enabled = 0;
539 memcpy(&dsa.depth, &ctx->state.g3d.dsa.depth,
540 sizeof(struct pipe_depth_state));
541 cso_set_depth_stencil_alpha(ctx->cso_context, &dsa);
542
543 /* render the quad to propagate the rendering from stencil */
544 renderer_draw_quad(ctx->renderer, min_x, min_y,
545 max_x, max_y, 0.0f/*depth should be disabled*/);
546
547 cso_restore_depth_stencil_alpha(ctx->cso_context);
548 }