| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322 |
- /*
- -----------------------------------------------------------------------------
- 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 "CmHardwarePixelBuffer.h"
- #include "CmTexture.h"
- #include "CmTextureST.h"
- #include "CmTextureData.h"
- #include "CmDataStream.h"
- #include "CmException.h"
- #include "CmDebug.h"
- namespace CamelotEngine {
- //--------------------------------------------------------------------------
- Texture::Texture()
- : // init defaults; can be overridden before load()
- mHeight(512),
- mWidth(512),
- mDepth(1),
- mNumRequestedMipmaps(0),
- mNumMipmaps(0),
- mMipmapsHardwareGenerated(false),
- mGamma(1.0f),
- mHwGamma(false),
- mFSAA(0),
- mTextureType(TEX_TYPE_2D),
- mFormat(PF_UNKNOWN),
- mUsage(TU_DEFAULT),
- mSrcFormat(PF_UNKNOWN),
- mSrcWidth(0),
- mSrcHeight(0),
- mSrcDepth(0),
- mDesiredFormat(PF_UNKNOWN),
- mDesiredIntegerBitDepth(0),
- mDesiredFloatBitDepth(0),
- mInternalResourcesCreated(false)
- {
-
- }
- //--------------------------------------------------------------------------
- void Texture::setFormat(PixelFormat pf)
- {
- mFormat = pf;
- mDesiredFormat = pf;
- mSrcFormat = pf;
- }
- //--------------------------------------------------------------------------
- bool Texture::hasAlpha(void) const
- {
- return PixelUtil::hasAlpha(mFormat);
- }
- //--------------------------------------------------------------------------
- void Texture::setDesiredIntegerBitDepth(UINT16 bits)
- {
- mDesiredIntegerBitDepth = bits;
- }
- //--------------------------------------------------------------------------
- UINT16 Texture::getDesiredIntegerBitDepth(void) const
- {
- return mDesiredIntegerBitDepth;
- }
- //--------------------------------------------------------------------------
- void Texture::setDesiredFloatBitDepth(UINT16 bits)
- {
- mDesiredFloatBitDepth = bits;
- }
- //--------------------------------------------------------------------------
- UINT16 Texture::getDesiredFloatBitDepth(void) const
- {
- return mDesiredFloatBitDepth;
- }
- //--------------------------------------------------------------------------
- void Texture::setDesiredBitDepths(UINT16 integerBits, UINT16 floatBits)
- {
- mDesiredIntegerBitDepth = integerBits;
- mDesiredFloatBitDepth = floatBits;
- }
- //--------------------------------------------------------------------------
- size_t Texture::calculateSize(void) const
- {
- return getNumFaces() * PixelUtil::getMemorySize(mWidth, mHeight, mDepth, mFormat);
- }
- //--------------------------------------------------------------------------
- size_t Texture::getNumFaces(void) const
- {
- return getTextureType() == TEX_TYPE_CUBE_MAP ? 6 : 1;
- }
- //-----------------------------------------------------------------------------
- void Texture::createInternalResources(void)
- {
- if (!mInternalResourcesCreated)
- {
- createInternalResourcesImpl();
- mInternalResourcesCreated = true;
- }
- }
- //-----------------------------------------------------------------------------
- void Texture::freeInternalResources(void)
- {
- if (mInternalResourcesCreated)
- {
- freeInternalResourcesImpl();
- mInternalResourcesCreated = false;
- }
- }
- //-----------------------------------------------------------------------------
- TextureDataPtr Texture::getTextureData(int face)
- {
- if(face < 0 || face >= getNumFaces())
- {
- CM_EXCEPT(InvalidParametersException, "Face index out of range: " + toString(face));
- }
- UINT32 numMips = getNumMipmaps();
- UINT32 totalSize = 0;
- UINT32 width = getWidth();
- UINT32 height = getHeight();
- UINT32 depth = getDepth();
- for(int j = 0; j < numMips; j++)
- {
- UINT32 currentMipSize = PixelUtil::getMemorySize(
- width, height, depth, mFormat);
- totalSize += currentMipSize;
- if(width != 1) width /= 2;
- if(height != 1) height /= 2;
- if(depth != 1) depth /= 2;
- }
- UINT8* buffer = new UINT8[totalSize]; // TextureData frees this
- TextureDataPtr texData(new TextureData(getWidth(), getHeight(), totalSize, mFormat, buffer, getDepth(), 0, getNumMipmaps()));
- for(int j = 0; j < numMips; j++)
- {
- PixelData pixels = texData->getPixels(j);
- getBuffer(face, j)->blitToMemory(pixels);
- }
- return texData;
- }
- //-----------------------------------------------------------------------------
- void Texture::setTextureData(int face, TextureDataPtr textureData)
- {
- if(face < 0 || face >= getNumFaces())
- {
- CM_EXCEPT(InvalidParametersException, "Face index out of range: " + toString(face));
- }
- if(mTextureData.size() <= face)
- mTextureData.resize(face + 1);
- mTextureData[face] = textureData;
- }
- //-----------------------------------------------------------------------------
- void Texture::initializeFromTextureData()
- {
- if(mTextureData.size() < 1)
- CM_EXCEPT(InvalidParametersException, "Cannot load empty vector of images");
- if(getTextureType() == TEX_TYPE_CUBE_MAP)
- {
- if(mTextureData.size() != 6)
- CM_EXCEPT(InvalidParametersException, "Cube map textures require six faces.");
- }
- else
- {
- if(mTextureData.size() > 1)
- {
- gDebug().log("Non-cube textures can only have one face. Loading only first face from the provided array.", "D3D9RenderSystem");
- }
- }
- // Set desired texture size and properties from images[0]
- mSrcWidth = mWidth = mTextureData[0]->getWidth();
- mSrcHeight = mHeight = mTextureData[0]->getHeight();
- mSrcDepth = mDepth = mTextureData[0]->getDepth();
- // Get source image format and adjust if required
- mSrcFormat = mTextureData[0]->getFormat();
- if (mDesiredFormat != PF_UNKNOWN)
- {
- // If have desired format, use it
- mFormat = mDesiredFormat;
- }
- else
- {
- // Get the format according with desired bit depth
- mFormat = PixelUtil::getFormatForBitDepths(mSrcFormat, mDesiredIntegerBitDepth, mDesiredFloatBitDepth);
- }
- // The custom mipmaps in the image have priority over everything
- size_t imageMips = mTextureData[0]->getNumMipmaps();
- if(imageMips > 0)
- {
- mNumMipmaps = mNumRequestedMipmaps = mTextureData[0]->getNumMipmaps();
- // Disable flag for auto mip generation
- mUsage &= ~TU_AUTOMIPMAP;
- }
- // Create the texture
- createInternalResources();
- // Check if we're loading one image with multiple faces
- // or a vector of images representing the faces
- size_t faces;
- if(mTextureData.size() > 1)
- faces = mTextureData.size();
- else
- faces = 1;
- // Check wether number of faces in images exceeds number of faces
- // in this texture. If so, clamp it.
- if(faces > getNumFaces())
- faces = getNumFaces();
- // Main loading loop
- // imageMips == 0 if the image has no custom mipmaps, otherwise contains the number of custom mips
- for(size_t mip = 0; mip<=imageMips; ++mip)
- {
- for(size_t i = 0; i < faces; ++i)
- {
- PixelData src = mTextureData[i]->getPixels(mip);
- // Sets to treated format in case is difference
- src.format = mSrcFormat;
- if(mGamma != 1.0f) {
- // Apply gamma correction
- // Do not overwrite original image but do gamma correction in temporary buffer
- MemoryDataStreamPtr buf(new MemoryDataStream(
- PixelUtil::getMemorySize(
- src.getWidth(), src.getHeight(), src.getDepth(), src.format)));
- PixelData corrected = PixelData(src.getWidth(), src.getHeight(), src.getDepth(), src.format, buf->getPtr());
- PixelUtil::bulkPixelConversion(src, corrected);
- PixelUtil::applyGamma(static_cast<UINT8*>(corrected.data), mGamma, corrected.getConsecutiveSize(),
- static_cast<UINT8>(PixelUtil::getNumElemBits(src.format)));
- // Destination: entire texture. blitFromMemory does the scaling to
- // a power of two for us when needed
- getBuffer(i, mip)->blitFromMemory(corrected);
- }
- else
- {
- // Destination: entire texture. blitFromMemory does the scaling to
- // a power of two for us when needed
- getBuffer(i, mip)->blitFromMemory(src);
- }
- }
- }
- // Update size (the final size, not including temp space)
- mSize = getNumFaces() * PixelUtil::getMemorySize(mWidth, mHeight, mDepth, mFormat);
- }
- //-----------------------------------------------------------------------------
- void Texture::unloadImpl(void)
- {
- freeInternalResources();
- }
- //-----------------------------------------------------------------------------
- void Texture::copyToTexture( TexturePtr& target )
- {
- if(target->getNumFaces() != getNumFaces())
- {
- CM_EXCEPT(InvalidParametersException,
- "Texture types must match");
- }
- size_t numMips = std::min(getNumMipmaps(), target->getNumMipmaps());
- if((mUsage & TU_AUTOMIPMAP) || (target->getUsage()&TU_AUTOMIPMAP))
- numMips = 0;
- for(unsigned int face=0; face<getNumFaces(); face++)
- {
- for(unsigned int mip=0; mip<=numMips; mip++)
- {
- target->getBuffer(face, mip)->blit(getBuffer(face, mip));
- }
- }
- }
- /************************************************************************/
- /* SERIALIZATION */
- /************************************************************************/
- SerializableType* Texture::getSerializable() const
- {
- static TextureST serializableType;
- return &serializableType;
- }
- Texture* Texture::newObject()
- {
- CM_EXCEPT(InternalErrorException, "Cannot instantiate abstract class!");
- }
- }
|