00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
00030
00031
00032
00033
00034
00035
00036
00037
00038
00039
00040
00041
00042
00043 #include <stdlib.h>
00044 #include <stdio.h>
00045
00046 #include <OSGConfig.h>
00047
00048 #include <OSGGL.h>
00049 #include <OSGGLU.h>
00050 #include <OSGGLEXT.h>
00051
00052 #include <OSGBaseFunctions.h>
00053
00054 #include "OSGDrawActionBase.h"
00055 #include "OSGWindow.h"
00056
00057 #include "OSGProgramChunk.h"
00058
00059 OSG_USING_NAMESPACE
00060
00061
00062
00063
00064
00075
00076
00077
00078
00079 StateChunkClass ProgramChunk::_class("Program");
00080
00081 UInt32 ProgramChunk::_funcGenPrograms;
00082 UInt32 ProgramChunk::_funcProgramString;
00083 UInt32 ProgramChunk::_funcBindProgram;
00084 UInt32 ProgramChunk::_funcDeletePrograms;
00085 UInt32 ProgramChunk::_funcProgramLocalParameter4fv;
00086 UInt32 ProgramChunk::_funcGetProgramiv;
00087
00088
00089
00090
00091
00092 void ProgramChunk::initMethod (void)
00093 {
00094 }
00095
00096
00097
00098
00099
00100
00101
00102
00103
00104
00105
00106
00107 ProgramChunk::ProgramChunk(void) :
00108 Inherited()
00109 {
00110 UInt32 extension = Window::registerExtension("GL_ARB_vertex_program");
00111
00112 _funcGenPrograms =
00113 Window::registerFunction (OSG_DLSYM_UNDERSCORE"glGenProgramsARB",
00114 extension);
00115 _funcProgramString =
00116 Window::registerFunction (OSG_DLSYM_UNDERSCORE"glProgramStringARB",
00117 extension);
00118 _funcBindProgram =
00119 Window::registerFunction (OSG_DLSYM_UNDERSCORE"glBindProgramARB",
00120 extension);
00121 _funcDeletePrograms =
00122 Window::registerFunction (OSG_DLSYM_UNDERSCORE"glDeleteProgramsARB",
00123 extension);
00124 _funcProgramLocalParameter4fv =
00125 Window::registerFunction (OSG_DLSYM_UNDERSCORE
00126 "glProgramLocalParameter4fvARB",
00127 extension);
00128 _funcGetProgramiv =
00129 Window::registerFunction (OSG_DLSYM_UNDERSCORE"glGetProgramivARB",
00130 extension);
00131 }
00132
00133 ProgramChunk::ProgramChunk(const ProgramChunk &source) :
00134 Inherited(source)
00135 {
00136 }
00137
00138 ProgramChunk::~ProgramChunk(void)
00139 {
00140 if(getGLId() > 0)
00141 Window::destroyGLObject(getGLId(), 1);
00142 }
00143
00144
00145
00146 void ProgramChunk::onCreate(const ProgramChunk *)
00147 {
00148 }
00149
00150
00151
00152
00153 const StateChunkClass *ProgramChunk::getClass( void ) const
00154 {
00155 return &_class;
00156 }
00157
00158
00159
00160 void ProgramChunk::changed(BitVector whichField, UInt32 origin)
00161 {
00162 Inherited::changed(whichField, origin);
00163
00164 if(whichField & ProgramFieldMask)
00165 {
00166 Window::reinitializeGLObject(getGLId());
00167 }
00168
00169 if(whichField & ParamValuesFieldMask)
00170 {
00171 Window::refreshGLObject(getGLId());
00172 }
00173 }
00174
00175
00176
00177 void ProgramChunk::dump( UInt32 ,
00178 const BitVector ) const
00179 {
00180 SLOG << "Dump ProgramChunk NI" << std::endl;
00181 }
00182
00183
00184
00187 bool ProgramChunk::read(const char *file)
00188 {
00189 std::ifstream s(file);
00190
00191 if(s.good())
00192 {
00193 return read(s);
00194 }
00195 else
00196 {
00197 FWARNING(("ProgramChunk::read: couldn't open '%s' for reading!\n",
00198 file));
00199 return false;
00200 }
00201 }
00202
00205 bool ProgramChunk::read(std::istream &stream)
00206 {
00207 #define BUFSIZE 200
00208
00209 getProgram().erase();
00210 char buf[BUFSIZE];
00211
00212 if(!stream.good())
00213 {
00214 FWARNING(("ProgramChunk::read: stream is not good!\n"));
00215 return false;
00216
00217 }
00218
00219 do
00220 {
00221 stream.read(buf, BUFSIZE);
00222 getProgram().append(buf, stream.gcount());
00223 }
00224 while(!stream.eof());
00225
00226 return true;
00227 }
00228
00231 bool ProgramChunk::addParameter(const char *name,
00232 Int16 index)
00233 {
00234 if(index < 0)
00235 return true;
00236
00237 if(getParamNames().size() <= UInt16(index))
00238 {
00239 getParamNames().resize(index + 1);
00240 }
00241 getParamNames()[index] = name;
00242 return false;
00243 }
00244
00245 const Vec4f& ProgramChunk::getParameter(Int16 index)
00246 {
00247 static const Vec4f bad(-1e10,-1e10,-1e10);
00248
00249 if(index < 0)
00250 return bad;
00251
00252 if(getParamValues().size() <= UInt16(index))
00253 {
00254 return getParamValues()[index];
00255 }
00256
00257 return bad;
00258 }
00259
00262 bool ProgramChunk::setParameter(Int16 index, const Vec4f& value)
00263 {
00264 if(index < 0)
00265 return true;
00266
00267 if(getParamValues().size() <= UInt16(index))
00268 {
00269 getParamValues().resize(index + 1);
00270 }
00271 getParamValues()[index] = value;
00272 return false;
00273 }
00274
00277 Int16 ProgramChunk::findParameter(const std::string &name)
00278 {
00279 MField<std::string>::iterator it;
00280
00281 it = std::find(getParamNames().begin(), getParamNames().end(), name);
00282
00283 if(it == getParamNames().end())
00284 return -1;
00285
00286 return it - getParamNames().begin();
00287 }
00288
00289
00290
00291
00294 void ProgramChunk::printCompileError(Window *win, UInt32 idstatus)
00295 {
00296 Window::GLObjectStatusE mode;
00297 UInt32 id;
00298
00299 Window::unpackIdStatus(idstatus, id, mode);
00300
00301 GLint pos;
00302 glGetIntegerv(GL_PROGRAM_ERROR_POSITION_ARB, &pos);
00303
00304 FWARNING(("ProgramChunk(%p:%d,%d): error compiling program "
00305 "at position %d: %s\n",
00306 win, id, mode, pos, glGetString(GL_PROGRAM_ERROR_STRING_ARB)));
00307
00308 UInt32 start = 0, end, line = 0;
00309
00310 for(end = 0; end < getProgram().size(); ++end)
00311 {
00312 if(getProgram()[end] == '\n')
00313 {
00314 ++line;
00315
00316 if(UInt32(pos) < end)
00317 break;
00318
00319 start = end + 1;
00320 }
00321 }
00322
00323 std::string mesg;
00324
00325 for(UInt32 i = start; i < end; ++i)
00326 {
00327 if(i == pos)
00328 {
00329 mesg += '>';
00330 mesg += '>';
00331 }
00332
00333 mesg += getProgram()[i];
00334
00335 if(i == pos)
00336 {
00337 mesg += '<';
00338 mesg += '<';
00339 }
00340 }
00341
00342 SWARNING << "Location (line " << line << "): " << mesg << endLog;
00343 }
00344
00348 void ProgramChunk::handleGL(Window *win, UInt32 idstatus, GLenum target, UInt32 extension)
00349 {
00350 Window::GLObjectStatusE mode;
00351 UInt32 osgid;
00352 GLuint id;
00353
00354 Window::unpackIdStatus(idstatus, osgid, mode);
00355
00356
00357
00358
00359
00360
00361
00362 if(!win->hasExtension(extension))
00363 return;
00364
00365 id = win->getGLObjectId(osgid);
00366
00367 if(mode == Window::destroy)
00368 {
00369
00370 void (OSG_APIENTRY* deletePrograms)(GLsizei num, const GLuint *progs) =
00371 (void (OSG_APIENTRY*)(GLsizei num, const GLuint *progs))
00372 win->getFunction(_funcDeletePrograms);
00373
00374 deletePrograms(1, &id);
00375 win->setGLObjectId(osgid, 0);
00376 }
00377 else if(mode == Window::finaldestroy)
00378 {
00379
00380 }
00381 else if(mode == Window::initialize || mode == Window::reinitialize ||
00382 mode == Window::needrefresh)
00383 {
00384 if(mode == Window::initialize)
00385 {
00386
00387 void (OSG_APIENTRY* genPrograms)(GLsizei n, GLuint *prog) =
00388 (void (OSG_APIENTRY*)(GLsizei n, GLuint *prog))
00389 win->getFunction(_funcGenPrograms);
00390 genPrograms(1, &id);
00391 win->setGLObjectId(osgid, id);
00392 }
00393
00394
00395 void (OSG_APIENTRY* bindProgram)(GLenum target, GLuint prog) =
00396 (void (OSG_APIENTRY*)(GLenum target, GLuint prog))
00397 win->getFunction(_funcBindProgram);
00398
00399 glErr("ProgramChunk::handleGL: bindProgram precheck");
00400
00401 bindProgram(target, id);
00402
00403 glErr("ProgramChunk::handleGL: bindProgram postcheck");
00404
00405 if(mode != Window::needrefresh)
00406 {
00407
00408 void (OSG_APIENTRY* programString)(GLenum target, GLenum format,
00409 GLsizei lesn, const void *string) =
00410 (void (OSG_APIENTRY*)(GLenum target, GLenum format,
00411 GLsizei len, const void *string))
00412 win->getFunction(_funcProgramString);
00413
00414 glErr("ProgramChunk::handleGL: programString precheck");
00415
00416 glEnable(target);
00417
00418 glErr("ProgramChunk::handleGL: enable postcheck");
00419
00420 programString(target, GL_PROGRAM_FORMAT_ASCII_ARB,
00421 getProgram().size(), getProgram().c_str());
00422
00423 GLenum err = glGetError();
00424
00425 if(err == GL_INVALID_OPERATION)
00426 {
00427 printCompileError(win, idstatus);
00428 }
00429 else if (err != GL_NO_ERROR)
00430 {
00431 SWARNING << "ProgramChunk::programString postcheck failed:"
00432 << gluErrorString(err) << endLog;
00433 }
00434
00435 glDisable(target);
00436
00437 glErr("ProgramChunk::handleGL: disable postcheck");
00438 }
00439
00440 void (OSG_APIENTRY* programLocalParameter4fv)(GLenum target,
00441 GLuint index, const GLfloat *params) =
00442 (void (OSG_APIENTRY*)(GLenum target,
00443 GLuint index, const GLfloat *params))
00444 win->getFunction(_funcProgramLocalParameter4fv);
00445
00446 glErr("ProgramChunk::handleGL: programLocalParameter precheck");
00447
00448 for(UInt16 i = 0; i < getParamValues().size(); ++i)
00449 {
00450 Vec4f &val=getParamValues()[i];
00451
00452 programLocalParameter4fv(target, i, val.getValues());
00453
00454 glErr("ProgramChunk::handleGL: programLocalParameter");
00455 }
00456
00457 glErr("ProgramChunk::handleGL: programLocalParameter postcheck");
00458 }
00459 else
00460 {
00461 SWARNING << "ProgramChunk(" << this << "::handleGL: Illegal mode: "
00462 << mode << " for id " << id << std::endl;
00463 }
00464
00465 }
00466
00467 void ProgramChunk::activate(DrawActionBase *action, UInt32)
00468 {
00469
00470 GLenum target = getTarget();
00471 UInt32 extension = getExtension();
00472
00473 if(!action->getWindow()->hasExtension(extension))
00474 {
00475 return;
00476 }
00477
00478 if(getProgram().empty())
00479 return;
00480
00481 action->getWindow()->validateGLObject(getGLId());
00482
00483
00484 void (OSG_APIENTRY* bindProgram)(GLenum target, GLuint prog) =
00485 (void (OSG_APIENTRY*)(GLenum target, GLuint prog))
00486 action->getWindow()->getFunction(_funcBindProgram);
00487
00488 glErr("ProgramChunk::activate: bindProgram precheck");
00489
00490 glEnable(target);
00491
00492 glErr("ProgramChunk::activate: enable postcheck");
00493
00494 bindProgram(target, action->getWindow()->getGLObjectId(getGLId()));
00495
00496 glErr("ProgramChunk::activate: bindProgram postcheck");
00497 }
00498
00499 void ProgramChunk::changeFrom(DrawActionBase *action,
00500 StateChunk * old_chunk,
00501 UInt32 )
00502 {
00503 ProgramChunk * old = dynamic_cast<ProgramChunk*>(old_chunk);
00504
00505 if(old == NULL)
00506 {
00507 FWARNING(( "ProgramChunk::changeFrom: caught non-ProgramChunk!\n"));
00508 return;
00509 }
00510
00511
00512 GLenum target = getTarget();
00513 UInt32 extension = getExtension();
00514
00515 if(!action->getWindow()->hasExtension(extension))
00516 return;
00517
00518 if(getProgram().empty())
00519 {
00520 if(old->getProgram().empty())
00521 return;
00522
00523 glDisable(target);
00524 }
00525
00526 action->getWindow()->validateGLObject(getGLId());
00527
00528
00529 void (OSG_APIENTRY* bindProgram)(GLenum target, GLuint prog) =
00530 (void (OSG_APIENTRY*)(GLenum target, GLuint prog))
00531 action->getWindow()->getFunction(_funcBindProgram);
00532
00533 glErr("ProgramChunk::changeFrom: bindProgram precheck");
00534
00535 if(old->getProgram().empty())
00536 glEnable(target);
00537
00538 glErr("ProgramChunk::changeFrom: enable postcheck");
00539
00540 bindProgram(target, action->getWindow()->getGLObjectId(getGLId()));
00541
00542 glErr("ProgramChunk::changeFrom: bindProgram postcheck");
00543 }
00544
00545 void ProgramChunk::deactivate(DrawActionBase *action, UInt32)
00546 {
00547
00548 GLenum target = getTarget();
00549 UInt32 extension = getExtension();
00550
00551 if(!action->getWindow()->hasExtension(extension))
00552 {
00553 return;
00554 }
00555
00556 if(getProgram().empty())
00557 {
00558 return;
00559 }
00560
00561
00562 void (OSG_APIENTRY* bindProgram)(GLenum target, GLuint prog) =
00563 (void (OSG_APIENTRY*)(GLenum target, GLuint prog))
00564 action->getWindow()->getFunction(_funcBindProgram);
00565
00566
00567 glErr("ProgramChunk::deactivate: bindProgram precheck");
00568
00569 bindProgram(target, action->getWindow()->getGLObjectId(getGLId()));
00570
00571 glErr("ProgramChunk::deactivate: bindProgram postcheck");
00572
00573 glDisable(target);
00574
00575 glErr("ProgramChunk::deactivate: disable postcheck");
00576 }
00577
00582 UInt32 ProgramChunk::getExtension(void) const
00583 {
00584 FWARNING(( "ProgramChunk::getExtension called!\n" ));
00585 return 0;
00586 }
00587
00591 GLenum ProgramChunk::getTarget(void) const
00592 {
00593 FWARNING(( "ProgramChunk::getTarget called!\n" ));
00594 return 0;
00595 }
00596
00600 const char *ProgramChunk::getTargetName(void) const
00601 {
00602 FWARNING(( "ProgramChunk::getTargetName called!\n" ));
00603 return "ERROR";
00604 }
00605
00606
00607
00608 bool ProgramChunk::isTransparent(void) const
00609 {
00610 return false;
00611 }
00612
00613 Real32 ProgramChunk::switchCost(StateChunk *)
00614 {
00615 return 0;
00616 }
00617
00618 bool ProgramChunk::operator < (const StateChunk &other) const
00619 {
00620 return this < &other;
00621 }
00622
00623 bool ProgramChunk::operator == (const StateChunk &other) const
00624 {
00625 ProgramChunk const *tother = dynamic_cast<ProgramChunk const*>(&other);
00626
00627 if(!tother)
00628 return false;
00629
00630 if(tother == this)
00631 return true;
00632
00633 if(getProgram() != tother->getProgram() ||
00634 getParamValues().size() != tother->getParamValues().size() ||
00635 getParamNames().size() != tother->getParamNames().size()
00636 )
00637 return false;
00638
00639
00640
00641 return false;
00642 }
00643
00644 bool ProgramChunk::operator != (const StateChunk &other) const
00645 {
00646 return ! (*this == other);
00647 }
00648
00649
00650
00651
00652
00653 #ifdef OSG_SGI_CC
00654 #pragma set woff 1174
00655 #endif
00656
00657 #ifdef OSG_LINUX_ICC
00658 #pragma warning( disable : 177 )
00659 #endif
00660
00661 namespace
00662 {
00663 static Char8 cvsid_cpp [] = "@(#)$Id: $";
00664 static Char8 cvsid_hpp [] = OSGPROGRAMCHUNKBASE_HEADER_CVSID;
00665 static Char8 cvsid_inl [] = OSGPROGRAMCHUNKBASE_INLINE_CVSID;
00666
00667 static Char8 cvsid_fields_hpp[] = OSGPROGRAMCHUNKFIELDS_HEADER_CVSID;
00668 }
00669
00670 #ifdef __sgi
00671 #pragma reset woff 1174
00672 #endif
00673