CmTexture.cpp 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322
  1. /*
  2. -----------------------------------------------------------------------------
  3. This source file is part of OGRE
  4. (Object-oriented Graphics Rendering Engine)
  5. For the latest info, see http://www.ogre3d.org/
  6. Copyright (c) 2000-2011 Torus Knot Software Ltd
  7. Permission is hereby granted, free of charge, to any person obtaining a copy
  8. of this software and associated documentation files (the "Software"), to deal
  9. in the Software without restriction, including without limitation the rights
  10. to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
  11. copies of the Software, and to permit persons to whom the Software is
  12. furnished to do so, subject to the following conditions:
  13. The above copyright notice and this permission notice shall be included in
  14. all copies or substantial portions of the Software.
  15. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
  16. IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
  17. FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
  18. AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
  19. LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
  20. OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
  21. THE SOFTWARE.
  22. -----------------------------------------------------------------------------
  23. */
  24. #include "CmHardwarePixelBuffer.h"
  25. #include "CmTexture.h"
  26. #include "CmTextureST.h"
  27. #include "CmTextureData.h"
  28. #include "CmDataStream.h"
  29. #include "CmException.h"
  30. #include "CmDebug.h"
  31. namespace CamelotEngine {
  32. //--------------------------------------------------------------------------
  33. Texture::Texture()
  34. : // init defaults; can be overridden before load()
  35. mHeight(512),
  36. mWidth(512),
  37. mDepth(1),
  38. mNumRequestedMipmaps(0),
  39. mNumMipmaps(0),
  40. mMipmapsHardwareGenerated(false),
  41. mGamma(1.0f),
  42. mHwGamma(false),
  43. mFSAA(0),
  44. mTextureType(TEX_TYPE_2D),
  45. mFormat(PF_UNKNOWN),
  46. mUsage(TU_DEFAULT),
  47. mSrcFormat(PF_UNKNOWN),
  48. mSrcWidth(0),
  49. mSrcHeight(0),
  50. mSrcDepth(0),
  51. mDesiredFormat(PF_UNKNOWN),
  52. mDesiredIntegerBitDepth(0),
  53. mDesiredFloatBitDepth(0),
  54. mInternalResourcesCreated(false)
  55. {
  56. }
  57. //--------------------------------------------------------------------------
  58. void Texture::setFormat(PixelFormat pf)
  59. {
  60. mFormat = pf;
  61. mDesiredFormat = pf;
  62. mSrcFormat = pf;
  63. }
  64. //--------------------------------------------------------------------------
  65. bool Texture::hasAlpha(void) const
  66. {
  67. return PixelUtil::hasAlpha(mFormat);
  68. }
  69. //--------------------------------------------------------------------------
  70. void Texture::setDesiredIntegerBitDepth(UINT16 bits)
  71. {
  72. mDesiredIntegerBitDepth = bits;
  73. }
  74. //--------------------------------------------------------------------------
  75. UINT16 Texture::getDesiredIntegerBitDepth(void) const
  76. {
  77. return mDesiredIntegerBitDepth;
  78. }
  79. //--------------------------------------------------------------------------
  80. void Texture::setDesiredFloatBitDepth(UINT16 bits)
  81. {
  82. mDesiredFloatBitDepth = bits;
  83. }
  84. //--------------------------------------------------------------------------
  85. UINT16 Texture::getDesiredFloatBitDepth(void) const
  86. {
  87. return mDesiredFloatBitDepth;
  88. }
  89. //--------------------------------------------------------------------------
  90. void Texture::setDesiredBitDepths(UINT16 integerBits, UINT16 floatBits)
  91. {
  92. mDesiredIntegerBitDepth = integerBits;
  93. mDesiredFloatBitDepth = floatBits;
  94. }
  95. //--------------------------------------------------------------------------
  96. size_t Texture::calculateSize(void) const
  97. {
  98. return getNumFaces() * PixelUtil::getMemorySize(mWidth, mHeight, mDepth, mFormat);
  99. }
  100. //--------------------------------------------------------------------------
  101. size_t Texture::getNumFaces(void) const
  102. {
  103. return getTextureType() == TEX_TYPE_CUBE_MAP ? 6 : 1;
  104. }
  105. //-----------------------------------------------------------------------------
  106. void Texture::createInternalResources(void)
  107. {
  108. if (!mInternalResourcesCreated)
  109. {
  110. createInternalResourcesImpl();
  111. mInternalResourcesCreated = true;
  112. }
  113. }
  114. //-----------------------------------------------------------------------------
  115. void Texture::freeInternalResources(void)
  116. {
  117. if (mInternalResourcesCreated)
  118. {
  119. freeInternalResourcesImpl();
  120. mInternalResourcesCreated = false;
  121. }
  122. }
  123. //-----------------------------------------------------------------------------
  124. TextureDataPtr Texture::getTextureData(int face)
  125. {
  126. if(face < 0 || face >= getNumFaces())
  127. {
  128. CM_EXCEPT(InvalidParametersException, "Face index out of range: " + toString(face));
  129. }
  130. UINT32 numMips = getNumMipmaps();
  131. UINT32 totalSize = 0;
  132. UINT32 width = getWidth();
  133. UINT32 height = getHeight();
  134. UINT32 depth = getDepth();
  135. for(int j = 0; j < numMips; j++)
  136. {
  137. UINT32 currentMipSize = PixelUtil::getMemorySize(
  138. width, height, depth, mFormat);
  139. totalSize += currentMipSize;
  140. if(width != 1) width /= 2;
  141. if(height != 1) height /= 2;
  142. if(depth != 1) depth /= 2;
  143. }
  144. UINT8* buffer = new UINT8[totalSize]; // TextureData frees this
  145. TextureDataPtr texData(new TextureData(getWidth(), getHeight(), totalSize, mFormat, buffer, getDepth(), 0, getNumMipmaps()));
  146. for(int j = 0; j < numMips; j++)
  147. {
  148. PixelData pixels = texData->getPixels(j);
  149. getBuffer(face, j)->blitToMemory(pixels);
  150. }
  151. return texData;
  152. }
  153. //-----------------------------------------------------------------------------
  154. void Texture::setTextureData(int face, TextureDataPtr textureData)
  155. {
  156. if(face < 0 || face >= getNumFaces())
  157. {
  158. CM_EXCEPT(InvalidParametersException, "Face index out of range: " + toString(face));
  159. }
  160. if(mTextureData.size() <= face)
  161. mTextureData.resize(face + 1);
  162. mTextureData[face] = textureData;
  163. }
  164. //-----------------------------------------------------------------------------
  165. void Texture::initializeFromTextureData()
  166. {
  167. if(mTextureData.size() < 1)
  168. CM_EXCEPT(InvalidParametersException, "Cannot load empty vector of images");
  169. if(getTextureType() == TEX_TYPE_CUBE_MAP)
  170. {
  171. if(mTextureData.size() != 6)
  172. CM_EXCEPT(InvalidParametersException, "Cube map textures require six faces.");
  173. }
  174. else
  175. {
  176. if(mTextureData.size() > 1)
  177. {
  178. gDebug().log("Non-cube textures can only have one face. Loading only first face from the provided array.", "D3D9RenderSystem");
  179. }
  180. }
  181. // Set desired texture size and properties from images[0]
  182. mSrcWidth = mWidth = mTextureData[0]->getWidth();
  183. mSrcHeight = mHeight = mTextureData[0]->getHeight();
  184. mSrcDepth = mDepth = mTextureData[0]->getDepth();
  185. // Get source image format and adjust if required
  186. mSrcFormat = mTextureData[0]->getFormat();
  187. if (mDesiredFormat != PF_UNKNOWN)
  188. {
  189. // If have desired format, use it
  190. mFormat = mDesiredFormat;
  191. }
  192. else
  193. {
  194. // Get the format according with desired bit depth
  195. mFormat = PixelUtil::getFormatForBitDepths(mSrcFormat, mDesiredIntegerBitDepth, mDesiredFloatBitDepth);
  196. }
  197. // The custom mipmaps in the image have priority over everything
  198. size_t imageMips = mTextureData[0]->getNumMipmaps();
  199. if(imageMips > 0)
  200. {
  201. mNumMipmaps = mNumRequestedMipmaps = mTextureData[0]->getNumMipmaps();
  202. // Disable flag for auto mip generation
  203. mUsage &= ~TU_AUTOMIPMAP;
  204. }
  205. // Create the texture
  206. createInternalResources();
  207. // Check if we're loading one image with multiple faces
  208. // or a vector of images representing the faces
  209. size_t faces;
  210. if(mTextureData.size() > 1)
  211. faces = mTextureData.size();
  212. else
  213. faces = 1;
  214. // Check wether number of faces in images exceeds number of faces
  215. // in this texture. If so, clamp it.
  216. if(faces > getNumFaces())
  217. faces = getNumFaces();
  218. // Main loading loop
  219. // imageMips == 0 if the image has no custom mipmaps, otherwise contains the number of custom mips
  220. for(size_t mip = 0; mip<=imageMips; ++mip)
  221. {
  222. for(size_t i = 0; i < faces; ++i)
  223. {
  224. PixelData src = mTextureData[i]->getPixels(mip);
  225. // Sets to treated format in case is difference
  226. src.format = mSrcFormat;
  227. if(mGamma != 1.0f) {
  228. // Apply gamma correction
  229. // Do not overwrite original image but do gamma correction in temporary buffer
  230. MemoryDataStreamPtr buf(new MemoryDataStream(
  231. PixelUtil::getMemorySize(
  232. src.getWidth(), src.getHeight(), src.getDepth(), src.format)));
  233. PixelData corrected = PixelData(src.getWidth(), src.getHeight(), src.getDepth(), src.format, buf->getPtr());
  234. PixelUtil::bulkPixelConversion(src, corrected);
  235. PixelUtil::applyGamma(static_cast<UINT8*>(corrected.data), mGamma, corrected.getConsecutiveSize(),
  236. static_cast<UINT8>(PixelUtil::getNumElemBits(src.format)));
  237. // Destination: entire texture. blitFromMemory does the scaling to
  238. // a power of two for us when needed
  239. getBuffer(i, mip)->blitFromMemory(corrected);
  240. }
  241. else
  242. {
  243. // Destination: entire texture. blitFromMemory does the scaling to
  244. // a power of two for us when needed
  245. getBuffer(i, mip)->blitFromMemory(src);
  246. }
  247. }
  248. }
  249. // Update size (the final size, not including temp space)
  250. mSize = getNumFaces() * PixelUtil::getMemorySize(mWidth, mHeight, mDepth, mFormat);
  251. }
  252. //-----------------------------------------------------------------------------
  253. void Texture::unloadImpl(void)
  254. {
  255. freeInternalResources();
  256. }
  257. //-----------------------------------------------------------------------------
  258. void Texture::copyToTexture( TexturePtr& target )
  259. {
  260. if(target->getNumFaces() != getNumFaces())
  261. {
  262. CM_EXCEPT(InvalidParametersException,
  263. "Texture types must match");
  264. }
  265. size_t numMips = std::min(getNumMipmaps(), target->getNumMipmaps());
  266. if((mUsage & TU_AUTOMIPMAP) || (target->getUsage()&TU_AUTOMIPMAP))
  267. numMips = 0;
  268. for(unsigned int face=0; face<getNumFaces(); face++)
  269. {
  270. for(unsigned int mip=0; mip<=numMips; mip++)
  271. {
  272. target->getBuffer(face, mip)->blit(getBuffer(face, mip));
  273. }
  274. }
  275. }
  276. /************************************************************************/
  277. /* SERIALIZATION */
  278. /************************************************************************/
  279. SerializableType* Texture::getSerializable() const
  280. {
  281. static TextureST serializableType;
  282. return &serializableType;
  283. }
  284. Texture* Texture::newObject()
  285. {
  286. CM_EXCEPT(InternalErrorException, "Cannot instantiate abstract class!");
  287. }
  288. }