1 /**************************************************************************
3 * Copyright 2009 VMware, Inc. All Rights Reserved.
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:
13 * The above copyright notice and this permission notice (including the
14 * next paragraph) shall be included in all copies or substantial portions
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.
25 **************************************************************************/
29 #include "matrix.h" /*for floatsEqual*/
30 #include "vg_context.h"
34 #include "util_array.h"
35 #include "VG/openvg.h"
37 #include "pipe/p_context.h"
38 #include "pipe/p_defines.h"
39 #include "pipe/p_state.h"
40 #include "pipe/p_inlines.h"
41 #include "pipe/p_screen.h"
43 #include "util/u_draw_quad.h"
44 #include "util/u_math.h"
49 #define DEBUG_POLYGON 0
61 struct pipe_buffer
*vbuf
;
62 struct pipe_screen
*screen
;
65 static float *ptr_to_vertex(float *data
, int idx
)
67 return data
+ (idx
* COMPONENTS
);
71 static void polygon_print(struct polygon
*poly
)
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]);
80 debug_printf("\nend\n");
85 struct polygon
* polygon_create(int size
)
87 struct polygon
*poly
= (struct polygon
*)malloc(sizeof(struct polygon
));
89 poly
->data
= malloc(sizeof(float) * COMPONENTS
* size
);
92 poly
->dirty
= VG_TRUE
;
98 struct polygon
* polygon_create_from_data(float *data
, int size
)
100 struct polygon
*poly
= polygon_create(size
);
102 memcpy(poly
->data
, data
, sizeof(float) * COMPONENTS
* size
);
103 poly
->num_verts
= size
;
104 poly
->dirty
= VG_TRUE
;
110 void polygon_destroy(struct polygon
*poly
)
113 pipe_buffer_reference(&poly
->vbuf
, NULL
);
119 void polygon_resize(struct polygon
*poly
, int new_size
)
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
);
127 poly
->size
= new_size
;
128 poly
->dirty
= VG_TRUE
;
131 int polygon_size(struct polygon
*poly
)
136 int polygon_vertex_count(struct polygon
*poly
)
138 return poly
->num_verts
;
141 float * polygon_data(struct polygon
*poly
)
146 void polygon_vertex_append(struct polygon
*p
,
151 debug_printf("Append vertex [%f, %f]\n", x
, y
);
153 if (p
->num_verts
>= p
->size
) {
154 polygon_resize(p
, p
->size
* 2);
157 vert
= ptr_to_vertex(p
->data
, p
->num_verts
);
164 void polygon_set_vertex(struct polygon
*p
, int idx
,
168 if (idx
>= p
->num_verts
) {
169 /*fixme: error reporting*/
174 vert
= ptr_to_vertex(p
->data
, idx
);
180 void polygon_vertex(struct polygon
*p
, int idx
,
184 if (idx
>= p
->num_verts
) {
185 /*fixme: error reporting*/
190 vert
= ptr_to_vertex(p
->data
, idx
);
195 void polygon_bounding_rect(struct polygon
*p
,
199 float minx
, miny
, maxx
, maxy
;
200 float *vert
= ptr_to_vertex(p
->data
, 0);
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
);
211 maxx
= MAX2(vert
[0], maxx
);
212 maxy
= MAX2(vert
[1], maxy
);
217 rect
[2] = maxx
- minx
;
218 rect
[3] = maxy
- miny
;
221 int polygon_contains_point(struct polygon
*p
,
227 void polygon_append_polygon(struct polygon
*dst
,
230 if (dst
->num_verts
+ src
->num_verts
>= dst
->size
) {
231 polygon_resize(dst
, dst
->num_verts
+ src
->num_verts
* 1.5);
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
;
238 VGboolean
polygon_is_closed(struct polygon
*p
)
240 VGfloat start
[2], end
[2];
242 polygon_vertex(p
, 0, start
);
243 polygon_vertex(p
, p
->num_verts
- 1, end
);
245 return floatsEqual(start
[0], end
[0]) && floatsEqual(start
[1], end
[1]);
248 static void set_blend_for_fill(struct pipe_blend_state
*blend
)
250 memset(blend
, 0, sizeof(struct pipe_blend_state
));
251 blend
->colormask
= 0; /*disable colorwrites*/
253 blend
->rgb_src_factor
= PIPE_BLENDFACTOR_ONE
;
254 blend
->alpha_src_factor
= PIPE_BLENDFACTOR_ONE
;
255 blend
->rgb_dst_factor
= PIPE_BLENDFACTOR_INV_SRC_ALPHA
;
256 blend
->alpha_dst_factor
= PIPE_BLENDFACTOR_INV_SRC_ALPHA
;
259 static void draw_polygon(struct vg_context
*ctx
,
260 struct polygon
*poly
)
263 struct pipe_context
*pipe
;
264 struct pipe_vertex_buffer vbuffer
;
265 struct pipe_vertex_element velement
;
267 vert_size
= poly
->num_verts
* COMPONENTS
* sizeof(float);
269 /*polygon_print(poly);*/
273 if (poly
->vbuf
== NULL
|| poly
->dirty
) {
275 pipe_buffer_reference(&poly
->vbuf
,
278 poly
->screen
= pipe
->screen
;
279 poly
->vbuf
= pipe_user_buffer_create(poly
->screen
,
282 poly
->dirty
= VG_FALSE
;
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
);
294 /* tell pipe about the vertex attributes */
295 velement
.src_offset
= 0;
296 velement
.vertex_buffer_index
= 0;
297 velement
.src_format
= PIPE_FORMAT_R32G32_FLOAT
;
298 velement
.nr_components
= COMPONENTS
;
299 pipe
->set_vertex_elements(pipe
, 1, &velement
);
302 pipe
->draw_arrays(pipe
, PIPE_PRIM_TRIANGLE_FAN
,
306 void polygon_fill(struct polygon
*poly
, struct vg_context
*ctx
)
308 struct pipe_depth_stencil_alpha_state dsa
;
309 struct pipe_blend_state blend
;
311 VGfloat min_x
, min_y
, max_x
, max_y
;
313 polygon_bounding_rect(poly
, bounds
);
316 max_x
= bounds
[0] + bounds
[2];
317 max_y
= bounds
[1] + bounds
[3];
320 debug_printf("Poly bounds are [%f, %f], [%f, %f]\n",
321 min_x
, min_y
, max_x
, max_y
);
324 set_blend_for_fill(&blend
);
326 memset(&dsa
, 0, sizeof(struct pipe_depth_stencil_alpha_state
));
328 cso_save_blend(ctx
->cso_context
);
329 cso_save_depth_stencil_alpha(ctx
->cso_context
);
331 dsa
.stencil
[0].enabled
= 1;
332 if (ctx
->state
.vg
.fill_rule
== VG_EVEN_ODD
) {
333 dsa
.stencil
[0].writemask
= 1;
334 dsa
.stencil
[0].fail_op
= PIPE_STENCIL_OP_KEEP
;
335 dsa
.stencil
[0].zfail_op
= PIPE_STENCIL_OP_KEEP
;
336 dsa
.stencil
[0].zpass_op
= PIPE_STENCIL_OP_INVERT
;
337 dsa
.stencil
[0].func
= PIPE_FUNC_ALWAYS
;
338 dsa
.stencil
[0].ref_value
= 0;
339 dsa
.stencil
[0].valuemask
= ~0;
341 cso_set_blend(ctx
->cso_context
, &blend
);
342 cso_set_depth_stencil_alpha(ctx
->cso_context
, &dsa
);
343 draw_polygon(ctx
, poly
);
344 } else if (ctx
->state
.vg
.fill_rule
== VG_NON_ZERO
) {
345 struct pipe_screen
*screen
= ctx
->pipe
->screen
;
347 if (screen
->get_param(screen
, PIPE_CAP_TWO_SIDED_STENCIL
)) {
349 dsa
.stencil
[0].writemask
= ~0;
350 dsa
.stencil
[0].fail_op
= PIPE_STENCIL_OP_KEEP
;
351 dsa
.stencil
[0].zfail_op
= PIPE_STENCIL_OP_KEEP
;
352 dsa
.stencil
[0].zpass_op
= PIPE_STENCIL_OP_INCR_WRAP
;
353 dsa
.stencil
[0].func
= PIPE_FUNC_ALWAYS
;
354 dsa
.stencil
[0].ref_value
= 0;
355 dsa
.stencil
[0].valuemask
= ~0;
358 dsa
.stencil
[1].enabled
= 1;
359 dsa
.stencil
[1].writemask
= ~0;
360 dsa
.stencil
[1].fail_op
= PIPE_STENCIL_OP_KEEP
;
361 dsa
.stencil
[1].zfail_op
= PIPE_STENCIL_OP_KEEP
;
362 dsa
.stencil
[1].zpass_op
= PIPE_STENCIL_OP_DECR_WRAP
;
363 dsa
.stencil
[1].func
= PIPE_FUNC_ALWAYS
;
364 dsa
.stencil
[1].ref_value
= 0;
365 dsa
.stencil
[1].valuemask
= ~0;
367 cso_set_blend(ctx
->cso_context
, &blend
);
368 cso_set_depth_stencil_alpha(ctx
->cso_context
, &dsa
);
369 draw_polygon(ctx
, poly
);
371 struct pipe_rasterizer_state raster
;
373 memcpy(&raster
, &ctx
->state
.g3d
.rasterizer
, sizeof(struct pipe_rasterizer_state
));
375 cso_save_rasterizer(ctx
->cso_context
);
376 dsa
.stencil
[0].func
= PIPE_FUNC_ALWAYS
;
377 dsa
.stencil
[0].ref_value
= 0;
378 dsa
.stencil
[0].valuemask
= ~0;
380 raster
.cull_mode
= raster
.front_winding
^ PIPE_WINDING_BOTH
;
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
;
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
);
390 raster
.cull_mode
= raster
.front_winding
;
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
);
398 cso_restore_rasterizer(ctx
->cso_context
);
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].ref_value
= 0;
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
);
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*/);
420 cso_restore_depth_stencil_alpha(ctx
->cso_context
);
423 void polygon_array_fill(struct polygon_array
*polyarray
, struct vg_context
*ctx
)
425 struct array
*polys
= polyarray
->array
;
426 struct pipe_depth_stencil_alpha_state dsa
;
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
;
436 debug_printf("%s: Poly bounds are [%f, %f], [%f, %f]\n",
438 min_x
, min_y
, max_x
, max_y
);
441 set_blend_for_fill(&blend
);
443 memset(&dsa
, 0, sizeof(struct pipe_depth_stencil_alpha_state
));
445 cso_save_blend(ctx
->cso_context
);
446 cso_save_depth_stencil_alpha(ctx
->cso_context
);
448 dsa
.stencil
[0].enabled
= 1;
449 if (ctx
->state
.vg
.fill_rule
== VG_EVEN_ODD
) {
450 dsa
.stencil
[0].writemask
= 1;
451 dsa
.stencil
[0].fail_op
= PIPE_STENCIL_OP_KEEP
;
452 dsa
.stencil
[0].zfail_op
= PIPE_STENCIL_OP_KEEP
;
453 dsa
.stencil
[0].zpass_op
= PIPE_STENCIL_OP_INVERT
;
454 dsa
.stencil
[0].func
= PIPE_FUNC_ALWAYS
;
455 dsa
.stencil
[0].ref_value
= 0;
456 dsa
.stencil
[0].valuemask
= ~0;
458 cso_set_blend(ctx
->cso_context
, &blend
);
459 cso_set_depth_stencil_alpha(ctx
->cso_context
, &dsa
);
460 for (i
= 0; i
< polys
->num_elements
; ++i
) {
461 struct polygon
*poly
= (((struct polygon
**)polys
->data
)[i
]);
462 draw_polygon(ctx
, poly
);
464 } else if (ctx
->state
.vg
.fill_rule
== VG_NON_ZERO
) {
465 struct pipe_screen
*screen
= ctx
->pipe
->screen
;
467 if (screen
->get_param(screen
, PIPE_CAP_TWO_SIDED_STENCIL
)) {
469 dsa
.stencil
[0].writemask
= ~0;
470 dsa
.stencil
[0].fail_op
= PIPE_STENCIL_OP_KEEP
;
471 dsa
.stencil
[0].zfail_op
= PIPE_STENCIL_OP_KEEP
;
472 dsa
.stencil
[0].zpass_op
= PIPE_STENCIL_OP_INCR_WRAP
;
473 dsa
.stencil
[0].func
= PIPE_FUNC_ALWAYS
;
474 dsa
.stencil
[0].ref_value
= 0;
475 dsa
.stencil
[0].valuemask
= ~0;
478 dsa
.stencil
[1].enabled
= 1;
479 dsa
.stencil
[1].writemask
= ~0;
480 dsa
.stencil
[1].fail_op
= PIPE_STENCIL_OP_KEEP
;
481 dsa
.stencil
[1].zfail_op
= PIPE_STENCIL_OP_KEEP
;
482 dsa
.stencil
[1].zpass_op
= PIPE_STENCIL_OP_DECR_WRAP
;
483 dsa
.stencil
[1].func
= PIPE_FUNC_ALWAYS
;
484 dsa
.stencil
[1].ref_value
= 0;
485 dsa
.stencil
[1].valuemask
= ~0;
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
);
494 struct pipe_rasterizer_state raster
;
496 memcpy(&raster
, &ctx
->state
.g3d
.rasterizer
, sizeof(struct pipe_rasterizer_state
));
498 cso_save_rasterizer(ctx
->cso_context
);
499 dsa
.stencil
[0].func
= PIPE_FUNC_ALWAYS
;
500 dsa
.stencil
[0].ref_value
= 0;
501 dsa
.stencil
[0].valuemask
= ~0;
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
;
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
);
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
);
527 cso_restore_rasterizer(ctx
->cso_context
);
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].ref_value
= 0;
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
);
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*/);
549 cso_restore_depth_stencil_alpha(ctx
->cso_context
);