st/vega: Add POLYGON_STENCIL and POLYGON_FILL renderer state.
authorChia-I Wu <olv@lunarg.com>
Sat, 27 Nov 2010 07:04:30 +0000 (15:04 +0800)
committerChia-I Wu <olv@lunarg.com>
Wed, 1 Dec 2010 03:23:49 +0000 (11:23 +0800)
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.

src/gallium/state_trackers/vega/polygon.c
src/gallium/state_trackers/vega/renderer.c
src/gallium/state_trackers/vega/renderer.h

index ca8831064c919ed6db9554754ed667e8455aaaac..a491de27fa675613c9197f6263a3ab389eece1cc 100644 (file)
@@ -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);
-
-   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);
-
-   cso_save_blend(ctx->cso_context);
-   cso_save_depth_stencil_alpha(ctx->cso_context);
-
-   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;
-
-      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);
-      }
-   }
+   polygon_prepare_buffer(ctx, poly);
+
+   /* 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;
+
+   /* 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;
+
+   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);
 
-   /* 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);
-
-   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);
-
-   cso_save_blend(ctx->cso_context);
-   cso_save_depth_stencil_alpha(ctx->cso_context);
-
-   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;
-
-      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);
-      }
+   /* 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;
+
+   /* tell renderer about the vertex buffer */
+   memset(&vbuffer, 0, sizeof(vbuffer));
+   vbuffer.stride = COMPONENTS * sizeof(float);  /* vertex size */
+   vbuffer.buffer_offset = 0;
+
+   /* 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]);
+
+      polygon_prepare_buffer(ctx, poly);
+      vbuffer.buffer = poly->vbuf;
+      vbuffer.max_index = poly->num_verts - 1;
+
+      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);
 }
index e14eb4706e472cac8cc218bcc343b5306ae4dcad..7543fa1d41ad8debc208057cabb04a21356e3065 100644 (file)
@@ -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;
index 288c17f9c893216c5403271c11262b5d17ea69e6..8d13c02f3bea7fca6344d013159b1cf07db10e9f 100644 (file)
@@ -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,