ReactOS Fundraising Campaign 2012
 
€ 4,410 / € 30,000

Information | Donate

Home | Info | Community | Development | myReactOS | Contact Us

  1. Home
  2. Community
  3. Development
  4. myReactOS
  5. Fundraiser 2012

  1. Main Page
  2. Alphabetical List
  3. Data Structures
  4. Directories
  5. File List
  6. Data Fields
  7. Globals
  8. Related Pages

ReactOS Development > Doxygen

programopt.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 doxygen 1.7.6.1

ReactOS is a registered trademark or a trademark of ReactOS Foundation in the United States and other countries.