Implement shader concatenation for glBitmap.
authorBrian <brian.paul@tungstengraphics.com>
Wed, 31 Oct 2007 00:38:32 +0000 (18:38 -0600)
committerBrian <brian.paul@tungstengraphics.com>
Wed, 31 Oct 2007 00:38:32 +0000 (18:38 -0600)
src/mesa/state_tracker/st_cb_drawpixels.c
src/mesa/state_tracker/st_context.h

index 1864d65ee8bd6a3698bdfa0cc55a35786b8ae935..ffaa34d7d31e12e602dc613c0f76cd7b73d9cfeb 100644 (file)
 
 
 /**
- * Create a simple fragment shader that does a TEX() instruction to get
- * the fragment color.
- * If bitmapMode, use KIL instruction to kill the "0-pixels".
+ * Make fragment program for glBitmap:
+ *   Sample the texture and kill the fragment if the bit is 0.
+ * This program will be combined with the user's fragment program.
  */
 static struct st_fragment_program *
-make_bitmap_fragment_shader(struct st_context *st)
+make_bitmap_fragment_program(GLcontext *ctx)
 {
-   /* only make programs once and re-use */
-   static struct st_fragment_program *prog = NULL;
-   GLcontext *ctx = st->ctx;
    struct st_fragment_program *stfp;
    struct gl_program *p;
    GLuint ic = 0;
 
-   if (prog)
-      return prog;
-
    p = ctx->Driver.NewProgram(ctx, GL_FRAGMENT_PROGRAM_ARB, 0);
    if (!p)
       return NULL;
 
-   p->NumInstructions = 6;
+   p->NumInstructions = 5;
 
    p->Instructions = _mesa_alloc_instructions(p->NumInstructions);
    if (!p->Instructions) {
@@ -89,11 +83,6 @@ make_bitmap_fragment_shader(struct st_context *st)
    }
    _mesa_init_instructions(p->Instructions, p->NumInstructions);
 
-   /*
-    * XXX, we need to compose this fragment shader with the current
-    * user-provided fragment shader so the fragment program is applied
-    * to the fragments which aren't culled.
-    */
    /* TEX tmp0, fragment.texcoord[0], texture[0], 2D; */
    p->Instructions[ic].Opcode = OPCODE_TEX;
    p->Instructions[ic].DstReg.File = PROGRAM_TEMPORARY;
@@ -133,34 +122,84 @@ make_bitmap_fragment_shader(struct st_context *st)
    p->Instructions[ic].SrcReg[0].Index = 0;
    ic++;
 
-   /* MOV result.color, fragment.color */
-   p->Instructions[ic].Opcode = OPCODE_MOV;
-   p->Instructions[ic].DstReg.File = PROGRAM_OUTPUT;
-   p->Instructions[ic].DstReg.Index = FRAG_RESULT_COLR;
-   p->Instructions[ic].SrcReg[0].File = PROGRAM_INPUT;
-   p->Instructions[ic].SrcReg[0].Index = FRAG_ATTRIB_COL0;
-   ic++;
-
    /* END; */
    p->Instructions[ic++].Opcode = OPCODE_END;
 
    assert(ic == p->NumInstructions);
 
-   p->InputsRead = FRAG_BIT_TEX0 | FRAG_BIT_COL0;
-   p->OutputsWritten = (1 << FRAG_RESULT_COLR);
+   p->InputsRead = FRAG_BIT_TEX0;
+   p->OutputsWritten = 0x0;
 
    stfp = (struct st_fragment_program *) p;
-   st_translate_fragment_program(st, stfp, NULL,
+   st_translate_fragment_program(ctx->st, stfp, NULL,
                                  stfp->tokens, ST_MAX_SHADER_TOKENS);
 
-   prog = stfp;
+   return stfp;
+}
+
+
+/**
+ * Combine basic bitmap fragment program with the user-defined program.
+ */
+static struct st_fragment_program *
+combined_bitmap_fragment_program(GLcontext *ctx)
+{
+   struct st_context *st = ctx->st;
+   struct st_fragment_program *stfp;
+
+   if (!st->bitmap.program) {
+      /* create the basic bitmap fragment program */
+      st->bitmap.program = make_bitmap_fragment_program(ctx);
+   }
+
+   if (st->bitmap.user_prog_sn == st->fp->serialNo) {
+      /* re-use */
+      stfp = st->bitmap.combined_prog;
+   }
+   else {
+      /* Concatenate the bitmap program with the current user-defined program.
+       */
+      stfp = (struct st_fragment_program *)
+         _mesa_combine_programs(ctx,
+                                &st->bitmap.program->Base.Base,
+                                &st->fp->Base.Base);
+
+#if 0
+      {
+         struct gl_program *p = &stfp->Base.Base;
+         printf("Combined bitmap program:\n");
+         _mesa_print_program(p);
+         printf("InputsRead: 0x%x\n", p->InputsRead);
+         printf("OutputsWritten: 0x%x\n", p->OutputsWritten);
+         _mesa_print_parameter_list(p->Parameters);
+      }
+#endif
+
+      /* translate to TGSI tokens */
+      st_translate_fragment_program(st, stfp, NULL,
+                                    stfp->tokens, ST_MAX_SHADER_TOKENS);
+
+      /* save new program, update serial numbers */
+      st->bitmap.user_prog_sn = st->fp->serialNo;
+      st->bitmap.combined_prog = stfp;
+   }
+
+   /* Ideally we'd have updated the pipe constants during the normal
+    * st/atom mechanism.  But we can't since this is specific to glBitmap.
+    */
+   st_upload_constants(st, stfp->Base.Base.Parameters, PIPE_SHADER_FRAGMENT);
 
    return stfp;
 }
 
 
+
+/**
+ * Make fragment shader for glDraw/CopyPixels.  This shader is made
+ * by combining the pixel transfer shader with the user-defined shader.
+ */
 static struct st_fragment_program *
-make_drawpix_fragment_shader(GLcontext *ctx)
+combined_drawpix_fragment_program(GLcontext *ctx)
 {
    struct st_context *st = ctx->st;
    struct st_fragment_program *stfp;
@@ -168,13 +207,13 @@ make_drawpix_fragment_shader(GLcontext *ctx)
    if (st->pixel_xfer.program->serialNo == st->pixel_xfer.xfer_prog_sn
        && st->fp->serialNo == st->pixel_xfer.user_prog_sn) {
       /* the pixel tranfer program has not changed and the user-defined
-       * shader has not changed, so re-use the combined program.
+       * program has not changed, so re-use the combined program.
        */
       stfp = st->pixel_xfer.combined_prog;
    }
    else {
       /* Concatenate the pixel transfer program with the current user-
-       * defined shader.
+       * defined program.
        */
       stfp = (struct st_fragment_program *)
          _mesa_combine_programs(ctx,
@@ -241,7 +280,7 @@ make_fragment_shader_z(struct st_context *st)
    }
    _mesa_init_instructions(p->Instructions, p->NumInstructions);
 
-   /* TEX result.color, fragment.texcoord[0], texture[0], 2D; */
+   /* TEX result.depth, fragment.texcoord[0], texture[0], 2D; */
    p->Instructions[ic].Opcode = OPCODE_TEX;
    p->Instructions[ic].DstReg.File = PROGRAM_OUTPUT;
    p->Instructions[ic].DstReg.Index = FRAG_RESULT_DEPR;
@@ -945,7 +984,7 @@ st_DrawPixels(GLcontext *ctx, GLint x, GLint y, GLsizei width, GLsizei height,
    }
    else {
       ps = st->state.framebuffer.cbufs[0];
-      stfp = make_drawpix_fragment_shader(ctx);
+      stfp = combined_drawpix_fragment_program(ctx);
       stvp = make_vertex_shader(ctx->st, GL_FALSE);
       color = NULL;
    }
@@ -1122,16 +1161,13 @@ static void
 st_Bitmap(GLcontext *ctx, GLint x, GLint y, GLsizei width, GLsizei height,
           const struct gl_pixelstore_attrib *unpack, const GLubyte *bitmap )
 {
-   struct st_vertex_program *stvp;
    struct st_fragment_program *stfp;
+   struct st_vertex_program *stvp;
    struct st_context *st = ctx->st;
    struct pipe_mipmap_tree *mt;
 
-   /* create the fragment program */
-   stfp = make_bitmap_fragment_shader(ctx->st);
-
-   /* and vertex program */
    stvp = make_vertex_shader(ctx->st, GL_TRUE);
+   stfp = combined_bitmap_fragment_program(ctx);
 
    st_validate_state(st);
 
@@ -1248,7 +1284,7 @@ st_CopyPixels(GLcontext *ctx, GLint srcx, GLint srcy,
    if (type == GL_COLOR) {
       rbRead = st_renderbuffer(ctx->ReadBuffer->_ColorReadBuffer);
       color = NULL;
-      stfp = make_drawpix_fragment_shader(ctx);
+      stfp = combined_drawpix_fragment_program(ctx);
       stvp = make_vertex_shader(ctx->st, GL_FALSE);
    }
    else {
index 8bbfb0d6fecd5aa7dc09139f415274e3cd5c1578..7ab69df7c7bf17fb0694bb832c95e7a403b70d9d 100644 (file)
@@ -142,6 +142,12 @@ struct st_context
       GLuint combined_prog_sn;
    } pixel_xfer;
 
+   struct {
+      struct st_fragment_program *program;  /**< bitmap tex/kil program */
+      GLuint user_prog_sn;  /**< user fragment program serial no. */
+      struct st_fragment_program *combined_prog;
+   } bitmap;
+
    /**
     * Buffer object which stores the ctx->Current.Attrib[] values.
     * Used for vertex array drawing when we we need an attribute for