OSDN Git Service

st/vega: Add SCISSOR renderer state.
authorChia-I Wu <olv@lunarg.com>
Fri, 26 Nov 2010 14:49:20 +0000 (22:49 +0800)
committerChia-I Wu <olv@lunarg.com>
Wed, 1 Dec 2010 03:23:49 +0000 (11:23 +0800)
The state can be used to set rectangles of the depth buffer to 0.0f.
update_clip_state is changed to use the state for scissor update.

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

index 179b6f6..60c4315 100644 (file)
@@ -47,6 +47,7 @@ typedef enum {
    RENDERER_STATE_INIT,
    RENDERER_STATE_COPY,
    RENDERER_STATE_DRAWTEX,
+   RENDERER_STATE_SCISSOR,
    NUM_RENDERER_STATES
 } RendererState;
 
@@ -60,6 +61,7 @@ typedef enum {
 typedef enum {
    RENDERER_FS_COLOR,
    RENDERER_FS_TEXTURE,
+   RENDERER_FS_SCISSOR,
    NUM_RENDERER_FS
 } RendererFs;
 
@@ -89,6 +91,10 @@ struct renderer {
          VGint tex_width;
          VGint tex_height;
       } drawtex;
+
+      struct {
+         VGboolean restore_dsa;
+      } scissor;
    } u;
 };
 
@@ -175,6 +181,25 @@ static void renderer_set_vs(struct renderer *r, RendererVs id)
 }
 
 /**
+ * Create a simple fragment shader that sets the depth to 0.0f.
+ */
+static void *create_scissor_fs(struct pipe_context *pipe)
+{
+   struct ureg_program *ureg;
+   struct ureg_dst out;
+   struct ureg_src imm;
+
+   ureg = ureg_create(TGSI_PROCESSOR_FRAGMENT);
+   out = ureg_DECL_output(ureg, TGSI_SEMANTIC_POSITION, 0);
+   imm = ureg_imm4f(ureg, 0.0f, 0.0f, 0.0f, 0.0f);
+
+   ureg_MOV(ureg, ureg_writemask(out, TGSI_WRITEMASK_Z), imm);
+   ureg_END(ureg);
+
+   return ureg_create_shader_and_destroy(ureg, pipe);
+}
+
+/**
  * Set renderer fragment shader.
  *
  * This function modifies fragment_shader state.
@@ -193,6 +218,9 @@ static void renderer_set_fs(struct renderer *r, RendererFs id)
          fs = util_make_fragment_tex_shader(r->pipe,
                TGSI_TEXTURE_2D, TGSI_INTERPOLATE_LINEAR);
          break;
+      case RENDERER_FS_SCISSOR:
+         fs = create_scissor_fs(r->pipe);
+         break;
       default:
          assert(!"Unknown renderer fs id");
          break;
@@ -530,6 +558,71 @@ void renderer_drawtex_end(struct renderer *renderer)
    renderer->state = RENDERER_STATE_INIT;
 }
 
+/**
+ * Prepare the renderer for scissor update.  This will reset the depth buffer
+ * to 1.0f.
+ */
+VGboolean renderer_scissor_begin(struct renderer *renderer,
+                                 VGboolean restore_dsa)
+{
+   struct pipe_depth_stencil_alpha_state dsa;
+
+   assert(renderer->state == RENDERER_STATE_INIT);
+
+   if (restore_dsa)
+      cso_save_depth_stencil_alpha(renderer->cso);
+   cso_save_blend(renderer->cso);
+   cso_save_fragment_shader(renderer->cso);
+
+   /* enable depth writes */
+   memset(&dsa, 0, sizeof(dsa));
+   dsa.depth.enabled = 1;
+   dsa.depth.writemask = 1;
+   dsa.depth.func = PIPE_FUNC_ALWAYS;
+   cso_set_depth_stencil_alpha(renderer->cso, &dsa);
+
+   /* disable color writes */
+   renderer_set_blend(renderer, 0);
+   renderer_set_fs(renderer, RENDERER_FS_SCISSOR);
+
+   renderer->u.scissor.restore_dsa = restore_dsa;
+   renderer->state = RENDERER_STATE_SCISSOR;
+
+   /* clear the depth buffer to 1.0f */
+   renderer->pipe->clear(renderer->pipe,
+         PIPE_CLEAR_DEPTHSTENCIL, NULL, 1.0f, 0);
+
+   return VG_TRUE;
+}
+
+/**
+ * Add a scissor rectangle.  Depth values inside the rectangle will be set to
+ * 0.0f.
+ */
+void renderer_scissor(struct renderer *renderer,
+                      VGint x, VGint y, VGint width, VGint height)
+{
+   assert(renderer->state == RENDERER_STATE_SCISSOR);
+
+   renderer_quad_pos(renderer, x, y, x + width, y + height, VG_FALSE);
+   renderer_quad_draw(renderer);
+}
+
+/**
+ * End scissor update and restore the states.
+ */
+void renderer_scissor_end(struct renderer *renderer)
+{
+   assert(renderer->state == RENDERER_STATE_SCISSOR);
+
+   if (renderer->u.scissor.restore_dsa)
+      cso_restore_depth_stencil_alpha(renderer->cso);
+   cso_restore_blend(renderer->cso);
+   cso_restore_fragment_shader(renderer->cso);
+
+   renderer->state = RENDERER_STATE_INIT;
+}
+
 static void setup_shaders(struct renderer *ctx)
 {
    struct pipe_context *pipe = ctx->pipe;
index cc9e3dd..2644c9f 100644 (file)
@@ -60,6 +60,14 @@ void renderer_drawtex(struct renderer *renderer,
 
 void renderer_drawtex_end(struct renderer *renderer);
 
+VGboolean renderer_scissor_begin(struct renderer *renderer,
+                                 VGboolean restore_dsa);
+
+void renderer_scissor(struct renderer *renderer,
+                      VGint x, VGint y, VGint width, VGint height);
+
+void renderer_scissor_end(struct renderer *renderer);
+
 void renderer_draw_quad(struct renderer *,
                         VGfloat x1, VGfloat y1,
                         VGfloat x2, VGfloat y2,
index bd82a81..d534783 100644 (file)
@@ -44,6 +44,7 @@
 #include "util/u_memory.h"
 #include "util/u_blit.h"
 #include "util/u_sampler.h"
+#include "util/u_math.h"
 
 struct vg_context *_vg_context = 0;
 
@@ -276,65 +277,40 @@ static void update_clip_state(struct vg_context *ctx)
    memset(dsa, 0, sizeof(struct pipe_depth_stencil_alpha_state));
 
    if (state->scissoring) {
-      struct pipe_blend_state *blend = &ctx->state.g3d.blend;
       struct pipe_framebuffer_state *fb = &ctx->state.g3d.fb;
       int i;
 
-      dsa->depth.writemask = 1;/*glDepthMask(TRUE);*/
-      dsa->depth.func = PIPE_FUNC_ALWAYS;
-      dsa->depth.enabled = 1;
-
-      cso_save_blend(ctx->cso_context);
-      cso_save_fragment_shader(ctx->cso_context);
-      /* set a passthrough shader */
-      if (!ctx->pass_through_depth_fs)
-         ctx->pass_through_depth_fs = shader_create_from_text(ctx->pipe,
-                                                              pass_through_depth_asm,
-                                                              40,
-                                                              PIPE_SHADER_FRAGMENT);
-      cso_set_fragment_shader_handle(ctx->cso_context,
-                                     ctx->pass_through_depth_fs->driver);
-      cso_set_depth_stencil_alpha(ctx->cso_context, dsa);
-
-      ctx->pipe->clear(ctx->pipe, PIPE_CLEAR_DEPTHSTENCIL, NULL, 1.0, 0);
-
-      /* disable color writes */
-      blend->rt[0].colormask = 0; /*disable colorwrites*/
-      cso_set_blend(ctx->cso_context, blend);
-
-      /* enable scissoring */
+      renderer_scissor_begin(ctx->renderer, VG_FALSE);
+
       for (i = 0; i < state->scissor_rects_num; ++i) {
          const float x      = state->scissor_rects[i * 4 + 0].f;
          const float y      = state->scissor_rects[i * 4 + 1].f;
          const float width  = state->scissor_rects[i * 4 + 2].f;
          const float height = state->scissor_rects[i * 4 + 3].f;
-         VGfloat minx, miny, maxx, maxy;
-
-         minx = 0;
-         miny = 0;
-         maxx = fb->width;
-         maxy = fb->height;
-
-         if (x > minx)
-            minx = x;
-         if (y > miny)
-            miny = y;
-
-         if (x + width < maxx)
-            maxx = x + width;
-         if (y + height < maxy)
-            maxy = y + height;
-
-         /* check for null space */
-         if (minx >= maxx || miny >= maxy)
-            minx = miny = maxx = maxy = 0;
-
-         /*glClear(GL_DEPTH_BUFFER_BIT);*/
-         renderer_draw_quad(ctx->renderer, minx, miny, maxx, maxy, 0.0f);
+         VGint x0, y0, x1, y1, iw, ih;
+
+         x0 = (VGint) x;
+         y0 = (VGint) y;
+         if (x0 < 0)
+            x0 = 0;
+         if (y0 < 0)
+            y0 = 0;
+
+         /* note that x1 and y1 are exclusive */
+         x1 = (VGint) ceilf(x + width);
+         y1 = (VGint) ceilf(y + height);
+         if (x1 > fb->width)
+            x1 = fb->width;
+         if (y1 > fb->height)
+            y1 = fb->height;
+
+         iw = x1 - x0;
+         ih = y1 - y0;
+         if (iw > 0 && ih> 0 )
+            renderer_scissor(ctx->renderer, x0, y0, iw, ih);
       }
 
-      cso_restore_blend(ctx->cso_context);
-      cso_restore_fragment_shader(ctx->cso_context);
+      renderer_scissor_end(ctx->renderer);
 
       dsa->depth.enabled = 1; /* glEnable(GL_DEPTH_TEST); */
       dsa->depth.writemask = 0;/*glDepthMask(FALSE);*/