gallium: fix some bitmap frag shader issues
authorBrian Paul <brian.paul@tungstengraphics.com>
Wed, 23 Apr 2008 00:38:37 +0000 (18:38 -0600)
committerBrian Paul <brian.paul@tungstengraphics.com>
Wed, 23 Apr 2008 00:43:05 +0000 (18:43 -0600)
If texturing happens to be enabled when glBitmap() is called, need to be
careful about choosing a sampler unit, etc.

src/mesa/state_tracker/st_cb_bitmap.c
src/mesa/state_tracker/st_cb_program.c
src/mesa/state_tracker/st_context.h
src/mesa/state_tracker/st_program.h

index 701d1e397e337622b533c78534466e45633f8b93..7752b40e8ba04c5af2a4f29a6026bf6d1acdda64 100644 (file)
@@ -105,7 +105,7 @@ struct bitmap_cache
  * This program will be combined with the user's fragment program.
  */
 static struct st_fragment_program *
-make_bitmap_fragment_program(GLcontext *ctx)
+make_bitmap_fragment_program(GLcontext *ctx, GLuint samplerIndex)
 {
    struct st_fragment_program *stfp;
    struct gl_program *p;
@@ -130,7 +130,7 @@ make_bitmap_fragment_program(GLcontext *ctx)
    p->Instructions[ic].DstReg.Index = 0;
    p->Instructions[ic].SrcReg[0].File = PROGRAM_INPUT;
    p->Instructions[ic].SrcReg[0].Index = FRAG_ATTRIB_TEX0;
-   p->Instructions[ic].TexSrcUnit = 0;
+   p->Instructions[ic].TexSrcUnit = samplerIndex;
    p->Instructions[ic].TexSrcTarget = TEXTURE_2D_INDEX;
    ic++;
 
@@ -148,7 +148,7 @@ make_bitmap_fragment_program(GLcontext *ctx)
 
    p->InputsRead = FRAG_BIT_TEX0;
    p->OutputsWritten = 0x0;
-   p->SamplersUsed = 0x1;  /* sampler 0 (bit 0) is used */
+   p->SamplersUsed = (1 << samplerIndex);
 
    stfp = (struct st_fragment_program *) p;
    stfp->Base.UsesKill = GL_TRUE;
@@ -158,6 +158,19 @@ make_bitmap_fragment_program(GLcontext *ctx)
 }
 
 
+static int
+find_free_bit(uint bitfield)
+{
+   int i;
+   for (i = 0; i < 32; i++) {
+      if ((bitfield & (1 << i)) == 0) {
+         return i;
+      }
+   }
+   return -1;
+}
+
+
 /**
  * Combine basic bitmap fragment program with the user-defined program.
  */
@@ -165,28 +178,26 @@ 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);
-   }
+   struct st_fragment_program *stfp = st->fp;
 
-   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.
+   if (!stfp->bitmap_program) {
+      /*
+       * Generate new program which is the user-defined program prefixed
+       * with the bitmap sampler/kill instructions.
        */
-      stfp = (struct st_fragment_program *)
-         _mesa_combine_programs(ctx,
-                                &st->bitmap.program->Base.Base,
-                                &st->fp->Base.Base);
+      struct st_fragment_program *bitmap_prog;
+      uint sampler;
 
+      sampler = find_free_bit(st->fp->Base.Base.SamplersUsed);
+      bitmap_prog = make_bitmap_fragment_program(ctx, sampler);
+
+      stfp->bitmap_program = (struct st_fragment_program *)
+         _mesa_combine_programs(ctx,
+                                &bitmap_prog->Base.Base, &stfp->Base.Base);
+      stfp->bitmap_program->bitmap_sampler = sampler;
 #if 0
       {
-         struct gl_program *p = &stfp->Base.Base;
+         struct gl_program *p = &stfp->bitmap_program->Base.Base;
          printf("Combined bitmap program:\n");
          _mesa_print_program(p);
          printf("InputsRead: 0x%x\n", p->InputsRead);
@@ -196,11 +207,7 @@ combined_bitmap_fragment_program(GLcontext *ctx)
 #endif
 
       /* translate to TGSI tokens */
-      st_translate_fragment_program(st, stfp, NULL);
-
-      /* save new program, update serial numbers */
-      st->bitmap.user_prog_sn = st->fp->serialNo;
-      st->bitmap.combined_prog = stfp;
+      st_translate_fragment_program(st, stfp->bitmap_program, NULL);
    }
 
    /* Ideally we'd have updated the pipe constants during the normal
@@ -208,7 +215,7 @@ combined_bitmap_fragment_program(GLcontext *ctx)
     */
    st_upload_constants(st, stfp->Base.Base.Parameters, PIPE_SHADER_FRAGMENT);
 
-   return stfp;
+   return stfp->bitmap_program;
 }
 
 
@@ -451,10 +458,25 @@ draw_bitmap_quad(GLcontext *ctx, GLint x, GLint y, GLfloat z,
    /* vertex shader state: position + texcoord pass-through */
    cso_set_vertex_shader_handle(cso, st->bitmap.vs);
 
-   /* sampler / texture state */
-   cso_single_sampler(cso, 0, &st->bitmap.sampler);
-   cso_single_sampler_done(cso);
-   pipe->set_sampler_textures(pipe, 1, &pt);
+   /* user samplers, plus our bitmap sampler */
+   {
+      struct pipe_sampler_state *samplers[PIPE_MAX_SAMPLERS];
+      uint num = MAX2(stfp->bitmap_sampler + 1, st->state.num_samplers);
+      uint i;
+      for (i = 0; i < st->state.num_samplers; i++) {
+         samplers[i] = &st->state.samplers[i];
+      }
+      samplers[stfp->bitmap_sampler] = &st->bitmap.sampler;
+      cso_set_samplers(cso, num, (const struct pipe_sampler_state **) samplers);   }
+
+   /* user textures, plus the bitmap texture */
+   {
+      struct pipe_texture *textures[PIPE_MAX_SAMPLERS];
+      uint num = MAX2(stfp->bitmap_sampler + 1, st->state.num_textures);
+      memcpy(textures, st->state.sampler_texture, sizeof(textures));
+      textures[stfp->bitmap_sampler] = pt;
+      cso_set_sampler_textures(cso, num, textures);
+   }
 
    /* viewport state: viewport matching window dims */
    {
@@ -771,6 +793,7 @@ st_destroy_bitmap(struct st_context *st)
 {
    struct pipe_context *pipe = st->pipe;
 
+#if 0
    if (st->bitmap.combined_prog) {
       st_delete_program(st->ctx, &st->bitmap.combined_prog->Base.Base);
    }
@@ -778,7 +801,7 @@ st_destroy_bitmap(struct st_context *st)
    if (st->bitmap.program) {
       st_delete_program(st->ctx, &st->bitmap.program->Base.Base);
    }
-
+#endif
    if (st->bitmap.vs) {
       pipe->delete_vs_state(pipe, st->bitmap.vs);
       st->bitmap.vs = NULL;
index 003ec0d2b793b250ccf367ccf2799139e5a656ea..67f8b1f8ebbc89057292f9dca2da297f7f4bf57f 100644 (file)
@@ -159,6 +159,10 @@ st_delete_program(GLcontext *ctx, struct gl_program *prog)
             stfp->state.tokens = NULL;
          }
 
+         if (stfp->bitmap_program) {
+            st_delete_program(ctx, &stfp->bitmap_program->Base.Base);
+         }
+
          st_free_translated_vertex_programs(st, stfp->vertex_programs);
       }
       break;
index ae1ba41d4fb5faea31475180203257b2d84716a1..2851770d4cae3cf0dfe7f6b33e5c8cb8681c196a 100644 (file)
@@ -144,9 +144,6 @@ struct st_context
 
    /** for glBitmap */
    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;
       struct pipe_rasterizer_state rasterizer;
       struct pipe_sampler_state sampler;
       struct pipe_shader_state vert_shader;
index e58b8a185159afc969661e833dd772fa6730f3a1..1a2062131d03eb1ab51c3aede20b7080d453e98c 100644 (file)
@@ -69,6 +69,10 @@ struct st_fragment_program
     * outputs match this fragment program's inputs.
     */
    struct translated_vertex_program *vertex_programs;
+
+   /** Program prefixed with glBitmap prologue */
+   struct st_fragment_program *bitmap_program;
+   uint bitmap_sampler;
 };