root/OpenSceneGraph/trunk/src/osg/FragmentProgram.cpp @ 13041

Revision 13041, 10.3 kB (checked in by robert, 2 years ago)

Ran script to remove trailing spaces and tabs

  • Property svn:eol-style set to native
  • Property svn:keywords set to Author Date Id Revision
Line 
1/* -*-c++-*- OpenSceneGraph - Copyright (C) 1998-2006 Robert Osfield
2 *
3 * This library is open source and may be redistributed and/or modified under
4 * the terms of the OpenSceneGraph Public License (OSGPL) version 0.0 or
5 * (at your option) any later version.  The full license is in LICENSE file
6 * included with this distribution, and on the openscenegraph.org website.
7 *
8 * This library is distributed in the hope that it will be useful,
9 * but WITHOUT ANY WARRANTY; without even the implied warranty of
10 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
11 * OpenSceneGraph Public License for more details.
12*/
13#include <osg/Notify>
14#include <osg/GLExtensions>
15#include <osg/FragmentProgram>
16#include <osg/State>
17#include <osg/Timer>
18
19#include <list>
20
21#include <OpenThreads/ScopedLock>
22#include <OpenThreads/Mutex>
23
24using namespace osg;
25
26// static cache of deleted fragment programs which can only
27// by completely deleted once the appropriate OpenGL context
28// is set.
29typedef std::list<GLuint> FragmentProgramObjectList;
30typedef osg::buffered_object<FragmentProgramObjectList> DeletedFragmentProgramObjectCache;
31
32static OpenThreads::Mutex                s_mutex_deletedFragmentProgramObjectCache;
33static DeletedFragmentProgramObjectCache s_deletedFragmentProgramObjectCache;
34
35void FragmentProgram::deleteFragmentProgramObject(unsigned int contextID,GLuint handle)
36{
37    if (handle!=0)
38    {
39        OpenThreads::ScopedLock<OpenThreads::Mutex> lock(s_mutex_deletedFragmentProgramObjectCache);
40
41        // insert the handle into the cache for the appropriate context.
42        s_deletedFragmentProgramObjectCache[contextID].push_back(handle);
43    }
44}
45
46
47void FragmentProgram::flushDeletedFragmentProgramObjects(unsigned int contextID,double /*currentTime*/, double& availableTime)
48{
49    // if no time available don't try to flush objects.
50    if (availableTime<=0.0) return;
51
52    const osg::Timer& timer = *osg::Timer::instance();
53    osg::Timer_t start_tick = timer.tick();
54    double elapsedTime = 0.0;
55
56    {
57        OpenThreads::ScopedLock<OpenThreads::Mutex> lock(s_mutex_deletedFragmentProgramObjectCache);
58
59        const Extensions* extensions = getExtensions(contextID,true);
60
61        FragmentProgramObjectList& vpol = s_deletedFragmentProgramObjectCache[contextID];
62
63        for(FragmentProgramObjectList::iterator titr=vpol.begin();
64            titr!=vpol.end() && elapsedTime<availableTime;
65            )
66        {
67            extensions->glDeletePrograms( 1L, &(*titr ) );
68            titr = vpol.erase(titr);
69            elapsedTime = timer.delta_s(start_tick,timer.tick());
70        }
71    }
72
73    availableTime -= elapsedTime;
74}
75
76void FragmentProgram::discardDeletedFragmentProgramObjects(unsigned int contextID)
77{
78    OpenThreads::ScopedLock<OpenThreads::Mutex> lock(s_mutex_deletedFragmentProgramObjectCache);
79    FragmentProgramObjectList& vpol = s_deletedFragmentProgramObjectCache[contextID];
80    vpol.clear();
81}
82
83
84FragmentProgram::FragmentProgram()
85{
86}
87
88
89FragmentProgram::FragmentProgram(const FragmentProgram& vp,const CopyOp& copyop):
90    osg::StateAttribute(vp,copyop)
91{
92    _fragmentProgram = vp._fragmentProgram;
93
94    for( LocalParamList::const_iterator itr = vp._programLocalParameters.begin();
95        itr != vp._programLocalParameters.end(); ++itr )
96    {
97        _programLocalParameters[itr->first] = itr->second;
98    }
99
100    for( MatrixList::const_iterator mitr = vp._matrixList.begin();
101        mitr != vp._matrixList.end(); ++mitr )
102    {
103        _matrixList[mitr->first] = mitr->second;
104    }
105}
106
107
108// virtual
109FragmentProgram::~FragmentProgram()
110{
111    dirtyFragmentProgramObject();
112}
113
114void FragmentProgram::dirtyFragmentProgramObject()
115{
116    for(unsigned int i=0;i<_fragmentProgramIDList.size();++i)
117    {
118        if (_fragmentProgramIDList[i] != 0)
119        {
120            FragmentProgram::deleteFragmentProgramObject(i,_fragmentProgramIDList[i]);
121            _fragmentProgramIDList[i] = 0;
122        }
123    }
124}
125
126void FragmentProgram::apply(State& state) const
127{
128#ifdef OSG_GL_FIXED_FUNCTION_AVAILABLE
129
130    const unsigned int contextID = state.getContextID();
131    const Extensions* extensions = getExtensions(contextID,true);
132
133    if (!extensions->isFragmentProgramSupported())
134        return;
135
136
137    GLuint& fragmentProgramId=getFragmentProgramID(state.getContextID());
138
139    // Fragment Program
140    if (fragmentProgramId != 0)
141    {
142        extensions->glBindProgram( GL_FRAGMENT_PROGRAM_ARB, fragmentProgramId );
143    }
144    else if (!_fragmentProgram.empty())
145    {
146        glGetError(); // Reset Error flags.
147        extensions->glGenPrograms( 1, &fragmentProgramId );
148        extensions->glBindProgram( GL_FRAGMENT_PROGRAM_ARB, fragmentProgramId );
149        extensions->glProgramString( GL_FRAGMENT_PROGRAM_ARB, GL_PROGRAM_FORMAT_ASCII_ARB,
150                                     _fragmentProgram.length(), _fragmentProgram.c_str());
151
152        // Check for errors
153        GLint errorposition = 0;
154        glGetIntegerv(GL_PROGRAM_ERROR_POSITION_ARB, &errorposition);
155        if (errorposition != -1)
156        {
157            OSG_FATAL << "FragmentProgram: " << glGetString(GL_PROGRAM_ERROR_STRING_ARB) << std::endl;
158
159            std::string::size_type start = _fragmentProgram.rfind('\n', errorposition);
160            std::string::size_type stop  = _fragmentProgram.find('\n', errorposition);
161            if (start!=std::string::npos && stop!=std::string::npos)
162            {
163                OSG_FATAL << "             : " << _fragmentProgram.substr(start+1, stop-start-2) << std::endl;
164                std::string pointAtproblem(errorposition-(start+1), ' ');
165                OSG_FATAL << "             : " << pointAtproblem << '^' << std::endl;
166            }
167            return;
168        }
169    }
170
171    // Update local program parameters
172    {
173        for(LocalParamList::const_iterator itr=_programLocalParameters.begin();
174            itr!=_programLocalParameters.end();
175            ++itr)
176        {
177            extensions->glProgramLocalParameter4fv(GL_FRAGMENT_PROGRAM_ARB, (*itr).first, (*itr).second.ptr());
178        }
179    }
180
181    // Update matrix
182    if (!_matrixList.empty())
183    {
184        for(MatrixList::const_iterator itr = _matrixList.begin();
185            itr!=_matrixList.end();
186            ++itr)
187        {
188            glMatrixMode((*itr).first);
189            glLoadMatrix((*itr).second.ptr());
190        }
191        glMatrixMode(GL_MODELVIEW); // restore matrix mode
192    }
193#else
194    OSG_NOTICE<<"Warning: FragmentProgram::apply(State&) - not supported."<<std::endl;
195#endif
196}
197
198void FragmentProgram::resizeGLObjectBuffers(unsigned int maxSize)
199{
200    _fragmentProgramIDList.resize(maxSize);
201}
202
203void FragmentProgram::releaseGLObjects(State* state) const
204{
205    if (!state) const_cast<FragmentProgram*>(this)->dirtyFragmentProgramObject();
206    else
207    {
208        unsigned int contextID = state->getContextID();
209        if (_fragmentProgramIDList[contextID] != 0)
210        {
211            FragmentProgram::deleteFragmentProgramObject(contextID,_fragmentProgramIDList[contextID]);
212            _fragmentProgramIDList[contextID] = 0;
213        }
214    }
215}
216
217
218typedef buffered_value< ref_ptr<FragmentProgram::Extensions> > BufferedExtensions;
219static BufferedExtensions s_extensions;
220
221FragmentProgram::Extensions* FragmentProgram::getExtensions(unsigned int contextID,bool createIfNotInitalized)
222{
223    if (!s_extensions[contextID] && createIfNotInitalized) s_extensions[contextID] = new Extensions(contextID);
224    return s_extensions[contextID].get();
225}
226
227void FragmentProgram::setExtensions(unsigned int contextID,Extensions* extensions)
228{
229    s_extensions[contextID] = extensions;
230}
231
232FragmentProgram::Extensions::Extensions(unsigned int contextID)
233{
234    setupGLExtensions(contextID);
235}
236
237FragmentProgram::Extensions::Extensions(const Extensions& rhs):
238    Referenced()
239{
240    _isFragmentProgramSupported = rhs._isFragmentProgramSupported;
241    _glBindProgram = rhs._glBindProgram;
242    _glGenPrograms = rhs._glGenPrograms;
243    _glDeletePrograms = rhs._glDeletePrograms;
244    _glProgramString = rhs._glProgramString;
245    _glProgramLocalParameter4fv = rhs._glProgramLocalParameter4fv;
246}
247
248
249void FragmentProgram::Extensions::lowestCommonDenominator(const Extensions& rhs)
250{
251    if (!rhs._isFragmentProgramSupported) _isFragmentProgramSupported = false;
252
253    if (!rhs._glBindProgram) _glBindProgram = 0;
254    if (!rhs._glGenPrograms) _glGenPrograms = 0;
255    if (!rhs._glDeletePrograms) _glDeletePrograms = 0;
256    if (!rhs._glProgramString) _glProgramString = 0;
257    if (!rhs._glProgramLocalParameter4fv) _glProgramLocalParameter4fv = 0;
258
259}
260
261void FragmentProgram::Extensions::setupGLExtensions(unsigned int contextID)
262{
263    _isFragmentProgramSupported = isGLExtensionSupported(contextID,"GL_ARB_fragment_program");
264
265    setGLExtensionFuncPtr(_glBindProgram, "glBindProgramARB");
266    setGLExtensionFuncPtr(_glGenPrograms, "glGenProgramsARB");
267    setGLExtensionFuncPtr(_glDeletePrograms, "glDeleteProgramsARB");
268    setGLExtensionFuncPtr(_glProgramString, "glProgramStringARB");
269    setGLExtensionFuncPtr(_glProgramLocalParameter4fv, "glProgramLocalParameter4fvARB");
270}
271
272void FragmentProgram::Extensions::glBindProgram(GLenum target, GLuint id) const
273{
274    if (_glBindProgram)
275    {
276        _glBindProgram(target,id);
277    }
278    else
279    {
280        OSG_WARN<<"Error: glBindProgram not supported by OpenGL driver"<<std::endl;
281    }
282}
283
284void FragmentProgram::Extensions::glGenPrograms(GLsizei n, GLuint *programs) const
285{
286    if (_glGenPrograms)
287    {
288        _glGenPrograms(n,programs);
289    }
290    else
291    {
292        OSG_WARN<<"Error: glGenPrograms not supported by OpenGL driver"<<std::endl;
293    }
294}
295
296void FragmentProgram::Extensions::glDeletePrograms(GLsizei n, GLuint *programs) const
297{
298    if (_glDeletePrograms)
299    {
300        _glDeletePrograms(n,programs);
301    }
302    else
303    {
304        OSG_WARN<<"Error: glDeletePrograms not supported by OpenGL driver"<<std::endl;
305    }
306}
307
308void FragmentProgram::Extensions::glProgramString(GLenum target, GLenum format, GLsizei len, const void *string) const
309{
310    if (_glProgramString)
311    {
312        _glProgramString(target,format, len, string);
313    }
314    else
315    {
316        OSG_WARN<<"Error: glProgramString not supported by OpenGL driver"<<std::endl;
317    }
318}
319
320void FragmentProgram::Extensions::glProgramLocalParameter4fv(GLenum target, GLuint index, const GLfloat *params) const
321{
322    if (_glProgramLocalParameter4fv)
323    {
324        _glProgramLocalParameter4fv(target, index, params);
325    }
326    else
327    {
328        OSG_WARN<<"Error: glProgramLocalParameter4fv not supported by OpenGL driver"<<std::endl;
329    }
330}
Note: See TracBrowser for help on using the browser.