Planet
navi homePPSaboutscreenshotsdownloaddevelopmentforum

source: downloads/RenderSystems/GL/src/OgreGLHardwareIndexBuffer.cpp @ 1

Last change on this file since 1 was 1, checked in by landauf, 17 years ago
File size: 8.1 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 "OgreGLHardwareIndexBuffer.h"
30#include "OgreGLHardwareBufferManager.h"
31#include "OgreException.h"
32
33namespace Ogre {
34
35        //---------------------------------------------------------------------
36    GLHardwareIndexBuffer::GLHardwareIndexBuffer(IndexType idxType,
37        size_t numIndexes, HardwareBuffer::Usage usage, bool useShadowBuffer)
38        : HardwareIndexBuffer(idxType, numIndexes, usage, false, useShadowBuffer)
39    {
40        glGenBuffersARB( 1, &mBufferId );
41
42        if (!mBufferId)
43        {
44            OGRE_EXCEPT(Exception::ERR_INTERNAL_ERROR, 
45                "Cannot create GL index buffer", 
46                "GLHardwareIndexBuffer::GLHardwareIndexBuffer");
47        }
48
49        glBindBufferARB(GL_ELEMENT_ARRAY_BUFFER_ARB, mBufferId);
50
51        // Initialise buffer and set usage
52        glBufferDataARB(GL_ELEMENT_ARRAY_BUFFER_ARB, mSizeInBytes, NULL, 
53            GLHardwareBufferManager::getGLUsage(usage));
54
55        //std::cerr << "creating index buffer " << mBufferId << std::endl;
56    }
57        //---------------------------------------------------------------------
58    GLHardwareIndexBuffer::~GLHardwareIndexBuffer()
59    {
60        glDeleteBuffersARB(1, &mBufferId);
61    }
62        //---------------------------------------------------------------------
63    void* GLHardwareIndexBuffer::lockImpl(size_t offset, 
64        size_t length, LockOptions options)
65    {
66        GLenum access = 0;
67
68        if(mIsLocked)
69        {
70            OGRE_EXCEPT(Exception::ERR_INTERNAL_ERROR, 
71                "Invalid attempt to lock an index buffer that has already been locked",
72                    "GLHardwareIndexBuffer::lock");
73        }
74
75       
76                void* retPtr = 0;
77
78                // Try to use scratch buffers for smaller buffers
79                if(length < OGRE_GL_MAP_BUFFER_THRESHOLD)
80                {
81                        retPtr = static_cast<GLHardwareBufferManager*>(
82                                HardwareBufferManager::getSingletonPtr())->allocateScratch((uint32)length);
83                        if (retPtr)
84                        {
85                                mLockedToScratch = true;
86                                mScratchOffset = offset;
87                                mScratchSize = length;
88                                mScratchPtr = retPtr;
89                                mScratchUploadOnUnlock = (options != HBL_READ_ONLY);
90
91                                if (options != HBL_DISCARD)
92                                {
93                                        // have to read back the data before returning the pointer
94                                        readData(offset, length, retPtr);
95                                }
96                        }
97                }
98
99                if (!retPtr)
100                {
101                        glBindBufferARB( GL_ELEMENT_ARRAY_BUFFER_ARB, mBufferId );
102                        // Use glMapBuffer
103                        if(options == HBL_DISCARD)
104                        {
105                                // Discard the buffer
106                                glBufferDataARB(GL_ELEMENT_ARRAY_BUFFER_ARB, mSizeInBytes, NULL, 
107                                        GLHardwareBufferManager::getGLUsage(mUsage));
108                        }
109                        if (mUsage & HBU_WRITE_ONLY)
110                                access = GL_WRITE_ONLY_ARB;
111                        else if (options == HBL_READ_ONLY)
112                                access = GL_READ_ONLY_ARB;
113                        else
114                                access = GL_READ_WRITE_ARB;
115
116                        void* pBuffer = glMapBufferARB( GL_ELEMENT_ARRAY_BUFFER_ARB, access );
117
118                        if(pBuffer == 0)
119                        {
120                                OGRE_EXCEPT(Exception::ERR_INTERNAL_ERROR, 
121                                        "Index Buffer: Out of memory", 
122                                        "GLHardwareIndexBuffer::lock");
123                        }
124
125                        // return offsetted
126                        retPtr = static_cast<void*>(
127                                static_cast<unsigned char*>(pBuffer) + offset);
128
129                        mLockedToScratch = false;
130
131                }
132                mIsLocked = true;
133                return retPtr;
134    }
135        //---------------------------------------------------------------------
136        void GLHardwareIndexBuffer::unlockImpl(void)
137    {
138                if (mLockedToScratch)
139                {
140                        if (mScratchUploadOnUnlock)
141                        {
142                                // have to write the data back to vertex buffer
143                                writeData(mScratchOffset, mScratchSize, mScratchPtr, 
144                                        mScratchOffset == 0 && mScratchSize == getSizeInBytes());
145                        }
146
147                        // deallocate from scratch buffer
148                        static_cast<GLHardwareBufferManager*>(
149                                HardwareBufferManager::getSingletonPtr())->deallocateScratch(mScratchPtr);
150
151                        mLockedToScratch = false;
152                }
153                else
154                {
155
156                        glBindBufferARB( GL_ELEMENT_ARRAY_BUFFER_ARB, mBufferId );
157
158                        if(!glUnmapBufferARB( GL_ELEMENT_ARRAY_BUFFER_ARB ))
159                        {
160                                OGRE_EXCEPT(Exception::ERR_INTERNAL_ERROR, 
161                                        "Buffer data corrupted, please reload", 
162                                        "GLHardwareIndexBuffer::unlock");
163                        }
164                }
165
166        mIsLocked = false;
167    }
168        //---------------------------------------------------------------------
169    void GLHardwareIndexBuffer::readData(size_t offset, size_t length, 
170        void* pDest)
171    {
172        if(mUseShadowBuffer)
173        {
174            // get data from the shadow buffer
175            void* srcData = mpShadowBuffer->lock(offset, length, HBL_READ_ONLY);
176            memcpy(pDest, srcData, length);
177            mpShadowBuffer->unlock();
178        }
179        else
180        {
181            glBindBufferARB( GL_ELEMENT_ARRAY_BUFFER_ARB, mBufferId );
182            glGetBufferSubDataARB(GL_ELEMENT_ARRAY_BUFFER_ARB, offset, length, pDest);
183        }
184    }
185        //---------------------------------------------------------------------
186    void GLHardwareIndexBuffer::writeData(size_t offset, size_t length, 
187            const void* pSource, bool discardWholeBuffer)
188    {
189        glBindBufferARB( GL_ELEMENT_ARRAY_BUFFER_ARB, mBufferId );
190
191        // Update the shadow buffer
192        if(mUseShadowBuffer)
193        {
194            void* destData = mpShadowBuffer->lock(offset, length, 
195                discardWholeBuffer ? HBL_DISCARD : HBL_NORMAL);
196            memcpy(destData, pSource, length);
197            mpShadowBuffer->unlock();
198        }
199
200        if (offset == 0 && length == mSizeInBytes)
201        {
202            glBufferDataARB(GL_ELEMENT_ARRAY_BUFFER_ARB, mSizeInBytes, pSource,
203                GLHardwareBufferManager::getGLUsage(mUsage));
204        }
205        else
206        {
207            if(discardWholeBuffer)
208            {
209                glBufferDataARB(GL_ELEMENT_ARRAY_BUFFER_ARB, mSizeInBytes, NULL,
210                    GLHardwareBufferManager::getGLUsage(mUsage));
211            }
212
213            // Now update the real buffer
214            glBufferSubDataARB(GL_ELEMENT_ARRAY_BUFFER_ARB, offset, length, pSource);
215        }
216    }
217        //---------------------------------------------------------------------
218    void GLHardwareIndexBuffer::_updateFromShadow(void)
219    {
220        if (mUseShadowBuffer && mShadowUpdated && !mSuppressHardwareUpdate)
221        {
222            const void *srcData = mpShadowBuffer->lock(
223                mLockStart, mLockSize, HBL_READ_ONLY);
224
225            glBindBufferARB(GL_ELEMENT_ARRAY_BUFFER_ARB, mBufferId);
226
227            // Update whole buffer if possible, otherwise normal
228            if (mLockStart == 0 && mLockSize == mSizeInBytes)
229            {
230                glBufferDataARB(GL_ELEMENT_ARRAY_BUFFER_ARB, mSizeInBytes, srcData,
231                    GLHardwareBufferManager::getGLUsage(mUsage));
232            }
233            else
234            {
235                glBufferSubDataARB(GL_ELEMENT_ARRAY_BUFFER_ARB, mLockStart, mLockSize, srcData);
236            }
237
238            mpShadowBuffer->unlock();
239            mShadowUpdated = false;
240        }
241    }
242}
Note: See TracBrowser for help on using the repository browser.