util: add version of u_blit_pixels which takes a writemask
authorKeith Whitwell <keithw@vmware.com>
Wed, 2 Sep 2009 16:58:52 +0000 (17:58 +0100)
committerKeith Whitwell <keithw@vmware.com>
Wed, 2 Sep 2009 17:31:48 +0000 (18:31 +0100)
Values outside the writemask are set in the destination to {0,0,0,1}

src/gallium/auxiliary/util/u_blit.c
src/gallium/auxiliary/util/u_blit.h
src/gallium/auxiliary/util/u_simple_shaders.c
src/gallium/auxiliary/util/u_simple_shaders.h

index cda6dbd46d76d06bae88e45ba79ec9c66bb6c993..c516317d701113638fa362f64cfa040daf6c70f1 100644 (file)
@@ -62,7 +62,7 @@ struct blit_state
    struct pipe_viewport_state viewport;
 
    void *vs;
-   void *fs;
+   void *fs[TGSI_WRITEMASK_XYZW + 1];
 
    struct pipe_buffer *vbuf;  /**< quad vertices */
    unsigned vbuf_slot;
@@ -125,7 +125,7 @@ util_create_blit(struct pipe_context *pipe, struct cso_context *cso)
    }
 
    /* fragment shader */
-   ctx->fs = util_make_fragment_tex_shader(pipe);
+   ctx->fs[TGSI_WRITEMASK_XYZW] = util_make_fragment_tex_shader(pipe);
    ctx->vbuf = NULL;
 
    /* init vertex data that doesn't change */
@@ -146,9 +146,13 @@ void
 util_destroy_blit(struct blit_state *ctx)
 {
    struct pipe_context *pipe = ctx->pipe;
+   unsigned i;
 
    pipe->delete_vs_state(pipe, ctx->vs);
-   pipe->delete_fs_state(pipe, ctx->fs);
+
+   for (i = 0; i < Elements(ctx->fs); i++)
+      if (ctx->fs[i])
+         pipe->delete_fs_state(pipe, ctx->fs[i]);
 
    pipe_buffer_reference(&ctx->vbuf, NULL);
 
@@ -299,14 +303,15 @@ regions_overlap(int srcX0, int srcY0,
  * XXX need some control over blitting Z and/or stencil.
  */
 void
-util_blit_pixels(struct blit_state *ctx,
-                 struct pipe_surface *src,
-                 int srcX0, int srcY0,
-                 int srcX1, int srcY1,
-                 struct pipe_surface *dst,
-                 int dstX0, int dstY0,
-                 int dstX1, int dstY1,
-                 float z, uint filter)
+util_blit_pixels_writemask(struct blit_state *ctx,
+                           struct pipe_surface *src,
+                           int srcX0, int srcY0,
+                           int srcX1, int srcY1,
+                           struct pipe_surface *dst,
+                           int dstX0, int dstY0,
+                           int dstX1, int dstY1,
+                           float z, uint filter,
+                           uint writemask)
 {
    struct pipe_context *pipe = ctx->pipe;
    struct pipe_screen *screen = pipe->screen;
@@ -426,8 +431,11 @@ util_blit_pixels(struct blit_state *ctx,
    /* texture */
    cso_set_sampler_textures(ctx->cso, 1, &tex);
 
+   if (ctx->fs[writemask] == NULL)
+      ctx->fs[writemask] = util_make_fragment_tex_shader_writemask(pipe, writemask);
+
    /* shaders */
-   cso_set_fragment_shader_handle(ctx->cso, ctx->fs);
+   cso_set_fragment_shader_handle(ctx->cso, ctx->fs[writemask]);
    cso_set_vertex_shader_handle(ctx->cso, ctx->vs);
 
    /* drawing dest */
@@ -462,6 +470,27 @@ util_blit_pixels(struct blit_state *ctx,
 }
 
 
+void
+util_blit_pixels(struct blit_state *ctx,
+                 struct pipe_surface *src,
+                 int srcX0, int srcY0,
+                 int srcX1, int srcY1,
+                 struct pipe_surface *dst,
+                 int dstX0, int dstY0,
+                 int dstX1, int dstY1,
+                 float z, uint filter )
+{
+   util_blit_pixels_writemask( ctx, src, 
+                               srcX0, srcY0,
+                               srcX1, srcY1,
+                               dst,
+                               dstX0, dstY0,
+                               dstX1, dstY1,
+                               z, filter,
+                               TGSI_WRITEMASK_XYZW );
+}
+
+
 /* Release vertex buffer at end of frame to avoid synchronous
  * rendering.
  */
@@ -535,7 +564,7 @@ util_blit_pixels_tex(struct blit_state *ctx,
    cso_set_sampler_textures(ctx->cso, 1, &tex);
 
    /* shaders */
-   cso_set_fragment_shader_handle(ctx->cso, ctx->fs);
+   cso_set_fragment_shader_handle(ctx->cso, ctx->fs[TGSI_WRITEMASK_XYZW]);
    cso_set_vertex_shader_handle(ctx->cso, ctx->vs);
 
    /* drawing dest */
index c35beceda8d64e986c847a61b29382ff573df565..a102021529e8209e42e1f4070a2c7b6e3bc97b94 100644 (file)
@@ -60,6 +60,17 @@ util_blit_pixels(struct blit_state *ctx,
                  int dstX1, int dstY1,
                  float z, uint filter);
 
+void
+util_blit_pixels_writemask(struct blit_state *ctx,
+                           struct pipe_surface *src,
+                           int srcX0, int srcY0,
+                           int srcX1, int srcY1,
+                           struct pipe_surface *dst,
+                           int dstX0, int dstY0,
+                           int dstX1, int dstY1,
+                           float z, uint filter,
+                           uint writemask);
+
 extern void
 util_blit_pixels_tex(struct blit_state *ctx,
                      struct pipe_texture *tex,
index e519c354d257de372b2794bb26e26d7798a913ea..acc5b83c622ca18cb4f7373ab891857b3d359333 100644 (file)
@@ -152,11 +152,14 @@ util_make_vertex_passthrough_shader(struct pipe_context *pipe,
 
 /**
  * Make simple fragment texture shader:
- *  TEX OUT[0], IN[0], SAMP[0], 2D;
+ *  IMM {0,0,0,1}                         // (if writemask != 0xf)
+ *  MOV OUT[0], IMM[0]                    // (if writemask != 0xf)
+ *  TEX OUT[0].writemask, IN[0], SAMP[0], 2D;
  *  END;
  */
 void *
-util_make_fragment_tex_shader(struct pipe_context *pipe)
+util_make_fragment_tex_shader_writemask(struct pipe_context *pipe,
+                                        unsigned writemask )
 {
    struct pipe_shader_state shader;
    struct tgsi_token tokens[100];
@@ -217,12 +220,43 @@ util_make_fragment_tex_shader(struct pipe_context *pipe)
                                      header,
                                      Elements(tokens) - ti);
 
+
+   if (writemask != TGSI_WRITEMASK_XYZW) {
+      struct tgsi_full_immediate imm;
+      static const float value[4] = { 0, 0, 0, 1 };
+
+      imm = tgsi_default_full_immediate();
+      imm.Immediate.NrTokens += 4;
+      imm.Immediate.DataType = TGSI_IMM_FLOAT32;
+      imm.u.Pointer = value;
+
+      ti += tgsi_build_full_immediate(&imm,
+                                      &tokens[ti],
+                                      header,
+                                      Elements(tokens) - ti );
+
+      /* MOV instruction */
+      inst = tgsi_default_full_instruction();
+      inst.Instruction.Opcode = TGSI_OPCODE_MOV;
+      inst.Instruction.NumDstRegs = 1;
+      inst.FullDstRegisters[0].DstRegister.File = TGSI_FILE_OUTPUT;
+      inst.FullDstRegisters[0].DstRegister.Index = 0;
+      inst.Instruction.NumSrcRegs = 1;
+      inst.FullSrcRegisters[0].SrcRegister.File = TGSI_FILE_IMMEDIATE;
+      inst.FullSrcRegisters[0].SrcRegister.Index = 0;
+      ti += tgsi_build_full_instruction(&inst,
+                                        &tokens[ti],
+                                        header,
+                                        Elements(tokens) - ti );
+   }
+
    /* TEX instruction */
    inst = tgsi_default_full_instruction();
    inst.Instruction.Opcode = TGSI_OPCODE_TEX;
    inst.Instruction.NumDstRegs = 1;
    inst.FullDstRegisters[0].DstRegister.File = TGSI_FILE_OUTPUT;
    inst.FullDstRegisters[0].DstRegister.Index = 0;
+   inst.FullDstRegisters[0].DstRegister.WriteMask = writemask;
    inst.Instruction.NumSrcRegs = 2;
    inst.InstructionExtTexture.Texture = TGSI_TEXTURE_2D;
    inst.FullSrcRegisters[0].SrcRegister.File = TGSI_FILE_INPUT;
@@ -253,6 +287,13 @@ util_make_fragment_tex_shader(struct pipe_context *pipe)
    return pipe->create_fs_state(pipe, &shader);
 }
 
+void *
+util_make_fragment_tex_shader(struct pipe_context *pipe )
+{
+   return util_make_fragment_tex_shader_writemask( pipe,
+                                                   TGSI_WRITEMASK_XYZW );
+}
+
 
 
 
index 6f8d96af9bcbf17526ce8032b20f915e373f64b8..d2e80d6eb4d1dcaf9c63ec09bd36288fc8d3200e 100644 (file)
@@ -49,6 +49,10 @@ util_make_vertex_passthrough_shader(struct pipe_context *pipe,
                                     const uint *semantic_indexes);
 
 
+extern void *
+util_make_fragment_tex_shader_writemask(struct pipe_context *pipe, 
+                                        unsigned writemask );
+
 extern void *
 util_make_fragment_tex_shader(struct pipe_context *pipe);