| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346 |
- /*
- -----------------------------------------------------------------------------
- This source file is part of OGRE
- (Object-oriented Graphics Rendering Engine)
- For the latest info, see http://www.ogre3d.org/
- Copyright (c) 2000-2011 Torus Knot Software Ltd
- Permission is hereby granted, free of charge, to any person obtaining a copy
- of this software and associated documentation files (the "Software"), to deal
- in the Software without restriction, including without limitation the rights
- to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
- copies of the Software, and to permit persons to whom the Software is
- furnished to do so, subject to the following conditions:
- The above copyright notice and this permission notice shall be included in
- all copies or substantial portions of the Software.
- THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
- IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
- AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
- LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
- OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
- THE SOFTWARE.
- -----------------------------------------------------------------------------
- */
- #include "CmPixelBuffer.h"
- #include "CmTexture.h"
- #include "CmTextureRTTI.h"
- #include "CmDataStream.h"
- #include "CmException.h"
- #include "CmDebug.h"
- #include "CmRenderSystem.h"
- #include "CmAsyncOp.h"
- #if CM_DEBUG_MODE
- #define THROW_IF_NOT_RENDER_THREAD throwIfNotRenderThread();
- #else
- #define THROW_IF_NOT_RENDER_THREAD
- #endif
- namespace CamelotFramework {
- //--------------------------------------------------------------------------
- Texture::Texture()
- :
- mHeight(512),
- mWidth(512),
- mDepth(1),
- mNumMipmaps(0),
- mHwGamma(false),
- mFSAA(0),
- mTextureType(TEX_TYPE_2D),
- mFormat(PF_UNKNOWN),
- mUsage(TU_DEFAULT)
- {
-
- }
- //-------------------------------------------------------------------------
- void Texture::initialize(TextureType textureType, UINT32 width, UINT32 height, UINT32 depth, UINT32 numMipmaps,
- PixelFormat format, int usage, bool hwGamma, UINT32 fsaa, const String& fsaaHint)
- {
- mTextureType = textureType;
- mWidth = width;
- mHeight = height;
- mDepth = depth;
- mNumMipmaps = numMipmaps;
- mFormat = format;
- mUsage = usage;
- mHwGamma = hwGamma;
- mFSAA = fsaa;
- mFSAAHint = fsaaHint;
- mSize = getNumFaces() * PixelUtil::getMemorySize(mWidth, mHeight, mDepth, mFormat);
- Resource::initialize();
- }
- //--------------------------------------------------------------------------
- bool Texture::hasAlpha(void) const
- {
- return PixelUtil::hasAlpha(mFormat);
- }
- //--------------------------------------------------------------------------
- UINT32 Texture::calculateSize(void) const
- {
- return getNumFaces() * PixelUtil::getMemorySize(mWidth, mHeight, mDepth, mFormat);
- }
- //--------------------------------------------------------------------------
- UINT32 Texture::getNumFaces(void) const
- {
- return getTextureType() == TEX_TYPE_CUBE_MAP ? 6 : 1;
- }
- void Texture::writeSubresource(UINT32 subresourceIdx, const GpuResourceData& data)
- {
- THROW_IF_NOT_RENDER_THREAD;
- if(data.getTypeId() != TID_PixelData)
- CM_EXCEPT(InvalidParametersException, "Invalid GpuResourceData type. Only PixelData is supported.");
- const PixelData& pixelData = static_cast<const PixelData&>(data);
- UINT32 face = 0;
- UINT32 mip = 0;
- mapFromSubresourceIdx(subresourceIdx, face, mip);
- PixelData myData = lock(GBL_WRITE_ONLY_DISCARD, mip, face);
- PixelUtil::bulkPixelConversion(pixelData, myData);
- unlock();
- }
- void Texture::readSubresource(UINT32 subresourceIdx, GpuResourceData& data)
- {
- THROW_IF_NOT_RENDER_THREAD;
- if(data.getTypeId() != TID_PixelData)
- CM_EXCEPT(InvalidParametersException, "Invalid GpuResourceData type. Only PixelData is supported.");
- PixelData& pixelData = static_cast<PixelData&>(data);
- UINT32 face = 0;
- UINT32 mip = 0;
- mapFromSubresourceIdx(subresourceIdx, face, mip);
- PixelData myData = lock(GBL_READ_ONLY, mip, face);
- #if CM_DEBUG_MODE
- if(pixelData.getConsecutiveSize() != myData.getConsecutiveSize())
- {
- unlock();
- CM_EXCEPT(InternalErrorException, "Buffer sizes don't match");
- }
- #endif
- PixelUtil::bulkPixelConversion(myData, pixelData);
- unlock();
- }
- PixelDataPtr Texture::allocateSubresourceBuffer(UINT32 subresourceIdx) const
- {
- UINT32 face = 0;
- UINT32 mip = 0;
- mapFromSubresourceIdx(subresourceIdx, face, mip);
- UINT32 numMips = getNumMipmaps();
- UINT32 width = getWidth();
- UINT32 height = getHeight();
- UINT32 depth = getDepth();
- UINT32 totalSize = PixelUtil::getMemorySize(width, height, depth, mFormat);
- for(UINT32 j = 0; j < mip; j++)
- {
- totalSize = PixelUtil::getMemorySize(width, height, depth, mFormat);
- if(width != 1) width /= 2;
- if(height != 1) height /= 2;
- if(depth != 1) depth /= 2;
- }
- PixelDataPtr dst(CM_NEW(PixelData, PoolAlloc) PixelData(width, height, depth, getFormat()),
- &MemAllocDeleter<PixelData, PoolAlloc>::deleter);
- dst->allocateInternalBuffer();
- return dst;
- }
- void Texture::mapFromSubresourceIdx(UINT32 subresourceIdx, UINT32& face, UINT32& mip) const
- {
- UINT32 numMipmaps = getNumMipmaps() + 1;
- face = Math::FloorToInt((subresourceIdx) / (float)numMipmaps);
- mip = subresourceIdx % numMipmaps;
- }
- UINT32 Texture::mapToSubresourceIdx(UINT32 face, UINT32 mip) const
- {
- return face * (getNumMipmaps() + 1) + mip;
- }
- //----------------------------------------------------------------------------
- PixelData Texture::lock(GpuLockOptions options, UINT32 mipLevel, UINT32 face)
- {
- THROW_IF_NOT_RENDER_THREAD;
- if(mipLevel < 0 || mipLevel > mNumMipmaps)
- CM_EXCEPT(InvalidParametersException, "Invalid mip level: " + toString(mipLevel) + ". Min is 0, max is " + toString(getNumMipmaps()));
- if(face < 0 || face >= getNumFaces())
- CM_EXCEPT(InvalidParametersException, "Invalid face index: " + toString(face) + ". Min is 0, max is " + toString(getNumFaces()));
- return lockImpl(options, mipLevel, face);
- }
- //-----------------------------------------------------------------------------
- void Texture::unlock()
- {
- unlockImpl();
- }
- //-----------------------------------------------------------------------------
- void Texture::copy(TexturePtr& target)
- {
- if (target->getUsage() != this->getUsage() ||
- target->getTextureType() != this->getTextureType())
- {
- CM_EXCEPT(InvalidParametersException, "Source and destination textures must be of same type and must have the same usage and type.");
- }
- if(getWidth() != target->getWidth() || getHeight() != target->getHeight() || getDepth() != target->getDepth())
- {
- CM_EXCEPT(InvalidParametersException, "Texture sizes don't match." \
- " Width: " + toString(getWidth()) + "/" + toString(target->getWidth()) +
- " Height: " + toString(getHeight()) + "/" + toString(target->getHeight()) +
- " Depth: " + toString(getDepth()) + "/" + toString(target->getDepth()));
- }
- if(getNumFaces() != target->getNumFaces())
- {
- CM_EXCEPT(InvalidParametersException, "Number of texture faces doesn't match." \
- " Num faces: " + toString(getNumFaces()) + "/" + toString(target->getNumFaces()));
- }
- if(getNumMipmaps() != target->getNumMipmaps())
- {
- CM_EXCEPT(InvalidParametersException, "Number of mipmaps doesn't match." \
- " Num mipmaps: " + toString(getNumMipmaps()) + "/" + toString(target->getNumMipmaps()));
- }
- copyImpl(target);
- }
- //-----------------------------------------------------------------------------
- void Texture::throwIfNotRenderThread() const
- {
- if(CM_THREAD_CURRENT_ID != RenderSystem::instancePtr()->getRenderThreadId())
- CM_EXCEPT(InternalErrorException, "Calling an internal texture method from a non-render thread!");
- }
- /************************************************************************/
- /* TEXTURE VIEW */
- /************************************************************************/
- TextureViewPtr Texture::createView()
- {
- TextureViewPtr viewPtr(CM_NEW(TextureView, PoolAlloc) TextureView(), &CoreObject::_deleteDelayed<TextureView, PoolAlloc>);
- viewPtr->setThisPtr(viewPtr);
- return viewPtr;
- }
- void Texture::clearBufferViews()
- {
- mTextureViews.clear();
- }
- TextureViewPtr Texture::requestView(TexturePtr texture, UINT32 mostDetailMip, UINT32 numMips, UINT32 firstArraySlice, UINT32 numArraySlices, GpuViewUsage usage)
- {
- assert(texture != nullptr);
- TEXTURE_VIEW_DESC key;
- key.mostDetailMip = mostDetailMip;
- key.numMips = numMips;
- key.firstArraySlice = firstArraySlice;
- key.numArraySlices = numArraySlices;
- key.usage = usage;
- auto iterFind = texture->mTextureViews.find(key);
- if(iterFind == texture->mTextureViews.end())
- {
- TextureViewPtr newView = texture->createView();
- newView->initialize(texture, key);
- texture->mTextureViews[key] = CM_NEW(TextureViewReference, PoolAlloc) TextureViewReference(newView);
- iterFind = texture->mTextureViews.find(key);
- }
- iterFind->second->refCount++;
- return iterFind->second->view;
- }
- void Texture::releaseView(TextureViewPtr view)
- {
- assert(view != nullptr);
- TexturePtr texture = view->getTexture();
- auto iterFind = texture->mTextureViews.find(view->getDesc());
- if(iterFind == texture->mTextureViews.end())
- {
- CM_EXCEPT(InternalErrorException, "Trying to release a texture view that doesn't exist!");
- }
- iterFind->second->refCount--;
- if(iterFind->second->refCount == 0)
- {
- TextureViewReference* toRemove = iterFind->second;
- texture->mTextureViews.erase(iterFind);
- CM_DELETE(toRemove, TextureViewReference, PoolAlloc);
- }
- }
- /************************************************************************/
- /* SERIALIZATION */
- /************************************************************************/
- RTTITypeBase* Texture::getRTTIStatic()
- {
- return TextureRTTI::instance();
- }
- RTTITypeBase* Texture::getRTTI() const
- {
- return Texture::getRTTIStatic();
- }
- /************************************************************************/
- /* STATICS */
- /************************************************************************/
- HTexture Texture::create(TextureType texType, UINT32 width, UINT32 height, UINT32 depth,
- int num_mips, PixelFormat format, int usage, bool hwGammaCorrection, UINT32 fsaa, const String& fsaaHint)
- {
- TexturePtr texturePtr = TextureManager::instance().createTexture(texType,
- width, height, depth, num_mips, format, usage, hwGammaCorrection, fsaa, fsaaHint);
- return static_resource_cast<Texture>(Resource::_createResourceHandle(texturePtr));
- }
-
- HTexture Texture::create(TextureType texType, UINT32 width, UINT32 height,
- int num_mips, PixelFormat format, int usage, bool hwGammaCorrection, UINT32 fsaa, const String& fsaaHint)
- {
- TexturePtr texturePtr = TextureManager::instance().createTexture(texType,
- width, height, num_mips, format, usage, hwGammaCorrection, fsaa, fsaaHint);
- return static_resource_cast<Texture>(Resource::_createResourceHandle(texturePtr));
- }
- HTexture Texture::dummy()
- {
- return TextureManager::instance().getDummyTexture();
- }
- }
- #undef THROW_IF_NOT_RENDER_THREAD
|