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-2013 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, 00139 HBL_WRITE_ONLY 00140 00141 }; 00142 protected: 00143 size_t mSizeInBytes; 00144 Usage mUsage; 00145 bool mIsLocked; 00146 size_t mLockStart; 00147 size_t mLockSize; 00148 bool mSystemMemory; 00149 bool mUseShadowBuffer; 00150 HardwareBuffer* mShadowBuffer; 00151 bool mShadowUpdated; 00152 bool mSuppressHardwareUpdate; 00153 00155 virtual void* lockImpl(size_t offset, size_t length, LockOptions options) = 0; 00157 virtual void unlockImpl(void) = 0; 00158 00159 public: 00161 HardwareBuffer(Usage usage, bool systemMemory, bool useShadowBuffer) 00162 : mUsage(usage), mIsLocked(false), mLockStart(0), mLockSize(0), mSystemMemory(systemMemory), 00163 mUseShadowBuffer(useShadowBuffer), mShadowBuffer(NULL), mShadowUpdated(false), 00164 mSuppressHardwareUpdate(false) 00165 { 00166 // If use shadow buffer, upgrade to WRITE_ONLY on hardware side 00167 if (useShadowBuffer && usage == HBU_DYNAMIC) 00168 { 00169 mUsage = HBU_DYNAMIC_WRITE_ONLY; 00170 } 00171 else if (useShadowBuffer && usage == HBU_STATIC) 00172 { 00173 mUsage = HBU_STATIC_WRITE_ONLY; 00174 } 00175 } 00176 virtual ~HardwareBuffer() {} 00183 virtual void* lock(size_t offset, size_t length, LockOptions options) 00184 { 00185 assert(!isLocked() && "Cannot lock this buffer, it is already locked!"); 00186 00187 void* ret = NULL; 00188 if ((length + offset) > mSizeInBytes) 00189 { 00190 OGRE_EXCEPT(Exception::ERR_INVALIDPARAMS, 00191 "Lock request out of bounds.", 00192 "HardwareBuffer::lock"); 00193 } 00194 else if (mUseShadowBuffer) 00195 { 00196 if (options != HBL_READ_ONLY) 00197 { 00198 // we have to assume a read / write lock so we use the shadow buffer 00199 // and tag for sync on unlock() 00200 mShadowUpdated = true; 00201 } 00202 00203 ret = mShadowBuffer->lock(offset, length, options); 00204 } 00205 else 00206 { 00207 // Lock the real buffer if there is no shadow buffer 00208 ret = lockImpl(offset, length, options); 00209 mIsLocked = true; 00210 } 00211 mLockStart = offset; 00212 mLockSize = length; 00213 return ret; 00214 } 00215 00220 void* lock(LockOptions options) 00221 { 00222 return this->lock(0, mSizeInBytes, options); 00223 } 00236 virtual void unlock(void) 00237 { 00238 assert(isLocked() && "Cannot unlock this buffer, it is not locked!"); 00239 00240 // If we used the shadow buffer this time... 00241 if (mUseShadowBuffer && mShadowBuffer->isLocked()) 00242 { 00243 mShadowBuffer->unlock(); 00244 // Potentially update the 'real' buffer from the shadow buffer 00245 _updateFromShadow(); 00246 } 00247 else 00248 { 00249 // Otherwise, unlock the real one 00250 unlockImpl(); 00251 mIsLocked = false; 00252 } 00253 00254 } 00255 00262 virtual void readData(size_t offset, size_t length, void* pDest) = 0; 00271 virtual void writeData(size_t offset, size_t length, const void* pSource, 00272 bool discardWholeBuffer = false) = 0; 00273 00284 virtual void copyData(HardwareBuffer& srcBuffer, size_t srcOffset, 00285 size_t dstOffset, size_t length, bool discardWholeBuffer = false) 00286 { 00287 const void *srcData = srcBuffer.lock( 00288 srcOffset, length, HBL_READ_ONLY); 00289 this->writeData(dstOffset, length, srcData, discardWholeBuffer); 00290 srcBuffer.unlock(); 00291 } 00292 00298 virtual void copyData(HardwareBuffer& srcBuffer) 00299 { 00300 size_t sz = std::min(getSizeInBytes(), srcBuffer.getSizeInBytes()); 00301 copyData(srcBuffer, 0, 0, sz, true); 00302 } 00303 00305 virtual void _updateFromShadow(void) 00306 { 00307 if (mUseShadowBuffer && mShadowUpdated && !mSuppressHardwareUpdate) 00308 { 00309 // Do this manually to avoid locking problems 00310 const void *srcData = mShadowBuffer->lockImpl( 00311 mLockStart, mLockSize, HBL_READ_ONLY); 00312 // Lock with discard if the whole buffer was locked, otherwise normal 00313 LockOptions lockOpt; 00314 if (mLockStart == 0 && mLockSize == mSizeInBytes) 00315 lockOpt = HBL_DISCARD; 00316 else 00317 lockOpt = HBL_NORMAL; 00318 00319 void *destData = this->lockImpl( 00320 mLockStart, mLockSize, lockOpt); 00321 // Copy shadow to real 00322 memcpy(destData, srcData, mLockSize); 00323 this->unlockImpl(); 00324 mShadowBuffer->unlockImpl(); 00325 mShadowUpdated = false; 00326 } 00327 } 00328 00330 size_t getSizeInBytes(void) const { return mSizeInBytes; } 00332 Usage getUsage(void) const { return mUsage; } 00334 bool isSystemMemory(void) const { return mSystemMemory; } 00336 bool hasShadowBuffer(void) const { return mUseShadowBuffer; } 00338 bool isLocked(void) const { 00339 return mIsLocked || (mUseShadowBuffer && mShadowBuffer->isLocked()); 00340 } 00342 void suppressHardwareUpdate(bool suppress) { 00343 mSuppressHardwareUpdate = suppress; 00344 if (!suppress) 00345 _updateFromShadow(); 00346 } 00347 00348 00349 00350 00351 00352 }; 00357 template <typename T> struct HardwareBufferLockGuard 00358 { 00359 HardwareBufferLockGuard(const T& p, HardwareBuffer::LockOptions options) 00360 : pBuf(p) 00361 { 00362 pData = pBuf->lock(options); 00363 } 00364 HardwareBufferLockGuard(const T& p, size_t offset, size_t length, HardwareBuffer::LockOptions options) 00365 : pBuf(p) 00366 { 00367 pData = pBuf->lock(offset, length, options); 00368 } 00369 ~HardwareBufferLockGuard() 00370 { 00371 pBuf->unlock(); 00372 } 00373 00374 const T& pBuf; 00375 void* pData; 00376 }; 00377 } 00378 #endif 00379 00380
Copyright © 2012 Torus Knot Software Ltd

This work is licensed under a Creative Commons Attribution-ShareAlike 3.0 Unported License.
Last modified Mon Jul 27 2020 13:40:43