static int emit_vs_consts( struct svga_context *svga,
                           unsigned dirty )
{
   const struct svga_shader_result *result = svga->state.hw_draw.vs;
   const struct svga_vs_compile_key *key = &result->key.vkey;
   int ret = 0;
   unsigned offset;

   /* SVGA_NEW_VS_RESULT
    */
   if (result == NULL) 
      return 0;

   /* SVGA_NEW_VS_CONST_BUFFER 
    */
   ret = emit_consts( svga, 0, PIPE_SHADER_VERTEX );
   if (ret)
      return ret;

   offset = result->shader->info.file_max[TGSI_FILE_CONSTANT] + 1;

   /* SVGA_NEW_VS_RESULT
    */
   if (key->need_prescale) {
      ret = emit_const( svga, PIPE_SHADER_VERTEX, offset++,
                        svga->state.hw_clear.prescale.scale );
      if (ret)
         return ret;

      ret = emit_const( svga, PIPE_SHADER_VERTEX, offset++,
                        svga->state.hw_clear.prescale.translate );
      if (ret)
         return ret;
   }

   /* SVGA_NEW_ZERO_STRIDE
    */
   if (key->zero_stride_vertex_elements) {
      unsigned i, curr_zero_stride = 0;
      for (i = 0; i < PIPE_MAX_ATTRIBS; ++i) {
         if (key->zero_stride_vertex_elements & (1 << i)) {
            ret = emit_const( svga, PIPE_SHADER_VERTEX, offset++,
                              svga->curr.zero_stride_constants +
                              4 * curr_zero_stride );
            if (ret)
               return ret;
            ++curr_zero_stride;
         }
      }
   }

   return 0;
}
static int emit_fs_consts( struct svga_context *svga,
                           unsigned dirty )
{
   const struct svga_shader_result *result = svga->state.hw_draw.fs;
   const struct svga_fs_compile_key *key = &result->key.fkey;
   int ret = 0;

   ret = emit_consts( svga, 0, PIPE_SHADER_FRAGMENT );
   if (ret)
      return ret;

   /* The internally generated fragment shader for xor blending
    * doesn't have a 'result' struct.  It should be fixed to avoid
    * this special case, but work around it with a NULL check:
    */
   if (result != NULL &&
       key->num_unnormalized_coords)
   {
      unsigned offset = result->shader->info.file_max[TGSI_FILE_CONSTANT] + 1;
      int i;

      for (i = 0; i < key->num_textures; i++) {
         if (key->tex[i].unnormalized) {
            struct pipe_resource *tex = svga->curr.sampler_views[i]->texture;
            float data[4];

            data[0] = 1.0 / (float)tex->width0;
            data[1] = 1.0 / (float)tex->height0;
            data[2] = 1.0;
            data[3] = 1.0;

            ret = emit_const( svga,
                              PIPE_SHADER_FRAGMENT,
                              key->tex[i].width_height_idx + offset,
                              data );
            if (ret)
               return ret;
         }
      }

      offset += key->num_unnormalized_coords;
   }

   return 0;
}
static enum pipe_error
emit_vs_consts(struct svga_context *svga, unsigned dirty)
{
   const struct svga_shader_result *result = svga->state.hw_draw.vs;
   const struct svga_vs_compile_key *key;
   enum pipe_error ret = PIPE_OK;
   unsigned offset;

   /* SVGA_NEW_VS_RESULT
    */
   if (result == NULL)
      return PIPE_OK;

   key = &result->key.vkey;

   /* SVGA_NEW_VS_CONST_BUFFER
    */
   ret = emit_consts( svga, PIPE_SHADER_VERTEX );
   if (ret != PIPE_OK)
      return ret;

   /* offset = number of constants in the VS const buffer */
   offset = result->shader->info.file_max[TGSI_FILE_CONSTANT] + 1;

   /* SVGA_NEW_VS_PRESCALE
    * Put the viewport pre-scale/translate values into the const buffer.
    */
   if (key->need_prescale) {
      ret = emit_const( svga, PIPE_SHADER_VERTEX, offset++,
                        svga->state.hw_clear.prescale.scale );
      if (ret != PIPE_OK)
         return ret;

      ret = emit_const( svga, PIPE_SHADER_VERTEX, offset++,
                        svga->state.hw_clear.prescale.translate );
      if (ret != PIPE_OK)
         return ret;
   }

   return PIPE_OK;
}