Home | Info | Community | Development | myReactOS | Contact Us
ReactOS Development > Doxygenprogramopt.c
Go to the documentation of this file.
00001 /* 00002 * Mesa 3-D graphics library 00003 * Version: 6.5.3 00004 * 00005 * Copyright (C) 1999-2007 Brian Paul All Rights Reserved. 00006 * 00007 * Permission is hereby granted, free of charge, to any person obtaining a 00008 * copy of this software and associated documentation files (the "Software"), 00009 * to deal in the Software without restriction, including without limitation 00010 * the rights to use, copy, modify, merge, publish, distribute, sublicense, 00011 * and/or sell copies of the Software, and to permit persons to whom the 00012 * Software is furnished to do so, subject to the following conditions: 00013 * 00014 * The above copyright notice and this permission notice shall be included 00015 * in all copies or substantial portions of the Software. 00016 * 00017 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS 00018 * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 00019 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL 00020 * BRIAN PAUL BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN 00021 * AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN 00022 * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 00023 */ 00024 00034 #include "main/glheader.h" 00035 #include "main/context.h" 00036 #include "prog_parameter.h" 00037 #include "prog_statevars.h" 00038 #include "program.h" 00039 #include "programopt.h" 00040 #include "prog_instruction.h" 00041 00042 00048 void 00049 _mesa_insert_mvp_code(GLcontext *ctx, struct gl_vertex_program *vprog) 00050 { 00051 struct prog_instruction *newInst; 00052 const GLuint origLen = vprog->Base.NumInstructions; 00053 const GLuint newLen = origLen + 4; 00054 GLuint i; 00055 00056 /* 00057 * Setup state references for the modelview/projection matrix. 00058 * XXX we should check if these state vars are already declared. 00059 */ 00060 static const gl_state_index mvpState[4][STATE_LENGTH] = { 00061 { STATE_MVP_MATRIX, 0, 0, 0, 0 }, /* state.matrix.mvp.row[0] */ 00062 { STATE_MVP_MATRIX, 0, 1, 1, 0 }, /* state.matrix.mvp.row[1] */ 00063 { STATE_MVP_MATRIX, 0, 2, 2, 0 }, /* state.matrix.mvp.row[2] */ 00064 { STATE_MVP_MATRIX, 0, 3, 3, 0 }, /* state.matrix.mvp.row[3] */ 00065 }; 00066 GLint mvpRef[4]; 00067 00068 for (i = 0; i < 4; i++) { 00069 mvpRef[i] = _mesa_add_state_reference(vprog->Base.Parameters, 00070 mvpState[i]); 00071 } 00072 00073 /* Alloc storage for new instructions */ 00074 newInst = _mesa_alloc_instructions(newLen); 00075 if (!newInst) { 00076 _mesa_error(ctx, GL_OUT_OF_MEMORY, 00077 "glProgramString(inserting position_invariant code)"); 00078 return; 00079 } 00080 00081 /* 00082 * Generated instructions: 00083 * newInst[0] = DP4 result.position.x, mvp.row[0], vertex.position; 00084 * newInst[1] = DP4 result.position.y, mvp.row[1], vertex.position; 00085 * newInst[2] = DP4 result.position.z, mvp.row[2], vertex.position; 00086 * newInst[3] = DP4 result.position.w, mvp.row[3], vertex.position; 00087 */ 00088 _mesa_init_instructions(newInst, 4); 00089 for (i = 0; i < 4; i++) { 00090 newInst[i].Opcode = OPCODE_DP4; 00091 newInst[i].DstReg.File = PROGRAM_OUTPUT; 00092 newInst[i].DstReg.Index = VERT_RESULT_HPOS; 00093 newInst[i].DstReg.WriteMask = (WRITEMASK_X << i); 00094 newInst[i].SrcReg[0].File = PROGRAM_STATE_VAR; 00095 newInst[i].SrcReg[0].Index = mvpRef[i]; 00096 newInst[i].SrcReg[0].Swizzle = SWIZZLE_NOOP; 00097 newInst[i].SrcReg[1].File = PROGRAM_INPUT; 00098 newInst[i].SrcReg[1].Index = VERT_ATTRIB_POS; 00099 newInst[i].SrcReg[1].Swizzle = SWIZZLE_NOOP; 00100 } 00101 00102 /* Append original instructions after new instructions */ 00103 _mesa_copy_instructions (newInst + 4, vprog->Base.Instructions, origLen); 00104 00105 /* free old instructions */ 00106 _mesa_free_instructions(vprog->Base.Instructions, origLen); 00107 00108 /* install new instructions */ 00109 vprog->Base.Instructions = newInst; 00110 vprog->Base.NumInstructions = newLen; 00111 vprog->Base.InputsRead |= VERT_BIT_POS; 00112 vprog->Base.OutputsWritten |= (1 << VERT_RESULT_HPOS); 00113 } 00114 00115 00116 00125 void 00126 _mesa_append_fog_code(GLcontext *ctx, struct gl_fragment_program *fprog) 00127 { 00128 static const gl_state_index fogPStateOpt[STATE_LENGTH] 00129 = { STATE_INTERNAL, STATE_FOG_PARAMS_OPTIMIZED, 0, 0, 0 }; 00130 static const gl_state_index fogColorState[STATE_LENGTH] 00131 = { STATE_FOG_COLOR, 0, 0, 0, 0}; 00132 struct prog_instruction *newInst, *inst; 00133 const GLuint origLen = fprog->Base.NumInstructions; 00134 const GLuint newLen = origLen + 5; 00135 GLuint i; 00136 GLint fogPRefOpt, fogColorRef; /* state references */ 00137 GLuint colorTemp, fogFactorTemp; /* temporary registerss */ 00138 00139 if (fprog->FogOption == GL_NONE) { 00140 _mesa_problem(ctx, "_mesa_append_fog_code() called for fragment program" 00141 " with FogOption == GL_NONE"); 00142 return; 00143 } 00144 00145 /* Alloc storage for new instructions */ 00146 newInst = _mesa_alloc_instructions(newLen); 00147 if (!newInst) { 00148 _mesa_error(ctx, GL_OUT_OF_MEMORY, 00149 "glProgramString(inserting fog_option code)"); 00150 return; 00151 } 00152 00153 /* Copy orig instructions into new instruction buffer */ 00154 _mesa_copy_instructions(newInst, fprog->Base.Instructions, origLen); 00155 00156 /* PARAM fogParamsRefOpt = internal optimized fog params; */ 00157 fogPRefOpt 00158 = _mesa_add_state_reference(fprog->Base.Parameters, fogPStateOpt); 00159 /* PARAM fogColorRef = state.fog.color; */ 00160 fogColorRef 00161 = _mesa_add_state_reference(fprog->Base.Parameters, fogColorState); 00162 00163 /* TEMP colorTemp; */ 00164 colorTemp = fprog->Base.NumTemporaries++; 00165 /* TEMP fogFactorTemp; */ 00166 fogFactorTemp = fprog->Base.NumTemporaries++; 00167 00168 /* Scan program to find where result.color is written */ 00169 inst = newInst; 00170 for (i = 0; i < fprog->Base.NumInstructions; i++) { 00171 if (inst->Opcode == OPCODE_END) 00172 break; 00173 if (inst->DstReg.File == PROGRAM_OUTPUT && 00174 inst->DstReg.Index == FRAG_RESULT_COLR) { 00175 /* change the instruction to write to colorTemp w/ clamping */ 00176 inst->DstReg.File = PROGRAM_TEMPORARY; 00177 inst->DstReg.Index = colorTemp; 00178 inst->SaturateMode = SATURATE_ZERO_ONE; 00179 /* don't break (may be several writes to result.color) */ 00180 } 00181 inst++; 00182 } 00183 assert(inst->Opcode == OPCODE_END); /* we'll overwrite this inst */ 00184 00185 _mesa_init_instructions(inst, 5); 00186 00187 /* emit instructions to compute fog blending factor */ 00188 if (fprog->FogOption == GL_LINEAR) { 00189 /* MAD fogFactorTemp.x, fragment.fogcoord.x, fogPRefOpt.x, fogPRefOpt.y; */ 00190 inst->Opcode = OPCODE_MAD; 00191 inst->DstReg.File = PROGRAM_TEMPORARY; 00192 inst->DstReg.Index = fogFactorTemp; 00193 inst->DstReg.WriteMask = WRITEMASK_X; 00194 inst->SrcReg[0].File = PROGRAM_INPUT; 00195 inst->SrcReg[0].Index = FRAG_ATTRIB_FOGC; 00196 inst->SrcReg[0].Swizzle = SWIZZLE_XXXX; 00197 inst->SrcReg[1].File = PROGRAM_STATE_VAR; 00198 inst->SrcReg[1].Index = fogPRefOpt; 00199 inst->SrcReg[1].Swizzle = SWIZZLE_XXXX; 00200 inst->SrcReg[2].File = PROGRAM_STATE_VAR; 00201 inst->SrcReg[2].Index = fogPRefOpt; 00202 inst->SrcReg[2].Swizzle = SWIZZLE_YYYY; 00203 inst->SaturateMode = SATURATE_ZERO_ONE; 00204 inst++; 00205 } 00206 else { 00207 ASSERT(fprog->FogOption == GL_EXP || fprog->FogOption == GL_EXP2); 00208 /* fogPRefOpt.z = d/ln(2), fogPRefOpt.w = d/sqrt(ln(2) */ 00209 /* EXP: MUL fogFactorTemp.x, fogPRefOpt.z, fragment.fogcoord.x; */ 00210 /* EXP2: MUL fogFactorTemp.x, fogPRefOpt.w, fragment.fogcoord.x; */ 00211 inst->Opcode = OPCODE_MUL; 00212 inst->DstReg.File = PROGRAM_TEMPORARY; 00213 inst->DstReg.Index = fogFactorTemp; 00214 inst->DstReg.WriteMask = WRITEMASK_X; 00215 inst->SrcReg[0].File = PROGRAM_STATE_VAR; 00216 inst->SrcReg[0].Index = fogPRefOpt; 00217 inst->SrcReg[0].Swizzle 00218 = (fprog->FogOption == GL_EXP) ? SWIZZLE_ZZZZ : SWIZZLE_WWWW; 00219 inst->SrcReg[1].File = PROGRAM_INPUT; 00220 inst->SrcReg[1].Index = FRAG_ATTRIB_FOGC; 00221 inst->SrcReg[1].Swizzle = SWIZZLE_XXXX; 00222 inst++; 00223 if (fprog->FogOption == GL_EXP2) { 00224 /* MUL fogFactorTemp.x, fogFactorTemp.x, fogFactorTemp.x; */ 00225 inst->Opcode = OPCODE_MUL; 00226 inst->DstReg.File = PROGRAM_TEMPORARY; 00227 inst->DstReg.Index = fogFactorTemp; 00228 inst->DstReg.WriteMask = WRITEMASK_X; 00229 inst->SrcReg[0].File = PROGRAM_TEMPORARY; 00230 inst->SrcReg[0].Index = fogFactorTemp; 00231 inst->SrcReg[0].Swizzle = SWIZZLE_XXXX; 00232 inst->SrcReg[1].File = PROGRAM_TEMPORARY; 00233 inst->SrcReg[1].Index = fogFactorTemp; 00234 inst->SrcReg[1].Swizzle = SWIZZLE_XXXX; 00235 inst++; 00236 } 00237 /* EX2_SAT fogFactorTemp.x, -fogFactorTemp.x; */ 00238 inst->Opcode = OPCODE_EX2; 00239 inst->DstReg.File = PROGRAM_TEMPORARY; 00240 inst->DstReg.Index = fogFactorTemp; 00241 inst->DstReg.WriteMask = WRITEMASK_X; 00242 inst->SrcReg[0].File = PROGRAM_TEMPORARY; 00243 inst->SrcReg[0].Index = fogFactorTemp; 00244 inst->SrcReg[0].NegateBase = NEGATE_XYZW; 00245 inst->SrcReg[0].Swizzle = SWIZZLE_XXXX; 00246 inst->SaturateMode = SATURATE_ZERO_ONE; 00247 inst++; 00248 } 00249 /* LRP result.color.xyz, fogFactorTemp.xxxx, colorTemp, fogColorRef; */ 00250 inst->Opcode = OPCODE_LRP; 00251 inst->DstReg.File = PROGRAM_OUTPUT; 00252 inst->DstReg.Index = FRAG_RESULT_COLR; 00253 inst->DstReg.WriteMask = WRITEMASK_XYZ; 00254 inst->SrcReg[0].File = PROGRAM_TEMPORARY; 00255 inst->SrcReg[0].Index = fogFactorTemp; 00256 inst->SrcReg[0].Swizzle = SWIZZLE_XXXX; 00257 inst->SrcReg[1].File = PROGRAM_TEMPORARY; 00258 inst->SrcReg[1].Index = colorTemp; 00259 inst->SrcReg[1].Swizzle = SWIZZLE_NOOP; 00260 inst->SrcReg[2].File = PROGRAM_STATE_VAR; 00261 inst->SrcReg[2].Index = fogColorRef; 00262 inst->SrcReg[2].Swizzle = SWIZZLE_NOOP; 00263 inst++; 00264 /* MOV result.color.w, colorTemp.x; # copy alpha */ 00265 inst->Opcode = OPCODE_MOV; 00266 inst->DstReg.File = PROGRAM_OUTPUT; 00267 inst->DstReg.Index = FRAG_RESULT_COLR; 00268 inst->DstReg.WriteMask = WRITEMASK_W; 00269 inst->SrcReg[0].File = PROGRAM_TEMPORARY; 00270 inst->SrcReg[0].Index = colorTemp; 00271 inst->SrcReg[0].Swizzle = SWIZZLE_NOOP; 00272 inst++; 00273 /* END; */ 00274 inst->Opcode = OPCODE_END; 00275 inst++; 00276 00277 /* free old instructions */ 00278 _mesa_free_instructions(fprog->Base.Instructions, origLen); 00279 00280 /* install new instructions */ 00281 fprog->Base.Instructions = newInst; 00282 fprog->Base.NumInstructions = inst - newInst; 00283 fprog->Base.InputsRead |= FRAG_BIT_FOGC; 00284 /* XXX do this? fprog->FogOption = GL_NONE; */ 00285 } 00286 00287 00288 00289 static GLboolean 00290 is_texture_instruction(const struct prog_instruction *inst) 00291 { 00292 switch (inst->Opcode) { 00293 case OPCODE_TEX: 00294 case OPCODE_TXB: 00295 case OPCODE_TXD: 00296 case OPCODE_TXL: 00297 case OPCODE_TXP: 00298 case OPCODE_TXP_NV: 00299 return GL_TRUE; 00300 default: 00301 return GL_FALSE; 00302 } 00303 } 00304 00305 00313 void 00314 _mesa_count_texture_indirections(struct gl_program *prog) 00315 { 00316 GLuint indirections = 1; 00317 GLbitfield tempsOutput = 0x0; 00318 GLbitfield aluTemps = 0x0; 00319 GLuint i; 00320 00321 for (i = 0; i < prog->NumInstructions; i++) { 00322 const struct prog_instruction *inst = prog->Instructions + i; 00323 00324 if (is_texture_instruction(inst)) { 00325 if (((inst->SrcReg[0].File == PROGRAM_TEMPORARY) && 00326 (tempsOutput & (1 << inst->SrcReg[0].Index))) || 00327 ((inst->Opcode != OPCODE_KIL) && 00328 (inst->DstReg.File == PROGRAM_TEMPORARY) && 00329 (aluTemps & (1 << inst->DstReg.Index)))) 00330 { 00331 indirections++; 00332 tempsOutput = 0x0; 00333 aluTemps = 0x0; 00334 } 00335 } 00336 else { 00337 GLuint j; 00338 for (j = 0; j < 3; j++) { 00339 if (inst->SrcReg[j].File == PROGRAM_TEMPORARY) 00340 aluTemps |= (1 << inst->SrcReg[j].Index); 00341 } 00342 if (inst->DstReg.File == PROGRAM_TEMPORARY) 00343 aluTemps |= (1 << inst->DstReg.Index); 00344 } 00345 00346 if ((inst->Opcode != OPCODE_KIL) && (inst->DstReg.File == PROGRAM_TEMPORARY)) 00347 tempsOutput |= (1 << inst->DstReg.Index); 00348 } 00349 00350 prog->NumTexIndirections = indirections; 00351 } 00352 00353 00358 void 00359 _mesa_count_texture_instructions(struct gl_program *prog) 00360 { 00361 GLuint i; 00362 prog->NumTexInstructions = 0; 00363 for (i = 0; i < prog->NumInstructions; i++) { 00364 prog->NumTexInstructions += is_texture_instruction(prog->Instructions + i); 00365 } 00366 } 00367 00368 00377 void 00378 _mesa_remove_output_reads(struct gl_program *prog, enum register_file type) 00379 { 00380 GLuint i; 00381 GLint outputMap[VERT_RESULT_MAX]; 00382 GLuint numVaryingReads = 0; 00383 00384 assert(type == PROGRAM_VARYING || type == PROGRAM_OUTPUT); 00385 assert(prog->Target == GL_VERTEX_PROGRAM_ARB || type != PROGRAM_VARYING); 00386 00387 for (i = 0; i < VERT_RESULT_MAX; i++) 00388 outputMap[i] = -1; 00389 00390 /* look for instructions which read from varying vars */ 00391 for (i = 0; i < prog->NumInstructions; i++) { 00392 struct prog_instruction *inst = prog->Instructions + i; 00393 const GLuint numSrc = _mesa_num_inst_src_regs(inst->Opcode); 00394 GLuint j; 00395 for (j = 0; j < numSrc; j++) { 00396 if (inst->SrcReg[j].File == type) { 00397 /* replace the read with a temp reg */ 00398 const GLuint var = inst->SrcReg[j].Index; 00399 if (outputMap[var] == -1) { 00400 numVaryingReads++; 00401 outputMap[var] = _mesa_find_free_register(prog, 00402 PROGRAM_TEMPORARY); 00403 } 00404 inst->SrcReg[j].File = PROGRAM_TEMPORARY; 00405 inst->SrcReg[j].Index = outputMap[var]; 00406 } 00407 } 00408 } 00409 00410 if (numVaryingReads == 0) 00411 return; /* nothing to be done */ 00412 00413 /* look for instructions which write to the varying vars identified above */ 00414 for (i = 0; i < prog->NumInstructions; i++) { 00415 struct prog_instruction *inst = prog->Instructions + i; 00416 const GLuint numSrc = _mesa_num_inst_src_regs(inst->Opcode); 00417 GLuint j; 00418 for (j = 0; j < numSrc; j++) { 00419 if (inst->DstReg.File == type && 00420 outputMap[inst->DstReg.Index] >= 0) { 00421 /* change inst to write to the temp reg, instead of the varying */ 00422 inst->DstReg.File = PROGRAM_TEMPORARY; 00423 inst->DstReg.Index = outputMap[inst->DstReg.Index]; 00424 } 00425 } 00426 } 00427 00428 /* insert new instructions to copy the temp vars to the varying vars */ 00429 { 00430 struct prog_instruction *inst; 00431 GLint endPos, var; 00432 00433 /* Look for END instruction and insert the new varying writes */ 00434 endPos = -1; 00435 for (i = 0; i < prog->NumInstructions; i++) { 00436 struct prog_instruction *inst = prog->Instructions + i; 00437 if (inst->Opcode == OPCODE_END) { 00438 endPos = i; 00439 _mesa_insert_instructions(prog, i, numVaryingReads); 00440 break; 00441 } 00442 } 00443 00444 assert(endPos >= 0); 00445 00446 /* insert new MOV instructions here */ 00447 inst = prog->Instructions + endPos; 00448 for (var = 0; var < VERT_RESULT_MAX; var++) { 00449 if (outputMap[var] >= 0) { 00450 /* MOV VAR[var], TEMP[tmp]; */ 00451 inst->Opcode = OPCODE_MOV; 00452 inst->DstReg.File = type; 00453 inst->DstReg.Index = var; 00454 inst->SrcReg[0].File = PROGRAM_TEMPORARY; 00455 inst->SrcReg[0].Index = outputMap[var]; 00456 inst++; 00457 } 00458 } 00459 } 00460 } Generated on Sat May 26 2012 04:19:22 for ReactOS by
1.7.6.1
|