Planet
navi homePPSaboutscreenshotsdownloaddevelopmentforum

source: downloads/RenderSystems/GL/src/OgreGLHardwareVertexBuffer.cpp @ 3

Last change on this file since 3 was 3, checked in by anonymous, 17 years ago

=update

File size: 7.9 KB
Line 
1/*
2-----------------------------------------------------------------------------
3This source file is part of OGRE
4    (Object-oriented Graphics Rendering Engine)
5For the latest info, see http://www.ogre3d.org/
6
7Copyright (c) 2000-2006 Torus Knot Software Ltd
8Also see acknowledgements in Readme.html
9
10This program is free software; you can redistribute it and/or modify it under
11the terms of the GNU Lesser General Public License as published by the Free Software
12Foundation; either version 2 of the License, or (at your option) any later
13version.
14
15This program is distributed in the hope that it will be useful, but WITHOUT
16ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
17FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details.
18
19You should have received a copy of the GNU Lesser General Public License along with
20this program; if not, write to the Free Software Foundation, Inc., 59 Temple
21Place - Suite 330, Boston, MA 02111-1307, USA, or go to
22http://www.gnu.org/copyleft/lesser.txt.
23
24You may alternatively use this source under the terms of a specific version of
25the OGRE Unrestricted License provided you have obtained such a license from
26Torus Knot Software Ltd.
27-----------------------------------------------------------------------------
28*/
29#include "OgreGLHardwareBufferManager.h"
30#include "OgreGLHardwareVertexBuffer.h"
31#include "OgreException.h"
32#include "OgreLogManager.h"
33
34namespace Ogre {
35
36        //---------------------------------------------------------------------
37    GLHardwareVertexBuffer::GLHardwareVertexBuffer(size_t vertexSize, 
38        size_t numVertices, HardwareBuffer::Usage usage, bool useShadowBuffer)
39        : HardwareVertexBuffer(vertexSize, numVertices, usage, false, useShadowBuffer)
40    {
41        glGenBuffersARB( 1, &mBufferId );
42
43        if (!mBufferId)
44        {
45            OGRE_EXCEPT(Exception::ERR_INTERNAL_ERROR, 
46                "Cannot create GL vertex buffer", 
47                "GLHardwareVertexBuffer::GLHardwareVertexBuffer");
48        }
49
50        glBindBufferARB(GL_ARRAY_BUFFER_ARB, mBufferId);
51
52        // Initialise mapped buffer and set usage
53        glBufferDataARB(GL_ARRAY_BUFFER_ARB, mSizeInBytes, NULL, 
54            GLHardwareBufferManager::getGLUsage(usage));
55
56        //std::cerr << "creating vertex buffer = " << mBufferId << std::endl;
57    }
58        //---------------------------------------------------------------------
59    GLHardwareVertexBuffer::~GLHardwareVertexBuffer()
60    {
61        glDeleteBuffersARB(1, &mBufferId);
62    }
63        //---------------------------------------------------------------------
64    void* GLHardwareVertexBuffer::lockImpl(size_t offset, 
65        size_t length, LockOptions options)
66    {
67        GLenum access = 0;
68
69        if(mIsLocked)
70        {
71            OGRE_EXCEPT(Exception::ERR_INTERNAL_ERROR,
72                "Invalid attempt to lock an index buffer that has already been locked",
73                "GLHardwareIndexBuffer::lock");
74        }
75
76
77                void* retPtr = 0;
78
79                // Try to use scratch buffers for smaller buffers
80                if(length < OGRE_GL_MAP_BUFFER_THRESHOLD)
81                {
82                        // if this fails, we fall back on mapping
83                        retPtr = static_cast<GLHardwareBufferManager*>(
84                                HardwareBufferManager::getSingletonPtr())->allocateScratch((uint32)length);
85
86                        if (retPtr)
87                        {
88                                mLockedToScratch = true;
89                                mScratchOffset = offset;
90                                mScratchSize = length;
91                                mScratchPtr = retPtr;
92                                mScratchUploadOnUnlock = (options != HBL_READ_ONLY);
93
94                                if (options != HBL_DISCARD)
95                                {
96                                        // have to read back the data before returning the pointer
97                                        readData(offset, length, retPtr);
98                                }
99                        }
100                }
101               
102                if (!retPtr)
103                {
104                        // Use glMapBuffer
105                        glBindBufferARB( GL_ARRAY_BUFFER_ARB, mBufferId );
106                        // Use glMapBuffer
107                        if(options == HBL_DISCARD)
108                        {
109                                // Discard the buffer
110                                glBufferDataARB(GL_ARRAY_BUFFER_ARB, mSizeInBytes, NULL, 
111                                        GLHardwareBufferManager::getGLUsage(mUsage));
112
113                        }
114                        if (mUsage & HBU_WRITE_ONLY)
115                                access = GL_WRITE_ONLY_ARB;
116                        else if (options == HBL_READ_ONLY)
117                                access = GL_READ_ONLY_ARB;
118                        else
119                                access = GL_READ_WRITE_ARB;
120
121                        void* pBuffer = glMapBufferARB( GL_ARRAY_BUFFER_ARB, access);
122
123                        if(pBuffer == 0)
124                        {
125                                OGRE_EXCEPT(Exception::ERR_INTERNAL_ERROR, 
126                                        "Vertex Buffer: Out of memory", "GLHardwareVertexBuffer::lock");
127                        }
128
129                        // return offsetted
130                        retPtr = static_cast<void*>(
131                                static_cast<unsigned char*>(pBuffer) + offset);
132
133                        mLockedToScratch = false;
134                }
135                mIsLocked = true;
136                return retPtr;
137    }
138        //---------------------------------------------------------------------
139        void GLHardwareVertexBuffer::unlockImpl(void)
140    {
141                if (mLockedToScratch)
142                {
143                        if (mScratchUploadOnUnlock)
144                        {
145                                // have to write the data back to vertex buffer
146                                writeData(mScratchOffset, mScratchSize, mScratchPtr, 
147                                        mScratchOffset == 0 && mScratchSize == getSizeInBytes());
148                        }
149
150                        // deallocate from scratch buffer
151                        static_cast<GLHardwareBufferManager*>(
152                                HardwareBufferManager::getSingletonPtr())->deallocateScratch(mScratchPtr);
153
154                        mLockedToScratch = false;
155                }
156                else
157                {
158
159                        glBindBufferARB(GL_ARRAY_BUFFER_ARB, mBufferId);
160
161                        if(!glUnmapBufferARB( GL_ARRAY_BUFFER_ARB ))
162                        {
163                                OGRE_EXCEPT(Exception::ERR_INTERNAL_ERROR, 
164                                        "Buffer data corrupted, please reload", 
165                                        "GLHardwareVertexBuffer::unlock");
166                        }
167                }
168
169        mIsLocked = false;
170    }
171        //---------------------------------------------------------------------
172    void GLHardwareVertexBuffer::readData(size_t offset, size_t length, 
173        void* pDest)
174    {
175        if(mUseShadowBuffer)
176        {
177            // get data from the shadow buffer
178            void* srcData = mpShadowBuffer->lock(offset, length, HBL_READ_ONLY);
179            memcpy(pDest, srcData, length);
180            mpShadowBuffer->unlock();
181        }
182        else
183        {
184            // get data from the real buffer
185            glBindBufferARB(GL_ARRAY_BUFFER_ARB, mBufferId);
186       
187            glGetBufferSubDataARB(GL_ARRAY_BUFFER_ARB, offset, length, pDest);
188        }
189    }
190        //---------------------------------------------------------------------
191    void GLHardwareVertexBuffer::writeData(size_t offset, size_t length, 
192            const void* pSource, bool discardWholeBuffer)
193    {
194        glBindBufferARB(GL_ARRAY_BUFFER_ARB, mBufferId);
195
196        // Update the shadow buffer
197        if(mUseShadowBuffer)
198        {
199            void* destData = mpShadowBuffer->lock(offset, length, 
200                discardWholeBuffer ? HBL_DISCARD : HBL_NORMAL);
201            memcpy(destData, pSource, length);
202            mpShadowBuffer->unlock();
203        }
204
205        if (offset == 0 && length == mSizeInBytes)
206        {
207            glBufferDataARB(GL_ARRAY_BUFFER_ARB, mSizeInBytes, pSource, 
208                GLHardwareBufferManager::getGLUsage(mUsage));
209        }
210        else
211        {
212            if(discardWholeBuffer)
213            {
214                glBufferDataARB(GL_ARRAY_BUFFER_ARB, mSizeInBytes, NULL, 
215                    GLHardwareBufferManager::getGLUsage(mUsage));
216            }
217
218            // Now update the real buffer
219            glBufferSubDataARB(GL_ARRAY_BUFFER_ARB, offset, length, pSource); 
220        }
221    }
222        //---------------------------------------------------------------------
223    void GLHardwareVertexBuffer::_updateFromShadow(void)
224    {
225        if (mUseShadowBuffer && mShadowUpdated && !mSuppressHardwareUpdate)
226        {
227            const void *srcData = mpShadowBuffer->lock(
228                mLockStart, mLockSize, HBL_READ_ONLY);
229
230            glBindBufferARB(GL_ARRAY_BUFFER_ARB, mBufferId);
231
232            // Update whole buffer if possible, otherwise normal
233            if (mLockStart == 0 && mLockSize == mSizeInBytes)
234            {
235                glBufferDataARB(GL_ARRAY_BUFFER_ARB, mSizeInBytes, srcData,
236                    GLHardwareBufferManager::getGLUsage(mUsage));
237            }
238            else
239            {
240                glBufferSubDataARB(GL_ARRAY_BUFFER_ARB, mLockStart, mLockSize, srcData);
241            }
242
243            mpShadowBuffer->unlock();
244            mShadowUpdated = false;
245        }
246    }
247}
Note: See TracBrowser for help on using the repository browser.