mirror of
https://gitlab.freedesktop.org/mesa/mesa.git
synced 2026-05-06 13:48:06 +02:00
st/vega: Add POLYGON_STENCIL and POLYGON_FILL renderer state.
The states are designated for polygon filling. Polygon filling is a two-pass process utilizing the stencil buffer. polygon_fill and polygon_array_fill functions are updated to make use of the state.
This commit is contained in:
parent
b23f732075
commit
3b71cb6ad6
3 changed files with 270 additions and 233 deletions
|
|
@ -244,24 +244,11 @@ VGboolean polygon_is_closed(struct polygon *p)
|
|||
return floatsEqual(start[0], end[0]) && floatsEqual(start[1], end[1]);
|
||||
}
|
||||
|
||||
static void set_blend_for_fill(struct pipe_blend_state *blend)
|
||||
{
|
||||
memset(blend, 0, sizeof(struct pipe_blend_state));
|
||||
blend->rt[0].colormask = 0; /*disable colorwrites*/
|
||||
|
||||
blend->rt[0].rgb_src_factor = PIPE_BLENDFACTOR_ONE;
|
||||
blend->rt[0].alpha_src_factor = PIPE_BLENDFACTOR_ONE;
|
||||
blend->rt[0].rgb_dst_factor = PIPE_BLENDFACTOR_INV_SRC_ALPHA;
|
||||
blend->rt[0].alpha_dst_factor = PIPE_BLENDFACTOR_INV_SRC_ALPHA;
|
||||
}
|
||||
|
||||
static void draw_polygon(struct vg_context *ctx,
|
||||
struct polygon *poly)
|
||||
static void polygon_prepare_buffer(struct vg_context *ctx,
|
||||
struct polygon *poly)
|
||||
{
|
||||
int vert_size;
|
||||
struct pipe_context *pipe;
|
||||
struct pipe_vertex_buffer vbuffer;
|
||||
struct pipe_vertex_element velement;
|
||||
|
||||
vert_size = poly->num_verts * COMPONENTS * sizeof(float);
|
||||
|
||||
|
|
@ -281,35 +268,15 @@ static void draw_polygon(struct vg_context *ctx,
|
|||
PIPE_BIND_VERTEX_BUFFER);
|
||||
poly->dirty = VG_FALSE;
|
||||
}
|
||||
|
||||
|
||||
/* tell pipe about the vertex buffer */
|
||||
memset(&vbuffer, 0, sizeof(vbuffer));
|
||||
vbuffer.buffer = poly->vbuf;
|
||||
vbuffer.stride = COMPONENTS * sizeof(float); /* vertex size */
|
||||
vbuffer.buffer_offset = 0;
|
||||
vbuffer.max_index = poly->num_verts - 1;
|
||||
pipe->set_vertex_buffers(pipe, 1, &vbuffer);
|
||||
|
||||
/* tell pipe about the vertex attributes */
|
||||
memset(&velement, 0, sizeof(velement));
|
||||
velement.src_offset = 0;
|
||||
velement.instance_divisor = 0;
|
||||
velement.vertex_buffer_index = 0;
|
||||
velement.src_format = PIPE_FORMAT_R32G32_FLOAT;
|
||||
cso_set_vertex_elements(ctx->cso_context, 1, &velement);
|
||||
|
||||
/* draw */
|
||||
util_draw_arrays(pipe, PIPE_PRIM_TRIANGLE_FAN, 0, (uint) poly->num_verts);
|
||||
}
|
||||
|
||||
void polygon_fill(struct polygon *poly, struct vg_context *ctx)
|
||||
{
|
||||
struct pipe_depth_stencil_alpha_state dsa;
|
||||
struct pipe_stencil_ref sr;
|
||||
struct pipe_blend_state blend;
|
||||
struct pipe_vertex_element velement;
|
||||
struct pipe_vertex_buffer vbuffer;
|
||||
VGfloat bounds[4];
|
||||
VGfloat min_x, min_y, max_x, max_y;
|
||||
|
||||
assert(poly);
|
||||
polygon_bounding_rect(poly, bounds);
|
||||
min_x = bounds[0];
|
||||
|
|
@ -322,113 +289,42 @@ void polygon_fill(struct polygon *poly, struct vg_context *ctx)
|
|||
min_x, min_y, max_x, max_y);
|
||||
#endif
|
||||
|
||||
set_blend_for_fill(&blend);
|
||||
polygon_prepare_buffer(ctx, poly);
|
||||
|
||||
memset(&dsa, 0, sizeof(struct pipe_depth_stencil_alpha_state));
|
||||
memset(&sr, 0, sizeof(struct pipe_stencil_ref));
|
||||
/* only need a fixed 0. Rely on default or move it out at least? */
|
||||
cso_set_stencil_ref(ctx->cso_context, &sr);
|
||||
/* tell renderer about the vertex attributes */
|
||||
memset(&velement, 0, sizeof(velement));
|
||||
velement.src_offset = 0;
|
||||
velement.instance_divisor = 0;
|
||||
velement.vertex_buffer_index = 0;
|
||||
velement.src_format = PIPE_FORMAT_R32G32_FLOAT;
|
||||
|
||||
cso_save_blend(ctx->cso_context);
|
||||
cso_save_depth_stencil_alpha(ctx->cso_context);
|
||||
/* tell renderer about the vertex buffer */
|
||||
memset(&vbuffer, 0, sizeof(vbuffer));
|
||||
vbuffer.buffer = poly->vbuf;
|
||||
vbuffer.stride = COMPONENTS * sizeof(float); /* vertex size */
|
||||
vbuffer.buffer_offset = 0;
|
||||
vbuffer.max_index = poly->num_verts - 1;
|
||||
|
||||
dsa.stencil[0].enabled = 1;
|
||||
if (ctx->state.vg.fill_rule == VG_EVEN_ODD) {
|
||||
dsa.stencil[0].writemask = 1;
|
||||
dsa.stencil[0].fail_op = PIPE_STENCIL_OP_KEEP;
|
||||
dsa.stencil[0].zfail_op = PIPE_STENCIL_OP_KEEP;
|
||||
dsa.stencil[0].zpass_op = PIPE_STENCIL_OP_INVERT;
|
||||
dsa.stencil[0].func = PIPE_FUNC_ALWAYS;
|
||||
dsa.stencil[0].valuemask = ~0;
|
||||
renderer_polygon_stencil_begin(ctx->renderer,
|
||||
&velement, ctx->state.vg.fill_rule, VG_FALSE);
|
||||
renderer_polygon_stencil(ctx->renderer, &vbuffer,
|
||||
PIPE_PRIM_TRIANGLE_FAN, 0, (VGuint) poly->num_verts);
|
||||
renderer_polygon_stencil_end(ctx->renderer);
|
||||
|
||||
cso_set_blend(ctx->cso_context, &blend);
|
||||
cso_set_depth_stencil_alpha(ctx->cso_context, &dsa);
|
||||
draw_polygon(ctx, poly);
|
||||
} else if (ctx->state.vg.fill_rule == VG_NON_ZERO) {
|
||||
struct pipe_screen *screen = ctx->pipe->screen;
|
||||
|
||||
if (screen->get_param(screen, PIPE_CAP_TWO_SIDED_STENCIL)) {
|
||||
/* front */
|
||||
dsa.stencil[0].writemask = ~0;
|
||||
dsa.stencil[0].fail_op = PIPE_STENCIL_OP_KEEP;
|
||||
dsa.stencil[0].zfail_op = PIPE_STENCIL_OP_KEEP;
|
||||
dsa.stencil[0].zpass_op = PIPE_STENCIL_OP_INCR_WRAP;
|
||||
dsa.stencil[0].func = PIPE_FUNC_ALWAYS;
|
||||
dsa.stencil[0].valuemask = ~0;
|
||||
|
||||
/* back */
|
||||
dsa.stencil[1].enabled = 1;
|
||||
dsa.stencil[1].writemask = ~0;
|
||||
dsa.stencil[1].fail_op = PIPE_STENCIL_OP_KEEP;
|
||||
dsa.stencil[1].zfail_op = PIPE_STENCIL_OP_KEEP;
|
||||
dsa.stencil[1].zpass_op = PIPE_STENCIL_OP_DECR_WRAP;
|
||||
dsa.stencil[1].func = PIPE_FUNC_ALWAYS;
|
||||
dsa.stencil[1].valuemask = ~0;
|
||||
|
||||
cso_set_blend(ctx->cso_context, &blend);
|
||||
cso_set_depth_stencil_alpha(ctx->cso_context, &dsa);
|
||||
draw_polygon(ctx, poly);
|
||||
} else {
|
||||
struct pipe_rasterizer_state raster;
|
||||
|
||||
memcpy(&raster, &ctx->state.g3d.rasterizer, sizeof(struct pipe_rasterizer_state));
|
||||
|
||||
cso_save_rasterizer(ctx->cso_context);
|
||||
dsa.stencil[0].func = PIPE_FUNC_ALWAYS;
|
||||
dsa.stencil[0].valuemask = ~0;
|
||||
|
||||
raster.cull_face = PIPE_FACE_BACK;
|
||||
dsa.stencil[0].fail_op = PIPE_STENCIL_OP_KEEP;
|
||||
dsa.stencil[0].zfail_op = PIPE_STENCIL_OP_KEEP;
|
||||
dsa.stencil[0].zpass_op = PIPE_STENCIL_OP_INCR_WRAP;
|
||||
|
||||
cso_set_blend(ctx->cso_context, &blend);
|
||||
cso_set_depth_stencil_alpha(ctx->cso_context, &dsa);
|
||||
cso_set_rasterizer(ctx->cso_context, &raster);
|
||||
draw_polygon(ctx, poly);
|
||||
|
||||
raster.cull_face = PIPE_FACE_FRONT;
|
||||
dsa.stencil[0].fail_op = PIPE_STENCIL_OP_KEEP;
|
||||
dsa.stencil[0].zfail_op = PIPE_STENCIL_OP_KEEP;
|
||||
dsa.stencil[0].zpass_op = PIPE_STENCIL_OP_DECR_WRAP;
|
||||
cso_set_depth_stencil_alpha(ctx->cso_context, &dsa);
|
||||
cso_set_rasterizer(ctx->cso_context, &raster);
|
||||
draw_polygon(ctx, poly);
|
||||
|
||||
cso_restore_rasterizer(ctx->cso_context);
|
||||
}
|
||||
}
|
||||
|
||||
/* restore color writes */
|
||||
cso_restore_blend(ctx->cso_context);
|
||||
/* setup stencil ops */
|
||||
dsa.stencil[0].func = PIPE_FUNC_NOTEQUAL;
|
||||
dsa.stencil[0].fail_op = PIPE_STENCIL_OP_REPLACE;
|
||||
dsa.stencil[0].zfail_op = PIPE_STENCIL_OP_REPLACE;
|
||||
dsa.stencil[0].zpass_op = PIPE_STENCIL_OP_REPLACE;
|
||||
dsa.stencil[0].valuemask = dsa.stencil[0].writemask;
|
||||
dsa.stencil[1].enabled = 0;
|
||||
memcpy(&dsa.depth, &ctx->state.g3d.dsa.depth,
|
||||
sizeof(struct pipe_depth_state));
|
||||
cso_set_depth_stencil_alpha(ctx->cso_context, &dsa);
|
||||
|
||||
/* render the quad to propagate the rendering from stencil */
|
||||
renderer_draw_quad(ctx->renderer, min_x, min_y,
|
||||
max_x, max_y, 0.0f/*depth should be disabled*/);
|
||||
|
||||
cso_restore_depth_stencil_alpha(ctx->cso_context);
|
||||
renderer_polygon_fill_begin(ctx->renderer, VG_FALSE);
|
||||
renderer_polygon_fill(ctx->renderer, min_x, min_y, max_x, max_y);
|
||||
renderer_polygon_fill_end(ctx->renderer);
|
||||
}
|
||||
|
||||
void polygon_array_fill(struct polygon_array *polyarray, struct vg_context *ctx)
|
||||
{
|
||||
struct array *polys = polyarray->array;
|
||||
struct pipe_depth_stencil_alpha_state dsa;
|
||||
struct pipe_stencil_ref sr;
|
||||
struct pipe_blend_state blend;
|
||||
VGfloat min_x = polyarray->min_x;
|
||||
VGfloat min_y = polyarray->min_y;
|
||||
VGfloat max_x = polyarray->max_x;
|
||||
VGfloat max_y = polyarray->max_y;
|
||||
struct pipe_vertex_element velement;
|
||||
struct pipe_vertex_buffer vbuffer;
|
||||
VGint i;
|
||||
|
||||
|
||||
|
|
@ -438,111 +334,35 @@ void polygon_array_fill(struct polygon_array *polyarray, struct vg_context *ctx)
|
|||
min_x, min_y, max_x, max_y);
|
||||
#endif
|
||||
|
||||
set_blend_for_fill(&blend);
|
||||
/* tell renderer about the vertex attributes */
|
||||
memset(&velement, 0, sizeof(velement));
|
||||
velement.src_offset = 0;
|
||||
velement.instance_divisor = 0;
|
||||
velement.vertex_buffer_index = 0;
|
||||
velement.src_format = PIPE_FORMAT_R32G32_FLOAT;
|
||||
|
||||
memset(&dsa, 0, sizeof(struct pipe_depth_stencil_alpha_state));
|
||||
memset(&sr, 0, sizeof(struct pipe_stencil_ref));
|
||||
/* only need a fixed 0. Rely on default or move it out at least? */
|
||||
cso_set_stencil_ref(ctx->cso_context, &sr);
|
||||
/* tell renderer about the vertex buffer */
|
||||
memset(&vbuffer, 0, sizeof(vbuffer));
|
||||
vbuffer.stride = COMPONENTS * sizeof(float); /* vertex size */
|
||||
vbuffer.buffer_offset = 0;
|
||||
|
||||
cso_save_blend(ctx->cso_context);
|
||||
cso_save_depth_stencil_alpha(ctx->cso_context);
|
||||
/* prepare the stencil buffer */
|
||||
renderer_polygon_stencil_begin(ctx->renderer,
|
||||
&velement, ctx->state.vg.fill_rule, VG_FALSE);
|
||||
for (i = 0; i < polys->num_elements; ++i) {
|
||||
struct polygon *poly = (((struct polygon**)polys->data)[i]);
|
||||
|
||||
dsa.stencil[0].enabled = 1;
|
||||
if (ctx->state.vg.fill_rule == VG_EVEN_ODD) {
|
||||
dsa.stencil[0].writemask = 1;
|
||||
dsa.stencil[0].fail_op = PIPE_STENCIL_OP_KEEP;
|
||||
dsa.stencil[0].zfail_op = PIPE_STENCIL_OP_KEEP;
|
||||
dsa.stencil[0].zpass_op = PIPE_STENCIL_OP_INVERT;
|
||||
dsa.stencil[0].func = PIPE_FUNC_ALWAYS;
|
||||
dsa.stencil[0].valuemask = ~0;
|
||||
polygon_prepare_buffer(ctx, poly);
|
||||
vbuffer.buffer = poly->vbuf;
|
||||
vbuffer.max_index = poly->num_verts - 1;
|
||||
|
||||
cso_set_blend(ctx->cso_context, &blend);
|
||||
cso_set_depth_stencil_alpha(ctx->cso_context, &dsa);
|
||||
for (i = 0; i < polys->num_elements; ++i) {
|
||||
struct polygon *poly = (((struct polygon**)polys->data)[i]);
|
||||
draw_polygon(ctx, poly);
|
||||
}
|
||||
} else if (ctx->state.vg.fill_rule == VG_NON_ZERO) {
|
||||
struct pipe_screen *screen = ctx->pipe->screen;
|
||||
|
||||
if (screen->get_param(screen, PIPE_CAP_TWO_SIDED_STENCIL)) {
|
||||
/* front */
|
||||
dsa.stencil[0].writemask = ~0;
|
||||
dsa.stencil[0].fail_op = PIPE_STENCIL_OP_KEEP;
|
||||
dsa.stencil[0].zfail_op = PIPE_STENCIL_OP_KEEP;
|
||||
dsa.stencil[0].zpass_op = PIPE_STENCIL_OP_INCR_WRAP;
|
||||
dsa.stencil[0].func = PIPE_FUNC_ALWAYS;
|
||||
dsa.stencil[0].valuemask = ~0;
|
||||
|
||||
/* back */
|
||||
dsa.stencil[1].enabled = 1;
|
||||
dsa.stencil[1].writemask = ~0;
|
||||
dsa.stencil[1].fail_op = PIPE_STENCIL_OP_KEEP;
|
||||
dsa.stencil[1].zfail_op = PIPE_STENCIL_OP_KEEP;
|
||||
dsa.stencil[1].zpass_op = PIPE_STENCIL_OP_DECR_WRAP;
|
||||
dsa.stencil[1].func = PIPE_FUNC_ALWAYS;
|
||||
dsa.stencil[1].valuemask = ~0;
|
||||
|
||||
cso_set_blend(ctx->cso_context, &blend);
|
||||
cso_set_depth_stencil_alpha(ctx->cso_context, &dsa);
|
||||
for (i = 0; i < polys->num_elements; ++i) {
|
||||
struct polygon *poly = (((struct polygon**)polys->data)[i]);
|
||||
draw_polygon(ctx, poly);
|
||||
}
|
||||
} else {
|
||||
struct pipe_rasterizer_state raster;
|
||||
|
||||
memcpy(&raster, &ctx->state.g3d.rasterizer, sizeof(struct pipe_rasterizer_state));
|
||||
|
||||
cso_save_rasterizer(ctx->cso_context);
|
||||
dsa.stencil[0].func = PIPE_FUNC_ALWAYS;
|
||||
dsa.stencil[0].valuemask = ~0;
|
||||
|
||||
raster.cull_face = PIPE_FACE_BACK;
|
||||
dsa.stencil[0].fail_op = PIPE_STENCIL_OP_KEEP;
|
||||
dsa.stencil[0].zfail_op = PIPE_STENCIL_OP_KEEP;
|
||||
dsa.stencil[0].zpass_op = PIPE_STENCIL_OP_INCR_WRAP;
|
||||
|
||||
cso_set_blend(ctx->cso_context, &blend);
|
||||
cso_set_depth_stencil_alpha(ctx->cso_context, &dsa);
|
||||
cso_set_rasterizer(ctx->cso_context, &raster);
|
||||
for (i = 0; i < polys->num_elements; ++i) {
|
||||
struct polygon *poly = (((struct polygon**)polys->data)[i]);
|
||||
draw_polygon(ctx, poly);
|
||||
}
|
||||
|
||||
raster.cull_face = PIPE_FACE_FRONT;
|
||||
dsa.stencil[0].fail_op = PIPE_STENCIL_OP_KEEP;
|
||||
dsa.stencil[0].zfail_op = PIPE_STENCIL_OP_KEEP;
|
||||
dsa.stencil[0].zpass_op = PIPE_STENCIL_OP_DECR_WRAP;
|
||||
cso_set_depth_stencil_alpha(ctx->cso_context, &dsa);
|
||||
cso_set_rasterizer(ctx->cso_context, &raster);
|
||||
for (i = 0; i < polys->num_elements; ++i) {
|
||||
struct polygon *poly = (((struct polygon**)polys->data)[i]);
|
||||
draw_polygon(ctx, poly);
|
||||
}
|
||||
|
||||
cso_restore_rasterizer(ctx->cso_context);
|
||||
}
|
||||
renderer_polygon_stencil(ctx->renderer, &vbuffer,
|
||||
PIPE_PRIM_TRIANGLE_FAN, 0, (VGuint) poly->num_verts);
|
||||
}
|
||||
renderer_polygon_stencil_end(ctx->renderer);
|
||||
|
||||
/* restore color writes */
|
||||
cso_restore_blend(ctx->cso_context);
|
||||
/* setup stencil ops */
|
||||
dsa.stencil[0].func = PIPE_FUNC_NOTEQUAL;
|
||||
dsa.stencil[0].fail_op = PIPE_STENCIL_OP_REPLACE;
|
||||
dsa.stencil[0].zfail_op = PIPE_STENCIL_OP_REPLACE;
|
||||
dsa.stencil[0].zpass_op = PIPE_STENCIL_OP_REPLACE;
|
||||
dsa.stencil[0].valuemask = dsa.stencil[0].writemask;
|
||||
dsa.stencil[1].enabled = 0;
|
||||
memcpy(&dsa.depth, &ctx->state.g3d.dsa.depth,
|
||||
sizeof(struct pipe_depth_state));
|
||||
cso_set_depth_stencil_alpha(ctx->cso_context, &dsa);
|
||||
|
||||
/* render the quad to propagate the rendering from stencil */
|
||||
renderer_draw_quad(ctx->renderer, min_x, min_y,
|
||||
max_x, max_y, 0.0f/*depth should be disabled*/);
|
||||
|
||||
cso_restore_depth_stencil_alpha(ctx->cso_context);
|
||||
/* fill it */
|
||||
renderer_polygon_fill_begin(ctx->renderer, VG_FALSE);
|
||||
renderer_polygon_fill(ctx->renderer, min_x, min_y, max_x, max_y);
|
||||
renderer_polygon_fill_end(ctx->renderer);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -51,6 +51,8 @@ typedef enum {
|
|||
RENDERER_STATE_SCISSOR,
|
||||
RENDERER_STATE_CLEAR,
|
||||
RENDERER_STATE_FILTER,
|
||||
RENDERER_STATE_POLYGON_STENCIL,
|
||||
RENDERER_STATE_POLYGON_FILL,
|
||||
NUM_RENDERER_STATES
|
||||
} RendererState;
|
||||
|
||||
|
|
@ -103,6 +105,12 @@ struct renderer {
|
|||
VGboolean use_sampler;
|
||||
VGint tex_width, tex_height;
|
||||
} filter;
|
||||
|
||||
struct {
|
||||
struct pipe_depth_stencil_alpha_state dsa;
|
||||
VGboolean manual_two_sides;
|
||||
VGboolean restore_dsa;
|
||||
} polygon_stencil;
|
||||
} u;
|
||||
};
|
||||
|
||||
|
|
@ -837,6 +845,193 @@ void renderer_filter_end(struct renderer *renderer)
|
|||
renderer->state = RENDERER_STATE_INIT;
|
||||
}
|
||||
|
||||
/**
|
||||
* Prepare the renderer for polygon silhouette rendering.
|
||||
*/
|
||||
VGboolean renderer_polygon_stencil_begin(struct renderer *renderer,
|
||||
struct pipe_vertex_element *velem,
|
||||
VGFillRule rule,
|
||||
VGboolean restore_dsa)
|
||||
{
|
||||
struct pipe_depth_stencil_alpha_state *dsa;
|
||||
VGboolean manual_two_sides;
|
||||
|
||||
assert(renderer->state == RENDERER_STATE_INIT);
|
||||
|
||||
cso_save_blend(renderer->cso);
|
||||
cso_save_depth_stencil_alpha(renderer->cso);
|
||||
|
||||
cso_set_vertex_elements(renderer->cso, 1, velem);
|
||||
|
||||
/* disable color writes */
|
||||
renderer_set_blend(renderer, 0);
|
||||
|
||||
manual_two_sides = VG_FALSE;
|
||||
dsa = &renderer->u.polygon_stencil.dsa;
|
||||
memset(dsa, 0, sizeof(*dsa));
|
||||
if (rule == VG_EVEN_ODD) {
|
||||
dsa->stencil[0].enabled = 1;
|
||||
dsa->stencil[0].writemask = 1;
|
||||
dsa->stencil[0].fail_op = PIPE_STENCIL_OP_KEEP;
|
||||
dsa->stencil[0].zfail_op = PIPE_STENCIL_OP_KEEP;
|
||||
dsa->stencil[0].zpass_op = PIPE_STENCIL_OP_INVERT;
|
||||
dsa->stencil[0].func = PIPE_FUNC_ALWAYS;
|
||||
dsa->stencil[0].valuemask = ~0;
|
||||
}
|
||||
else {
|
||||
assert(rule == VG_NON_ZERO);
|
||||
|
||||
/* front face */
|
||||
dsa->stencil[0].enabled = 1;
|
||||
dsa->stencil[0].writemask = ~0;
|
||||
dsa->stencil[0].fail_op = PIPE_STENCIL_OP_KEEP;
|
||||
dsa->stencil[0].zfail_op = PIPE_STENCIL_OP_KEEP;
|
||||
dsa->stencil[0].zpass_op = PIPE_STENCIL_OP_INCR_WRAP;
|
||||
dsa->stencil[0].func = PIPE_FUNC_ALWAYS;
|
||||
dsa->stencil[0].valuemask = ~0;
|
||||
|
||||
if (renderer->pipe->screen->get_param(renderer->pipe->screen,
|
||||
PIPE_CAP_TWO_SIDED_STENCIL)) {
|
||||
/* back face */
|
||||
dsa->stencil[1] = dsa->stencil[0];
|
||||
dsa->stencil[1].zpass_op = PIPE_STENCIL_OP_DECR_WRAP;
|
||||
}
|
||||
else {
|
||||
manual_two_sides = VG_TRUE;
|
||||
}
|
||||
}
|
||||
cso_set_depth_stencil_alpha(renderer->cso, dsa);
|
||||
|
||||
if (manual_two_sides)
|
||||
cso_save_rasterizer(renderer->cso);
|
||||
|
||||
renderer->u.polygon_stencil.manual_two_sides = manual_two_sides;
|
||||
renderer->u.polygon_stencil.restore_dsa = restore_dsa;
|
||||
renderer->state = RENDERER_STATE_POLYGON_STENCIL;
|
||||
|
||||
return VG_TRUE;
|
||||
}
|
||||
|
||||
/**
|
||||
* Render a polygon silhouette to stencil buffer.
|
||||
*/
|
||||
void renderer_polygon_stencil(struct renderer *renderer,
|
||||
struct pipe_vertex_buffer *vbuf,
|
||||
VGuint mode, VGuint start, VGuint count)
|
||||
{
|
||||
assert(renderer->state == RENDERER_STATE_POLYGON_STENCIL);
|
||||
|
||||
renderer->pipe->set_vertex_buffers(renderer->pipe, 1, vbuf);
|
||||
|
||||
if (!renderer->u.polygon_stencil.manual_two_sides) {
|
||||
util_draw_arrays(renderer->pipe, mode, start, count);
|
||||
}
|
||||
else {
|
||||
struct pipe_rasterizer_state raster;
|
||||
struct pipe_depth_stencil_alpha_state dsa;
|
||||
|
||||
/* TODO do not access owner state */
|
||||
raster = renderer->owner->state.g3d.rasterizer;
|
||||
dsa = renderer->u.polygon_stencil.dsa;
|
||||
|
||||
/* front */
|
||||
raster.cull_face = PIPE_FACE_BACK;
|
||||
dsa.stencil[0].zpass_op = PIPE_STENCIL_OP_INCR_WRAP;
|
||||
|
||||
cso_set_rasterizer(renderer->cso, &raster);
|
||||
cso_set_depth_stencil_alpha(renderer->cso, &dsa);
|
||||
util_draw_arrays(renderer->pipe, mode, start, count);
|
||||
|
||||
/* back */
|
||||
raster.cull_face = PIPE_FACE_FRONT;
|
||||
dsa.stencil[0].zpass_op = PIPE_STENCIL_OP_DECR_WRAP;
|
||||
|
||||
cso_set_rasterizer(renderer->cso, &raster);
|
||||
cso_set_depth_stencil_alpha(renderer->cso, &dsa);
|
||||
util_draw_arrays(renderer->pipe, mode, start, count);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* End polygon silhouette rendering.
|
||||
*/
|
||||
void renderer_polygon_stencil_end(struct renderer *renderer)
|
||||
{
|
||||
assert(renderer->state == RENDERER_STATE_POLYGON_STENCIL);
|
||||
|
||||
if (renderer->u.polygon_stencil.manual_two_sides)
|
||||
cso_restore_rasterizer(renderer->cso);
|
||||
|
||||
/* restore color writes */
|
||||
cso_restore_blend(renderer->cso);
|
||||
|
||||
if (renderer->u.polygon_stencil.restore_dsa)
|
||||
cso_restore_depth_stencil_alpha(renderer->cso);
|
||||
|
||||
renderer->state = RENDERER_STATE_INIT;
|
||||
}
|
||||
|
||||
/**
|
||||
* Prepare the renderer for polygon filling.
|
||||
*/
|
||||
VGboolean renderer_polygon_fill_begin(struct renderer *renderer,
|
||||
VGboolean save_dsa)
|
||||
{
|
||||
struct pipe_depth_stencil_alpha_state dsa;
|
||||
struct pipe_stencil_ref sr;
|
||||
|
||||
assert(renderer->state == RENDERER_STATE_INIT);
|
||||
|
||||
if (save_dsa)
|
||||
cso_save_depth_stencil_alpha(renderer->cso);
|
||||
|
||||
/* only need a fixed 0. Rely on default or move it out at least? */
|
||||
memset(&sr, 0, sizeof(sr));
|
||||
cso_set_stencil_ref(renderer->cso, &sr);
|
||||
|
||||
/* setup stencil ops */
|
||||
memset(&dsa, 0, sizeof(dsa));
|
||||
dsa.stencil[0].enabled = 1;
|
||||
dsa.stencil[0].func = PIPE_FUNC_NOTEQUAL;
|
||||
dsa.stencil[0].fail_op = PIPE_STENCIL_OP_REPLACE;
|
||||
dsa.stencil[0].zfail_op = PIPE_STENCIL_OP_REPLACE;
|
||||
dsa.stencil[0].zpass_op = PIPE_STENCIL_OP_REPLACE;
|
||||
dsa.stencil[0].valuemask = ~0;
|
||||
dsa.stencil[0].writemask = ~0;
|
||||
/* TODO do not access owner state */
|
||||
dsa.depth = renderer->owner->state.g3d.dsa.depth;
|
||||
cso_set_depth_stencil_alpha(renderer->cso, &dsa);
|
||||
|
||||
renderer->state = RENDERER_STATE_POLYGON_FILL;
|
||||
|
||||
return VG_TRUE;
|
||||
}
|
||||
|
||||
/**
|
||||
* Fill a polygon.
|
||||
*/
|
||||
void renderer_polygon_fill(struct renderer *renderer,
|
||||
VGfloat min_x, VGfloat min_y,
|
||||
VGfloat max_x, VGfloat max_y)
|
||||
{
|
||||
assert(renderer->state == RENDERER_STATE_POLYGON_FILL);
|
||||
|
||||
renderer_quad_pos(renderer, min_x, min_y, max_x, max_y, VG_TRUE);
|
||||
renderer_quad_draw(renderer);
|
||||
}
|
||||
|
||||
/**
|
||||
* End polygon filling.
|
||||
*/
|
||||
void renderer_polygon_fill_end(struct renderer *renderer)
|
||||
{
|
||||
assert(renderer->state == RENDERER_STATE_POLYGON_FILL);
|
||||
|
||||
cso_restore_depth_stencil_alpha(renderer->cso);
|
||||
|
||||
renderer->state = RENDERER_STATE_INIT;
|
||||
}
|
||||
|
||||
static void setup_shaders(struct renderer *ctx)
|
||||
{
|
||||
struct pipe_context *pipe = ctx->pipe;
|
||||
|
|
|
|||
|
|
@ -37,6 +37,8 @@ struct pipe_resource;
|
|||
struct pipe_sampler_state;
|
||||
struct pipe_sampler_view;
|
||||
struct pipe_surface;
|
||||
struct pipe_vertex_element;
|
||||
struct pipe_vertex_buffer;
|
||||
|
||||
struct renderer *renderer_create(struct vg_context *owner);
|
||||
void renderer_destroy(struct renderer *);
|
||||
|
|
@ -94,6 +96,26 @@ void renderer_filter(struct renderer *renderer,
|
|||
|
||||
void renderer_filter_end(struct renderer *renderer);
|
||||
|
||||
VGboolean renderer_polygon_stencil_begin(struct renderer *renderer,
|
||||
struct pipe_vertex_element *velem,
|
||||
VGFillRule rule,
|
||||
VGboolean restore_dsa);
|
||||
|
||||
void renderer_polygon_stencil(struct renderer *renderer,
|
||||
struct pipe_vertex_buffer *vbuf,
|
||||
VGuint mode, VGuint start, VGuint count);
|
||||
|
||||
void renderer_polygon_stencil_end(struct renderer *renderer);
|
||||
|
||||
VGboolean renderer_polygon_fill_begin(struct renderer *renderer,
|
||||
VGboolean save_dsa);
|
||||
|
||||
void renderer_polygon_fill(struct renderer *renderer,
|
||||
VGfloat min_x, VGfloat min_y,
|
||||
VGfloat max_x, VGfloat max_y);
|
||||
|
||||
void renderer_polygon_fill_end(struct renderer *renderer);
|
||||
|
||||
void renderer_draw_quad(struct renderer *,
|
||||
VGfloat x1, VGfloat y1,
|
||||
VGfloat x2, VGfloat y2,
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue