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 (c) 2000-2012 Torus Knot Software Ltd 00008 00009 Permission is hereby granted, free of charge, to any person obtaining a copy 00010 of this software and associated documentation files (the "Software"), to deal 00011 in the Software without restriction, including without limitation the rights 00012 to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 00013 copies of the Software, and to permit persons to whom the Software is 00014 furnished to do so, subject to the following conditions: 00015 00016 The above copyright notice and this permission notice shall be included in 00017 all copies or substantial portions of the Software. 00018 00019 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 00020 IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 00021 FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 00022 AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 00023 LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 00024 OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 00025 THE SOFTWARE. 00026 ----------------------------------------------------------------------------- 00027 */ 00028 #ifndef __HardwareBuffer__ 00029 #define __HardwareBuffer__ 00030 00031 // Precompiler options 00032 #include "OgrePrerequisites.h" 00033 #include "OgreException.h" 00034 00035 namespace Ogre { 00036 00074 class _OgreExport HardwareBuffer : public BufferAlloc 00075 { 00076 00077 public: 00079 enum Usage 00080 { 00084 HBU_STATIC = 1, 00090 HBU_DYNAMIC = 2, 00097 HBU_WRITE_ONLY = 4, 00106 HBU_DISCARDABLE = 8, 00108 HBU_STATIC_WRITE_ONLY = 5, 00114 HBU_DYNAMIC_WRITE_ONLY = 6, 00116 HBU_DYNAMIC_WRITE_ONLY_DISCARDABLE = 14 00117 00118 00119 }; 00121 enum LockOptions 00122 { 00124 HBL_NORMAL, 00129 HBL_DISCARD, 00133 HBL_READ_ONLY, 00137 HBL_NO_OVERWRITE 00138 00139 }; 00140 protected: 00141 size_t mSizeInBytes; 00142 Usage mUsage; 00143 bool mIsLocked; 00144 size_t mLockStart; 00145 size_t mLockSize; 00146 bool mSystemMemory; 00147 bool mUseShadowBuffer; 00148 HardwareBuffer* mShadowBuffer; 00149 bool mShadowUpdated; 00150 bool mSuppressHardwareUpdate; 00151 00153 virtual void* lockImpl(size_t offset, size_t length, LockOptions options) = 0; 00155 virtual void unlockImpl(void) = 0; 00156 00157 public: 00159 HardwareBuffer(Usage usage, bool systemMemory, bool useShadowBuffer) 00160 : mUsage(usage), mIsLocked(false), mSystemMemory(systemMemory), 00161 mUseShadowBuffer(useShadowBuffer), mShadowBuffer(NULL), mShadowUpdated(false), 00162 mSuppressHardwareUpdate(false) 00163 { 00164 // If use shadow buffer, upgrade to WRITE_ONLY on hardware side 00165 if (useShadowBuffer && usage == HBU_DYNAMIC) 00166 { 00167 mUsage = HBU_DYNAMIC_WRITE_ONLY; 00168 } 00169 else if (useShadowBuffer && usage == HBU_STATIC) 00170 { 00171 mUsage = HBU_STATIC_WRITE_ONLY; 00172 } 00173 } 00174 virtual ~HardwareBuffer() {} 00181 virtual void* lock(size_t offset, size_t length, LockOptions options) 00182 { 00183 assert(!isLocked() && "Cannot lock this buffer, it is already locked!"); 00184 00185 void* ret = NULL; 00186 if ((length + offset) > mSizeInBytes) 00187 { 00188 OGRE_EXCEPT(Exception::ERR_INVALIDPARAMS, 00189 "Lock request out of bounds.", 00190 "HardwareBuffer::lock"); 00191 } 00192 else if (mUseShadowBuffer) 00193 { 00194 if (options != HBL_READ_ONLY) 00195 { 00196 // we have to assume a read / write lock so we use the shadow buffer 00197 // and tag for sync on unlock() 00198 mShadowUpdated = true; 00199 } 00200 00201 ret = mShadowBuffer->lock(offset, length, options); 00202 } 00203 else 00204 { 00205 // Lock the real buffer if there is no shadow buffer 00206 ret = lockImpl(offset, length, options); 00207 mIsLocked = true; 00208 } 00209 mLockStart = offset; 00210 mLockSize = length; 00211 return ret; 00212 } 00213 00218 void* lock(LockOptions options) 00219 { 00220 return this->lock(0, mSizeInBytes, options); 00221 } 00234 virtual void unlock(void) 00235 { 00236 assert(isLocked() && "Cannot unlock this buffer, it is not locked!"); 00237 00238 // If we used the shadow buffer this time... 00239 if (mUseShadowBuffer && mShadowBuffer->isLocked()) 00240 { 00241 mShadowBuffer->unlock(); 00242 // Potentially update the 'real' buffer from the shadow buffer 00243 _updateFromShadow(); 00244 } 00245 else 00246 { 00247 // Otherwise, unlock the real one 00248 unlockImpl(); 00249 mIsLocked = false; 00250 } 00251 00252 } 00253 00260 virtual void readData(size_t offset, size_t length, void* pDest) = 0; 00269 virtual void writeData(size_t offset, size_t length, const void* pSource, 00270 bool discardWholeBuffer = false) = 0; 00271 00282 virtual void copyData(HardwareBuffer& srcBuffer, size_t srcOffset, 00283 size_t dstOffset, size_t length, bool discardWholeBuffer = false) 00284 { 00285 const void *srcData = srcBuffer.lock( 00286 srcOffset, length, HBL_READ_ONLY); 00287 this->writeData(dstOffset, length, srcData, discardWholeBuffer); 00288 srcBuffer.unlock(); 00289 } 00290 00296 virtual void copyData(HardwareBuffer& srcBuffer) 00297 { 00298 size_t sz = std::min(getSizeInBytes(), srcBuffer.getSizeInBytes()); 00299 copyData(srcBuffer, 0, 0, sz, true); 00300 } 00301 00303 virtual void _updateFromShadow(void) 00304 { 00305 if (mUseShadowBuffer && mShadowUpdated && !mSuppressHardwareUpdate) 00306 { 00307 // Do this manually to avoid locking problems 00308 const void *srcData = mShadowBuffer->lockImpl( 00309 mLockStart, mLockSize, HBL_READ_ONLY); 00310 // Lock with discard if the whole buffer was locked, otherwise normal 00311 LockOptions lockOpt; 00312 if (mLockStart == 0 && mLockSize == mSizeInBytes) 00313 lockOpt = HBL_DISCARD; 00314 else 00315 lockOpt = HBL_NORMAL; 00316 00317 void *destData = this->lockImpl( 00318 mLockStart, mLockSize, lockOpt); 00319 // Copy shadow to real 00320 memcpy(destData, srcData, mLockSize); 00321 this->unlockImpl(); 00322 mShadowBuffer->unlockImpl(); 00323 mShadowUpdated = false; 00324 } 00325 } 00326 00328 size_t getSizeInBytes(void) const { return mSizeInBytes; } 00330 Usage getUsage(void) const { return mUsage; } 00332 bool isSystemMemory(void) const { return mSystemMemory; } 00334 bool hasShadowBuffer(void) const { return mUseShadowBuffer; } 00336 bool isLocked(void) const { 00337 return mIsLocked || (mUseShadowBuffer && mShadowBuffer->isLocked()); 00338 } 00340 void suppressHardwareUpdate(bool suppress) { 00341 mSuppressHardwareUpdate = suppress; 00342 if (!suppress) 00343 _updateFromShadow(); 00344 } 00345 00346 00347 00348 00349 00350 }; 00353 } 00354 #endif 00355 00356
Copyright © 2012 Torus Knot Software Ltd
This work is licensed under a Creative Commons Attribution-ShareAlike 3.0 Unported License.
Last modified Fri May 25 23:36:24 2012