From 0ea5fc66924303d1bf73ba283a383e2aadee02f2 Mon Sep 17 00:00:00 2001 From: neodarz Date: Sat, 11 Aug 2018 20:21:34 +0200 Subject: Initial commit --- ...river__opengl__vertex__program_8cpp-source.html | 1451 ++++++++++++++++++++ 1 file changed, 1451 insertions(+) create mode 100644 docs/doxygen/nel/driver__opengl__vertex__program_8cpp-source.html (limited to 'docs/doxygen/nel/driver__opengl__vertex__program_8cpp-source.html') diff --git a/docs/doxygen/nel/driver__opengl__vertex__program_8cpp-source.html b/docs/doxygen/nel/driver__opengl__vertex__program_8cpp-source.html new file mode 100644 index 00000000..01672cd0 --- /dev/null +++ b/docs/doxygen/nel/driver__opengl__vertex__program_8cpp-source.html @@ -0,0 +1,1451 @@ + + + + nevrax.org : docs + + + + + + + + + + + + + + +
# Home   # nevrax.com   
+ + + + +
Nevrax
+ + + + + + + + + + +
+ + +
+ Nevrax.org
+ + + + + + + +
#News
#Mailing-list
#Documentation
#CVS
#Bugs
#License
+
+ + +
+ + +
+Docs + +
+  + + + + + +
Documentation 
+ +
+Main Page   Namespace List   Class Hierarchy   Alphabetical List   Compound List   File List   Namespace Members   Compound Members   File Members   Related Pages   Search  
+

driver_opengl_vertex_program.cpp

Go to the documentation of this file.
00001 
+00009 /* Copyright, 2000 Nevrax Ltd.
+00010  *
+00011  * This file is part of NEVRAX NEL.
+00012  * NEVRAX NEL is free software; you can redistribute it and/or modify
+00013  * it under the terms of the GNU General Public License as published by
+00014  * the Free Software Foundation; either version 2, or (at your option)
+00015  * any later version.
+00016 
+00017  * NEVRAX NEL is distributed in the hope that it will be useful, but
+00018  * WITHOUT ANY WARRANTY; without even the implied warranty of
+00019  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+00020  * General Public License for more details.
+00021 
+00022  * You should have received a copy of the GNU General Public License
+00023  * along with NEVRAX NEL; see the file COPYING. If not, write to the
+00024  * Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston,
+00025  * MA 02111-1307, USA.
+00026  */
+00027 
+00028 #include "stdopengl.h"
+00029 
+00030 #include "3d/primitive_block.h"
+00031 #include "3d/vertex_program.h"
+00032 #include "3d/vertex_program_parse.h"
+00033 #include <algorithm>
+00034 
+00035 
+00036 using namespace std;
+00037 using namespace NLMISC;
+00038 
+00039  
+00040 namespace NL3D
+00041 {
+00042 
+00043 // ***************************************************************************
+00044 CVertexProgamDrvInfosGL::CVertexProgamDrvInfosGL (CDriverGL *drv, ItVtxPrgDrvInfoPtrList it) : IVertexProgramDrvInfos (drv, it) 
+00045 {
+00046         // Extension must exist
+00047         nlassert (drv->_Extensions.NVVertexProgram
+00048                       || drv->_Extensions.EXTVertexShader
+00049                      );
+00050 
+00051         if (drv->_Extensions.NVVertexProgram) // nvidia implemntation
+00052         {       
+00053                 // Generate a program
+00054                 nglGenProgramsNV (1, &ID);
+00055         }
+00056         else
+00057         {
+00058                 ID = nglGenVertexShadersEXT(1);
+00059         }
+00060 }
+00061 
+00062 
+00063 // ***************************************************************************
+00064 bool CDriverGL::isVertexProgramSupported () const
+00065 {       
+00066         return _Extensions.NVVertexProgram || _Extensions.EXTVertexShader;
+00067 }
+00068 
+00069 // ***************************************************************************
+00070 bool CDriverGL::isVertexProgramEmulated () const
+00071 {
+00072         return _Extensions.NVVertexProgramEmulated;
+00073 }
+00074 
+00075 
+00076 
+00077 // ***************************************************************************
+00078 bool CDriverGL::activeNVVertexProgram (CVertexProgram *program)
+00079 {
+00080         // Setup or unsetup ?
+00081         if (program)
+00082         {
+00083                 // Enable vertex program
+00084                 glEnable (GL_VERTEX_PROGRAM_NV);
+00085                 _VertexProgramEnabled= true;
+00086 
+00087 
+00088                 // Driver info
+00089                 CVertexProgamDrvInfosGL *drvInfo;
+00090 
+00091                 // Program setuped ?
+00092                 if (program->_DrvInfo==NULL)
+00093                 {
+00097                         CVPParser parser;
+00098                         CVPParser::TProgram parsedProgram;
+00099                         std::string errorOutput;
+00100                         bool result = parser.parse(program->getProgram().c_str(), parsedProgram, errorOutput);
+00101                         if (!result)
+00102                         {
+00103                                 nlwarning("Unable to parse a vertex program :");
+00104                                 nlwarning(errorOutput.c_str());
+00105                                 #ifdef NL_DEBUG
+00106                                         nlassert(0);
+00107                                 #endif
+00108                                 return false;
+00109                         }
+00110 
+00111                         // Insert into driver list. (so it is deleted when driver is deleted).
+00112                         ItVtxPrgDrvInfoPtrList  it= _VtxPrgDrvInfos.insert(_VtxPrgDrvInfos.end());
+00113 
+00114                         // Create a driver info
+00115                         *it = drvInfo = new CVertexProgamDrvInfosGL (this, it);
+00116 
+00117                         // Set the pointer
+00118                         program->_DrvInfo=drvInfo;                                              
+00119 
+00120                         // Compile the program
+00121                         nglLoadProgramNV (GL_VERTEX_PROGRAM_NV, drvInfo->ID, program->getProgram().length(), (const GLubyte*)program->getProgram().c_str());
+00122 
+00123                         // Get loading error code
+00124                         GLint errorOff;
+00125                         glGetIntegerv (GL_PROGRAM_ERROR_POSITION_NV, &errorOff);
+00126 
+00127                         // Compilation error ?
+00128                         if (errorOff>=0)
+00129                         {
+00130                                 // String length
+00131                                 uint length = program->getProgram ().length();
+00132                                 const char* sString= program->getProgram ().c_str();
+00133 
+00134                                 // Line count and char count
+00135                                 uint line=1;
+00136                                 uint charC=1;
+00137 
+00138                                 // Find the line
+00139                                 uint offset=0;
+00140                                 while ((offset<length)&&(offset<(uint)errorOff))
+00141                                 {
+00142                                         if (sString[offset]=='\n')
+00143                                         {
+00144                                                 line++;
+00145                                                 charC=1;
+00146                                         }
+00147                                         else
+00148                                                 charC++;
+00149 
+00150                                         // Next character
+00151                                         offset++;
+00152                                 }
+00153 
+00154                                 // Show the error
+00155                                 nlinfo ("Vertex program syntax error line %d character %d\n", line, charC);
+00156 
+00157                                 // Disable vertex program
+00158                                 glDisable (GL_VERTEX_PROGRAM_NV);
+00159                                 _VertexProgramEnabled= false;
+00160 
+00161                                 // Setup not ok
+00162                                 return false;
+00163                         }
+00164 
+00165                         // Setup ok
+00166                         return true;
+00167                 }
+00168                 else
+00169                 {
+00170                         // Cast the driver info pointer
+00171                         drvInfo=safe_cast<CVertexProgamDrvInfosGL*>((IVertexProgramDrvInfos*)program->_DrvInfo);
+00172                 }
+00173 
+00174                 // Setup this program
+00175                 nglBindProgramNV (GL_VERTEX_PROGRAM_NV, drvInfo->ID);
+00176                 _LastSetuppedVP = program;
+00177 
+00178                 // Ok
+00179                 return true;
+00180         }
+00181         else // Unsetup
+00182         {
+00183                 // Disable vertex program
+00184                 glDisable (GL_VERTEX_PROGRAM_NV);
+00185                 _VertexProgramEnabled= false;
+00186                 // Ok
+00187                 return true;
+00188         }
+00189 }
+00190 
+00191 
+00192 // ***************************************************************************
+00193 static 
+00194 inline GLenum convSwizzleToGLFormat(CVPSwizzle::EComp comp, bool negate)
+00195 {
+00196         if (!negate)
+00197         {
+00198                 switch(comp)
+00199                 {
+00200                         case CVPSwizzle::X: return GL_X_EXT;
+00201                         case CVPSwizzle::Y: return GL_Y_EXT;
+00202                         case CVPSwizzle::Z: return GL_Z_EXT;
+00203                         case CVPSwizzle::W: return GL_W_EXT;
+00204                         default:
+00205                                 nlstop;
+00206                                 return 0;
+00207                         break;
+00208                 }
+00209         }
+00210         else
+00211         {
+00212                 switch(comp)
+00213                 {
+00214                         case CVPSwizzle::X: return GL_NEGATIVE_X_EXT;
+00215                         case CVPSwizzle::Y: return GL_NEGATIVE_Y_EXT;
+00216                         case CVPSwizzle::Z: return GL_NEGATIVE_Z_EXT;
+00217                         case CVPSwizzle::W: return GL_NEGATIVE_W_EXT;
+00218                         default:
+00219                                 nlstop;
+00220                                 return 0;
+00221                         break;
+00222                 }
+00223         }
+00224 }
+00225 
+00226 // ***************************************************************************
+00229 static GLuint convOutputRegisterToEXTVertexShader(CVPOperand::EOutputRegister r)
+00230 {
+00231         switch (r)
+00232         {
+00233                 case    CVPOperand::OHPosition:                 return GL_OUTPUT_VERTEX_EXT;
+00234                 case    CVPOperand::OPrimaryColor:              return GL_OUTPUT_COLOR0_EXT;
+00235                 case    CVPOperand::OSecondaryColor:    return GL_OUTPUT_COLOR1_EXT;
+00236                 case    CVPOperand::OBackFacePrimaryColor:
+00237                         nlwarning("Backface color used in a vertex program is not supported by device, defaulting to front color");
+00238                         return GL_OUTPUT_COLOR0_EXT;
+00239                 break;
+00240                 case    CVPOperand::OBackFaceSecondaryColor:
+00241                         nlwarning("Backface color used in a vertex program is not supported by device, defaulting to front color");
+00242                         return GL_OUTPUT_COLOR1_EXT;
+00243                 break;
+00244                 case    CVPOperand::OFogCoord:                  return GL_OUTPUT_FOG_EXT;
+00245                 case    CVPOperand::OPointSize:                 nlstop; return 0; // sorry, not supported
+00246                 case    CVPOperand::OTex0:                              return GL_OUTPUT_TEXTURE_COORD0_EXT;
+00247                 case    CVPOperand::OTex1:                              return GL_OUTPUT_TEXTURE_COORD1_EXT;
+00248                 case    CVPOperand::OTex2:                              return GL_OUTPUT_TEXTURE_COORD2_EXT;
+00249                 case    CVPOperand::OTex3:                              return GL_OUTPUT_TEXTURE_COORD3_EXT;
+00250                 case    CVPOperand::OTex4:                              return GL_OUTPUT_TEXTURE_COORD4_EXT;
+00251                 case    CVPOperand::OTex5:                              return GL_OUTPUT_TEXTURE_COORD5_EXT;
+00252                 case    CVPOperand::OTex6:                              return GL_OUTPUT_TEXTURE_COORD6_EXT;
+00253                 case    CVPOperand::OTex7:                              return GL_OUTPUT_TEXTURE_COORD7_EXT;
+00254                 default:
+00255                         nlstop;
+00256                 break;
+00257         }
+00258         return 0;
+00259 }
+00260 
+00261 // ***************************************************************************
+00264 static uint convInputRegisterToVBFlag(uint index)
+00265 {
+00266         switch (index)
+00267         {       
+00268                 case CVPOperand::IPosition:                             return CVertexBuffer::PositionFlag;
+00269                 case CVPOperand::IWeight:                               return CVertexBuffer::WeightFlag;
+00270                 case CVPOperand::INormal:                               return CVertexBuffer::NormalFlag;
+00271                 case CVPOperand::IPrimaryColor:                 return CVertexBuffer::PrimaryColorFlag;
+00272                 case CVPOperand::ISecondaryColor:               return CVertexBuffer::SecondaryColorFlag;
+00273                 case CVPOperand::IFogCoord:                             return CVertexBuffer::FogFlag;
+00274                 case CVPOperand::IPaletteSkin:                  return CVertexBuffer::PaletteSkinFlag;
+00275                 case CVPOperand::IEmpty: nlassert(0); break;
+00276                 case CVPOperand::ITex0:
+00277                 case CVPOperand::ITex1: 
+00278                 case CVPOperand::ITex2:
+00279                 case CVPOperand::ITex3:
+00280                 case CVPOperand::ITex4:
+00281                 case CVPOperand::ITex5:
+00282                 case CVPOperand::ITex6:
+00283                 case CVPOperand::ITex7:
+00284                 case CVPOperand::ITex8:
+00285                         return CVertexBuffer::TexCoord0Flag << (index - CVPOperand::ITex0);
+00286                 default:
+00287                         nlassert(0);
+00288                 break;
+00289         }
+00290         return 0;
+00291 }
+00292 
+00293 
+00294 
+00295 // A macro to debug the generated instruction
+00296 #define DEBUG_SETUP_EXT_VERTEX_SHADER
+00297 
+00298 #ifdef DEBUG_SETUP_EXT_VERTEX_SHADER
+00299         #define EVS_INFO(what) nlinfo(what)
+00300 #else
+00301         #define EVS_INFO(what)
+00302 #endif
+00303 
+00304 
+00305 // For debugging with swizzling
+00306 static void doSwizzle(GLuint res, GLuint in, GLenum outX, GLenum outY, GLenum outZ, GLenum outW)
+00307 {
+00308         nglSwizzleEXT(res, in, outX, outY, outZ, outW);
+00309 #ifdef DEBUG_SETUP_EXT_VERTEX_SHADER
+00310         std::string swzStr = "Swizzle : ";
+00311         GLenum swz[] = { outX, outY, outZ, outW };              
+00312         for(uint k = 0; k < 4; ++k)
+00313         {
+00314                 switch(swz[k])
+00315                 {
+00316                         case GL_X_EXT:
+00317                                 swzStr +=" X";
+00318                         break;
+00319                         case GL_NEGATIVE_X_EXT:
+00320                                 swzStr +=" -X";
+00321                         break;
+00322                         case GL_Y_EXT:
+00323                                 swzStr +=" Y";
+00324                         break;
+00325                         case GL_NEGATIVE_Y_EXT:
+00326                                 swzStr +=" -Y";
+00327                         break;
+00328                         break;
+00329                         case GL_Z_EXT:
+00330                                 swzStr +=" Z";
+00331                         break;
+00332                         case GL_NEGATIVE_Z_EXT:
+00333                                 swzStr +=" -Z";
+00334                         break;
+00335                         case GL_W_EXT:
+00336                                 swzStr +=" W";
+00337                         break;
+00338                         case GL_NEGATIVE_W_EXT:
+00339                                 swzStr +=" -W";
+00340                         break;
+00341                         case GL_ZERO_EXT:
+00342                                 swzStr +="0";
+00343                         break;
+00344                         case GL_ONE_EXT:
+00345                                 swzStr +="1";
+00346                         break;
+00347                 }
+00348         }
+00349         EVS_INFO(swzStr.c_str());
+00350 #endif
+00351 
+00352 }
+00353 
+00354 // Perform write mask and output de bug informations
+00355 static void doWriteMask(GLuint res, GLuint in, GLenum outX, GLenum outY, GLenum outZ, GLenum outW)
+00356 {
+00357         nglWriteMaskEXT(res, in, outX, outY, outZ, outW);
+00358         #ifdef DEBUG_SETUP_EXT_VERTEX_SHADER
+00359         nlinfo("Write Mask : %c%c%c%c",
+00360                    outX ? 'x' : '-',
+00361                    outY ? 'y' : '-',
+00362                    outZ ? 'z' : '-',
+00363                    outW ? 'w' : '-'                
+00364                   );
+00365         #endif
+00366 }
+00367 
+00368 // ***************************************************************************
+00371 bool CDriverGL::setupEXTVertexShader(const CVPParser::TProgram &program, GLuint id, uint variants[EVSNumVariants], uint16 &usedInputRegisters)
+00372 {
+00373         // counter to see what is generated
+00374         uint numOp = 0;
+00375         uint numOpIndex = 0;
+00376         uint numSwizzle = 0;
+00377         uint numEC = 0; // extract component
+00378         uint numIC = 0; // insert component
+00379         uint numWM = 0; // write maks
+00380 
+00381         
+00382         #ifdef DEBUG_SETUP_EXT_VERTEX_SHADER
+00383                 nlinfo("**********************************************************");
+00384         #endif
+00385 
+00386         // clear last error
+00387         GLenum glError = glGetError();
+00388 
+00389         // allocate the symbols
+00390         nglBindVertexShaderEXT(id);
+00391         nglBeginVertexShaderEXT();
+00392         {                               
+00393                 // Allocate register and variant
+00394                 GLuint firstRegister = nglGenSymbolsEXT(GL_VECTOR_EXT, GL_LOCAL_EXT, GL_FULL_RANGE_EXT, 12); // 12 register
+00395                 GLuint firstTempRegister = nglGenSymbolsEXT(GL_VECTOR_EXT, GL_LOCAL_EXT, GL_FULL_RANGE_EXT, 4); // 4  temp register used for swizzle & indexing
+00396                 GLuint firstTempScalar = nglGenSymbolsEXT(GL_SCALAR_EXT, GL_LOCAL_EXT, GL_FULL_RANGE_EXT, 3); // 3  temp scalars used for EXPP & LOGG emulation
+00397                 GLuint firstAddressRegister = nglGenSymbolsEXT(GL_SCALAR_EXT, GL_LOCAL_EXT, GL_FULL_RANGE_EXT, 1);
+00398 
+00399                 // allocate variants
+00400                 variants[EVSSecondaryColorVariant] = nglGenSymbolsEXT(GL_VECTOR_EXT, GL_VARIANT_EXT, GL_NORMALIZED_RANGE_EXT, 1);
+00401                 variants[EVSFogCoordsVariant] = nglGenSymbolsEXT(GL_VECTOR_EXT, GL_VARIANT_EXT, GL_FULL_RANGE_EXT, 1);
+00402                 variants[EVSSkinWeightVariant] = nglGenSymbolsEXT(GL_VECTOR_EXT, GL_VARIANT_EXT, GL_NORMALIZED_RANGE_EXT, 1);
+00403                 variants[EVSPaletteSkinVariant] = nglGenSymbolsEXT(GL_VECTOR_EXT, GL_VARIANT_EXT, GL_FULL_RANGE_EXT, 1);
+00404 
+00405                 // allocate one temporary register for fog before conversion
+00406                 GLuint fogTemp = nglGenSymbolsEXT(GL_VECTOR_EXT, GL_LOCAL_EXT, GL_FULL_RANGE_EXT, 1);
+00407 
+00408 
+00409                 // local constant : 0 and 1
+00410                 GLuint cteOne = nglGenSymbolsEXT(GL_SCALAR_EXT, GL_LOCAL_CONSTANT_EXT, GL_FULL_RANGE_EXT, 1);
+00411                 GLuint cteZero = nglGenSymbolsEXT(GL_SCALAR_EXT, GL_LOCAL_CONSTANT_EXT, GL_FULL_RANGE_EXT, 1);
+00412 
+00413 
+00414                 float oneValue = 1.f;
+00415                 float zeroValue = 0.f;
+00416 
+00417                 nglSetLocalConstantEXT( cteOne, GL_FLOAT, &oneValue);
+00418                 nglSetLocalConstantEXT( cteZero, GL_FLOAT, &zeroValue);
+00419 
+00420 
+00421                 
+00422                 if (firstRegister == 0)
+00423                 {
+00424                         nlwarning("Unable to allocate local registers for EXT_vertex_shader");
+00425                         return false;
+00426                 }
+00427                 if (firstTempRegister == 0)
+00428                 {
+00429                         nlwarning("Unable to allocate local temp registers for EXT_vertex_shader");
+00430                         return false;
+00431                 }
+00432                 if (firstTempScalar == 0)
+00433                 {
+00434                         nlwarning("Unable to allocate temp scalar registers for EXT_vertex_shader");
+00435                         return false;
+00436                 }
+00437                 if (firstAddressRegister == 0)
+00438                 {
+00439                         nlwarning("Unable to allocate address register for EXT_vertex_shader");
+00440                         return false;
+00441                 }
+00442 
+00443                 uint k;
+00444                 for(k = 0; k < EVSNumVariants; ++k)
+00445                 {
+00446                         if (variants[k] == 0)
+00447                         {
+00448                                 nlwarning("Unable to allocate variants for EXT_vertex_shader");
+00449                                 return false;
+00450                         }
+00451                 }
+00452 
+00453                 // Mask of output component that are being written
+00454                 uint componentWritten[16];
+00455                 std::fill(componentWritten, componentWritten + 16, 0);
+00456                 
+00457                 //
+00458                 GLuint srcValue[3];
+00459                 //
+00460                 GLuint destValue;
+00461                 GLuint maskedDestValue;
+00462                 
+00463 
+00464                 uint l;
+00465                 // convert each instruction of the vertex program
+00466                 for(k = 0; k < program.size(); ++k)
+00467                 {
+00468                         // get src values, eventually applying swizzle, negate, and index on them
+00469                         uint numSrc = program[k].getNumUsedSrc();
+00470                         for(l = 0; l < numSrc; ++l)
+00471                         {
+00472                                 EVS_INFO(("Build source " + toString(l)).c_str());
+00473                                 const CVPOperand &operand = program[k].getSrc(l);
+00474                                 switch (operand.Type)
+00475                                 {
+00476                                         case CVPOperand::InputRegister: 
+00477                                         {
+00478                                                 switch(operand.Value.InputRegisterValue)
+00479                                                 {
+00480                                                         case  0: srcValue[l] = _EVSPositionHandle; EVS_INFO("Src = position"); break;
+00481                                                         case  1: srcValue[l] = variants[EVSSkinWeightVariant]; EVS_INFO("Src = skin weight"); break;
+00482                                                         case  2: srcValue[l] = _EVSNormalHandle; EVS_INFO("Src = normal"); break;
+00483                                                         case  3: srcValue[l] = _EVSColorHandle; EVS_INFO("Src = color 0"); break;
+00484                                                         case  4: srcValue[l] = variants[EVSSecondaryColorVariant]; EVS_INFO("Src = color 1"); break;
+00485                                                         case  5: srcValue[l] = variants[EVSFogCoordsVariant]; EVS_INFO("Src = fog coord"); break;
+00486                                                         case  6: srcValue[l] = variants[EVSPaletteSkinVariant]; EVS_INFO("Src = palette skin"); break;
+00487                                                         case  7: nlstop; // not supported
+00488                                                         case  8:
+00489                                                         case  9:
+00490                                                         case  10:
+00491                                                         case  11:
+00492                                                         case  12:
+00493                                                         case  13:
+00494                                                         case  14:
+00495                                                         case  15:
+00496                                                         {                                                               
+00497                                                                 EVS_INFO(("Src = Tex" + toString(operand.Value.InputRegisterValue - 8)).c_str());
+00498                                                                 srcValue[l] = _EVSTexHandle[operand.Value.InputRegisterValue - 8];
+00499                                                                 if (srcValue[l] == 0)
+00500                                                                 {                                                               
+00501                                                                         nlwarning("Trying to read an unaccessible texture coords for the device when using EXT_vertex_shader, shader loading failed");
+00502                                                                         return false;
+00503                                                                 }
+00504                                                         }
+00505                                                         break;
+00506                                                         default:
+00507                                                                 nlstop; // invalid value
+00508                                                         break;
+00509                                                 }
+00510                                         }
+00511                                         break;
+00512                                         case CVPOperand::Constant: 
+00513                                                 srcValue[l] = _EVSConstantHandle + operand.Value.ConstantValue; 
+00514                                                 EVS_INFO(("Src = constant" + toString(operand.Value.ConstantValue)).c_str());
+00515                                         break;
+00516                                         case CVPOperand::Variable: 
+00517                                                 srcValue[l] = firstRegister + operand.Value.VariableValue;
+00518                                                 EVS_INFO(("Src = variable register" + toString(operand.Value.VariableValue)).c_str());
+00519                                         break;
+00520                                         default:
+00521                                                 nlassert(0);
+00522                                         break;
+00523                                 }
+00524                                 // test if indexed access is used (can be used on one register only)
+00525                                 if (operand.Type == CVPOperand::Constant && operand.Indexed)
+00526                                 {
+00527                                         nglShaderOp2EXT(GL_OP_INDEX_EXT, firstTempRegister + 3, firstAddressRegister, srcValue[l]);
+00528                                         EVS_INFO("GL_OP_INDEX_EXT");
+00529                                         ++ numOpIndex;
+00530                                         srcValue[l] = firstTempRegister + 3;
+00531                                         glError = glGetError();
+00532                                         nlassert(glError == GL_NO_ERROR)
+00533                                 }
+00534 
+00535                                 // test if swizzle or negate is used
+00536                                 if (!operand.Swizzle.isIdentity() || operand.Negate)
+00537                                 {
+00538                                         // if the instruction reads a scalar, no need for swizzle (except if negate is used)
+00539                                         if (!                                           
+00540                                                 (
+00541                                                  (program[k].Opcode == CVPInstruction::RSQ
+00542                                                   || program[k].Opcode == CVPInstruction::RCP
+00543                                                   || program[k].Opcode == CVPInstruction::LOG
+00544                                                   || program[k].Opcode == CVPInstruction::EXPP
+00545                                              ) 
+00546                                                  && 
+00547                                                  !operand.Negate
+00548                                                 )
+00549                                         )
+00550                                         {                                       
+00551                                                 // need a temp register for swizzle and/or negate
+00552                                                 doSwizzle(firstTempRegister + l, srcValue[l],
+00553                                                                           convSwizzleToGLFormat(operand.Swizzle.Comp[0], operand.Negate),
+00554                                                                           convSwizzleToGLFormat(operand.Swizzle.Comp[1], operand.Negate),
+00555                                                                           convSwizzleToGLFormat(operand.Swizzle.Comp[2], operand.Negate),
+00556                                                                           convSwizzleToGLFormat(operand.Swizzle.Comp[3], operand.Negate));                                              
+00557                                                 ++numSwizzle;
+00558                                                 srcValue[l] = firstTempRegister + l;
+00559                                                 glError = glGetError();
+00560                                                 nlassert(glError == GL_NO_ERROR)
+00561                                         }
+00562                                 }
+00563                         }
+00564 
+00565                         // get dest value
+00566                         const CVPOperand &destOperand = program[k].Dest;
+00567                         switch(destOperand.Type)
+00568                         {
+00569                                 case CVPOperand::Variable: 
+00570                                         destValue = firstRegister + destOperand.Value.VariableValue; 
+00571                                 break;
+00572                                 case CVPOperand::OutputRegister:
+00573                                         if (destOperand.Value.OutputRegisterValue != CVPOperand::OFogCoord)
+00574                                         {                                       
+00575                                                 destValue = convOutputRegisterToEXTVertexShader(destOperand.Value.OutputRegisterValue);
+00576                                         }
+00577                                         else
+00578                                         {
+00579                                                 destValue = fogTemp;
+00580                                         }
+00581                                 break;
+00582                                 case CVPOperand::AddressRegister:
+00583                                         destValue = firstAddressRegister;
+00584                                 break;
+00585                                 default:
+00586                                         nlassert(0);
+00587                                 break;
+00588                         }
+00589 
+00590                         uint writeMask = program[k].Dest.WriteMask;
+00591                         CVPInstruction::EOpcode opcode = program[k].Opcode;
+00592                         uint outputRegisterIndex = destOperand.Value.OutputRegisterValue;
+00593                         nlassert(outputRegisterIndex < 16);
+00594 
+00595                         // Tells wether the output has already been written before the final write mask. This happens with instructions LOG, EXPP, LIT, RSQ and RCP,
+00596                         // because they write their output component by components
+00597                         bool outputWritten = false;
+00598 
+00599                         // test for write mask                                          
+00600                         if (writeMask != 0x0f) 
+00601                         {                                       
+00605                                 if (!(destOperand.Type == CVPOperand::OutputRegister && destValue == fogTemp))
+00606                                 {
+00607                                         // For instructions that write their output components by components, we don't need an intermediary register
+00608                                         if (opcode == CVPInstruction::LOG
+00609                                                 || opcode == CVPInstruction::EXPP
+00610                                                 || opcode == CVPInstruction::LIT
+00611                                                 || opcode == CVPInstruction::RSQ
+00612                                                 || opcode == CVPInstruction::RCP
+00613                                            )
+00614                                         {
+00615                                                 outputWritten = true;   
+00616                                         }
+00617                                         else
+00618                                         {                                       
+00619                                                 maskedDestValue = destValue;
+00620                                                 // use a temp register before masking
+00621                                                 destValue = firstTempRegister;
+00622                                         }
+00623                                 }
+00624                                 else
+00625                                 {
+00626                                         componentWritten[outputRegisterIndex] = 0xf;
+00627                                 }
+00628                         }
+00629                         else
+00630                         {
+00631                                 if (destOperand.Type == CVPOperand::OutputRegister)
+00632                                 {
+00633                                         componentWritten[outputRegisterIndex] = 0xf; // say all components have been written for that output                            
+00634                                 }
+00635                         }                       
+00636                         
+00637                         // generate opcode
+00638                         switch (opcode)
+00639                         {
+00640                                 case  CVPInstruction::ARL:
+00641                                 {                                       
+00642                                         nlassert(program[k].Src1.Swizzle.isScalar());
+00643                                         GLuint index = program[k].Src1.Swizzle.Comp[0];
+00644                                         nglExtractComponentEXT(firstAddressRegister, srcValue[0],  index);
+00645                                         EVS_INFO("Extract component");
+00646                                         ++numEC;
+00647                                 }
+00648                                 break;
+00649                                 case  CVPInstruction::MOV:
+00650                                 {                                                                                       
+00651                                         nglShaderOp1EXT(GL_OP_MOV_EXT, destValue, srcValue[0]);
+00652                                         EVS_INFO("GL_OP_MOV_EXT");
+00653                                         ++numOp;                                        
+00654                                 }
+00655                                 break;
+00656                                 case  CVPInstruction::MUL: 
+00657                                         nglShaderOp2EXT(GL_OP_MUL_EXT, destValue, srcValue[0], srcValue[1]); 
+00658                                         EVS_INFO("GL_OP_MUL_EXT");
+00659                                         ++numOp;
+00660                                 break;
+00661                                 case  CVPInstruction::ADD: 
+00662                                         nglShaderOp2EXT(GL_OP_ADD_EXT, destValue, srcValue[0], srcValue[1]); 
+00663                                         EVS_INFO("GL_OP_ADD_EXT");
+00664                                         ++numOp;
+00665                                 break;
+00666                                 case  CVPInstruction::MAD: 
+00667                                         nglShaderOp3EXT(GL_OP_MADD_EXT, destValue, srcValue[0], srcValue[1], srcValue[2]); 
+00668                                         EVS_INFO("GL_OP_MADD_EXT");
+00669                                         ++numOp;
+00670                                 break;
+00671                                 case  CVPInstruction::RSQ:
+00672                                 {
+00673                                         nlassert(program[k].Src1.Swizzle.isScalar());
+00674                                         // extract the component we need
+00675                                         GLuint index = program[k].Src1.Swizzle.Comp[0];
+00676                                         nglExtractComponentEXT(firstTempScalar, srcValue[0],  index);
+00677                                         EVS_INFO("Extract component");
+00678                                         ++numEC;
+00679                                         nglShaderOp1EXT(GL_OP_RECIP_SQRT_EXT, firstTempScalar + 1, firstTempScalar);
+00680                                         EVS_INFO("GL_OP_RECIP_SQRT_EXT");
+00681                                         ++numOp;
+00682                                         // duplicate result in destination
+00683                                         for(uint l = 0; l < 4; ++l)
+00684                                         {
+00685                                                 if (writeMask & (1 << l))
+00686                                                 {                                               
+00687                                                         nglInsertComponentEXT(destValue, firstTempScalar + 1, l);
+00688                                                         EVS_INFO("Insert component");
+00689                                                         nlassert(glGetError() == GL_NO_ERROR);
+00690                                                 }
+00691                                         }
+00692                                 }
+00693                                 break;
+00694                                 case  CVPInstruction::DP3: 
+00695                                         nglShaderOp2EXT(GL_OP_DOT3_EXT, destValue, srcValue[0], srcValue[1]);
+00696                                         EVS_INFO("GL_OP_DOT3_EXT");
+00697                                         ++numOp;
+00698                                 break;
+00699                                 case  CVPInstruction::DP4: 
+00700                                         nglShaderOp2EXT(GL_OP_DOT4_EXT, destValue, srcValue[0], srcValue[1]); 
+00701                                         EVS_INFO("GL_OP_DOT4_EXT");
+00702                                         ++numOp;
+00703                                 break;
+00704                                 case  CVPInstruction::DST: 
+00705                                         doSwizzle(firstTempRegister, srcValue[0], GL_ONE_EXT, GL_Y_EXT, GL_Z_EXT, GL_ONE_EXT);
+00706                                         EVS_INFO("GL_OP_DOT4_EXT");
+00707                                         ++numOp;
+00708                                         doSwizzle(firstTempRegister + 1, srcValue[1], GL_ONE_EXT, GL_Y_EXT, GL_ONE_EXT, GL_W_EXT);                                      
+00709                                         ++numSwizzle;
+00710                                         nglShaderOp2EXT(GL_OP_MUL_EXT, destValue, firstTempRegister, firstTempRegister + 1);
+00711                                         EVS_INFO("GL_OP_MUL_EXT");
+00712                                         ++numOp;
+00713                                 break;                                  
+00714                                 case  CVPInstruction::LIT:
+00715                                 {
+00716                                         uint writeMask = program[k].Dest.WriteMask;                                     
+00717                                         nglExtractComponentEXT(firstTempScalar, srcValue[0], 0); // extract X from the source
+00718                                         if (writeMask & 4)
+00719                                         {                                       
+00720                                                 nglExtractComponentEXT(firstTempScalar + 1, srcValue[0], 1); // extract Y from the source
+00721                                                 EVS_INFO("Extract component");
+00722                                                 ++numEC;
+00723                                                 nglExtractComponentEXT(firstTempScalar + 2, srcValue[0], 3); // extract W from the source
+00724                                                 EVS_INFO("Extract component");
+00725                                                 ++numEC;
+00726                                                 // result = X > 0 ? Y^W : 0                                     
+00727                                                 nglShaderOp2EXT(GL_OP_POWER_EXT, firstTempScalar + 2, firstTempScalar + 1, firstTempScalar + 2);
+00728                                                 EVS_INFO("GL_OP_POWER_EXT");
+00729                                                 ++numOp;
+00730                                                 nglShaderOp2EXT(GL_OP_SET_GE_EXT, firstTempScalar + 1, firstTempScalar, cteZero);
+00731                                                 EVS_INFO("GL_OP_SET_GE_EXT");
+00732                                                 ++numOp;
+00733                                                 nglShaderOp2EXT(GL_OP_MUL_EXT, firstTempScalar + 2, firstTempScalar + 2, firstTempScalar + 1);
+00734                                                 EVS_INFO("GL_OP_MUL_EXT");
+00735                                                 ++numOp;
+00736                                                 // store result
+00737                                                 nglInsertComponentEXT(destValue, firstTempScalar + 2, 2);
+00738                                                 EVS_INFO("Insert component");
+00739                                                 ++numIC;
+00740                                         }
+00741                                         if (writeMask & 2) 
+00742                                         {
+00743                                                 // clamp N.L to [0, 1]
+00744                                                 nglShaderOp3EXT(GL_OP_CLAMP_EXT, firstTempScalar, firstTempScalar, cteZero, cteOne);
+00745                                                 EVS_INFO("GL_OP_CLAMP_EXT");
+00746                                                 ++numOp;
+00747                                                 nglInsertComponentEXT(destValue, firstTempScalar, 1);
+00748                                                 EVS_INFO("Insert component");
+00749                                                 ++numIC;
+00750                                         }
+00751                                         // set x and w to 1 if they are not masked
+00752                                         if (writeMask & (1 + 8)) 
+00753                                         {                                       
+00754                                                 doSwizzle(destValue, destValue, 
+00755                                                                           (writeMask & 1) ? GL_ONE_EXT : GL_X_EXT,
+00756                                                                           GL_Y_EXT,
+00757                                                                           GL_Z_EXT,
+00758                                                                           (writeMask & 8) ? GL_ONE_EXT : GL_W_EXT);                                             
+00759                                                 ++numSwizzle;
+00760                                         }                                       
+00761                                                  
+00762                                 }
+00763                                 break;
+00764                                 case  CVPInstruction::MIN: 
+00765                                         nglShaderOp2EXT(GL_OP_MIN_EXT, destValue, srcValue[0], srcValue[1]);
+00766                                         EVS_INFO("GL_OP_MIN_EXT");
+00767                                         ++numOp;
+00768                                 break;
+00769                                 case  CVPInstruction::MAX: 
+00770                                         nglShaderOp2EXT(GL_OP_MAX_EXT, destValue, srcValue[0], srcValue[1]);
+00771                                         EVS_INFO("GL_OP_MAX_EXT");
+00772                                         ++numOp;
+00773                                 break;
+00774                                 case  CVPInstruction::SLT: 
+00775                                         nglShaderOp2EXT(GL_OP_SET_LT_EXT, destValue, srcValue[0], srcValue[1]);
+00776                                         EVS_INFO("GL_OP_SET_LT_EXT");
+00777                                         ++numOp;
+00778                                 break;
+00779                                 case  CVPInstruction::SGE: 
+00780                                         nglShaderOp2EXT(GL_OP_SET_GE_EXT, destValue, srcValue[0], srcValue[1]);
+00781                                         EVS_INFO("GL_OP_SET_GE_EXT");
+00782                                         ++numOp;
+00783                                 break;
+00784                                 case  CVPInstruction::EXPP:
+00785                                 {                       
+00786                                         uint writeMask = program[k].Dest.WriteMask;
+00787                                         nlassert(program[k].Src1.Swizzle.isScalar());
+00788                                         GLuint compIndex = program[k].Src1.Swizzle.Comp[0];
+00789                                         nglExtractComponentEXT(firstTempScalar + 2, srcValue[0], compIndex); // extract W from the source
+00790                                         EVS_INFO("Extract component");
+00791                                         ++numEC;
+00792                                         if (writeMask & 1)
+00793                                         {                                       
+00794                                                 nglShaderOp1EXT(GL_OP_FLOOR_EXT, firstTempScalar, firstTempScalar + 2); // (int) W
+00795                                                 EVS_INFO("GL_OP_FLOOR_EXT");
+00796                                                 ++numOp;
+00797                                                 nglShaderOp1EXT(GL_OP_EXP_BASE_2_EXT, firstTempScalar, firstTempScalar); // 2 ^ (int) W         
+00798                                                 EVS_INFO("GL_OP_EXP_BASE_2_EXT");
+00799                                                 ++numOp;
+00800                                         }
+00801                                         if (writeMask & 2) 
+00802                                         {                                       
+00803                                                 nglShaderOp1EXT(GL_OP_FRAC_EXT, firstTempScalar + 1, firstTempScalar + 2); // frac(W)
+00804                                                 EVS_INFO("GL_OP_FRAC_EXT");
+00805                                                 ++numOp;
+00806                                         }
+00807                                         if (writeMask & 4) nglShaderOp1EXT(GL_OP_EXP_BASE_2_EXT, firstTempScalar + 2, firstTempScalar + 2); // 2 ^W
+00808                                         // store the results
+00809                                         if (writeMask & 1) { nglInsertComponentEXT(destValue, firstTempScalar, 0); EVS_INFO("Insert component"); ++numIC;  }
+00810                                         if (writeMask & 2) { nglInsertComponentEXT(destValue, firstTempScalar + 1, 1); EVS_INFO("Insert component"); ++numIC; }
+00811                                         if (writeMask & 4) { nglInsertComponentEXT(destValue, firstTempScalar + 2, 2); EVS_INFO("Insert component"); ++numIC; }
+00812                                         // set W to 1 and leave other values unchanged
+00813                                         if (writeMask & 8) { doSwizzle(destValue, destValue, GL_X_EXT, GL_Y_EXT, GL_Z_EXT, GL_ONE_EXT); ++numSwizzle; }
+00814                                 }
+00815                                 break;
+00816                                 case  CVPInstruction::LOG:
+00817                                 {                                       
+00818                                         uint writeMask = program[k].Dest.WriteMask;
+00819                                         nlassert(program[k].Src1.Swizzle.isScalar());
+00820                                         // extract the component we need
+00821                                         nglExtractComponentEXT(firstTempScalar, srcValue[0], (GLuint) program[k].Src1.Swizzle.Comp[0]);
+00822                                         EVS_INFO("Extract component");
+00823                                         ++numEC;
+00824                                         // get abs(src) : abs(src) = max(src, -src)
+00825                                         nglShaderOp1EXT(GL_OP_NEGATE_EXT, firstTempScalar + 1, firstTempScalar);
+00826                                         EVS_INFO("GL_OP_NEGATE_EXT");
+00827                                         ++numOp;
+00828                                         nglShaderOp2EXT(GL_OP_MAX_EXT, firstTempScalar, firstTempScalar, firstTempScalar + 1);
+00829                                         EVS_INFO("GL_OP_MAX_EXT");
+00830                                         ++numOp;
+00831                                         nglShaderOp1EXT(GL_OP_LOG_BASE_2_EXT, firstTempScalar, firstTempScalar); // (int) W
+00832                                         EVS_INFO("GL_OP_LOG_BASE_2_EXT");
+00833                                         ++numOp;
+00834                                         // store the results
+00835                                         for(uint l = 0; l < 4; ++l)
+00836                                         {
+00837                                                 if (writeMask & (1 << l))
+00838                                                 {                                               
+00839                                                         nglInsertComponentEXT(destValue, firstTempScalar, l);
+00840                                                         EVS_INFO("Insert component");
+00841                                                         nlassert(glGetError() == GL_NO_ERROR);
+00842                                                 }
+00843                                         }                                       
+00844                                 }
+00845                                 break;
+00846                                 case  CVPInstruction::RCP:
+00847                                 {
+00848                                         uint writeMask = program[k].Dest.WriteMask;
+00849                                         nlassert(program[k].Src1.Swizzle.isScalar());
+00850                                         // extract the component we need
+00851                                         nglExtractComponentEXT(firstTempScalar, srcValue[0], (GLuint) program[k].Src1.Swizzle.Comp[0]);
+00852                                         EVS_INFO("Extract component");
+00853                                         ++numEC;
+00854                                         nglShaderOp1EXT(GL_OP_RECIP_EXT, firstTempScalar + 1, firstTempScalar);
+00855                                         EVS_INFO("GL_OP_RECIP_EXT");
+00856                                         ++numOp;
+00857                                         // duplicate result in destination
+00858                                         for(uint l = 0; l < 4; ++l)
+00859                                         {
+00860                                                 if (writeMask & (1 << l))
+00861                                                 {                                               
+00862                                                         nglInsertComponentEXT(destValue, firstTempScalar + 1, l);
+00863                                                         EVS_INFO("insert component");
+00864                                                         ++numIC;
+00865                                                 }
+00866                                         }
+00867                                 }                                       
+00868                                 break;
+00869                         }
+00870 
+00871                         glError = glGetError();
+00872                         nlassert(glError == GL_NO_ERROR)
+00873 
+00874                                 
+00875                         // apply write mask if any
+00876                         if (writeMask != 0x0f)
+00877                         {                                                                       
+00878                                 if (destOperand.Type == CVPOperand::OutputRegister && destValue != fogTemp)
+00879                                 {
+00880                                         uint &outputMask = componentWritten[outputRegisterIndex];
+00881                                         // is a texture coordinate or a color being written ?
+00882                                         if ((maskedDestValue >= GL_OUTPUT_TEXTURE_COORD0_EXT && maskedDestValue <= GL_OUTPUT_TEXTURE_COORD7_EXT)
+00883                                                 || maskedDestValue == GL_OUTPUT_COLOR0_EXT
+00884                                                 || maskedDestValue == GL_OUTPUT_COLOR1_EXT
+00885                                            )
+00886                                         {                                       
+00887                                                 // test if this is the last time this output will be written
+00888                                                 bool found = false;
+00889                                                 // if this was the last write for this output, must set unfilled component
+00890                                                 // NB : this loop could be optimized, but vertex program are rather short for now ..
+00891                                                 for(uint m = k + 1; m < program.size(); ++m)
+00892                                                 {
+00893                                                         if (program[m].Dest.Type == CVPOperand::OutputRegister) // another output to this texture ?
+00894                                                         {
+00895                                                                 if (program[m].Dest.Value.OutputRegisterValue == program[k].Dest.Value.OutputRegisterValue)
+00896                                                                 {
+00897                                                                         found = true;
+00898                                                                         break;
+00899                                                                 }
+00900                                                         }
+00901                                                 }
+00902 
+00903                                                 if (found)
+00904                                                 {
+00905                                                         if (!outputWritten)
+00906                                                         {                                                       
+00907                                                                 // write values
+00908                                                                 doWriteMask(maskedDestValue, destValue,
+00909                                                                                                 writeMask & 1 ? GL_TRUE : GL_FALSE,
+00910                                                                                                 writeMask & 2 ? GL_TRUE : GL_FALSE,
+00911                                                                                                 writeMask & 4 ? GL_TRUE : GL_FALSE,
+00912                                                                                                 writeMask & 8 ? GL_TRUE : GL_FALSE);
+00913                                                                 ++numWM;
+00914                                                         }
+00915                                                 }
+00916                                                 else // this is the last write, check if the mask is complete
+00917                                                 {
+00918                                                         if ((outputMask | writeMask) == 0xf)
+00919                                                         {
+00920                                                                 if (!outputWritten)
+00921                                                                 {
+00922                                                                         // ok, after this call everything has been written
+00923                                                                         // write values
+00924                                                                             doWriteMask(maskedDestValue, destValue,
+00925                                                                                                         writeMask & 1 ? GL_TRUE : GL_FALSE,
+00926                                                                                                         writeMask & 2 ? GL_TRUE : GL_FALSE,
+00927                                                                                                         writeMask & 4 ? GL_TRUE : GL_FALSE,
+00928                                                                                                         writeMask & 8 ? GL_TRUE : GL_FALSE);
+00929                                                                         ++numWM;
+00930                                                                 }
+00931                                                         }
+00932                                                         else
+00933                                                         {
+00934                                                                 uint prevMask = outputMask;
+00935                                                                 uint newMask  = writeMask | outputMask;
+00936                                                                 
+00937                                                                 // complete unused entries
+00938 
+00939                                                                 // if primary color is output, then the default color is white
+00940                                                                 if (maskedDestValue == GL_OUTPUT_COLOR0_EXT)
+00941                                                                 {
+00942                                                                         doSwizzle(firstTempRegister, destValue,
+00943                                                                                                   newMask & 1 ? GL_X_EXT : GL_ONE_EXT,
+00944                                                                                                   newMask & 2 ? GL_Y_EXT : GL_ONE_EXT,
+00945                                                                                                   newMask & 4 ? GL_Z_EXT : GL_ONE_EXT,
+00946                                                                                                   newMask & 8 ? GL_W_EXT : GL_ONE_EXT);
+00947                                                                 }
+00948                                                                 else
+00949                                                                 {                                                               
+00950                                                                         doSwizzle(firstTempRegister, destValue,
+00951                                                                                                   newMask & 1 ? GL_X_EXT : GL_ZERO_EXT,
+00952                                                                                                   newMask & 2 ? GL_Y_EXT : GL_ZERO_EXT,
+00953                                                                                                   newMask & 4 ? GL_Z_EXT : GL_ZERO_EXT,
+00954                                                                                                   newMask & 8 ? GL_W_EXT : GL_ONE_EXT);
+00955                                                                 }
+00956                                                                 if (!outputWritten)
+00957                                                                 {                                                       
+00958                                                                         ++numWM;
+00959                                                                             doWriteMask(maskedDestValue, firstTempRegister,
+00960                                                                                                         prevMask & 1 ? GL_FALSE : GL_TRUE,
+00961                                                                                                         prevMask & 2 ? GL_FALSE : GL_TRUE,
+00962                                                                                                         prevMask & 4 ? GL_FALSE : GL_TRUE,
+00963                                                                                                         prevMask & 8 ? GL_FALSE : GL_TRUE
+00964                                                                                                   );                                                                    
+00965                                                                         ++numWM;
+00966                                                                 }
+00967                                                                 outputMask = 0xf;
+00968                                                         }
+00969                                                 }                                                                               
+00970                                         }
+00971                                         else
+00972                                         {
+00973                                                 if (!outputWritten)
+00974                                                 {
+00975                                                             doWriteMask(maskedDestValue, destValue,
+00976                                                                                         writeMask & 1 ? GL_TRUE : GL_FALSE,
+00977                                                                                         writeMask & 2 ? GL_TRUE : GL_FALSE,
+00978                                                                                         writeMask & 4 ? GL_TRUE : GL_FALSE,
+00979                                                                                         writeMask & 8 ? GL_TRUE : GL_FALSE);
+00980                                                         ++numWM;
+00981                                                 }
+00982                                         }
+00983                                         // complete the mask 
+00984                                         outputMask |= writeMask;
+00985                                 }
+00986                                 else if (destOperand.Type != CVPOperand::OutputRegister)
+00987                                 {
+00988                                         if (!outputWritten)
+00989                                         {
+00990                                                     doWriteMask(maskedDestValue, destValue,
+00991                                                                                 writeMask & 1 ? GL_TRUE : GL_FALSE,
+00992                                                                                 writeMask & 2 ? GL_TRUE : GL_FALSE,
+00993                                                                                 writeMask & 4 ? GL_TRUE : GL_FALSE,
+00994                                                                                 writeMask & 8 ? GL_TRUE : GL_FALSE);
+00995                                                 ++numWM;
+00996                                         }
+00997                                 }                               
+00998                         }
+00999 
+01000                         glError = glGetError();
+01001                         nlassert(glError == GL_NO_ERROR)
+01002                 }
+01003 
+01004                 
+01005 
+01006                 // if color have not been written, write with default values
+01007                 if (componentWritten[CVPOperand::OPrimaryColor] == 0)
+01008                 {
+01009                         // we specify vertex coord has input for swizzle, but we don't read any component.. 
+01010                         doSwizzle(GL_OUTPUT_COLOR0_EXT, _EVSPositionHandle, GL_ONE_EXT, GL_ONE_EXT, GL_ONE_EXT, GL_ONE_EXT);
+01011                         EVS_INFO("Swizzle (Complete primary color)");
+01012                         ++numSwizzle;
+01013                 }
+01014                 else
+01015                 {
+01016                         nlassert(componentWritten[CVPOperand::OPrimaryColor] == 0xf)
+01017                 }
+01018                 if (componentWritten[CVPOperand::OSecondaryColor] == 0)
+01019                 {
+01020                         // we specify vertex coord has input for swizzle, but we don't read any component..
+01021                         doSwizzle(GL_OUTPUT_COLOR1_EXT, _EVSPositionHandle, GL_ZERO_EXT, GL_ZERO_EXT, GL_ZERO_EXT, GL_ONE_EXT);
+01022                         EVS_INFO("Swizzle (Complete secondary color)");
+01023                         ++numSwizzle;
+01024                 }
+01025                 else
+01026                 {
+01027                         nlassert(componentWritten[CVPOperand::OSecondaryColor] == 0xf)
+01028                 }
+01029                 nlassert(componentWritten[CVPOperand::OHPosition] == 0xf); // should have written all component of position     
+01030 
+01031                 glError = glGetError();
+01032                 nlassert(glError == GL_NO_ERROR);
+01033 
+01034                 // if fog has been written, perform conversion
+01035                 if (componentWritten[CVPOperand::OFogCoord] == 0xf)
+01036                 {
+01037                         // Well this could be avoided, but we should make 2 cases for each vertex program.. :(
+01038                         doSwizzle(firstTempRegister, _EVSConstantHandle + 96, GL_X_EXT, GL_X_EXT, GL_X_EXT, GL_X_EXT);
+01039                         doSwizzle(firstTempRegister + 1, _EVSConstantHandle + 96, GL_Y_EXT, GL_Y_EXT, GL_Y_EXT, GL_Y_EXT);                      
+01040                         nglShaderOp3EXT(GL_OP_MADD_EXT, firstTempRegister + 2, fogTemp, firstTempRegister, firstTempRegister + 1);
+01041                         EVS_INFO("Use MAD for fog conversion");
+01042                         nglExtractComponentEXT(GL_OUTPUT_FOG_EXT, firstTempRegister + 2, 0);
+01043                         EVS_INFO("Extract component to fog");
+01044                 }
+01045 
+01046                 glError = glGetError();
+01047                 nlassert(glError == GL_NO_ERROR);
+01048         }
+01049         nglEndVertexShaderEXT();
+01050 
+01051         glError = glGetError();
+01052         nlassert(glError == GL_NO_ERROR);
+01053 
+01054         GLboolean optimizedShader;
+01055         glGetBooleanv(GL_VERTEX_SHADER_OPTIMIZED_EXT, &optimizedShader);
+01056         if (!optimizedShader)
+01057         {
+01058                 nlwarning("Failed to optimize a vertex program with the EXT_vertex_shader extension, this shader will be disabled");
+01059                 return false;
+01060         }       
+01061 
+01062         // see which input registers are used
+01063         usedInputRegisters = 0;
+01064         
+01065         uint k, l;
+01066         // convert each instruction of the vertex program
+01067         for(k = 0; k < program.size(); ++k)
+01068         {
+01069                 uint numSrc = program[k].getNumUsedSrc();
+01070                 for(l = 0; l < numSrc; ++l)
+01071                 {
+01072                         const CVPOperand &op = program[k].getSrc(l);
+01073                         if (op.Type == CVPOperand::InputRegister)
+01074                         {
+01075                                 usedInputRegisters |= convInputRegisterToVBFlag(op.Value.InputRegisterValue);
+01076                         }
+01077                 }               
+01078         }
+01079 
+01080 #ifdef DEBUG_SETUP_EXT_VERTEX_SHADER
+01081         nlinfo("========================");
+01082         nlinfo("num Opcode  = %d", numOp);
+01083         nlinfo("num Indexing = %d", numOpIndex);
+01084         nlinfo("num Swizzle = %d", numSwizzle);
+01085         nlinfo("num extract component = %d", numEC);
+01086         nlinfo("num insert component = %d", numIC);     
+01087         nlinfo("num write mask = %d", numWM);
+01088 #endif
+01089 
+01090         return true;
+01091                         
+01092 }
+01093 
+01094 // ***************************************************************************
+01095 bool CDriverGL::activeEXTVertexShader (CVertexProgram *program)
+01096 {
+01097         // Setup or unsetup ?
+01098         if (program)
+01099         {               
+01100                 // Driver info
+01101                 CVertexProgamDrvInfosGL *drvInfo;
+01102 
+01103                 // Program setuped ?
+01104                 if (program->_DrvInfo==NULL)
+01105                 {
+01106                         // try to parse the program
+01107                         CVPParser parser;
+01108                         CVPParser::TProgram parsedProgram;
+01109                         std::string errorOutput;
+01110                         bool result = parser.parse(program->getProgram().c_str(), parsedProgram, errorOutput);
+01111                         if (!result)
+01112                         {
+01113                                 nlwarning("Unable to parse a vertex program.");
+01114                                 #ifdef NL_DEBUG
+01115                                         nlerror(errorOutput.c_str());
+01116                                 #endif
+01117                                 return false;
+01118                         }
+01119 
+01120                         /* 
+01121                         FILE *f = fopen("c:\\test.txt", "wb");
+01122                         if (f)
+01123                         {
+01124                                 std::string vpText;
+01125                                 CVPParser::dump(parsedProgram, vpText);
+01126                                 fwrite(vpText.c_str(), vpText.size(), 1, f);
+01127                                 fclose(f);
+01128                         }
+01129                         */
+01130 
+01131                         // Insert into driver list. (so it is deleted when driver is deleted).
+01132                         ItVtxPrgDrvInfoPtrList  it= _VtxPrgDrvInfos.insert(_VtxPrgDrvInfos.end());
+01133 
+01134                         // Create a driver info
+01135                         *it = drvInfo = new CVertexProgamDrvInfosGL (this, it);
+01136                         // Set the pointer
+01137                         program->_DrvInfo=drvInfo;
+01138 
+01139                         if (!setupEXTVertexShader(parsedProgram, drvInfo->ID, drvInfo->Variants, drvInfo->UsedVertexComponents))
+01140                         {
+01141                                 delete drvInfo;
+01142                                 program->_DrvInfo = NULL;
+01143                                 _VtxPrgDrvInfos.erase(it);
+01144                                 return false;
+01145                         }
+01146                 }
+01147                 else
+01148                 {
+01149                         // Cast the driver info pointer
+01150                         drvInfo=safe_cast<CVertexProgamDrvInfosGL*>((IVertexProgramDrvInfos*)program->_DrvInfo);
+01151                 }
+01152 
+01153                 glEnable( GL_VERTEX_SHADER_EXT);
+01154                 _VertexProgramEnabled = true;
+01155                 nglBindVertexShaderEXT( drvInfo->ID );
+01156                 _LastSetuppedVP = program;
+01157         }
+01158         else
+01159         {
+01160                 glDisable( GL_VERTEX_SHADER_EXT );
+01161                 _VertexProgramEnabled = false;
+01162         }
+01163         return true;    
+01164 }
+01165 
+01166 // ***************************************************************************
+01167 bool CDriverGL::activeVertexProgram (CVertexProgram *program)
+01168 {
+01169         // Extension here ?
+01170         if (_Extensions.NVVertexProgram)
+01171         {
+01172                 return activeNVVertexProgram(program);
+01173         }
+01174         else if (_Extensions.EXTVertexShader)
+01175         {
+01176                 return activeEXTVertexShader(program);          
+01177         }
+01178 
+01179         // Can't do anything
+01180         return false;
+01181 }
+01182 
+01183 
+01184 // ***************************************************************************
+01185 
+01186 void CDriverGL::setConstant (uint index, float f0, float f1, float f2, float f3)
+01187 {
+01188         // Vertex program exist ?
+01189         if (_Extensions.NVVertexProgram)
+01190         {
+01191                 // Setup constant
+01192                 nglProgramParameter4fNV (GL_VERTEX_PROGRAM_NV, index, f0, f1, f2, f3);
+01193         }
+01194         else if (_Extensions.EXTVertexShader)
+01195         {
+01196                 float datas[] = { f0, f1, f2, f3 };
+01197                 nglSetInvariantEXT(_EVSConstantHandle + index, GL_FLOAT, datas);
+01198         }                
+01199 }
+01200 
+01201 
+01202 // ***************************************************************************
+01203 
+01204 void CDriverGL::setConstant (uint index, double d0, double d1, double d2, double d3)
+01205 {
+01206         // Vertex program exist ?
+01207         if (_Extensions.NVVertexProgram)
+01208         {
+01209                 // Setup constant
+01210                 nglProgramParameter4dNV (GL_VERTEX_PROGRAM_NV, index, d0, d1, d2, d3);
+01211         }
+01212         else if (_Extensions.EXTVertexShader)
+01213         {
+01214                 double datas[] = { d0, d1, d2, d3 };
+01215                 nglSetInvariantEXT(_EVSConstantHandle + index, GL_DOUBLE, datas);
+01216         }
+01217 }
+01218 
+01219 
+01220 // ***************************************************************************
+01221 
+01222 void CDriverGL::setConstant (uint index, const NLMISC::CVector& value)
+01223 {
+01224         // Vertex program exist ?
+01225         if (_Extensions.NVVertexProgram)
+01226         {
+01227                 // Setup constant
+01228                 nglProgramParameter4fNV (GL_VERTEX_PROGRAM_NV, index, value.x, value.y, value.z, 0);    
+01229         }
+01230         else if (_Extensions.EXTVertexShader)
+01231         {
+01232                 float datas[] = { value.x, value.y, value.z, 0 };
+01233                 nglSetInvariantEXT(_EVSConstantHandle + index, GL_FLOAT, datas);
+01234         }
+01235 }
+01236 
+01237 
+01238 // ***************************************************************************
+01239 
+01240 void CDriverGL::setConstant (uint index, const NLMISC::CVectorD& value)
+01241 {
+01242         // Vertex program exist ?
+01243         if (_Extensions.NVVertexProgram)
+01244         {
+01245                 // Setup constant
+01246                 nglProgramParameter4dNV (GL_VERTEX_PROGRAM_NV, index, value.x, value.y, value.z, 0);
+01247         }
+01248         else if (_Extensions.EXTVertexShader)
+01249         {
+01250                 double datas[] = { value.x, value.y, value.z, 0 };
+01251                 nglSetInvariantEXT(_EVSConstantHandle + index, GL_DOUBLE, datas);
+01252         }
+01253 }
+01254 
+01255 
+01256 // ***************************************************************************
+01257 void    CDriverGL::setConstant (uint index, uint num, const float *src)
+01258 {
+01259         // Vertex program exist ?
+01260         if (_Extensions.NVVertexProgram)
+01261         {
+01262                 nglProgramParameters4fvNV(GL_VERTEX_PROGRAM_NV, index, num, src);
+01263         }       
+01264         else if (_Extensions.EXTVertexShader)
+01265         {
+01266                 for(uint k = 0; k < num; ++k)
+01267                 {                                       
+01268                         nglSetInvariantEXT(_EVSConstantHandle + index + k, GL_FLOAT, (void *) (src + 4 * k));
+01269                 }
+01270         }       
+01271 }
+01272 
+01273 // ***************************************************************************
+01274 void    CDriverGL::setConstant (uint index, uint num, const double *src)
+01275 {
+01276         // Vertex program exist ?
+01277         if (_Extensions.NVVertexProgram)
+01278         {
+01279                 nglProgramParameters4dvNV(GL_VERTEX_PROGRAM_NV, index, num, src);
+01280         }
+01281         else if (_Extensions.EXTVertexShader)
+01282         {
+01283                 for(uint k = 0; k < num; ++k)
+01284                 {                                       
+01285                         nglSetInvariantEXT(_EVSConstantHandle + index + k, GL_DOUBLE, (void *) (src + 4 * k));
+01286                 }
+01287         }
+01288 }
+01289 
+01290 // ***************************************************************************
+01291 
+01292 const uint CDriverGL::GLMatrix[IDriver::NumMatrix]=
+01293 {
+01294         GL_MODELVIEW,
+01295         GL_PROJECTION,
+01296         GL_MODELVIEW_PROJECTION_NV
+01297 };
+01298 
+01299 
+01300 // ***************************************************************************
+01301 
+01302 const uint CDriverGL::GLTransform[IDriver::NumTransform]=
+01303 {
+01304         GL_IDENTITY_NV,
+01305         GL_INVERSE_NV,
+01306         GL_TRANSPOSE_NV,
+01307         GL_INVERSE_TRANSPOSE_NV
+01308 };
+01309 
+01310 
+01311 // ***************************************************************************
+01312 
+01313 void CDriverGL::setConstantMatrix (uint index, IDriver::TMatrix matrix, IDriver::TTransform transform)
+01314 {
+01315         // Vertex program exist ?
+01316         if (_Extensions.NVVertexProgram)
+01317         {
+01318                 // First, ensure that the render setup is correclty setuped.
+01319                 refreshRenderSetup();
+01320 
+01321                 // Track the matrix
+01322                 nglTrackMatrixNV (GL_VERTEX_PROGRAM_NV, index, GLMatrix[matrix], GLTransform[transform]);
+01323                 // Release Track => matrix data is copied.
+01324                 nglTrackMatrixNV (GL_VERTEX_PROGRAM_NV, index, GL_NONE, GL_IDENTITY_NV);
+01325         }
+01326         else if (_Extensions.EXTVertexShader)
+01327         {
+01328                 // First, ensure that the render setup is correctly setuped.
+01329                 refreshRenderSetup();           
+01330                 CMatrix mat;            
+01331                 switch (matrix)
+01332                 {
+01333                         case IDriver::ModelView:
+01334                                 mat = _ModelViewMatrix;
+01335                         break;
+01336                         case IDriver::Projection:
+01337                         {
+01338                                 refreshProjMatrixFromGL();
+01339                                 mat = _GLProjMat;
+01340                         }
+01341                         break;
+01342                         case IDriver::ModelViewProjection:
+01343                                 refreshProjMatrixFromGL();                              
+01344                                 mat = _GLProjMat * _ModelViewMatrix;
+01345                         break;
+01346                 }
+01347 
+01348                 switch(transform)
+01349                 {
+01350                         case IDriver::Identity: break;
+01351                         case IDriver::Inverse:
+01352                                 mat.invert();
+01353                         break;          
+01354                         case IDriver::Transpose:
+01355                                 mat.transpose();                                                                
+01356                         break;
+01357                         case IDriver::InverseTranspose:
+01358                                 mat.invert();
+01359                                 mat.transpose();                                
+01360                         break;
+01361                 }
+01362                 mat.transpose();
+01363                 float matDatas[16];
+01364                 mat.get(matDatas);
+01365                 nglSetInvariantEXT(_EVSConstantHandle + index, GL_FLOAT, matDatas);
+01366                 nglSetInvariantEXT(_EVSConstantHandle + index + 1, GL_FLOAT, matDatas + 4);
+01367                 nglSetInvariantEXT(_EVSConstantHandle + index + 2, GL_FLOAT, matDatas + 8);
+01368                 nglSetInvariantEXT(_EVSConstantHandle + index + 3, GL_FLOAT, matDatas + 12);
+01369         }                
+01370 }
+01371 
+01372 // ***************************************************************************
+01373 
+01374 void CDriverGL::enableVertexProgramDoubleSidedColor(bool doubleSided)
+01375 {
+01376         // Vertex program exist ?
+01377         if (_Extensions.NVVertexProgram)
+01378         {
+01379                 // change mode (not cached because supposed to be rare)
+01380                 if(doubleSided)
+01381                         glEnable (GL_VERTEX_PROGRAM_TWO_SIDE_NV);
+01382                 else
+01383                         glDisable (GL_VERTEX_PROGRAM_TWO_SIDE_NV);
+01384         }       
+01385 }
+01386 
+01387 
+01388 // ***************************************************************************
+01389 bool CDriverGL::supportVertexProgramDoubleSidedColor() const
+01390 {
+01391         // currenlty only supported by NV_VERTEX_PROGRAM
+01392         return _Extensions.NVVertexProgram;
+01393 }
+01394 
+01395 
+01396 } // NL3D
+
+ + +
                                                                                                                                                                    +
+ + -- cgit v1.2.1