1bf215546Sopenharmony_ci/************************************************************************** 2bf215546Sopenharmony_ci * 3bf215546Sopenharmony_ci * Copyright 2009 Marek Olšák <maraeo@gmail.com> 4bf215546Sopenharmony_ci * 5bf215546Sopenharmony_ci * Permission is hereby granted, free of charge, to any person obtaining a 6bf215546Sopenharmony_ci * copy of this software and associated documentation files (the 7bf215546Sopenharmony_ci * "Software"), to deal in the Software without restriction, including 8bf215546Sopenharmony_ci * without limitation the rights to use, copy, modify, merge, publish, 9bf215546Sopenharmony_ci * distribute, sub license, and/or sell copies of the Software, and to 10bf215546Sopenharmony_ci * permit persons to whom the Software is furnished to do so, subject to 11bf215546Sopenharmony_ci * the following conditions: 12bf215546Sopenharmony_ci * 13bf215546Sopenharmony_ci * The above copyright notice and this permission notice (including the 14bf215546Sopenharmony_ci * next paragraph) shall be included in all copies or substantial portions 15bf215546Sopenharmony_ci * of the Software. 16bf215546Sopenharmony_ci * 17bf215546Sopenharmony_ci * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS 18bf215546Sopenharmony_ci * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 19bf215546Sopenharmony_ci * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. 20bf215546Sopenharmony_ci * IN NO EVENT SHALL VMWARE AND/OR ITS SUPPLIERS BE LIABLE FOR 21bf215546Sopenharmony_ci * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, 22bf215546Sopenharmony_ci * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE 23bf215546Sopenharmony_ci * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 24bf215546Sopenharmony_ci * 25bf215546Sopenharmony_ci **************************************************************************/ 26bf215546Sopenharmony_ci 27bf215546Sopenharmony_ci/* This file contains the vertex shader tranformations for SW TCL needed 28bf215546Sopenharmony_ci * to overcome the limitations of the r300 rasterizer. 29bf215546Sopenharmony_ci * 30bf215546Sopenharmony_ci * Transformations: 31bf215546Sopenharmony_ci * 1) If the secondary color output is present, the primary color must be 32bf215546Sopenharmony_ci * present too. 33bf215546Sopenharmony_ci * 2) If any back-face color output is present, there must be all 4 color 34bf215546Sopenharmony_ci * outputs and missing ones must be inserted. 35bf215546Sopenharmony_ci * 3) Insert a trailing texcoord output containing a copy of POS, for WPOS. 36bf215546Sopenharmony_ci * 37bf215546Sopenharmony_ci * I know this code is cumbersome, but I don't know of any nicer way 38bf215546Sopenharmony_ci * of transforming TGSI shaders. ~ M. 39bf215546Sopenharmony_ci */ 40bf215546Sopenharmony_ci 41bf215546Sopenharmony_ci#include "r300_vs.h" 42bf215546Sopenharmony_ci 43bf215546Sopenharmony_ci#include <stdio.h> 44bf215546Sopenharmony_ci 45bf215546Sopenharmony_ci#include "tgsi/tgsi_transform.h" 46bf215546Sopenharmony_ci#include "tgsi/tgsi_dump.h" 47bf215546Sopenharmony_ci 48bf215546Sopenharmony_ci#include "draw/draw_context.h" 49bf215546Sopenharmony_ci 50bf215546Sopenharmony_cistruct vs_transform_context { 51bf215546Sopenharmony_ci struct tgsi_transform_context base; 52bf215546Sopenharmony_ci 53bf215546Sopenharmony_ci boolean color_used[2]; 54bf215546Sopenharmony_ci boolean bcolor_used[2]; 55bf215546Sopenharmony_ci 56bf215546Sopenharmony_ci /* Index of the pos output, typically 0. */ 57bf215546Sopenharmony_ci unsigned pos_output; 58bf215546Sopenharmony_ci /* Index of the pos temp where all writes of pos are redirected to. */ 59bf215546Sopenharmony_ci unsigned pos_temp; 60bf215546Sopenharmony_ci /* The index of the last generic output, after which we insert a new 61bf215546Sopenharmony_ci * output for WPOS. */ 62bf215546Sopenharmony_ci int last_generic; 63bf215546Sopenharmony_ci 64bf215546Sopenharmony_ci unsigned num_outputs; 65bf215546Sopenharmony_ci /* Used to shift output decl. indices when inserting new ones. */ 66bf215546Sopenharmony_ci unsigned decl_shift; 67bf215546Sopenharmony_ci /* Used to remap writes to output decls if their indices changed. */ 68bf215546Sopenharmony_ci unsigned out_remap[32]; 69bf215546Sopenharmony_ci 70bf215546Sopenharmony_ci /* First instruction processed? */ 71bf215546Sopenharmony_ci boolean first_instruction; 72bf215546Sopenharmony_ci /* End instruction processed? */ 73bf215546Sopenharmony_ci boolean end_instruction; 74bf215546Sopenharmony_ci 75bf215546Sopenharmony_ci boolean temp_used[1024]; 76bf215546Sopenharmony_ci}; 77bf215546Sopenharmony_ci 78bf215546Sopenharmony_cistatic void emit_temp(struct tgsi_transform_context *ctx, unsigned reg) 79bf215546Sopenharmony_ci{ 80bf215546Sopenharmony_ci struct tgsi_full_declaration decl; 81bf215546Sopenharmony_ci 82bf215546Sopenharmony_ci decl = tgsi_default_full_declaration(); 83bf215546Sopenharmony_ci decl.Declaration.File = TGSI_FILE_TEMPORARY; 84bf215546Sopenharmony_ci decl.Range.First = decl.Range.Last = reg; 85bf215546Sopenharmony_ci ctx->emit_declaration(ctx, &decl); 86bf215546Sopenharmony_ci} 87bf215546Sopenharmony_ci 88bf215546Sopenharmony_cistatic void emit_output(struct tgsi_transform_context *ctx, 89bf215546Sopenharmony_ci unsigned name, unsigned index, unsigned interp, 90bf215546Sopenharmony_ci unsigned reg) 91bf215546Sopenharmony_ci{ 92bf215546Sopenharmony_ci struct vs_transform_context *vsctx = (struct vs_transform_context *)ctx; 93bf215546Sopenharmony_ci struct tgsi_full_declaration decl; 94bf215546Sopenharmony_ci 95bf215546Sopenharmony_ci decl = tgsi_default_full_declaration(); 96bf215546Sopenharmony_ci decl.Declaration.File = TGSI_FILE_OUTPUT; 97bf215546Sopenharmony_ci decl.Declaration.Interpolate = 1; 98bf215546Sopenharmony_ci decl.Declaration.Semantic = TRUE; 99bf215546Sopenharmony_ci decl.Semantic.Name = name; 100bf215546Sopenharmony_ci decl.Semantic.Index = index; 101bf215546Sopenharmony_ci decl.Range.First = decl.Range.Last = reg; 102bf215546Sopenharmony_ci decl.Interp.Interpolate = interp; 103bf215546Sopenharmony_ci ctx->emit_declaration(ctx, &decl); 104bf215546Sopenharmony_ci ++vsctx->num_outputs; 105bf215546Sopenharmony_ci} 106bf215546Sopenharmony_ci 107bf215546Sopenharmony_cistatic void insert_output_before(struct tgsi_transform_context *ctx, 108bf215546Sopenharmony_ci struct tgsi_full_declaration *before, 109bf215546Sopenharmony_ci unsigned name, unsigned index, unsigned interp) 110bf215546Sopenharmony_ci{ 111bf215546Sopenharmony_ci struct vs_transform_context *vsctx = (struct vs_transform_context *)ctx; 112bf215546Sopenharmony_ci unsigned i; 113bf215546Sopenharmony_ci 114bf215546Sopenharmony_ci /* Make a place for the new output. */ 115bf215546Sopenharmony_ci for (i = before->Range.First; i < ARRAY_SIZE(vsctx->out_remap); i++) { 116bf215546Sopenharmony_ci ++vsctx->out_remap[i]; 117bf215546Sopenharmony_ci } 118bf215546Sopenharmony_ci 119bf215546Sopenharmony_ci /* Insert the new output. */ 120bf215546Sopenharmony_ci emit_output(ctx, name, index, interp, 121bf215546Sopenharmony_ci before->Range.First + vsctx->decl_shift); 122bf215546Sopenharmony_ci 123bf215546Sopenharmony_ci ++vsctx->decl_shift; 124bf215546Sopenharmony_ci} 125bf215546Sopenharmony_ci 126bf215546Sopenharmony_cistatic void insert_output_after(struct tgsi_transform_context *ctx, 127bf215546Sopenharmony_ci struct tgsi_full_declaration *after, 128bf215546Sopenharmony_ci unsigned name, unsigned index, unsigned interp) 129bf215546Sopenharmony_ci{ 130bf215546Sopenharmony_ci struct vs_transform_context *vsctx = (struct vs_transform_context *)ctx; 131bf215546Sopenharmony_ci unsigned i; 132bf215546Sopenharmony_ci 133bf215546Sopenharmony_ci /* Make a place for the new output. */ 134bf215546Sopenharmony_ci for (i = after->Range.First+1; i < ARRAY_SIZE(vsctx->out_remap); i++) { 135bf215546Sopenharmony_ci ++vsctx->out_remap[i]; 136bf215546Sopenharmony_ci } 137bf215546Sopenharmony_ci 138bf215546Sopenharmony_ci /* Insert the new output. */ 139bf215546Sopenharmony_ci emit_output(ctx, name, index, interp, 140bf215546Sopenharmony_ci after->Range.First + 1); 141bf215546Sopenharmony_ci 142bf215546Sopenharmony_ci ++vsctx->decl_shift; 143bf215546Sopenharmony_ci} 144bf215546Sopenharmony_ci 145bf215546Sopenharmony_cistatic void transform_decl(struct tgsi_transform_context *ctx, 146bf215546Sopenharmony_ci struct tgsi_full_declaration *decl) 147bf215546Sopenharmony_ci{ 148bf215546Sopenharmony_ci struct vs_transform_context *vsctx = (struct vs_transform_context *)ctx; 149bf215546Sopenharmony_ci unsigned i; 150bf215546Sopenharmony_ci 151bf215546Sopenharmony_ci if (decl->Declaration.File == TGSI_FILE_OUTPUT) { 152bf215546Sopenharmony_ci switch (decl->Semantic.Name) { 153bf215546Sopenharmony_ci case TGSI_SEMANTIC_POSITION: 154bf215546Sopenharmony_ci vsctx->pos_output = decl->Range.First; 155bf215546Sopenharmony_ci break; 156bf215546Sopenharmony_ci 157bf215546Sopenharmony_ci case TGSI_SEMANTIC_COLOR: 158bf215546Sopenharmony_ci assert(decl->Semantic.Index < 2); 159bf215546Sopenharmony_ci 160bf215546Sopenharmony_ci /* We must rasterize the first color if the second one is 161bf215546Sopenharmony_ci * used, otherwise the rasterizer doesn't do the color 162bf215546Sopenharmony_ci * selection correctly. Declare it, but don't write to it. */ 163bf215546Sopenharmony_ci if (decl->Semantic.Index == 1 && !vsctx->color_used[0]) { 164bf215546Sopenharmony_ci insert_output_before(ctx, decl, TGSI_SEMANTIC_COLOR, 0, 165bf215546Sopenharmony_ci TGSI_INTERPOLATE_LINEAR); 166bf215546Sopenharmony_ci vsctx->color_used[0] = TRUE; 167bf215546Sopenharmony_ci } 168bf215546Sopenharmony_ci break; 169bf215546Sopenharmony_ci 170bf215546Sopenharmony_ci case TGSI_SEMANTIC_BCOLOR: 171bf215546Sopenharmony_ci assert(decl->Semantic.Index < 2); 172bf215546Sopenharmony_ci 173bf215546Sopenharmony_ci /* We must rasterize all 4 colors if back-face colors are 174bf215546Sopenharmony_ci * used, otherwise the rasterizer doesn't do the color 175bf215546Sopenharmony_ci * selection correctly. Declare it, but don't write to it. */ 176bf215546Sopenharmony_ci if (!vsctx->color_used[0]) { 177bf215546Sopenharmony_ci insert_output_before(ctx, decl, TGSI_SEMANTIC_COLOR, 0, 178bf215546Sopenharmony_ci TGSI_INTERPOLATE_LINEAR); 179bf215546Sopenharmony_ci vsctx->color_used[0] = TRUE; 180bf215546Sopenharmony_ci } 181bf215546Sopenharmony_ci if (!vsctx->color_used[1]) { 182bf215546Sopenharmony_ci insert_output_before(ctx, decl, TGSI_SEMANTIC_COLOR, 1, 183bf215546Sopenharmony_ci TGSI_INTERPOLATE_LINEAR); 184bf215546Sopenharmony_ci vsctx->color_used[1] = TRUE; 185bf215546Sopenharmony_ci } 186bf215546Sopenharmony_ci if (decl->Semantic.Index == 1 && !vsctx->bcolor_used[0]) { 187bf215546Sopenharmony_ci insert_output_before(ctx, decl, TGSI_SEMANTIC_BCOLOR, 0, 188bf215546Sopenharmony_ci TGSI_INTERPOLATE_LINEAR); 189bf215546Sopenharmony_ci vsctx->bcolor_used[0] = TRUE; 190bf215546Sopenharmony_ci } 191bf215546Sopenharmony_ci break; 192bf215546Sopenharmony_ci 193bf215546Sopenharmony_ci case TGSI_SEMANTIC_GENERIC: 194bf215546Sopenharmony_ci vsctx->last_generic = MAX2(vsctx->last_generic, decl->Semantic.Index); 195bf215546Sopenharmony_ci break; 196bf215546Sopenharmony_ci } 197bf215546Sopenharmony_ci 198bf215546Sopenharmony_ci /* Since we're inserting new outputs in between, the following outputs 199bf215546Sopenharmony_ci * should be moved to the right so that they don't overlap with 200bf215546Sopenharmony_ci * the newly added ones. */ 201bf215546Sopenharmony_ci decl->Range.First += vsctx->decl_shift; 202bf215546Sopenharmony_ci decl->Range.Last += vsctx->decl_shift; 203bf215546Sopenharmony_ci 204bf215546Sopenharmony_ci ++vsctx->num_outputs; 205bf215546Sopenharmony_ci } else if (decl->Declaration.File == TGSI_FILE_TEMPORARY) { 206bf215546Sopenharmony_ci for (i = decl->Range.First; i <= decl->Range.Last; i++) { 207bf215546Sopenharmony_ci vsctx->temp_used[i] = TRUE; 208bf215546Sopenharmony_ci } 209bf215546Sopenharmony_ci } 210bf215546Sopenharmony_ci 211bf215546Sopenharmony_ci ctx->emit_declaration(ctx, decl); 212bf215546Sopenharmony_ci 213bf215546Sopenharmony_ci /* Insert BCOLOR1 if needed. */ 214bf215546Sopenharmony_ci if (decl->Declaration.File == TGSI_FILE_OUTPUT && 215bf215546Sopenharmony_ci decl->Semantic.Name == TGSI_SEMANTIC_BCOLOR && 216bf215546Sopenharmony_ci !vsctx->bcolor_used[1]) { 217bf215546Sopenharmony_ci insert_output_after(ctx, decl, TGSI_SEMANTIC_BCOLOR, 1, 218bf215546Sopenharmony_ci TGSI_INTERPOLATE_LINEAR); 219bf215546Sopenharmony_ci } 220bf215546Sopenharmony_ci} 221bf215546Sopenharmony_ci 222bf215546Sopenharmony_cistatic void transform_inst(struct tgsi_transform_context *ctx, 223bf215546Sopenharmony_ci struct tgsi_full_instruction *inst) 224bf215546Sopenharmony_ci{ 225bf215546Sopenharmony_ci struct vs_transform_context *vsctx = (struct vs_transform_context *) ctx; 226bf215546Sopenharmony_ci struct tgsi_full_instruction new_inst; 227bf215546Sopenharmony_ci unsigned i; 228bf215546Sopenharmony_ci 229bf215546Sopenharmony_ci if (!vsctx->first_instruction) { 230bf215546Sopenharmony_ci vsctx->first_instruction = TRUE; 231bf215546Sopenharmony_ci 232bf215546Sopenharmony_ci /* Insert the generic output for WPOS. */ 233bf215546Sopenharmony_ci emit_output(ctx, TGSI_SEMANTIC_GENERIC, vsctx->last_generic + 1, 234bf215546Sopenharmony_ci TGSI_INTERPOLATE_PERSPECTIVE, vsctx->num_outputs); 235bf215546Sopenharmony_ci 236bf215546Sopenharmony_ci /* Find a free temp for POSITION. */ 237bf215546Sopenharmony_ci for (i = 0; i < ARRAY_SIZE(vsctx->temp_used); i++) { 238bf215546Sopenharmony_ci if (!vsctx->temp_used[i]) { 239bf215546Sopenharmony_ci emit_temp(ctx, i); 240bf215546Sopenharmony_ci vsctx->pos_temp = i; 241bf215546Sopenharmony_ci break; 242bf215546Sopenharmony_ci } 243bf215546Sopenharmony_ci } 244bf215546Sopenharmony_ci } 245bf215546Sopenharmony_ci 246bf215546Sopenharmony_ci if (inst->Instruction.Opcode == TGSI_OPCODE_END) { 247bf215546Sopenharmony_ci /* MOV OUT[pos_output], TEMP[pos_temp]; */ 248bf215546Sopenharmony_ci new_inst = tgsi_default_full_instruction(); 249bf215546Sopenharmony_ci new_inst.Instruction.Opcode = TGSI_OPCODE_MOV; 250bf215546Sopenharmony_ci new_inst.Instruction.NumDstRegs = 1; 251bf215546Sopenharmony_ci new_inst.Dst[0].Register.File = TGSI_FILE_OUTPUT; 252bf215546Sopenharmony_ci new_inst.Dst[0].Register.Index = vsctx->pos_output; 253bf215546Sopenharmony_ci new_inst.Dst[0].Register.WriteMask = TGSI_WRITEMASK_XYZW; 254bf215546Sopenharmony_ci new_inst.Instruction.NumSrcRegs = 1; 255bf215546Sopenharmony_ci new_inst.Src[0].Register.File = TGSI_FILE_TEMPORARY; 256bf215546Sopenharmony_ci new_inst.Src[0].Register.Index = vsctx->pos_temp; 257bf215546Sopenharmony_ci ctx->emit_instruction(ctx, &new_inst); 258bf215546Sopenharmony_ci 259bf215546Sopenharmony_ci /* MOV OUT[n-1], TEMP[pos_temp]; */ 260bf215546Sopenharmony_ci new_inst = tgsi_default_full_instruction(); 261bf215546Sopenharmony_ci new_inst.Instruction.Opcode = TGSI_OPCODE_MOV; 262bf215546Sopenharmony_ci new_inst.Instruction.NumDstRegs = 1; 263bf215546Sopenharmony_ci new_inst.Dst[0].Register.File = TGSI_FILE_OUTPUT; 264bf215546Sopenharmony_ci new_inst.Dst[0].Register.Index = vsctx->num_outputs - 1; 265bf215546Sopenharmony_ci new_inst.Dst[0].Register.WriteMask = TGSI_WRITEMASK_XYZW; 266bf215546Sopenharmony_ci new_inst.Instruction.NumSrcRegs = 1; 267bf215546Sopenharmony_ci new_inst.Src[0].Register.File = TGSI_FILE_TEMPORARY; 268bf215546Sopenharmony_ci new_inst.Src[0].Register.Index = vsctx->pos_temp; 269bf215546Sopenharmony_ci ctx->emit_instruction(ctx, &new_inst); 270bf215546Sopenharmony_ci 271bf215546Sopenharmony_ci vsctx->end_instruction = TRUE; 272bf215546Sopenharmony_ci } else { 273bf215546Sopenharmony_ci /* Not an END instruction. */ 274bf215546Sopenharmony_ci /* Fix writes to outputs. */ 275bf215546Sopenharmony_ci for (i = 0; i < inst->Instruction.NumDstRegs; i++) { 276bf215546Sopenharmony_ci struct tgsi_full_dst_register *dst = &inst->Dst[i]; 277bf215546Sopenharmony_ci if (dst->Register.File == TGSI_FILE_OUTPUT) { 278bf215546Sopenharmony_ci if (dst->Register.Index == vsctx->pos_output) { 279bf215546Sopenharmony_ci /* Replace writes to OUT[pos_output] with TEMP[pos_temp]. */ 280bf215546Sopenharmony_ci dst->Register.File = TGSI_FILE_TEMPORARY; 281bf215546Sopenharmony_ci dst->Register.Index = vsctx->pos_temp; 282bf215546Sopenharmony_ci } else { 283bf215546Sopenharmony_ci /* Not a position, good... 284bf215546Sopenharmony_ci * Since we were changing the indices of output decls, 285bf215546Sopenharmony_ci * we must redirect writes into them too. */ 286bf215546Sopenharmony_ci dst->Register.Index = vsctx->out_remap[dst->Register.Index]; 287bf215546Sopenharmony_ci } 288bf215546Sopenharmony_ci } 289bf215546Sopenharmony_ci } 290bf215546Sopenharmony_ci 291bf215546Sopenharmony_ci /* Inserting 2 instructions before the END opcode moves all following 292bf215546Sopenharmony_ci * labels by 2. Subroutines are always after the END opcode so 293bf215546Sopenharmony_ci * they're always moved. */ 294bf215546Sopenharmony_ci if (inst->Instruction.Opcode == TGSI_OPCODE_CAL) { 295bf215546Sopenharmony_ci inst->Label.Label += 2; 296bf215546Sopenharmony_ci } 297bf215546Sopenharmony_ci /* The labels of the following opcodes are moved only after 298bf215546Sopenharmony_ci * the END opcode. */ 299bf215546Sopenharmony_ci if (vsctx->end_instruction && 300bf215546Sopenharmony_ci (inst->Instruction.Opcode == TGSI_OPCODE_IF || 301bf215546Sopenharmony_ci inst->Instruction.Opcode == TGSI_OPCODE_ELSE || 302bf215546Sopenharmony_ci inst->Instruction.Opcode == TGSI_OPCODE_BGNLOOP || 303bf215546Sopenharmony_ci inst->Instruction.Opcode == TGSI_OPCODE_ENDLOOP)) { 304bf215546Sopenharmony_ci inst->Label.Label += 2; 305bf215546Sopenharmony_ci } 306bf215546Sopenharmony_ci } 307bf215546Sopenharmony_ci 308bf215546Sopenharmony_ci ctx->emit_instruction(ctx, inst); 309bf215546Sopenharmony_ci} 310bf215546Sopenharmony_ci 311bf215546Sopenharmony_civoid r300_draw_init_vertex_shader(struct r300_context *r300, 312bf215546Sopenharmony_ci struct r300_vertex_shader *vs) 313bf215546Sopenharmony_ci{ 314bf215546Sopenharmony_ci struct draw_context *draw = r300->draw; 315bf215546Sopenharmony_ci struct tgsi_shader_info info; 316bf215546Sopenharmony_ci struct vs_transform_context transform; 317bf215546Sopenharmony_ci const uint newLen = tgsi_num_tokens(vs->state.tokens) + 100; 318bf215546Sopenharmony_ci struct pipe_shader_state new_vs = { 319bf215546Sopenharmony_ci .type = PIPE_SHADER_IR_TGSI, 320bf215546Sopenharmony_ci .tokens = tgsi_alloc_tokens(newLen) 321bf215546Sopenharmony_ci }; 322bf215546Sopenharmony_ci unsigned i; 323bf215546Sopenharmony_ci 324bf215546Sopenharmony_ci tgsi_scan_shader(vs->state.tokens, &info); 325bf215546Sopenharmony_ci 326bf215546Sopenharmony_ci memset(&transform, 0, sizeof(transform)); 327bf215546Sopenharmony_ci for (i = 0; i < ARRAY_SIZE(transform.out_remap); i++) { 328bf215546Sopenharmony_ci transform.out_remap[i] = i; 329bf215546Sopenharmony_ci } 330bf215546Sopenharmony_ci transform.last_generic = -1; 331bf215546Sopenharmony_ci transform.base.transform_instruction = transform_inst; 332bf215546Sopenharmony_ci transform.base.transform_declaration = transform_decl; 333bf215546Sopenharmony_ci 334bf215546Sopenharmony_ci for (i = 0; i < info.num_outputs; i++) { 335bf215546Sopenharmony_ci unsigned index = info.output_semantic_index[i]; 336bf215546Sopenharmony_ci 337bf215546Sopenharmony_ci switch (info.output_semantic_name[i]) { 338bf215546Sopenharmony_ci case TGSI_SEMANTIC_COLOR: 339bf215546Sopenharmony_ci assert(index < 2); 340bf215546Sopenharmony_ci transform.color_used[index] = TRUE; 341bf215546Sopenharmony_ci break; 342bf215546Sopenharmony_ci 343bf215546Sopenharmony_ci case TGSI_SEMANTIC_BCOLOR: 344bf215546Sopenharmony_ci assert(index < 2); 345bf215546Sopenharmony_ci transform.bcolor_used[index] = TRUE; 346bf215546Sopenharmony_ci break; 347bf215546Sopenharmony_ci } 348bf215546Sopenharmony_ci } 349bf215546Sopenharmony_ci 350bf215546Sopenharmony_ci new_vs.tokens = tgsi_transform_shader(vs->state.tokens, newLen, &transform.base); 351bf215546Sopenharmony_ci if (!new_vs.tokens) 352bf215546Sopenharmony_ci return; 353bf215546Sopenharmony_ci 354bf215546Sopenharmony_ci#if 0 355bf215546Sopenharmony_ci printf("----------------------------------------------\norig shader:\n"); 356bf215546Sopenharmony_ci tgsi_dump(vs->state.tokens, 0); 357bf215546Sopenharmony_ci printf("----------------------------------------------\nnew shader:\n"); 358bf215546Sopenharmony_ci tgsi_dump(new_vs.tokens, 0); 359bf215546Sopenharmony_ci printf("----------------------------------------------\n"); 360bf215546Sopenharmony_ci#endif 361bf215546Sopenharmony_ci 362bf215546Sopenharmony_ci /* Free old tokens. */ 363bf215546Sopenharmony_ci FREE((void*)vs->state.tokens); 364bf215546Sopenharmony_ci 365bf215546Sopenharmony_ci vs->draw_vs = draw_create_vertex_shader(draw, &new_vs); 366bf215546Sopenharmony_ci 367bf215546Sopenharmony_ci /* Instead of duplicating and freeing the tokens, copy the pointer directly. */ 368bf215546Sopenharmony_ci vs->state.tokens = new_vs.tokens; 369bf215546Sopenharmony_ci 370bf215546Sopenharmony_ci /* Init the VS output table for the rasterizer. */ 371bf215546Sopenharmony_ci r300_init_vs_outputs(r300, vs); 372bf215546Sopenharmony_ci 373bf215546Sopenharmony_ci /* Make the last generic be WPOS. */ 374bf215546Sopenharmony_ci vs->shader->outputs.wpos = vs->shader->outputs.generic[transform.last_generic + 1]; 375bf215546Sopenharmony_ci vs->shader->outputs.generic[transform.last_generic + 1] = ATTR_UNUSED; 376bf215546Sopenharmony_ci} 377