st_atom_shader.c

Go to the documentation of this file.
00001 /**************************************************************************
00002  * 
00003  * Copyright 2003 Tungsten Graphics, Inc., Cedar Park, Texas.
00004  * All Rights Reserved.
00005  * 
00006  * Permission is hereby granted, free of charge, to any person obtaining a
00007  * copy of this software and associated documentation files (the
00008  * "Software"), to deal in the Software without restriction, including
00009  * without limitation the rights to use, copy, modify, merge, publish,
00010  * distribute, sub license, and/or sell copies of the Software, and to
00011  * permit persons to whom the Software is furnished to do so, subject to
00012  * the following conditions:
00013  * 
00014  * The above copyright notice and this permission notice (including the
00015  * next paragraph) shall be included in all copies or substantial portions
00016  * of the Software.
00017  * 
00018  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
00019  * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
00020  * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.
00021  * IN NO EVENT SHALL TUNGSTEN GRAPHICS AND/OR ITS SUPPLIERS BE LIABLE FOR
00022  * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
00023  * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
00024  * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
00025  * 
00026  **************************************************************************/
00027 
00040 #include "main/imports.h"
00041 #include "main/mtypes.h"
00042 #include "main/macros.h"
00043 #include "shader/program.h"
00044 
00045 #include "pipe/p_context.h"
00046 #include "pipe/p_shader_tokens.h"
00047 
00048 #include "util/u_simple_shaders.h"
00049 
00050 #include "cso_cache/cso_context.h"
00051 
00052 #include "st_context.h"
00053 #include "st_atom.h"
00054 #include "st_program.h"
00055 #include "st_atom_shader.h"
00056 #include "st_mesa_to_tgsi.h"
00057 
00058 
00063 struct translated_vertex_program
00064 {
00065    struct st_vertex_program *master;
00066 
00068    GLbitfield frag_inputs;
00069 
00071    GLuint serialNo;
00072 
00074    GLuint output_to_slot[VERT_RESULT_MAX];
00075    ubyte output_to_semantic_name[VERT_RESULT_MAX];
00076    ubyte output_to_semantic_index[VERT_RESULT_MAX];
00077 
00079    struct st_vertex_program *vp;
00080 
00081    struct translated_vertex_program *next;  
00082 };
00083 
00084 
00085 
00091 static GLint
00092 vp_out_to_fp_in(GLuint vertResult)
00093 {
00094    if (vertResult >= VERT_RESULT_TEX0 &&
00095        vertResult < VERT_RESULT_TEX0 + MAX_TEXTURE_COORD_UNITS)
00096       return FRAG_ATTRIB_TEX0 + (vertResult - VERT_RESULT_TEX0);
00097 
00098    if (vertResult >= VERT_RESULT_VAR0 &&
00099        vertResult < VERT_RESULT_VAR0 + MAX_VARYING)
00100       return FRAG_ATTRIB_VAR0 + (vertResult - VERT_RESULT_VAR0);
00101 
00102    switch (vertResult) {
00103    case VERT_RESULT_HPOS:
00104       return FRAG_ATTRIB_WPOS;
00105    case VERT_RESULT_COL0:
00106       return FRAG_ATTRIB_COL0;
00107    case VERT_RESULT_COL1:
00108       return FRAG_ATTRIB_COL1;
00109    case VERT_RESULT_FOGC:
00110       return FRAG_ATTRIB_FOGC;
00111    default:
00112       /* Back-face colors, edge flags, etc */
00113       return -1;
00114    }
00115 }
00116 
00117 
00123 static struct translated_vertex_program *
00124 find_translated_vp(struct st_context *st,
00125                    struct st_vertex_program *stvp,
00126                    struct st_fragment_program *stfp)
00127 {
00128    static const GLuint UNUSED = ~0;
00129    struct translated_vertex_program *xvp;
00130    const GLbitfield fragInputsRead = stfp->Base.Base.InputsRead;
00131 
00132    /*
00133     * Translate fragment program if needed.
00134     */
00135    if (!stfp->state.tokens) {
00136       GLuint inAttr, numIn = 0;
00137 
00138       for (inAttr = 0; inAttr < FRAG_ATTRIB_MAX; inAttr++) {
00139          if (fragInputsRead & (1 << inAttr)) {
00140             stfp->input_to_slot[inAttr] = numIn;
00141             numIn++;
00142          }
00143          else {
00144             stfp->input_to_slot[inAttr] = UNUSED;
00145          }
00146       }
00147 
00148       stfp->num_input_slots = numIn;
00149 
00150       assert(stfp->Base.Base.NumInstructions > 1);
00151 
00152       st_translate_fragment_program(st, stfp, stfp->input_to_slot);
00153    }
00154 
00155 
00156    /* See if we've got a translated vertex program whose outputs match
00157     * the fragment program's inputs.
00158     * XXX This could be a hash lookup, using InputsRead as the key.
00159     */
00160    for (xvp = stfp->vertex_programs; xvp; xvp = xvp->next) {
00161       if (xvp->master == stvp && xvp->frag_inputs == fragInputsRead) {
00162          break;
00163       }
00164    }
00165 
00166    /* No?  Allocate translated vp object now */
00167    if (!xvp) {
00168       xvp = CALLOC_STRUCT(translated_vertex_program);
00169       xvp->frag_inputs = fragInputsRead;
00170       xvp->master = stvp;
00171 
00172       xvp->next = stfp->vertex_programs;
00173       stfp->vertex_programs = xvp;
00174    }
00175 
00176    /* See if we need to translate vertex program to TGSI form */
00177    if (xvp->serialNo != stvp->serialNo) {
00178       GLuint outAttr, dummySlot;
00179       const GLbitfield outputsWritten = stvp->Base.Base.OutputsWritten;
00180       GLuint numVpOuts = 0;
00181       GLboolean emitPntSize = GL_FALSE, emitBFC0 = GL_FALSE, emitBFC1 = GL_FALSE;
00182       GLint maxGeneric;
00183 
00184       /* Compute mapping of vertex program outputs to slots, which depends
00185        * on the fragment program's input->slot mapping.
00186        */
00187       for (outAttr = 0; outAttr < VERT_RESULT_MAX; outAttr++) {
00188          /* set defaults: */
00189          xvp->output_to_slot[outAttr] = UNUSED;
00190          xvp->output_to_semantic_name[outAttr] = TGSI_SEMANTIC_COUNT;
00191          xvp->output_to_semantic_index[outAttr] = 99;
00192 
00193          if (outAttr == VERT_RESULT_HPOS) {
00194             /* always put xformed position into slot zero */
00195             xvp->output_to_slot[VERT_RESULT_HPOS] = 0;
00196             xvp->output_to_semantic_name[outAttr] = TGSI_SEMANTIC_POSITION;
00197             xvp->output_to_semantic_index[outAttr] = 0;
00198             numVpOuts++;
00199          }
00200          else if (outputsWritten & (1 << outAttr)) {
00201             /* see if the frag prog wants this vert output */
00202             GLint fpInAttrib = vp_out_to_fp_in(outAttr);
00203             if (fpInAttrib >= 0) {
00204                GLuint fpInSlot = stfp->input_to_slot[fpInAttrib];
00205                if (fpInSlot != ~0) {
00206                   /* match this vp output to the fp input */
00207                   GLuint vpOutSlot = stfp->input_map[fpInSlot];
00208                   xvp->output_to_slot[outAttr] = vpOutSlot;
00209                   xvp->output_to_semantic_name[outAttr] = stfp->input_semantic_name[fpInSlot];
00210                   xvp->output_to_semantic_index[outAttr] = stfp->input_semantic_index[fpInSlot];
00211                   numVpOuts++;
00212                }
00213             }
00214             else if (outAttr == VERT_RESULT_PSIZ)
00215                emitPntSize = GL_TRUE;
00216             else if (outAttr == VERT_RESULT_BFC0)
00217                emitBFC0 = GL_TRUE;
00218             else if (outAttr == VERT_RESULT_BFC1)
00219                emitBFC1 = GL_TRUE;
00220          }
00221 #if 0 /*debug*/
00222          printf("assign vp output_to_slot[%d] = %d\n", outAttr, 
00223                 xvp->output_to_slot[outAttr]);
00224 #endif
00225       }
00226 
00227       /* must do these last */
00228       if (emitPntSize) {
00229          xvp->output_to_slot[VERT_RESULT_PSIZ] = numVpOuts++;
00230          xvp->output_to_semantic_name[VERT_RESULT_PSIZ] = TGSI_SEMANTIC_PSIZE;
00231          xvp->output_to_semantic_index[VERT_RESULT_PSIZ] = 0;
00232       }
00233       if (emitBFC0) {
00234          xvp->output_to_slot[VERT_RESULT_BFC0] = numVpOuts++;
00235          xvp->output_to_semantic_name[VERT_RESULT_BFC0] = TGSI_SEMANTIC_COLOR;
00236          xvp->output_to_semantic_index[VERT_RESULT_BFC0] = 0;
00237       }
00238       if (emitBFC1) {
00239          xvp->output_to_slot[VERT_RESULT_BFC1] = numVpOuts++;
00240          xvp->output_to_semantic_name[VERT_RESULT_BFC0] = TGSI_SEMANTIC_COLOR;
00241          xvp->output_to_semantic_index[VERT_RESULT_BFC0] = 1;
00242       }
00243 
00244       /* Unneeded vertex program outputs will go to this slot.
00245        * We could use this info to do dead code elimination in the
00246        * vertex program.
00247        */
00248       dummySlot = numVpOuts;
00249 
00250       /* find max GENERIC slot index */
00251       maxGeneric = -1;
00252       for (outAttr = 0; outAttr < VERT_RESULT_MAX; outAttr++) {
00253          if (xvp->output_to_semantic_name[outAttr] == TGSI_SEMANTIC_GENERIC) {
00254             maxGeneric = MAX2(maxGeneric,
00255                               xvp->output_to_semantic_index[outAttr]);
00256          }
00257       }
00258 
00259       /* Map vert program outputs that aren't used to the dummy slot
00260        * (and an unused generic attribute slot).
00261        */
00262       for (outAttr = 0; outAttr < VERT_RESULT_MAX; outAttr++) {
00263          if (outputsWritten & (1 << outAttr)) {
00264             if (xvp->output_to_slot[outAttr] == UNUSED) {
00265                xvp->output_to_slot[outAttr] = dummySlot;
00266                xvp->output_to_semantic_name[outAttr] = TGSI_SEMANTIC_GENERIC;
00267                xvp->output_to_semantic_index[outAttr] = maxGeneric + 1;
00268             }
00269          }
00270 
00271 #if 0 /*debug*/
00272          printf("vp output_to_slot[%d] = %d\n", outAttr, 
00273                 xvp->output_to_slot[outAttr]);
00274 #endif
00275       }
00276 
00277       assert(stvp->Base.Base.NumInstructions > 1);
00278 
00279       st_translate_vertex_program(st, stvp, xvp->output_to_slot,
00280                                   xvp->output_to_semantic_name,
00281                                   xvp->output_to_semantic_index);
00282 
00283       xvp->vp = stvp;
00284 
00285       /* translated VP is up to date now */
00286       xvp->serialNo = stvp->serialNo;
00287    }
00288 
00289    return xvp;
00290 }
00291 
00292 
00293 void
00294 st_free_translated_vertex_programs(struct st_context *st,
00295                                    struct translated_vertex_program *xvp)
00296 {
00297    struct translated_vertex_program *next;
00298 
00299    while (xvp) {
00300       next = xvp->next;
00301       free(xvp);
00302       xvp = next;
00303    }
00304 }
00305 
00306 
00307 static void *
00308 get_passthrough_fs(struct st_context *st)
00309 {
00310    struct pipe_shader_state shader;
00311 
00312    if (!st->passthrough_fs) {
00313       st->passthrough_fs =
00314          util_make_fragment_passthrough_shader(st->pipe, &shader);
00315 #if 0      /* We actually need to keep the tokens around at this time */
00316       util_free_shader(&shader);
00317 #endif
00318    }
00319 
00320    return st->passthrough_fs;
00321 }
00322 
00323 
00324 static void
00325 update_linkage( struct st_context *st )
00326 {
00327    struct st_vertex_program *stvp;
00328    struct st_fragment_program *stfp;
00329    struct translated_vertex_program *xvp;
00330 
00331    /* find active shader and params -- Should be covered by
00332     * ST_NEW_VERTEX_PROGRAM
00333     */
00334    assert(st->ctx->VertexProgram._Current);
00335    stvp = st_vertex_program(st->ctx->VertexProgram._Current);
00336    assert(stvp->Base.Base.Target == GL_VERTEX_PROGRAM_ARB);
00337 
00338    assert(st->ctx->FragmentProgram._Current);
00339    stfp = st_fragment_program(st->ctx->FragmentProgram._Current);
00340    assert(stfp->Base.Base.Target == GL_FRAGMENT_PROGRAM_ARB);
00341 
00342    xvp = find_translated_vp(st, stvp, stfp);
00343 
00344    st_reference_vertprog(st, &st->vp, stvp);
00345    st_reference_fragprog(st, &st->fp, stfp);
00346 
00347    cso_set_vertex_shader_handle(st->cso_context, stvp->driver_shader);
00348 
00349    if (st->missing_textures) {
00350       /* use a pass-through frag shader that uses no textures */
00351       void *fs = get_passthrough_fs(st);
00352       cso_set_fragment_shader_handle(st->cso_context, fs);
00353    }
00354    else {
00355       cso_set_fragment_shader_handle(st->cso_context, stfp->driver_shader);
00356    }
00357 
00358    st->vertex_result_to_slot = xvp->output_to_slot;
00359 }
00360 
00361 
00362 const struct st_tracked_state st_update_shader = {
00363    "st_update_shader",                                  /* name */
00364    {                                                    /* dirty */
00365       0,                                                /* mesa */
00366       ST_NEW_VERTEX_PROGRAM | ST_NEW_FRAGMENT_PROGRAM   /* st */
00367    },
00368    update_linkage                                       /* update */
00369 };

Generated on Tue Sep 29 06:25:18 2009 for Gallium3D by  doxygen 1.5.4