diff options
Diffstat (limited to 'src/mesa/state_tracker')
24 files changed, 434 insertions, 700 deletions
| diff --git a/src/mesa/state_tracker/st_atom.c b/src/mesa/state_tracker/st_atom.c index 0e89a624c4..73df44d198 100644 --- a/src/mesa/state_tracker/st_atom.c +++ b/src/mesa/state_tracker/st_atom.c @@ -46,7 +46,8 @@ static const struct st_tracked_state *atoms[] =     &st_update_clip,     &st_finalize_textures, -   &st_update_shader, +   &st_update_fp, +   &st_update_vp,     &st_update_rasterizer,     &st_update_polygon_stipple, diff --git a/src/mesa/state_tracker/st_atom.h b/src/mesa/state_tracker/st_atom.h index c7cffd85c8..f34b49203b 100644 --- a/src/mesa/state_tracker/st_atom.h +++ b/src/mesa/state_tracker/st_atom.h @@ -47,7 +47,8 @@ void st_validate_state( struct st_context *st );  extern const struct st_tracked_state st_update_framebuffer;  extern const struct st_tracked_state st_update_clip;  extern const struct st_tracked_state st_update_depth_stencil_alpha; -extern const struct st_tracked_state st_update_shader; +extern const struct st_tracked_state st_update_fp; +extern const struct st_tracked_state st_update_vp;  extern const struct st_tracked_state st_update_rasterizer;  extern const struct st_tracked_state st_update_polygon_stipple;  extern const struct st_tracked_state st_update_viewport; diff --git a/src/mesa/state_tracker/st_atom_framebuffer.c b/src/mesa/state_tracker/st_atom_framebuffer.c index e18c0f6e0a..8ca4335e33 100644 --- a/src/mesa/state_tracker/st_atom_framebuffer.c +++ b/src/mesa/state_tracker/st_atom_framebuffer.c @@ -40,6 +40,7 @@  #include "pipe/p_inlines.h"  #include "cso_cache/cso_context.h"  #include "util/u_rect.h" +#include "util/u_math.h" @@ -64,8 +65,8 @@ update_renderbuffer_surface(struct st_context *st,        GLuint level;        /* find matching mipmap level size */        for (level = 0; level <= texture->last_level; level++) { -         if (texture->width[level] == rtt_width && -             texture->height[level] == rtt_height) { +         if (u_minify(texture->width0, level) == rtt_width && +             u_minify(texture->height0, level) == rtt_height) {              pipe_surface_reference(&strb->surface, NULL); diff --git a/src/mesa/state_tracker/st_atom_pixeltransfer.c b/src/mesa/state_tracker/st_atom_pixeltransfer.c index babfcc87b4..4b35f59cc2 100644 --- a/src/mesa/state_tracker/st_atom_pixeltransfer.c +++ b/src/mesa/state_tracker/st_atom_pixeltransfer.c @@ -145,7 +145,7 @@ load_color_map_texture(GLcontext *ctx, struct pipe_texture *pt)     const GLuint gSize = ctx->PixelMaps.GtoG.Size;     const GLuint bSize = ctx->PixelMaps.BtoB.Size;     const GLuint aSize = ctx->PixelMaps.AtoA.Size; -   const uint texSize = pt->width[0]; +   const uint texSize = pt->width0;     uint *dest;     uint i, j; diff --git a/src/mesa/state_tracker/st_atom_sampler.c b/src/mesa/state_tracker/st_atom_sampler.c index 6611956ae8..d6e3a3e561 100644 --- a/src/mesa/state_tracker/st_atom_sampler.c +++ b/src/mesa/state_tracker/st_atom_sampler.c @@ -229,14 +229,23 @@ update_samplers(struct st_context *st)           /*printf("%s su=%u non-null\n", __FUNCTION__, su);*/           cso_single_sampler(st->cso_context, su, sampler); +         if (su < st->ctx->Const.MaxVertexTextureImageUnits) { +            cso_single_vertex_sampler(st->cso_context, su, sampler); +         }        }        else {           /*printf("%s su=%u null\n", __FUNCTION__, su);*/           cso_single_sampler(st->cso_context, su, NULL); +         if (su < st->ctx->Const.MaxVertexTextureImageUnits) { +            cso_single_vertex_sampler(st->cso_context, su, NULL); +         }        }     }     cso_single_sampler_done(st->cso_context); +   if (st->ctx->Const.MaxVertexTextureImageUnits > 0) { +      cso_single_vertex_sampler_done(st->cso_context); +   }  } diff --git a/src/mesa/state_tracker/st_atom_shader.c b/src/mesa/state_tracker/st_atom_shader.c index 6e311e537e..09baff875b 100644 --- a/src/mesa/state_tracker/st_atom_shader.c +++ b/src/mesa/state_tracker/st_atom_shader.c @@ -56,82 +56,18 @@  #include "st_mesa_to_tgsi.h" -/** - * This represents a vertex program, especially translated to match - * the inputs of a particular fragment shader. - */ -struct translated_vertex_program -{ -   struct st_vertex_program *master; - -   /** The fragment shader "signature" this vertex shader is meant for: */ -   GLbitfield frag_inputs; - -   /** Compared against master vertex program's serialNo: */ -   GLuint serialNo; - -   /** Maps VERT_RESULT_x to slot */ -   GLuint output_to_slot[VERT_RESULT_MAX]; -   ubyte output_to_semantic_name[VERT_RESULT_MAX]; -   ubyte output_to_semantic_index[VERT_RESULT_MAX]; - -   /** Pointer to the translated vertex program */ -   struct st_vertex_program *vp; - -   struct translated_vertex_program *next;  /**< next in linked list */ -}; - - - -/** - * Given a vertex program output attribute, return the corresponding - * fragment program input attribute. - * \return -1 for vertex outputs that have no corresponding fragment input - */ -static GLint -vp_out_to_fp_in(GLuint vertResult) -{ -   if (vertResult >= VERT_RESULT_TEX0 && -       vertResult < VERT_RESULT_TEX0 + MAX_TEXTURE_COORD_UNITS) -      return FRAG_ATTRIB_TEX0 + (vertResult - VERT_RESULT_TEX0); -   if (vertResult >= VERT_RESULT_VAR0 && -       vertResult < VERT_RESULT_VAR0 + MAX_VARYING) -      return FRAG_ATTRIB_VAR0 + (vertResult - VERT_RESULT_VAR0); -   switch (vertResult) { -   case VERT_RESULT_HPOS: -      return FRAG_ATTRIB_WPOS; -   case VERT_RESULT_COL0: -      return FRAG_ATTRIB_COL0; -   case VERT_RESULT_COL1: -      return FRAG_ATTRIB_COL1; -   case VERT_RESULT_FOGC: -      return FRAG_ATTRIB_FOGC; -   default: -      /* Back-face colors, edge flags, etc */ -      return -1; -   } -} - -/** - * Find a translated vertex program that corresponds to stvp and - * has outputs matched to stfp's inputs. - * This performs vertex and fragment translation (to TGSI) when needed. +/* + * Translate fragment program if needed.   */ -static struct translated_vertex_program * -find_translated_vp(struct st_context *st, -                   struct st_vertex_program *stvp, -                   struct st_fragment_program *stfp) +static void +translate_fp(struct st_context *st, +             struct st_fragment_program *stfp)  { -   static const GLuint UNUSED = ~0; -   struct translated_vertex_program *xvp;     const GLbitfield fragInputsRead = stfp->Base.Base.InputsRead; -   /* -    * Translate fragment program if needed. -    */     if (!stfp->state.tokens) {        GLuint inAttr, numIn = 0; @@ -141,7 +77,7 @@ find_translated_vp(struct st_context *st,              numIn++;           }           else { -            stfp->input_to_slot[inAttr] = UNUSED; +            stfp->input_to_slot[inAttr] = -1;           }        } @@ -151,170 +87,63 @@ find_translated_vp(struct st_context *st,        st_translate_fragment_program(st, stfp, stfp->input_to_slot);     } +} -   /* See if we've got a translated vertex program whose outputs match -    * the fragment program's inputs. -    * XXX This could be a hash lookup, using InputsRead as the key. -    */ -   for (xvp = stfp->vertex_programs; xvp; xvp = xvp->next) { -      if (xvp->master == stvp && xvp->frag_inputs == fragInputsRead) { -         break; -      } -   } - -   /* No?  Allocate translated vp object now */ -   if (!xvp) { -      xvp = ST_CALLOC_STRUCT(translated_vertex_program); -      xvp->frag_inputs = fragInputsRead; -      xvp->master = stvp; -      xvp->next = stfp->vertex_programs; -      stfp->vertex_programs = xvp; -   } +/** + * Find a translated vertex program that corresponds to stvp and + * has outputs matched to stfp's inputs. + * This performs vertex and fragment translation (to TGSI) when needed. + */ +static struct st_vp_varient * +find_translated_vp(struct st_context *st, +                   struct st_vertex_program *stvp ) +{ +   struct st_vp_varient *vpv; +   struct st_vp_varient_key key; -   /* See if we need to translate vertex program to TGSI form */ -   if (xvp->serialNo != stvp->serialNo) { -      GLuint outAttr; -      const GLbitfield64 outputsWritten = stvp->Base.Base.OutputsWritten; -      GLuint numVpOuts = 0; -      GLboolean emitPntSize = GL_FALSE, emitBFC0 = GL_FALSE, emitBFC1 = GL_FALSE; -      GLbitfield usedGenerics = 0x0; -      GLbitfield usedOutputSlots = 0x0; +   /* Nothing in our key yet.  This will change: +    */ +   memset(&key, 0, sizeof key); +   key.dummy = 0; -      /* Compute mapping of vertex program outputs to slots, which depends -       * on the fragment program's input->slot mapping. +   /* Do we need to throw away old translations after a change in the +    * GL program string? +    */ +   if (stvp->serialNo != stvp->lastSerialNo) { +      /* These may have changed if the program string changed.         */ -      for (outAttr = 0; outAttr < VERT_RESULT_MAX; outAttr++) { -         /* set defaults: */ -         xvp->output_to_slot[outAttr] = UNUSED; -         xvp->output_to_semantic_name[outAttr] = TGSI_SEMANTIC_COUNT; -         xvp->output_to_semantic_index[outAttr] = 99; - -         if (outAttr == VERT_RESULT_HPOS) { -            /* always put xformed position into slot zero */ -            GLuint slot = 0; -            xvp->output_to_slot[VERT_RESULT_HPOS] = slot; -            xvp->output_to_semantic_name[outAttr] = TGSI_SEMANTIC_POSITION; -            xvp->output_to_semantic_index[outAttr] = 0; -            numVpOuts++; -            usedOutputSlots |= (1 << slot); -         } -         else if (outputsWritten & (1 << outAttr)) { -            /* see if the frag prog wants this vert output */ -            GLint fpInAttrib = vp_out_to_fp_in(outAttr); -            if (fpInAttrib >= 0) { -               GLuint fpInSlot = stfp->input_to_slot[fpInAttrib]; -               if (fpInSlot != ~0) { -                  /* match this vp output to the fp input */ -                  GLuint vpOutSlot = stfp->input_map[fpInSlot]; -                  xvp->output_to_slot[outAttr] = vpOutSlot; -                  xvp->output_to_semantic_name[outAttr] = stfp->input_semantic_name[fpInSlot]; -                  xvp->output_to_semantic_index[outAttr] = stfp->input_semantic_index[fpInSlot]; -                  numVpOuts++; -                  usedOutputSlots |= (1 << vpOutSlot); -               } -               else { -#if 0 /*debug*/ -                  printf("VP output %d not used by FP\n", outAttr); -#endif -               } -            } -            else if (outAttr == VERT_RESULT_PSIZ) -               emitPntSize = GL_TRUE; -            else if (outAttr == VERT_RESULT_BFC0) -               emitBFC0 = GL_TRUE; -            else if (outAttr == VERT_RESULT_BFC1) -               emitBFC1 = GL_TRUE; -         } -#if 0 /*debug*/ -         printf("assign vp output_to_slot[%d] = %d\n", outAttr,  -                xvp->output_to_slot[outAttr]); -#endif -      } - -      /* must do these last */ -      if (emitPntSize) { -         GLuint slot = numVpOuts++; -         xvp->output_to_slot[VERT_RESULT_PSIZ] = slot; -         xvp->output_to_semantic_name[VERT_RESULT_PSIZ] = TGSI_SEMANTIC_PSIZE; -         xvp->output_to_semantic_index[VERT_RESULT_PSIZ] = 0; -         usedOutputSlots |= (1 << slot); -      } -      if (emitBFC0) { -         GLuint slot = numVpOuts++; -         xvp->output_to_slot[VERT_RESULT_BFC0] = slot; -         xvp->output_to_semantic_name[VERT_RESULT_BFC0] = TGSI_SEMANTIC_COLOR; -         xvp->output_to_semantic_index[VERT_RESULT_BFC0] = 0; -         usedOutputSlots |= (1 << slot); -      } -      if (emitBFC1) { -         GLuint slot = numVpOuts++; -         xvp->output_to_slot[VERT_RESULT_BFC1] = slot; -         xvp->output_to_semantic_name[VERT_RESULT_BFC1] = TGSI_SEMANTIC_COLOR; -         xvp->output_to_semantic_index[VERT_RESULT_BFC1] = 1; -         usedOutputSlots |= (1 << slot); -      } - -      /* build usedGenerics mask */ -      usedGenerics = 0x0; -      for (outAttr = 0; outAttr < VERT_RESULT_MAX; outAttr++) { -         if (xvp->output_to_semantic_name[outAttr] == TGSI_SEMANTIC_GENERIC) { -            usedGenerics |= (1 << xvp->output_to_semantic_index[outAttr]); -         } -      } +      st_prepare_vertex_program( st, stvp ); -      /* For each vertex program output that doesn't match up to a fragment -       * program input, map the vertex program output to a free slot and -       * free generic attribute. +      /* We are now up-to-date:         */ -      for (outAttr = 0; outAttr < VERT_RESULT_MAX; outAttr++) { -         if (outputsWritten & (1 << outAttr)) { -            if (xvp->output_to_slot[outAttr] == UNUSED) { -               GLint freeGeneric = _mesa_ffs(~usedGenerics) - 1; -               GLint freeSlot = _mesa_ffs(~usedOutputSlots) - 1; -               usedGenerics |= (1 << freeGeneric); -               usedOutputSlots |= (1 << freeSlot); -               xvp->output_to_slot[outAttr] = freeSlot; -               xvp->output_to_semantic_name[outAttr] = TGSI_SEMANTIC_GENERIC; -               xvp->output_to_semantic_index[outAttr] = freeGeneric; -            } -         } - -#if 0 /*debug*/ -         printf("vp output_to_slot[%d] = %d\n", outAttr,  -                xvp->output_to_slot[outAttr]); -#endif +      stvp->lastSerialNo = stvp->serialNo; +   } +    +   /* See if we've got a translated vertex program whose outputs match +    * the fragment program's inputs. +    */ +   for (vpv = stvp->varients; vpv; vpv = vpv->next) { +      if (memcmp(&vpv->key, &key, sizeof key) == 0) { +         break;        } +   } -      assert(stvp->Base.Base.NumInstructions > 1); - -      st_translate_vertex_program(st, stvp, xvp->output_to_slot, -                                  xvp->output_to_semantic_name, -                                  xvp->output_to_semantic_index); - -      xvp->vp = stvp; - -      /* translated VP is up to date now */ -      xvp->serialNo = stvp->serialNo; +   /* No?  Perform new translation here. */ +   if (!vpv) { +      vpv = st_translate_vertex_program(st, stvp, &key); +      if (!vpv) +         return NULL; +       +      vpv->next = stvp->varients; +      stvp->varients = vpv;     } -   return xvp; +   return vpv;  } -void -st_free_translated_vertex_programs(struct st_context *st, -                                   struct translated_vertex_program *xvp) -{ -   struct translated_vertex_program *next; - -   while (xvp) { -      next = xvp->next; -      _mesa_free(xvp); -      xvp = next; -   } -}  static void * @@ -328,32 +157,19 @@ get_passthrough_fs(struct st_context *st)     return st->passthrough_fs;  } -  static void -update_linkage( struct st_context *st ) +update_fp( struct st_context *st )  { -   struct st_vertex_program *stvp;     struct st_fragment_program *stfp; -   struct translated_vertex_program *xvp; - -   /* find active shader and params -- Should be covered by -    * ST_NEW_VERTEX_PROGRAM -    */ -   assert(st->ctx->VertexProgram._Current); -   stvp = st_vertex_program(st->ctx->VertexProgram._Current); -   assert(stvp->Base.Base.Target == GL_VERTEX_PROGRAM_ARB);     assert(st->ctx->FragmentProgram._Current);     stfp = st_fragment_program(st->ctx->FragmentProgram._Current);     assert(stfp->Base.Base.Target == GL_FRAGMENT_PROGRAM_ARB); -   xvp = find_translated_vp(st, stvp, stfp); +   translate_fp(st, stfp); -   st_reference_vertprog(st, &st->vp, stvp);     st_reference_fragprog(st, &st->fp, stfp); -   cso_set_vertex_shader_handle(st->cso_context, stvp->driver_shader); -     if (st->missing_textures) {        /* use a pass-through frag shader that uses no textures */        void *fs = get_passthrough_fs(st); @@ -362,16 +178,48 @@ update_linkage( struct st_context *st )     else {        cso_set_fragment_shader_handle(st->cso_context, stfp->driver_shader);     } +} + +const struct st_tracked_state st_update_fp = { +   "st_update_fp",					/* name */ +   {							/* dirty */ +      0,						/* mesa */ +      ST_NEW_FRAGMENT_PROGRAM                           /* st */ +   }, +   update_fp  					/* update */ +}; + + + + +static void +update_vp( struct st_context *st ) +{ +   struct st_vertex_program *stvp; + +   /* find active shader and params -- Should be covered by +    * ST_NEW_VERTEX_PROGRAM +    */ +   assert(st->ctx->VertexProgram._Current); +   stvp = st_vertex_program(st->ctx->VertexProgram._Current); +   assert(stvp->Base.Base.Target == GL_VERTEX_PROGRAM_ARB); + +   st->vp_varient = find_translated_vp(st, stvp); + +   st_reference_vertprog(st, &st->vp, stvp); + +   cso_set_vertex_shader_handle(st->cso_context,  +                                st->vp_varient->driver_shader); -   st->vertex_result_to_slot = xvp->output_to_slot; +   st->vertex_result_to_slot = stvp->result_to_output;  } -const struct st_tracked_state st_update_shader = { -   "st_update_shader",					/* name */ +const struct st_tracked_state st_update_vp = { +   "st_update_vp",					/* name */     {							/* dirty */        0,						/* mesa */ -      ST_NEW_VERTEX_PROGRAM | ST_NEW_FRAGMENT_PROGRAM	/* st */ +      ST_NEW_VERTEX_PROGRAM                             /* st */     }, -   update_linkage					/* update */ +   update_vp					/* update */  }; diff --git a/src/mesa/state_tracker/st_atom_texture.c b/src/mesa/state_tracker/st_atom_texture.c index 4d4f97da7e..0b68447d21 100644 --- a/src/mesa/state_tracker/st_atom_texture.c +++ b/src/mesa/state_tracker/st_atom_texture.c @@ -32,6 +32,8 @@    */ +#include "main/macros.h" +  #include "st_context.h"  #include "st_atom.h"  #include "st_texture.h" @@ -99,6 +101,12 @@ update_textures(struct st_context *st)     cso_set_sampler_textures(st->cso_context,                              st->state.num_textures,                              st->state.sampler_texture); +   if (st->ctx->Const.MaxVertexTextureImageUnits > 0) { +      cso_set_vertex_sampler_textures(st->cso_context, +                                      MIN2(st->state.num_textures, +                                           st->ctx->Const.MaxVertexTextureImageUnits), +                                      st->state.sampler_texture); +   }  } diff --git a/src/mesa/state_tracker/st_cb_bitmap.c b/src/mesa/state_tracker/st_cb_bitmap.c index 1960d171bf..1bdeaccda3 100644 --- a/src/mesa/state_tracker/st_cb_bitmap.c +++ b/src/mesa/state_tracker/st_cb_bitmap.c @@ -169,11 +169,6 @@ make_bitmap_fragment_program(GLcontext *ctx, GLuint samplerIndex)     stfp = (struct st_fragment_program *) p;     stfp->Base.UsesKill = GL_TRUE; -   /* No need to send this incomplete program down to hardware: -    * -    * st_translate_fragment_program(ctx->st, stfp, NULL); -    */ -     return stfp;  } diff --git a/src/mesa/state_tracker/st_cb_drawpixels.c b/src/mesa/state_tracker/st_cb_drawpixels.c index 1d33e81c2c..03617b7a93 100644 --- a/src/mesa/state_tracker/st_cb_drawpixels.c +++ b/src/mesa/state_tracker/st_cb_drawpixels.c @@ -60,6 +60,7 @@  #include "pipe/p_context.h"  #include "pipe/p_defines.h"  #include "pipe/p_inlines.h" +#include "tgsi/tgsi_ureg.h"  #include "util/u_tile.h"  #include "util/u_draw_quad.h"  #include "util/u_math.h" @@ -236,78 +237,41 @@ make_fragment_shader_z(struct st_context *st)   * Create a simple vertex shader that just passes through the   * vertex position and texcoord (and optionally, color).   */ -static struct st_vertex_program * -st_make_passthrough_vertex_shader(struct st_context *st, GLboolean passColor) +static void * +st_make_passthrough_vertex_shader(struct st_context *st,  +                                  GLboolean passColor)  { -   GLcontext *ctx = st->ctx; -   struct st_vertex_program *stvp; -   struct gl_program *p; -   GLuint ic = 0; - -   if (st->drawpix.vert_shaders[passColor]) -      return st->drawpix.vert_shaders[passColor]; - -   /* -    * Create shader now -    */ -   p = ctx->Driver.NewProgram(ctx, GL_VERTEX_PROGRAM_ARB, 0); -   if (!p) -      return NULL; - -   if (passColor) -      p->NumInstructions = 4; -   else -      p->NumInstructions = 3; - -   p->Instructions = _mesa_alloc_instructions(p->NumInstructions); -   if (!p->Instructions) { -      ctx->Driver.DeleteProgram(ctx, p); -      return NULL; -   } -   _mesa_init_instructions(p->Instructions, p->NumInstructions); -   /* MOV result.pos, vertex.pos; */ -   p->Instructions[0].Opcode = OPCODE_MOV; -   p->Instructions[0].DstReg.File = PROGRAM_OUTPUT; -   p->Instructions[0].DstReg.Index = VERT_RESULT_HPOS; -   p->Instructions[0].SrcReg[0].File = PROGRAM_INPUT; -   p->Instructions[0].SrcReg[0].Index = VERT_ATTRIB_POS; -   /* MOV result.texcoord0, vertex.texcoord0; */ -   p->Instructions[1].Opcode = OPCODE_MOV; -   p->Instructions[1].DstReg.File = PROGRAM_OUTPUT; -   p->Instructions[1].DstReg.Index = VERT_RESULT_TEX0; -   p->Instructions[1].SrcReg[0].File = PROGRAM_INPUT; -   p->Instructions[1].SrcReg[0].Index = VERT_ATTRIB_TEX0; -   ic = 2; -   if (passColor) { -      /* MOV result.color0, vertex.color0; */ -      p->Instructions[ic].Opcode = OPCODE_MOV; -      p->Instructions[ic].DstReg.File = PROGRAM_OUTPUT; -      p->Instructions[ic].DstReg.Index = VERT_RESULT_COL0; -      p->Instructions[ic].SrcReg[0].File = PROGRAM_INPUT; -      p->Instructions[ic].SrcReg[0].Index = VERT_ATTRIB_COLOR0; -      ic++; -   } +   if (!st->drawpix.vert_shaders[passColor]) { +      struct ureg_program *ureg =  +         ureg_create( TGSI_PROCESSOR_VERTEX ); -   /* END; */ -   p->Instructions[ic].Opcode = OPCODE_END; -   ic++; +      if (ureg == NULL) +         return NULL; -   assert(ic == p->NumInstructions); +      /* MOV result.pos, vertex.pos; */ +      ureg_MOV(ureg,  +               ureg_DECL_output( ureg, TGSI_SEMANTIC_POSITION, 0 ), +               ureg_DECL_vs_input( ureg, 0 )); +       +      /* MOV result.texcoord0, vertex.texcoord0; */ +      ureg_MOV(ureg,  +               ureg_DECL_output( ureg, TGSI_SEMANTIC_GENERIC, 0 ), +               ureg_DECL_vs_input( ureg, 1 )); +       +      if (passColor) { +         /* MOV result.color0, vertex.color0; */ +         ureg_MOV(ureg,  +                  ureg_DECL_output( ureg, TGSI_SEMANTIC_COLOR, 0 ), +                  ureg_DECL_vs_input( ureg, 2 )); +      } -   p->InputsRead = VERT_BIT_POS | VERT_BIT_TEX0; -   p->OutputsWritten = ((1 << VERT_RESULT_TEX0) | -                        (1 << VERT_RESULT_HPOS)); -   if (passColor) { -      p->InputsRead |= VERT_BIT_COLOR0; -      p->OutputsWritten |= (1 << VERT_RESULT_COL0); +      ureg_END( ureg ); +       +      st->drawpix.vert_shaders[passColor] =  +         ureg_create_shader_and_destroy( ureg, st->pipe );     } -   stvp = (struct st_vertex_program *) p; -   st_translate_vertex_program(st, stvp, NULL, NULL, NULL); - -   st->drawpix.vert_shaders[passColor] = stvp; - -   return stvp; +   return st->drawpix.vert_shaders[passColor];  } @@ -539,8 +503,8 @@ draw_textured_quad(GLcontext *ctx, GLint x, GLint y, GLfloat z,                     GLsizei width, GLsizei height,                     GLfloat zoomX, GLfloat zoomY,                     struct pipe_texture *pt, -                   struct st_vertex_program *stvp, -                   struct st_fragment_program *stfp, +                   void *driver_vp, +                   void *driver_fp,                     const GLfloat *color,                     GLboolean invertTex)  { @@ -575,10 +539,10 @@ draw_textured_quad(GLcontext *ctx, GLint x, GLint y, GLfloat z,     }     /* fragment shader state: TEX lookup program */ -   cso_set_fragment_shader_handle(cso, stfp->driver_shader); +   cso_set_fragment_shader_handle(cso, driver_fp);     /* vertex shader state: position + texcoord pass-through */ -   cso_set_vertex_shader_handle(cso, stvp->driver_shader); +   cso_set_vertex_shader_handle(cso, driver_vp);     /* texture sampling state: */ @@ -621,10 +585,10 @@ draw_textured_quad(GLcontext *ctx, GLint x, GLint y, GLfloat z,        struct pipe_texture *textures[2];        textures[0] = pt;        textures[1] = st->pixel_xfer.pixelmap_texture; -      pipe->set_sampler_textures(pipe, 2, textures); +      pipe->set_fragment_sampler_textures(pipe, 2, textures);     }     else { -      pipe->set_sampler_textures(pipe, 1, &pt); +      pipe->set_fragment_sampler_textures(pipe, 1, &pt);     }     /* Compute window coords (y=0=bottom) with pixel zoom. @@ -637,8 +601,8 @@ draw_textured_quad(GLcontext *ctx, GLint x, GLint y, GLfloat z,     y1 = y + height * ctx->Pixel.ZoomY;     draw_quad(ctx, x0, y0, z, x1, y1, color, invertTex, -	     (GLfloat) width / pt->width[0], -	     (GLfloat) height / pt->height[0]); +	     (GLfloat) width / pt->width0, +	     (GLfloat) height / pt->height0);     /* restore state */     cso_restore_rasterizer(cso); @@ -806,7 +770,7 @@ st_DrawPixels(GLcontext *ctx, GLint x, GLint y, GLsizei width, GLsizei height,                const struct gl_pixelstore_attrib *unpack, const GLvoid *pixels)  {     struct st_fragment_program *stfp; -   struct st_vertex_program *stvp; +   void *driver_vp;     struct st_context *st = st_context(ctx);     struct pipe_surface *ps;     const GLfloat *color; @@ -826,13 +790,13 @@ st_DrawPixels(GLcontext *ctx, GLint x, GLint y, GLsizei width, GLsizei height,     if (format == GL_DEPTH_COMPONENT) {        ps = st->state.framebuffer.zsbuf;        stfp = make_fragment_shader_z(st); -      stvp = st_make_passthrough_vertex_shader(st, GL_TRUE); +      driver_vp = st_make_passthrough_vertex_shader(st, GL_TRUE);        color = ctx->Current.RasterColor;     }     else {        ps = st->state.framebuffer.cbufs[0];        stfp = combined_drawpix_fragment_program(ctx); -      stvp = st_make_passthrough_vertex_shader(st, GL_FALSE); +      driver_vp = st_make_passthrough_vertex_shader(st, GL_FALSE);        color = NULL;     } @@ -843,7 +807,10 @@ st_DrawPixels(GLcontext *ctx, GLint x, GLint y, GLsizei width, GLsizei height,        if (pt) {           draw_textured_quad(ctx, x, y, ctx->Current.RasterPos[2],                              width, height, ctx->Pixel.ZoomX, ctx->Pixel.ZoomY, -                            pt, stvp, stfp, color, GL_FALSE); +                            pt,  +                            driver_vp,  +                            stfp->driver_shader, +                            color, GL_FALSE);           pipe_texture_reference(&pt, NULL);        }     } @@ -960,7 +927,7 @@ st_CopyPixels(GLcontext *ctx, GLint srcx, GLint srcy,     struct pipe_context *pipe = st->pipe;     struct pipe_screen *screen = pipe->screen;     struct st_renderbuffer *rbRead; -   struct st_vertex_program *stvp; +   void *driver_vp;     struct st_fragment_program *stfp;     struct pipe_texture *pt;     GLfloat *color; @@ -1009,14 +976,14 @@ st_CopyPixels(GLcontext *ctx, GLint srcx, GLint srcy,        rbRead = st_get_color_read_renderbuffer(ctx);        color = NULL;        stfp = combined_drawpix_fragment_program(ctx); -      stvp = st_make_passthrough_vertex_shader(st, GL_FALSE); +      driver_vp = st_make_passthrough_vertex_shader(st, GL_FALSE);     }     else {        assert(type == GL_DEPTH);        rbRead = st_renderbuffer(ctx->ReadBuffer->_DepthBuffer);        color = ctx->Current.Attrib[VERT_ATTRIB_COLOR0];        stfp = make_fragment_shader_z(st); -      stvp = st_make_passthrough_vertex_shader(st, GL_TRUE); +      driver_vp = st_make_passthrough_vertex_shader(st, GL_TRUE);     }     srcFormat = rbRead->texture->format; @@ -1148,7 +1115,10 @@ st_CopyPixels(GLcontext *ctx, GLint srcx, GLint srcy,     /* draw textured quad */     draw_textured_quad(ctx, dstx, dsty, ctx->Current.RasterPos[2],                        width, height, ctx->Pixel.ZoomX, ctx->Pixel.ZoomY, -                      pt, stvp, stfp, color, GL_TRUE); +                      pt,  +                      driver_vp,  +                      stfp->driver_shader, +                      color, GL_TRUE);     pipe_texture_reference(&pt, NULL);  } diff --git a/src/mesa/state_tracker/st_cb_fbo.c b/src/mesa/state_tracker/st_cb_fbo.c index 65ce12ccd4..659a6c9193 100644 --- a/src/mesa/state_tracker/st_cb_fbo.c +++ b/src/mesa/state_tracker/st_cb_fbo.c @@ -128,9 +128,9 @@ st_renderbuffer_alloc_storage(GLcontext * ctx, struct gl_renderbuffer *rb,        template.target = PIPE_TEXTURE_2D;        template.format = format;        pf_get_block(format, &template.block); -      template.width[0] = width; -      template.height[0] = height; -      template.depth[0] = 1; +      template.width0 = width; +      template.height0 = height; +      template.depth0 = 1;        template.last_level = 0;        template.nr_samples = rb->NumSamples;        if (pf_is_depth_stencil(format)) { @@ -376,7 +376,7 @@ st_render_texture(GLcontext *ctx,     rb->_BaseFormat = texImage->_BaseFormat;     /*printf("***** render to texture level %d: %d x %d\n", att->TextureLevel, rb->Width, rb->Height);*/ -   /*printf("***** pipe texture %d x %d\n", pt->width[0], pt->height[0]);*/ +   /*printf("***** pipe texture %d x %d\n", pt->width0, pt->height0);*/     pipe_texture_reference( &strb->texture, pt ); diff --git a/src/mesa/state_tracker/st_cb_program.c b/src/mesa/state_tracker/st_cb_program.c index b2d5c39a3a..8c276f8128 100644 --- a/src/mesa/state_tracker/st_cb_program.c +++ b/src/mesa/state_tracker/st_cb_program.c @@ -138,24 +138,7 @@ st_delete_program(GLcontext *ctx, struct gl_program *prog)     case GL_VERTEX_PROGRAM_ARB:        {           struct st_vertex_program *stvp = (struct st_vertex_program *) prog; - -         if (stvp->driver_shader) { -            cso_delete_vertex_shader(st->cso_context, stvp->driver_shader); -            stvp->driver_shader = NULL; -         } - -         if (stvp->draw_shader) { -#if FEATURE_feedback || FEATURE_drawpix -            /* this would only have been allocated for the RasterPos path */ -            draw_delete_vertex_shader(st->draw, stvp->draw_shader); -            stvp->draw_shader = NULL; -#endif -         } - -         if (stvp->state.tokens) { -            st_free_tokens(stvp->state.tokens); -            stvp->state.tokens = NULL; -         } +         st_vp_release_varients( st, stvp );        }        break;     case GL_FRAGMENT_PROGRAM_ARB: @@ -177,8 +160,6 @@ st_delete_program(GLcontext *ctx, struct gl_program *prog)              _mesa_reference_program(ctx, &prg, NULL);              stfp->bitmap_program = NULL;           } - -         st_free_translated_vertex_programs(st, stfp->vertex_programs);        }        break;     default: @@ -219,8 +200,6 @@ static void st_program_string_notify( GLcontext *ctx,           stfp->state.tokens = NULL;        } -      stfp->param_state = stfp->Base.Base.Parameters->StateFlags; -        if (st->fp == stfp)  	 st->dirty.st |= ST_NEW_FRAGMENT_PROGRAM;     } @@ -229,25 +208,7 @@ static void st_program_string_notify( GLcontext *ctx,        stvp->serialNo++; -      if (stvp->driver_shader) { -         cso_delete_vertex_shader(st->cso_context, stvp->driver_shader); -         stvp->driver_shader = NULL; -      } - -      if (stvp->draw_shader) { -#if FEATURE_feedback || FEATURE_drawpix -         /* this would only have been allocated for the RasterPos path */ -         draw_delete_vertex_shader(st->draw, stvp->draw_shader); -         stvp->draw_shader = NULL; -#endif -      } - -      if (stvp->state.tokens) { -         st_free_tokens(stvp->state.tokens); -         stvp->state.tokens = NULL; -      } - -      stvp->param_state = stvp->Base.Base.Parameters->StateFlags; +      st_vp_release_varients( st, stvp );        if (st->vp == stvp)  	 st->dirty.st |= ST_NEW_VERTEX_PROGRAM; diff --git a/src/mesa/state_tracker/st_cb_readpixels.c b/src/mesa/state_tracker/st_cb_readpixels.c index 772bb3bb69..103861d6f9 100644 --- a/src/mesa/state_tracker/st_cb_readpixels.c +++ b/src/mesa/state_tracker/st_cb_readpixels.c @@ -243,7 +243,7 @@ st_fast_readpixels(GLcontext *ctx, struct st_renderbuffer *strb,        GLint row, col, dy, dstStride;        if (st_fb_orientation(ctx->ReadBuffer) == Y_0_TOP) { -         y = strb->texture->height[0] - y - height; +         y = strb->texture->height0 - y - height;        }        trans = st_cond_flush_get_tex_transfer(st_context(ctx), strb->texture, diff --git a/src/mesa/state_tracker/st_cb_texture.c b/src/mesa/state_tracker/st_cb_texture.c index d4630a514f..3a2337802f 100644 --- a/src/mesa/state_tracker/st_cb_texture.c +++ b/src/mesa/state_tracker/st_cb_texture.c @@ -406,9 +406,9 @@ compress_with_blit(GLcontext * ctx,     templ.target = PIPE_TEXTURE_2D;     templ.format = st_mesa_format_to_pipe_format(mesa_format);     pf_get_block(templ.format, &templ.block); -   templ.width[0] = width; -   templ.height[0] = height; -   templ.depth[0] = 1; +   templ.width0 = width; +   templ.height0 = height; +   templ.depth0 = 1;     templ.last_level = 0;     templ.tex_usage = PIPE_TEXTURE_USAGE_SAMPLER;     src_tex = screen->texture_create(screen, &templ); @@ -1761,9 +1761,9 @@ st_finalize_texture(GLcontext *ctx,        if (stObj->pt->target != gl_target_to_pipe(stObj->base.Target) ||            stObj->pt->format != fmt ||            stObj->pt->last_level < stObj->lastLevel || -          stObj->pt->width[0] != firstImage->base.Width2 || -          stObj->pt->height[0] != firstImage->base.Height2 || -          stObj->pt->depth[0] != firstImage->base.Depth2 || +          stObj->pt->width0 != firstImage->base.Width2 || +          stObj->pt->height0 != firstImage->base.Height2 || +          stObj->pt->depth0 != firstImage->base.Depth2 ||            stObj->pt->block.size != blockSize)        {           pipe_texture_reference(&stObj->pt, NULL); diff --git a/src/mesa/state_tracker/st_context.h b/src/mesa/state_tracker/st_context.h index 18adb35e87..b760728658 100644 --- a/src/mesa/state_tracker/st_context.h +++ b/src/mesa/state_tracker/st_context.h @@ -127,6 +127,8 @@ struct st_context     struct st_vertex_program *vp;    /**< Currently bound vertex program */     struct st_fragment_program *fp;  /**< Currently bound fragment program */ +   struct st_vp_varient *vp_varient; +     struct gl_texture_object *default_texture;     struct { diff --git a/src/mesa/state_tracker/st_debug.c b/src/mesa/state_tracker/st_debug.c index 3009cde9d5..6e699ca552 100644 --- a/src/mesa/state_tracker/st_debug.c +++ b/src/mesa/state_tracker/st_debug.c @@ -86,7 +86,8 @@ st_print_current(void)     }  #endif -   tgsi_dump( st->vp->state.tokens, 0 ); +   if (st->vp->varients) +      tgsi_dump( st->vp->varients[0].state.tokens, 0 );     if (st->vp->Base.Base.Parameters)        _mesa_print_parameter_list(st->vp->Base.Base.Parameters); diff --git a/src/mesa/state_tracker/st_draw.c b/src/mesa/state_tracker/st_draw.c index 68bc76b572..e13ae57a0e 100644 --- a/src/mesa/state_tracker/st_draw.c +++ b/src/mesa/state_tracker/st_draw.c @@ -573,7 +573,7 @@ st_draw_vbo(GLcontext *ctx,     /* must get these after state validation! */     vp = ctx->st->vp; -   vs = &ctx->st->vp->state; +   vs = &ctx->st->vp_varient->state;  #if 0     if (MESA_VERBOSE & VERBOSE_GLSL) { diff --git a/src/mesa/state_tracker/st_draw_feedback.c b/src/mesa/state_tracker/st_draw_feedback.c index b2d682ef64..d793f820bc 100644 --- a/src/mesa/state_tracker/st_draw_feedback.c +++ b/src/mesa/state_tracker/st_draw_feedback.c @@ -120,10 +120,10 @@ st_feedback_draw_vbo(GLcontext *ctx,     /* must get these after state validation! */     vp = ctx->st->vp; -   vs = &st->vp->state; +   vs = &st->vp_varient->state; -   if (!st->vp->draw_shader) { -      st->vp->draw_shader = draw_create_vertex_shader(draw, vs); +   if (!st->vp_varient->draw_shader) { +      st->vp_varient->draw_shader = draw_create_vertex_shader(draw, vs);     }     /* @@ -136,7 +136,7 @@ st_feedback_draw_vbo(GLcontext *ctx,     draw_set_viewport_state(draw, &st->state.viewport);     draw_set_clip_state(draw, &st->state.clip);     draw_set_rasterizer_state(draw, &st->state.rasterizer); -   draw_bind_vertex_shader(draw, st->vp->draw_shader); +   draw_bind_vertex_shader(draw, st->vp_varient->draw_shader);     set_feedback_vertex_format(ctx);     /* loop over TGSI shader inputs to determine vertex buffer diff --git a/src/mesa/state_tracker/st_extensions.c b/src/mesa/state_tracker/st_extensions.c index 57fe72d76a..ef3cbc53ee 100644 --- a/src/mesa/state_tracker/st_extensions.c +++ b/src/mesa/state_tracker/st_extensions.c @@ -92,6 +92,10 @@ void st_init_limits(struct st_context *st)        = _min(screen->get_param(screen, PIPE_CAP_MAX_VERTEX_TEXTURE_UNITS),               MAX_VERTEX_TEXTURE_IMAGE_UNITS); +   c->MaxCombinedTextureImageUnits +      = _min(screen->get_param(screen, PIPE_CAP_MAX_COMBINED_SAMPLERS), +             MAX_COMBINED_TEXTURE_IMAGE_UNITS); +     c->MaxTextureCoordUnits        = _min(c->MaxTextureImageUnits, MAX_TEXTURE_COORD_UNITS); diff --git a/src/mesa/state_tracker/st_gen_mipmap.c b/src/mesa/state_tracker/st_gen_mipmap.c index 16ca2771b0..f8068fa12b 100644 --- a/src/mesa/state_tracker/st_gen_mipmap.c +++ b/src/mesa/state_tracker/st_gen_mipmap.c @@ -38,6 +38,7 @@  #include "pipe/p_defines.h"  #include "pipe/p_inlines.h"  #include "util/u_gen_mipmap.h" +#include "util/u_math.h"  #include "cso_cache/cso_cache.h"  #include "cso_cache/cso_context.h" @@ -133,14 +134,14 @@ fallback_generate_mipmap(GLcontext *ctx, GLenum target,        srcTrans = st_cond_flush_get_tex_transfer(st_context(ctx), pt, face,  						srcLevel, zslice,  						PIPE_TRANSFER_READ, 0, 0, -						pt->width[srcLevel], -						pt->height[srcLevel]); +						u_minify(pt->width0, srcLevel), +						u_minify(pt->height0, srcLevel));        dstTrans = st_cond_flush_get_tex_transfer(st_context(ctx), pt, face,  						dstLevel, zslice,  						PIPE_TRANSFER_WRITE, 0, 0, -						pt->width[dstLevel], -						pt->height[dstLevel]); +						u_minify(pt->width0, dstLevel), +						u_minify(pt->height0, dstLevel));        srcData = (ubyte *) screen->transfer_map(screen, srcTrans);        dstData = (ubyte *) screen->transfer_map(screen, dstTrans); @@ -149,13 +150,17 @@ fallback_generate_mipmap(GLcontext *ctx, GLenum target,        dstStride = dstTrans->stride / dstTrans->block.size;        _mesa_generate_mipmap_level(target, datatype, comps, -                   0 /*border*/, -                   pt->width[srcLevel], pt->height[srcLevel], pt->depth[srcLevel], -                   srcData, -                   srcStride, /* stride in texels */ -                   pt->width[dstLevel], pt->height[dstLevel], pt->depth[dstLevel], -                   dstData, -                   dstStride); /* stride in texels */ +                                  0 /*border*/, +                                  u_minify(pt->width0, srcLevel), +                                  u_minify(pt->height0, srcLevel), +                                  u_minify(pt->depth0, srcLevel), +                                  srcData, +                                  srcStride, /* stride in texels */ +                                  u_minify(pt->width0, dstLevel), +                                  u_minify(pt->height0, dstLevel), +                                  u_minify(pt->depth0, dstLevel), +                                  dstData, +                                  dstStride); /* stride in texels */        screen->transfer_unmap(screen, srcTrans);        screen->transfer_unmap(screen, dstTrans); @@ -232,9 +237,9 @@ st_generate_mipmap(GLcontext *ctx, GLenum target,                                      oldTex->target,                                      oldTex->format,                                      lastLevel, -                                    oldTex->width[0], -                                    oldTex->height[0], -                                    oldTex->depth[0], +                                    oldTex->width0, +                                    oldTex->height0, +                                    oldTex->depth0,                                      oldTex->tex_usage);        /* The texture isn't in a "complete" state yet so set the expected @@ -269,9 +274,9 @@ st_generate_mipmap(GLcontext *ctx, GLenum target,           = _mesa_get_tex_image(ctx, texObj, target, srcLevel);        struct gl_texture_image *dstImage;        struct st_texture_image *stImage; -      uint dstWidth = pt->width[dstLevel]; -      uint dstHeight = pt->height[dstLevel]; -      uint dstDepth = pt->depth[dstLevel]; +      uint dstWidth = u_minify(pt->width0, dstLevel); +      uint dstHeight = u_minify(pt->height0, dstLevel); +      uint dstDepth = u_minify(pt->depth0, dstLevel);         uint border = srcImage->Border;        dstImage = _mesa_get_tex_image(ctx, texObj, target, dstLevel); diff --git a/src/mesa/state_tracker/st_mesa_to_tgsi.c b/src/mesa/state_tracker/st_mesa_to_tgsi.c index 3d6c215819..5e8e61135e 100644 --- a/src/mesa/state_tracker/st_mesa_to_tgsi.c +++ b/src/mesa/state_tracker/st_mesa_to_tgsi.c @@ -676,6 +676,31 @@ emit_inverted_wpos( struct st_translate *t,  /** + * OpenGL's fragment gl_FrontFace input is 1 for front-facing, 0 for back. + * TGSI uses +1 for front, -1 for back. + * This function converts the TGSI value to the GL value.  Simply clamping/ + * saturating the value to [0,1] does the job. + */ +static void +emit_face_var( struct st_translate *t, +               const struct gl_program *program ) +{ +   struct ureg_program *ureg = t->ureg; +   struct ureg_dst face_temp = ureg_DECL_temporary( ureg ); +   struct ureg_src face_input = t->inputs[t->inputMapping[FRAG_ATTRIB_FACE]]; + +   /* MOV_SAT face_temp, input[face] +    */ +   face_temp = ureg_saturate( face_temp ); +   ureg_MOV( ureg, face_temp, face_input ); + +   /* Use face_temp as face input from here on: +    */ +   t->inputs[t->inputMapping[FRAG_ATTRIB_FACE]] = ureg_src(face_temp); +} + + +/**   * Translate Mesa program to TGSI format.   * \param program  the program to translate   * \param numInputs  number of input registers used @@ -704,12 +729,10 @@ st_translate_mesa_program(     const ubyte inputSemanticName[],     const ubyte inputSemanticIndex[],     const GLuint interpMode[], -   const GLbitfield inputFlags[],     GLuint numOutputs,     const GLuint outputMapping[],     const ubyte outputSemanticName[], -   const ubyte outputSemanticIndex[], -   const GLbitfield outputFlags[] ) +   const ubyte outputSemanticIndex[] )  {     struct st_translate translate, *t;     struct ureg_program *ureg; @@ -748,6 +771,10 @@ st_translate_mesa_program(           emit_inverted_wpos( t, program );        } +      if (program->InputsRead & FRAG_BIT_FACE) { +         emit_face_var( t, program ); +      } +        /*         * Declare output attributes.         */ diff --git a/src/mesa/state_tracker/st_mesa_to_tgsi.h b/src/mesa/state_tracker/st_mesa_to_tgsi.h index c0d1ff59e1..dc0362fe79 100644 --- a/src/mesa/state_tracker/st_mesa_to_tgsi.h +++ b/src/mesa/state_tracker/st_mesa_to_tgsi.h @@ -49,12 +49,10 @@ st_translate_mesa_program(     const ubyte inputSemanticName[],     const ubyte inputSemanticIndex[],     const GLuint interpMode[], -   const GLbitfield inputFlags[],     GLuint numOutputs,     const GLuint outputMapping[],     const ubyte outputSemanticName[], -   const ubyte outputSemanticIndex[], -   const GLbitfield outputFlags[] ); +   const ubyte outputSemanticIndex[] );  void  st_free_tokens(const struct tgsi_token *tokens); diff --git a/src/mesa/state_tracker/st_program.c b/src/mesa/state_tracker/st_program.c index 190b6a5526..d66f45d13e 100644 --- a/src/mesa/state_tracker/st_program.c +++ b/src/mesa/state_tracker/st_program.c @@ -49,6 +49,36 @@  #include "st_mesa_to_tgsi.h"  #include "cso_cache/cso_context.h" +   /* Clean out any old compilations: +    */ +void +st_vp_release_varients( struct st_context *st, +                        struct st_vertex_program *stvp ) +{ +   struct st_vp_varient *vpv; + +   for (vpv = stvp->varients; vpv; ) { +      struct st_vp_varient *next = vpv->next; + +      if (vpv->driver_shader)  +         cso_delete_vertex_shader(st->cso_context, vpv->driver_shader); +       +      if (vpv->draw_shader) +         draw_delete_vertex_shader( st->draw, vpv->draw_shader ); +       +      if (vpv->state.tokens) +         st_free_tokens(vpv->state.tokens); +       +      FREE( vpv ); + +      vpv = next; +   } + +   stvp->varients = NULL; +} + + +  /**   * Translate a Mesa vertex shader into a TGSI shader. @@ -58,31 +88,13 @@   * \return  pointer to cached pipe_shader object.   */  void -st_translate_vertex_program(struct st_context *st, -                            struct st_vertex_program *stvp, -                            const GLuint outputMapping[], -                            const ubyte *outputSemanticName, -                            const ubyte *outputSemanticIndex) +st_prepare_vertex_program(struct st_context *st, +                            struct st_vertex_program *stvp)  { -   struct pipe_context *pipe = st->pipe; -   GLuint defaultOutputMapping[VERT_RESULT_MAX]; -   GLuint attr, i; -   GLuint num_generic = 0; - -   ubyte vs_input_semantic_name[PIPE_MAX_SHADER_INPUTS]; -   ubyte vs_input_semantic_index[PIPE_MAX_SHADER_INPUTS]; -   uint vs_num_inputs = 0; - -   ubyte vs_output_semantic_name[PIPE_MAX_SHADER_OUTPUTS]; -   ubyte vs_output_semantic_index[PIPE_MAX_SHADER_OUTPUTS]; -   uint vs_num_outputs = 0; - -   GLbitfield input_flags[MAX_PROGRAM_INPUTS]; -   GLbitfield output_flags[MAX_PROGRAM_OUTPUTS]; +   GLuint attr; -   /*memset(&vs, 0, sizeof(vs));*/ -   memset(input_flags, 0, sizeof(input_flags)); -   memset(output_flags, 0, sizeof(output_flags)); +   stvp->num_inputs = 0; +   stvp->num_outputs = 0;     if (stvp->Base.IsPositionInvariant)        _mesa_insert_mvp_code(st->ctx, &stvp->Base); @@ -93,162 +105,56 @@ st_translate_vertex_program(struct st_context *st,      */     for (attr = 0; attr < VERT_ATTRIB_MAX; attr++) {        if (stvp->Base.Base.InputsRead & (1 << attr)) { -         const GLuint slot = vs_num_inputs; - -         vs_num_inputs++; - -         stvp->input_to_index[attr] = slot; -         stvp->index_to_input[slot] = attr; - -         switch (attr) { -         case VERT_ATTRIB_POS: -            vs_input_semantic_name[slot] = TGSI_SEMANTIC_POSITION; -            vs_input_semantic_index[slot] = 0; -            break; -         case VERT_ATTRIB_WEIGHT: -            /* fall-through */ -         case VERT_ATTRIB_NORMAL: -            /* just label as a generic */ -            vs_input_semantic_name[slot] = TGSI_SEMANTIC_GENERIC; -            vs_input_semantic_index[slot] = 0; -            break; -         case VERT_ATTRIB_COLOR0: -            vs_input_semantic_name[slot] = TGSI_SEMANTIC_COLOR; -            vs_input_semantic_index[slot] = 0; -            break; -         case VERT_ATTRIB_COLOR1: -            vs_input_semantic_name[slot] = TGSI_SEMANTIC_COLOR; -            vs_input_semantic_index[slot] = 1; -            break; -         case VERT_ATTRIB_FOG: -            vs_input_semantic_name[slot] = TGSI_SEMANTIC_FOG; -            vs_input_semantic_index[slot] = 0; -            break; -         case VERT_ATTRIB_POINT_SIZE: -            vs_input_semantic_name[slot] = TGSI_SEMANTIC_PSIZE; -            vs_input_semantic_index[slot] = 0; -            break; -         case VERT_ATTRIB_TEX0: -         case VERT_ATTRIB_TEX1: -         case VERT_ATTRIB_TEX2: -         case VERT_ATTRIB_TEX3: -         case VERT_ATTRIB_TEX4: -         case VERT_ATTRIB_TEX5: -         case VERT_ATTRIB_TEX6: -         case VERT_ATTRIB_TEX7: -            assert(slot < Elements(vs_input_semantic_name)); -            vs_input_semantic_name[slot] = TGSI_SEMANTIC_GENERIC; -            vs_input_semantic_index[slot] = num_generic++; -            break; -         case VERT_ATTRIB_GENERIC0: -         case VERT_ATTRIB_GENERIC1: -         case VERT_ATTRIB_GENERIC2: -         case VERT_ATTRIB_GENERIC3: -         case VERT_ATTRIB_GENERIC4: -         case VERT_ATTRIB_GENERIC5: -         case VERT_ATTRIB_GENERIC6: -         case VERT_ATTRIB_GENERIC7: -         case VERT_ATTRIB_GENERIC8: -         case VERT_ATTRIB_GENERIC9: -         case VERT_ATTRIB_GENERIC10: -         case VERT_ATTRIB_GENERIC11: -         case VERT_ATTRIB_GENERIC12: -         case VERT_ATTRIB_GENERIC13: -         case VERT_ATTRIB_GENERIC14: -         case VERT_ATTRIB_GENERIC15: -            assert(attr < VERT_ATTRIB_MAX); -            assert(slot < Elements(vs_input_semantic_name)); -            vs_input_semantic_name[slot] = TGSI_SEMANTIC_GENERIC; -            vs_input_semantic_index[slot] = num_generic++; -            break; -         default: -            assert(0); -         } - -         input_flags[slot] = stvp->Base.Base.InputFlags[attr]; -      } -   } - -#if 0 -   if (outputMapping && outputSemanticName) { -      printf("VERT_RESULT  written  out_slot  semantic_name  semantic_index\n"); -      for (attr = 0; attr < VERT_RESULT_MAX; attr++) { -         printf("    %-2d          %c       %3d          %2d              %2d\n", -                attr,  -                ((stvp->Base.Base.OutputsWritten & (1 << attr)) ? 'Y' : ' '), -                outputMapping[attr], -                outputSemanticName[attr], -                outputSemanticIndex[attr]); +         stvp->input_to_index[attr] = stvp->num_inputs; +         stvp->index_to_input[stvp->num_inputs] = attr; +         stvp->num_inputs++;        }     } -#endif -   /* initialize output semantics to defaults */ -   for (i = 0; i < PIPE_MAX_SHADER_OUTPUTS; i++) { -      assert(i < Elements(vs_output_semantic_name)); -      vs_output_semantic_name[i] = TGSI_SEMANTIC_GENERIC; -      vs_output_semantic_index[i] = 0; -      output_flags[i] = 0x0; -   } - -   num_generic = 0; -   /* -    * Determine number of outputs, the (default) output register -    * mapping and the semantic information for each output. +   /* Compute mapping of vertex program outputs to slots.      */     for (attr = 0; attr < VERT_RESULT_MAX; attr++) { -      if (stvp->Base.Base.OutputsWritten & (1 << attr)) { -         GLuint slot; - -         /* XXX -          * Pass in the fragment program's input's semantic info. -          * Use the generic semantic indexes from there, instead of -          * guessing below. -          */ +      if ((stvp->Base.Base.OutputsWritten & (1 << attr)) == 0) { +         stvp->result_to_output[attr] = ~0; +      } +      else { +         unsigned slot = stvp->num_outputs++; -         if (outputMapping) { -            slot = outputMapping[attr]; -            assert(slot != ~0); -         } -         else { -            slot = vs_num_outputs; -            vs_num_outputs++; -            defaultOutputMapping[attr] = slot; -         } +         stvp->result_to_output[attr] = slot;           switch (attr) {           case VERT_RESULT_HPOS: -            assert(slot == 0); -            vs_output_semantic_name[slot] = TGSI_SEMANTIC_POSITION; -            vs_output_semantic_index[slot] = 0; +            stvp->output_semantic_name[slot] = TGSI_SEMANTIC_POSITION; +            stvp->output_semantic_index[slot] = 0;              break;           case VERT_RESULT_COL0: -            vs_output_semantic_name[slot] = TGSI_SEMANTIC_COLOR; -            vs_output_semantic_index[slot] = 0; +            stvp->output_semantic_name[slot] = TGSI_SEMANTIC_COLOR; +            stvp->output_semantic_index[slot] = 0;              break;           case VERT_RESULT_COL1: -            vs_output_semantic_name[slot] = TGSI_SEMANTIC_COLOR; -            vs_output_semantic_index[slot] = 1; +            stvp->output_semantic_name[slot] = TGSI_SEMANTIC_COLOR; +            stvp->output_semantic_index[slot] = 1;              break;           case VERT_RESULT_BFC0: -            vs_output_semantic_name[slot] = TGSI_SEMANTIC_BCOLOR; -            vs_output_semantic_index[slot] = 0; +            stvp->output_semantic_name[slot] = TGSI_SEMANTIC_BCOLOR; +            stvp->output_semantic_index[slot] = 0;              break;           case VERT_RESULT_BFC1: -            vs_output_semantic_name[slot] = TGSI_SEMANTIC_BCOLOR; -            vs_output_semantic_index[slot] = 1; +            stvp->output_semantic_name[slot] = TGSI_SEMANTIC_BCOLOR; +            stvp->output_semantic_index[slot] = 1;              break;           case VERT_RESULT_FOGC: -            vs_output_semantic_name[slot] = TGSI_SEMANTIC_FOG; -            vs_output_semantic_index[slot] = 0; +            stvp->output_semantic_name[slot] = TGSI_SEMANTIC_FOG; +            stvp->output_semantic_index[slot] = 0;              break;           case VERT_RESULT_PSIZ: -            vs_output_semantic_name[slot] = TGSI_SEMANTIC_PSIZE; -            vs_output_semantic_index[slot] = 0; +            stvp->output_semantic_name[slot] = TGSI_SEMANTIC_PSIZE; +            stvp->output_semantic_index[slot] = 0;              break;           case VERT_RESULT_EDGE:              assert(0);              break; +           case VERT_RESULT_TEX0:           case VERT_RESULT_TEX1:           case VERT_RESULT_TEX2: @@ -257,92 +163,50 @@ st_translate_vertex_program(struct st_context *st,           case VERT_RESULT_TEX5:           case VERT_RESULT_TEX6:           case VERT_RESULT_TEX7: -            /* fall-through */ +            stvp->output_semantic_name[slot] = TGSI_SEMANTIC_GENERIC; +            stvp->output_semantic_index[slot] = attr - VERT_RESULT_TEX0; +            break; +           case VERT_RESULT_VAR0: -            /* fall-through */           default: -            assert(slot < Elements(vs_output_semantic_name)); -            if (outputSemanticName) { -               /* use provided semantic into */ -               assert(outputSemanticName[attr] != TGSI_SEMANTIC_COUNT); -               vs_output_semantic_name[slot] = outputSemanticName[attr]; -               vs_output_semantic_index[slot] = outputSemanticIndex[attr]; -            } -            else { -               /* use default semantic info */ -               vs_output_semantic_name[slot] = TGSI_SEMANTIC_GENERIC; -               vs_output_semantic_index[slot] = num_generic++; -            } +            assert(attr < VERT_RESULT_MAX); +            stvp->output_semantic_name[slot] = TGSI_SEMANTIC_GENERIC; +            stvp->output_semantic_index[slot] = (FRAG_ATTRIB_VAR0 -  +                                                FRAG_ATTRIB_TEX0 + +                                                attr -  +                                                VERT_RESULT_VAR0); +            break;           } - -         assert(slot < Elements(output_flags)); -         output_flags[slot] = stvp->Base.Base.OutputFlags[attr]; -      } -   } - -   if (outputMapping) { -      /* find max output slot referenced to compute vs_num_outputs */ -      GLuint maxSlot = 0; -      for (attr = 0; attr < VERT_RESULT_MAX; attr++) { -         if (outputMapping[attr] != ~0 && outputMapping[attr] > maxSlot) -            maxSlot = outputMapping[attr];        } -      vs_num_outputs = maxSlot + 1; -   } -   else { -      outputMapping = defaultOutputMapping;     } +} -#if 0 /* debug */ -   { -      GLuint i; -      printf("outputMapping? %d\n", outputMapping ? 1 : 0); -      if (outputMapping) { -         printf("attr -> slot\n"); -         for (i = 0; i < 16;  i++) { -            printf(" %2d       %3d\n", i, outputMapping[i]); -         } -      } -      printf("slot    sem_name  sem_index\n"); -      for (i = 0; i < vs_num_outputs; i++) { -         printf(" %2d         %d         %d\n", -                i, -                vs_output_semantic_name[i], -                vs_output_semantic_index[i]); -      } -   } -#endif -   /* free old shader state, if any */ -   if (stvp->state.tokens) { -      st_free_tokens(stvp->state.tokens); -      stvp->state.tokens = NULL; -   } -   if (stvp->driver_shader) { -      cso_delete_vertex_shader(st->cso_context, stvp->driver_shader); -      stvp->driver_shader = NULL; -   } +struct st_vp_varient * +st_translate_vertex_program(struct st_context *st, +                            struct st_vertex_program *stvp, +                            const struct st_vp_varient_key *key) +{ +   struct st_vp_varient *vpv = CALLOC_STRUCT(st_vp_varient); +   struct pipe_context *pipe = st->pipe; -   stvp->state.tokens =  +   vpv->state.tokens =         st_translate_mesa_program(st->ctx,                                  TGSI_PROCESSOR_VERTEX,                                  &stvp->Base.Base,                                  /* inputs */ -                                vs_num_inputs, +                                stvp->num_inputs,                                  stvp->input_to_index, -                                vs_input_semantic_name, -                                vs_input_semantic_index, +                                NULL, /* input semantic name */ +                                NULL, /* input semantic index */                                  NULL, -                                input_flags,                                  /* outputs */ -                                vs_num_outputs, -                                outputMapping, -                                vs_output_semantic_name, -                                vs_output_semantic_index, -                                output_flags ); +                                stvp->num_outputs, +                                stvp->result_to_output, +                                stvp->output_semantic_name, +                                stvp->output_semantic_index ); -   stvp->num_inputs = vs_num_inputs; -   stvp->driver_shader = pipe->create_vs_state(pipe, &stvp->state); +   vpv->driver_shader = pipe->create_vs_state(pipe, &vpv->state);     if ((ST_DEBUG & DEBUG_TGSI) && (ST_DEBUG & DEBUG_MESA)) {        _mesa_print_program(&stvp->Base.Base); @@ -350,9 +214,11 @@ st_translate_vertex_program(struct st_context *st,     }     if (ST_DEBUG & DEBUG_TGSI) { -      tgsi_dump( stvp->state.tokens, 0 ); +      tgsi_dump( vpv->state.tokens, 0 );        debug_printf("\n");     } + +   return vpv;  } @@ -375,7 +241,6 @@ st_translate_fragment_program(struct st_context *st,     GLuint attr;     const GLbitfield inputsRead = stfp->Base.Base.InputsRead;     GLuint vslot = 0; -   GLuint num_generic = 0;     uint fs_num_inputs = 0; @@ -383,13 +248,6 @@ st_translate_fragment_program(struct st_context *st,     ubyte fs_output_semantic_index[PIPE_MAX_SHADER_OUTPUTS];     uint fs_num_outputs = 0; -   GLbitfield input_flags[MAX_PROGRAM_INPUTS]; -   GLbitfield output_flags[MAX_PROGRAM_OUTPUTS]; - -   /*memset(&fs, 0, sizeof(fs));*/ -   memset(input_flags, 0, sizeof(input_flags)); -   memset(output_flags, 0, sizeof(output_flags)); -     /* which vertex output goes to the first fragment input: */     if (inputsRead & FRAG_BIT_WPOS)        vslot = 0; @@ -432,14 +290,25 @@ st_translate_fragment_program(struct st_context *st,              break;           case FRAG_ATTRIB_FACE:              stfp->input_semantic_name[slot] = TGSI_SEMANTIC_FACE; -            stfp->input_semantic_index[slot] = num_generic++; +            stfp->input_semantic_index[slot] = 0;              interpMode[slot] = TGSI_INTERPOLATE_CONSTANT;              break; -         case FRAG_ATTRIB_PNTC: -            stfp->input_semantic_name[slot] = TGSI_SEMANTIC_GENERIC; -            stfp->input_semantic_index[slot] = num_generic++; -            interpMode[slot] = TGSI_INTERPOLATE_PERSPECTIVE; -            break; + +            /* In most cases, there is nothing special about these +             * inputs, so adopt a convention to use the generic +             * semantic name and the mesa FRAG_ATTRIB_ number as the +             * index.  +             *  +             * All that is required is that the vertex shader labels +             * its own outputs similarly, and that the vertex shader +             * generates at least every output required by the +             * fragment shader plus fixed-function hardware (such as +             * BFC). +             *  +             * There is no requirement that semantic indexes start at +             * zero or be restricted to a particular range -- nobody +             * should be building tables based on semantic index. +             */           case FRAG_ATTRIB_TEX0:           case FRAG_ATTRIB_TEX1:           case FRAG_ATTRIB_TEX2: @@ -448,19 +317,18 @@ st_translate_fragment_program(struct st_context *st,           case FRAG_ATTRIB_TEX5:           case FRAG_ATTRIB_TEX6:           case FRAG_ATTRIB_TEX7: -            stfp->input_semantic_name[slot] = TGSI_SEMANTIC_GENERIC; -            stfp->input_semantic_index[slot] = num_generic++; -            interpMode[slot] = TGSI_INTERPOLATE_PERSPECTIVE; -            break; +         case FRAG_ATTRIB_PNTC:           case FRAG_ATTRIB_VAR0: -            /* fall-through */           default: +            /* Actually, let's try and zero-base this just for +             * readability of the generated TGSI. +             */ +            assert(attr >= FRAG_ATTRIB_TEX0); +            stfp->input_semantic_index[slot] = (attr - FRAG_ATTRIB_TEX0);              stfp->input_semantic_name[slot] = TGSI_SEMANTIC_GENERIC; -            stfp->input_semantic_index[slot] = num_generic++;              interpMode[slot] = TGSI_INTERPOLATE_PERSPECTIVE; +            break;           } - -         input_flags[slot] = stfp->Base.Base.InputFlags[attr];        }     } @@ -498,8 +366,6 @@ st_translate_fragment_program(struct st_context *st,                 break;              } -            output_flags[fs_num_outputs] = stfp->Base.Base.OutputFlags[attr]; -              fs_num_outputs++;           }        } @@ -518,13 +384,11 @@ st_translate_fragment_program(struct st_context *st,                                  stfp->input_semantic_name,                                  stfp->input_semantic_index,                                  interpMode, -                                input_flags,                                  /* outputs */                                  fs_num_outputs,                                  outputMapping,                                  fs_output_semantic_name, -                                fs_output_semantic_index, -                                output_flags ); +                                fs_output_semantic_index );     stfp->driver_shader = pipe->create_fs_state(pipe, &stfp->state); diff --git a/src/mesa/state_tracker/st_program.h b/src/mesa/state_tracker/st_program.h index e2e5eddef2..88aadbd751 100644 --- a/src/mesa/state_tracker/st_program.h +++ b/src/mesa/state_tracker/st_program.h @@ -64,41 +64,70 @@ struct st_fragment_program     struct pipe_shader_state state;     void *driver_shader; -   GLuint param_state; - -   /** List of vertex programs which have been translated such that their -    * 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;  }; + +struct st_vp_varient_key +{ +   char dummy;                  /* currently unused */ +}; + + +/** + * This represents a vertex program, especially translated to match + * the inputs of a particular fragment shader. + */ +struct st_vp_varient +{ +   /* Parameters which generated this translated version of a vertex +    * shader: +    */ +   struct st_vp_varient_key key; + +   /** TGSI tokens -- why? +    */ +   struct pipe_shader_state state; + +   /** Driver's compiled shader */ +   void *driver_shader; + +   /** For using our private draw module (glRasterPos) */ +   struct draw_vertex_shader *draw_shader; + +   /** Next in linked list */ +   struct st_vp_varient *next;   +}; + + + +  /**   * Derived from Mesa gl_fragment_program:   */  struct st_vertex_program  {     struct gl_vertex_program Base;  /**< The Mesa vertex program */ -   GLuint serialNo; +   GLuint serialNo, lastSerialNo;     /** maps a Mesa VERT_ATTRIB_x to a packed TGSI input index */     GLuint input_to_index[VERT_ATTRIB_MAX];     /** maps a TGSI input index back to a Mesa VERT_ATTRIB_x */     GLuint index_to_input[PIPE_MAX_SHADER_INPUTS]; -     GLuint num_inputs; -   struct pipe_shader_state state; -   void *driver_shader; +   /** Maps VERT_RESULT_x to slot */ +   GLuint result_to_output[VERT_RESULT_MAX]; +   ubyte output_semantic_name[VERT_RESULT_MAX]; +   ubyte output_semantic_index[VERT_RESULT_MAX]; +   GLuint num_outputs; -   /** For using our private draw module (glRasterPos) */ -   struct draw_vertex_shader *draw_shader; - -   GLuint param_state; +   /** List of translated varients of this vertex program. +    */ +   struct st_vp_varient *varients;  }; @@ -143,13 +172,21 @@ st_translate_fragment_program(struct st_context *st,                                const GLuint inputMapping[]); +/* Called after program string change, discard all previous + * compilation results. + */  extern void +st_prepare_vertex_program(struct st_context *st, +                          struct st_vertex_program *stvp); + +extern struct st_vp_varient *  st_translate_vertex_program(struct st_context *st, -                            struct st_vertex_program *vp, -                            const GLuint vert_output_to_slot[], -                            const ubyte *fs_input_semantic_name, -                            const ubyte *fs_input_semantic_index); +                            struct st_vertex_program *stvp, +                            const struct st_vp_varient_key *key); +void +st_vp_release_varients( struct st_context *st, +                        struct st_vertex_program *stvp );  extern void  st_print_shaders(GLcontext *ctx); diff --git a/src/mesa/state_tracker/st_texture.c b/src/mesa/state_tracker/st_texture.c index 10f1351283..dbccee86c1 100644 --- a/src/mesa/state_tracker/st_texture.c +++ b/src/mesa/state_tracker/st_texture.c @@ -44,6 +44,7 @@  #include "pipe/p_defines.h"  #include "pipe/p_inlines.h"  #include "util/u_rect.h" +#include "util/u_math.h"  #define DBG if(0) printf @@ -100,9 +101,9 @@ st_texture_create(struct st_context *st,     pt.target = target;     pt.format = format;     pt.last_level = last_level; -   pt.width[0] = width0; -   pt.height[0] = height0; -   pt.depth[0] = depth0; +   pt.width0 = width0; +   pt.height0 = height0; +   pt.depth0 = depth0;     pf_get_block(format, &pt.block);     pt.tex_usage = usage; @@ -135,9 +136,9 @@ st_texture_match_image(const struct pipe_texture *pt,     /* Test if this image's size matches what's expected in the      * established texture.      */ -   if (image->Width != pt->width[level] || -       image->Height != pt->height[level] || -       image->Depth != pt->depth[level]) +   if (image->Width != u_minify(pt->width0, level) || +       image->Height != u_minify(pt->height0, level) || +       image->Depth != u_minify(pt->depth0, level))        return GL_FALSE;     return GL_TRUE; @@ -265,7 +266,7 @@ st_texture_image_data(struct st_context *st,  {     struct pipe_context *pipe = st->pipe;     struct pipe_screen *screen = pipe->screen; -   GLuint depth = dst->depth[level]; +   GLuint depth = u_minify(dst->depth0, level);     GLuint i;     const GLubyte *srcUB = src;     struct pipe_transfer *dst_transfer; @@ -275,15 +276,16 @@ st_texture_image_data(struct st_context *st,     for (i = 0; i < depth; i++) {        dst_transfer = st_no_flush_get_tex_transfer(st, dst, face, level, i,  						  PIPE_TRANSFER_WRITE, 0, 0, -						  dst->width[level], -						  dst->height[level]); +						  u_minify(dst->width0, level), +                                                  u_minify(dst->height0, level));        st_surface_data(pipe, dst_transfer,  		      0, 0,                             /* dstx, dsty */  		      srcUB,  		      src_row_stride,  		      0, 0,                             /* source x, y */ -		      dst->width[level], dst->height[level]);       /* width, height */ +		      u_minify(dst->width0, level), +                      u_minify(dst->height0, level));      /* width, height */        screen->tex_transfer_destroy(dst_transfer); @@ -301,9 +303,9 @@ st_texture_image_copy(struct pipe_context *pipe,                        GLuint face)  {     struct pipe_screen *screen = pipe->screen; -   GLuint width = dst->width[dstLevel]; -   GLuint height = dst->height[dstLevel]; -   GLuint depth = dst->depth[dstLevel]; +   GLuint width = u_minify(dst->width0, dstLevel);  +   GLuint height = u_minify(dst->height0, dstLevel);  +   GLuint depth = u_minify(dst->depth0, dstLevel);      struct pipe_surface *src_surface;     struct pipe_surface *dst_surface;     GLuint i; @@ -313,13 +315,13 @@ st_texture_image_copy(struct pipe_context *pipe,        /* find src texture level of needed size */        for (srcLevel = 0; srcLevel <= src->last_level; srcLevel++) { -         if (src->width[srcLevel] == width && -             src->height[srcLevel] == height) { +         if (u_minify(src->width0, srcLevel) == width && +             u_minify(src->height0, srcLevel) == height) {              break;           }        } -      assert(src->width[srcLevel] == width); -      assert(src->height[srcLevel] == height); +      assert(u_minify(src->width0, srcLevel) == width); +      assert(u_minify(src->height0, srcLevel) == height);  #if 0        { | 
