Merge branch '7.8'
[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_resource *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_resource_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_resource_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 PIPE_BIND_VERTEX_BUFFER);
283 poly->dirty = VG_FALSE;
284 }
285
286
287 /* tell pipe about the vertex buffer */
288 memset(&vbuffer, 0, sizeof(vbuffer));
289 vbuffer.buffer = poly->vbuf;
290 vbuffer.stride = COMPONENTS * sizeof(float); /* vertex size */
291 vbuffer.buffer_offset = 0;
292 vbuffer.max_index = poly->num_verts - 1;
293 pipe->set_vertex_buffers(pipe, 1, &vbuffer);
294
295 /* tell pipe about the vertex attributes */
296 memset(&velement, 0, sizeof(velement));
297 velement.src_offset = 0;
298 velement.instance_divisor = 0;
299 velement.vertex_buffer_index = 0;
300 velement.src_format = PIPE_FORMAT_R32G32_FLOAT;
301 cso_set_vertex_elements(ctx->cso_context, 1, &velement);
302
303 /* draw */
304 pipe->draw_arrays(pipe, PIPE_PRIM_TRIANGLE_FAN,
305 0, poly->num_verts);
306 }
307
308 void polygon_fill(struct polygon *poly, struct vg_context *ctx)
309 {
310 struct pipe_depth_stencil_alpha_state dsa;
311 struct pipe_stencil_ref sr;
312 struct pipe_blend_state blend;
313 VGfloat bounds[4];
314 VGfloat min_x, min_y, max_x, max_y;
315 assert(poly);
316 polygon_bounding_rect(poly, bounds);
317 min_x = bounds[0];
318 min_y = bounds[1];
319 max_x = bounds[0] + bounds[2];
320 max_y = bounds[1] + bounds[3];
321
322 #if DEBUG_POLYGON
323 debug_printf("Poly bounds are [%f, %f], [%f, %f]\n",
324 min_x, min_y, max_x, max_y);
325 #endif
326
327 set_blend_for_fill(&blend);
328
329 memset(&dsa, 0, sizeof(struct pipe_depth_stencil_alpha_state));
330 memset(&sr, 0, sizeof(struct pipe_stencil_ref));
331 /* only need a fixed 0. Rely on default or move it out at least? */
332 cso_set_stencil_ref(ctx->cso_context, &sr);
333
334 cso_save_blend(ctx->cso_context);
335 cso_save_depth_stencil_alpha(ctx->cso_context);
336
337 dsa.stencil[0].enabled = 1;
338 if (ctx->state.vg.fill_rule == VG_EVEN_ODD) {
339 dsa.stencil[0].writemask = 1;
340 dsa.stencil[0].fail_op = PIPE_STENCIL_OP_KEEP;
341 dsa.stencil[0].zfail_op = PIPE_STENCIL_OP_KEEP;
342 dsa.stencil[0].zpass_op = PIPE_STENCIL_OP_INVERT;
343 dsa.stencil[0].func = PIPE_FUNC_ALWAYS;
344 dsa.stencil[0].valuemask = ~0;
345
346 cso_set_blend(ctx->cso_context, &blend);
347 cso_set_depth_stencil_alpha(ctx->cso_context, &dsa);
348 draw_polygon(ctx, poly);
349 } else if (ctx->state.vg.fill_rule == VG_NON_ZERO) {
350 struct pipe_screen *screen = ctx->pipe->screen;
351
352 if (screen->get_param(screen, PIPE_CAP_TWO_SIDED_STENCIL)) {
353 /* front */
354 dsa.stencil[0].writemask = ~0;
355 dsa.stencil[0].fail_op = PIPE_STENCIL_OP_KEEP;
356 dsa.stencil[0].zfail_op = PIPE_STENCIL_OP_KEEP;
357 dsa.stencil[0].zpass_op = PIPE_STENCIL_OP_INCR_WRAP;
358 dsa.stencil[0].func = PIPE_FUNC_ALWAYS;
359 dsa.stencil[0].valuemask = ~0;
360
361 /* back */
362 dsa.stencil[1].enabled = 1;
363 dsa.stencil[1].writemask = ~0;
364 dsa.stencil[1].fail_op = PIPE_STENCIL_OP_KEEP;
365 dsa.stencil[1].zfail_op = PIPE_STENCIL_OP_KEEP;
366 dsa.stencil[1].zpass_op = PIPE_STENCIL_OP_DECR_WRAP;
367 dsa.stencil[1].func = PIPE_FUNC_ALWAYS;
368 dsa.stencil[1].valuemask = ~0;
369
370 cso_set_blend(ctx->cso_context, &blend);
371 cso_set_depth_stencil_alpha(ctx->cso_context, &dsa);
372 draw_polygon(ctx, poly);
373 } else {
374 struct pipe_rasterizer_state raster;
375
376 memcpy(&raster, &ctx->state.g3d.rasterizer, sizeof(struct pipe_rasterizer_state));
377
378 cso_save_rasterizer(ctx->cso_context);
379 dsa.stencil[0].func = PIPE_FUNC_ALWAYS;
380 dsa.stencil[0].valuemask = ~0;
381
382 raster.cull_mode = raster.front_winding ^ PIPE_WINDING_BOTH;
383 dsa.stencil[0].fail_op = PIPE_STENCIL_OP_KEEP;
384 dsa.stencil[0].zfail_op = PIPE_STENCIL_OP_KEEP;
385 dsa.stencil[0].zpass_op = PIPE_STENCIL_OP_INCR_WRAP;
386
387 cso_set_blend(ctx->cso_context, &blend);
388 cso_set_depth_stencil_alpha(ctx->cso_context, &dsa);
389 cso_set_rasterizer(ctx->cso_context, &raster);
390 draw_polygon(ctx, poly);
391
392 raster.cull_mode = raster.front_winding;
393 dsa.stencil[0].fail_op = PIPE_STENCIL_OP_KEEP;
394 dsa.stencil[0].zfail_op = PIPE_STENCIL_OP_KEEP;
395 dsa.stencil[0].zpass_op = PIPE_STENCIL_OP_DECR_WRAP;
396 cso_set_depth_stencil_alpha(ctx->cso_context, &dsa);
397 cso_set_rasterizer(ctx->cso_context, &raster);
398 draw_polygon(ctx, poly);
399
400 cso_restore_rasterizer(ctx->cso_context);
401 }
402 }
403
404 /* restore color writes */
405 cso_restore_blend(ctx->cso_context);
406 /* setup stencil ops */
407 dsa.stencil[0].func = PIPE_FUNC_NOTEQUAL;
408 dsa.stencil[0].fail_op = PIPE_STENCIL_OP_REPLACE;
409 dsa.stencil[0].zfail_op = PIPE_STENCIL_OP_REPLACE;
410 dsa.stencil[0].zpass_op = PIPE_STENCIL_OP_REPLACE;
411 dsa.stencil[0].valuemask = dsa.stencil[0].writemask;
412 dsa.stencil[1].enabled = 0;
413 memcpy(&dsa.depth, &ctx->state.g3d.dsa.depth,
414 sizeof(struct pipe_depth_state));
415 cso_set_depth_stencil_alpha(ctx->cso_context, &dsa);
416
417 /* render the quad to propagate the rendering from stencil */
418 renderer_draw_quad(ctx->renderer, min_x, min_y,
419 max_x, max_y, 0.0f/*depth should be disabled*/);
420
421 cso_restore_depth_stencil_alpha(ctx->cso_context);
422 }
423
424 void polygon_array_fill(struct polygon_array *polyarray, struct vg_context *ctx)
425 {
426 struct array *polys = polyarray->array;
427 struct pipe_depth_stencil_alpha_state dsa;
428 struct pipe_stencil_ref sr;
429 struct pipe_blend_state blend;
430 VGfloat min_x = polyarray->min_x;
431 VGfloat min_y = polyarray->min_y;
432 VGfloat max_x = polyarray->max_x;
433 VGfloat max_y = polyarray->max_y;
434 VGint i;
435
436
437 #if DEBUG_POLYGON
438 debug_printf("%s: Poly bounds are [%f, %f], [%f, %f]\n",
439 __FUNCTION__,
440 min_x, min_y, max_x, max_y);
441 #endif
442
443 set_blend_for_fill(&blend);
444
445 memset(&dsa, 0, sizeof(struct pipe_depth_stencil_alpha_state));
446 memset(&sr, 0, sizeof(struct pipe_stencil_ref));
447 /* only need a fixed 0. Rely on default or move it out at least? */
448 cso_set_stencil_ref(ctx->cso_context, &sr);
449
450 cso_save_blend(ctx->cso_context);
451 cso_save_depth_stencil_alpha(ctx->cso_context);
452
453 dsa.stencil[0].enabled = 1;
454 if (ctx->state.vg.fill_rule == VG_EVEN_ODD) {
455 dsa.stencil[0].writemask = 1;
456 dsa.stencil[0].fail_op = PIPE_STENCIL_OP_KEEP;
457 dsa.stencil[0].zfail_op = PIPE_STENCIL_OP_KEEP;
458 dsa.stencil[0].zpass_op = PIPE_STENCIL_OP_INVERT;
459 dsa.stencil[0].func = PIPE_FUNC_ALWAYS;
460 dsa.stencil[0].valuemask = ~0;
461
462 cso_set_blend(ctx->cso_context, &blend);
463 cso_set_depth_stencil_alpha(ctx->cso_context, &dsa);
464 for (i = 0; i < polys->num_elements; ++i) {
465 struct polygon *poly = (((struct polygon**)polys->data)[i]);
466 draw_polygon(ctx, poly);
467 }
468 } else if (ctx->state.vg.fill_rule == VG_NON_ZERO) {
469 struct pipe_screen *screen = ctx->pipe->screen;
470
471 if (screen->get_param(screen, PIPE_CAP_TWO_SIDED_STENCIL)) {
472 /* front */
473 dsa.stencil[0].writemask = ~0;
474 dsa.stencil[0].fail_op = PIPE_STENCIL_OP_KEEP;
475 dsa.stencil[0].zfail_op = PIPE_STENCIL_OP_KEEP;
476 dsa.stencil[0].zpass_op = PIPE_STENCIL_OP_INCR_WRAP;
477 dsa.stencil[0].func = PIPE_FUNC_ALWAYS;
478 dsa.stencil[0].valuemask = ~0;
479
480 /* back */
481 dsa.stencil[1].enabled = 1;
482 dsa.stencil[1].writemask = ~0;
483 dsa.stencil[1].fail_op = PIPE_STENCIL_OP_KEEP;
484 dsa.stencil[1].zfail_op = PIPE_STENCIL_OP_KEEP;
485 dsa.stencil[1].zpass_op = PIPE_STENCIL_OP_DECR_WRAP;
486 dsa.stencil[1].func = PIPE_FUNC_ALWAYS;
487 dsa.stencil[1].valuemask = ~0;
488
489 cso_set_blend(ctx->cso_context, &blend);
490 cso_set_depth_stencil_alpha(ctx->cso_context, &dsa);
491 for (i = 0; i < polys->num_elements; ++i) {
492 struct polygon *poly = (((struct polygon**)polys->data)[i]);
493 draw_polygon(ctx, poly);
494 }
495 } else {
496 struct pipe_rasterizer_state raster;
497
498 memcpy(&raster, &ctx->state.g3d.rasterizer, sizeof(struct pipe_rasterizer_state));
499
500 cso_save_rasterizer(ctx->cso_context);
501 dsa.stencil[0].func = PIPE_FUNC_ALWAYS;
502 dsa.stencil[0].valuemask = ~0;
503
504 raster.cull_mode = raster.front_winding ^ PIPE_WINDING_BOTH;
505 dsa.stencil[0].fail_op = PIPE_STENCIL_OP_KEEP;
506 dsa.stencil[0].zfail_op = PIPE_STENCIL_OP_KEEP;
507 dsa.stencil[0].zpass_op = PIPE_STENCIL_OP_INCR_WRAP;
508
509 cso_set_blend(ctx->cso_context, &blend);
510 cso_set_depth_stencil_alpha(ctx->cso_context, &dsa);
511 cso_set_rasterizer(ctx->cso_context, &raster);
512 for (i = 0; i < polys->num_elements; ++i) {
513 struct polygon *poly = (((struct polygon**)polys->data)[i]);
514 draw_polygon(ctx, poly);
515 }
516
517 raster.cull_mode = raster.front_winding;
518 dsa.stencil[0].fail_op = PIPE_STENCIL_OP_KEEP;
519 dsa.stencil[0].zfail_op = PIPE_STENCIL_OP_KEEP;
520 dsa.stencil[0].zpass_op = PIPE_STENCIL_OP_DECR_WRAP;
521 cso_set_depth_stencil_alpha(ctx->cso_context, &dsa);
522 cso_set_rasterizer(ctx->cso_context, &raster);
523 for (i = 0; i < polys->num_elements; ++i) {
524 struct polygon *poly = (((struct polygon**)polys->data)[i]);
525 draw_polygon(ctx, poly);
526 }
527
528 cso_restore_rasterizer(ctx->cso_context);
529 }
530 }
531
532 /* restore color writes */
533 cso_restore_blend(ctx->cso_context);
534 /* setup stencil ops */
535 dsa.stencil[0].func = PIPE_FUNC_NOTEQUAL;
536 dsa.stencil[0].fail_op = PIPE_STENCIL_OP_REPLACE;
537 dsa.stencil[0].zfail_op = PIPE_STENCIL_OP_REPLACE;
538 dsa.stencil[0].zpass_op = PIPE_STENCIL_OP_REPLACE;
539 dsa.stencil[0].valuemask = dsa.stencil[0].writemask;
540 dsa.stencil[1].enabled = 0;
541 memcpy(&dsa.depth, &ctx->state.g3d.dsa.depth,
542 sizeof(struct pipe_depth_state));
543 cso_set_depth_stencil_alpha(ctx->cso_context, &dsa);
544
545 /* render the quad to propagate the rendering from stencil */
546 renderer_draw_quad(ctx->renderer, min_x, min_y,
547 max_x, max_y, 0.0f/*depth should be disabled*/);
548
549 cso_restore_depth_stencil_alpha(ctx->cso_context);
550 }