00001 /* 00002 ----------------------------------------------------------------------------- 00003 This source file is part of OGRE 00004 (Object-oriented Graphics Rendering Engine) 00005 For the latest info, see http://www.ogre3d.org/ 00006 00007 Copyright © 2000-2003 The OGRE Team 00008 Also see acknowledgements in Readme.html 00009 00010 This program is free software; you can redistribute it and/or modify it under 00011 the terms of the GNU Lesser General Public License as published by the Free Software 00012 Foundation; either version 2 of the License, or (at your option) any later 00013 version. 00014 00015 This program is distributed in the hope that it will be useful, but WITHOUT 00016 ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS 00017 FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. 00018 00019 You should have received a copy of the GNU Lesser General Public License along with 00020 this program; if not, write to the Free Software Foundation, Inc., 59 Temple 00021 Place - Suite 330, Boston, MA 02111-1307, USA, or go to 00022 http://www.gnu.org/copyleft/lesser.txt. 00023 ----------------------------------------------------------------------------- 00024 */ 00025 #include "OgreGLHardwareBufferManager.h" 00026 #include "OgreGLHardwareVertexBuffer.h" 00027 #include "OgreException.h" 00028 #include "OgreLogManager.h" 00029 00030 namespace Ogre { 00031 00032 //--------------------------------------------------------------------- 00033 GLHardwareVertexBuffer::GLHardwareVertexBuffer(size_t vertexSize, 00034 size_t numVertices, HardwareBuffer::Usage usage, bool useShadowBuffer) 00035 : HardwareVertexBuffer(vertexSize, numVertices, usage, false, useShadowBuffer) 00036 { 00037 glGenBuffersARB_ptr( 1, &mBufferId ); 00038 00039 if (!mBufferId) 00040 { 00041 Except(Exception::ERR_INTERNAL_ERROR, 00042 "Cannot create GL vertex buffer", 00043 "GLHardwareVertexBuffer::GLHardwareVertexBuffer"); 00044 } 00045 00046 glBindBufferARB_ptr(GL_ARRAY_BUFFER_ARB, mBufferId); 00047 00048 // Initialise mapped buffer and set usage 00049 glBufferDataARB_ptr(GL_ARRAY_BUFFER_ARB, mSizeInBytes, NULL, 00050 GLHardwareBufferManager::getGLUsage(usage)); 00051 00052 //std::cerr << "creating vertex buffer = " << mBufferId << std::endl; 00053 } 00054 //--------------------------------------------------------------------- 00055 GLHardwareVertexBuffer::~GLHardwareVertexBuffer() 00056 { 00057 glDeleteBuffersARB_ptr(1, &mBufferId); 00058 } 00059 //--------------------------------------------------------------------- 00060 void* GLHardwareVertexBuffer::lockImpl(size_t offset, 00061 size_t length, LockOptions options) 00062 { 00063 GLenum access = 0; 00064 00065 if(mIsLocked) 00066 { 00067 Except(Exception::ERR_INTERNAL_ERROR, 00068 "Invalid attempt to lock an index buffer that has already been locked", 00069 "GLHardwareIndexBuffer::lock"); 00070 } 00071 00072 glBindBufferARB_ptr(GL_ARRAY_BUFFER_ARB, mBufferId); 00073 00074 if(options == HBL_DISCARD) 00075 { 00076 //TODO: really we should use this to indicate our discard of the buffer 00077 //However it makes no difference to fps on nVidia, and can crash some ATI 00078 //glBufferDataARB_ptr(GL_ELEMENT_ARRAY_BUFFER_ARB, mSizeInBytes, NULL, 00079 // GLHardwareBufferManager::getGLUsage(mUsage)); 00080 00081 // TODO: we should be using the below implementation, but nVidia cards 00082 // choke on it and perform terribly - for investigation with nVidia 00083 //access = (mUsage == HBU_DYNAMIC || mUsage == HBU_STATIC) ? 00084 // GL_READ_WRITE_ARB : GL_WRITE_ONLY_ARB; 00085 access = GL_READ_WRITE; 00086 00087 } 00088 else if(options == HBL_READ_ONLY) 00089 { 00090 if(mUsage == HBU_WRITE_ONLY) 00091 { 00092 LogManager::getSingleton().logMessage( 00093 "GLHardwareVertexBuffer: Locking a write-only vertex " 00094 "buffer for reading, performance warning."); 00095 } 00096 access = GL_READ_ONLY_ARB; 00097 } 00098 else if(options == HBL_NORMAL || options == HBL_NO_OVERWRITE) 00099 { 00100 // TODO: we should be using the below implementation, but nVidia cards 00101 // choke on it and perform terribly - for investigation with nVidia 00102 //access = (mUsage == HBU_DYNAMIC || mUsage == HBU_STATIC) ? 00103 // GL_READ_WRITE_ARB : GL_WRITE_ONLY_ARB; 00104 access = GL_READ_WRITE; 00105 } 00106 else 00107 { 00108 Except(Exception::ERR_INTERNAL_ERROR, 00109 "Invalid locking option set", "GLHardwareVertexBuffer::lock"); 00110 } 00111 00112 void* pBuffer = glMapBufferARB_ptr( GL_ARRAY_BUFFER_ARB, access); 00113 00114 if(pBuffer == 0) 00115 { 00116 Except(Exception::ERR_INTERNAL_ERROR, 00117 "Vertex Buffer: Out of memory", "GLHardwareVertexBuffer::lock"); 00118 } 00119 00120 mIsLocked = true; 00121 // return offsetted 00122 return static_cast<void*>( 00123 static_cast<unsigned char*>(pBuffer) + offset); 00124 } 00125 //--------------------------------------------------------------------- 00126 void GLHardwareVertexBuffer::unlockImpl(void) 00127 { 00128 glBindBufferARB_ptr(GL_ARRAY_BUFFER_ARB, mBufferId); 00129 00130 if(!glUnmapBufferARB_ptr( GL_ARRAY_BUFFER_ARB )) 00131 { 00132 Except(Exception::ERR_INTERNAL_ERROR, 00133 "Buffer data corrupted, please reload", 00134 "GLHardwareVertexBuffer::unlock"); 00135 } 00136 00137 mIsLocked = false; 00138 } 00139 //--------------------------------------------------------------------- 00140 void GLHardwareVertexBuffer::readData(size_t offset, size_t length, 00141 void* pDest) 00142 { 00143 if(mUseShadowBuffer) 00144 { 00145 // get data from the shadow buffer 00146 void* srcData = mpShadowBuffer->lock(offset, length, HBL_READ_ONLY); 00147 memcpy(pDest, srcData, length); 00148 mpShadowBuffer->unlock(); 00149 } 00150 else 00151 { 00152 // get data from the real buffer 00153 glBindBufferARB_ptr(GL_ARRAY_BUFFER_ARB, mBufferId); 00154 00155 glGetBufferSubDataARB_ptr(GL_ARRAY_BUFFER_ARB, offset, length, pDest); 00156 } 00157 } 00158 //--------------------------------------------------------------------- 00159 void GLHardwareVertexBuffer::writeData(size_t offset, size_t length, 00160 const void* pSource, bool discardWholeBuffer) 00161 { 00162 glBindBufferARB_ptr(GL_ARRAY_BUFFER_ARB, mBufferId); 00163 00164 // Update the shadow buffer 00165 if(mUseShadowBuffer) 00166 { 00167 void* destData = mpShadowBuffer->lock(offset, length, 00168 discardWholeBuffer ? HBL_DISCARD : HBL_NORMAL); 00169 memcpy(destData, pSource, length); 00170 mpShadowBuffer->unlock(); 00171 } 00172 00173 if(discardWholeBuffer) 00174 { 00175 glBufferDataARB_ptr(GL_ARRAY_BUFFER_ARB, mSizeInBytes, NULL, 00176 GLHardwareBufferManager::getGLUsage(mUsage)); 00177 } 00178 00179 // Now update the real buffer 00180 glBufferSubDataARB_ptr(GL_ARRAY_BUFFER_ARB, offset, length, pSource); 00181 } 00182 //--------------------------------------------------------------------- 00183 00184 }
Copyright © 2002-2003 by The OGRE Team
Last modified Sun Nov 28 19:48:25 2004