BsTextureRTTI.h 6.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190
  1. //********************************** Banshee Engine (www.banshee3d.com) **************************************************//
  2. //**************** Copyright (c) 2016 Marko Pintera ([email protected]). All rights reserved. **********************//
  3. #pragma once
  4. #include "BsCorePrerequisites.h"
  5. #include "BsRTTIType.h"
  6. #include "BsTexture.h"
  7. #include "BsMath.h"
  8. #include "BsCoreThread.h"
  9. #include "BsRenderAPI.h"
  10. #include "BsTextureManager.h"
  11. #include "BsPixelData.h"
  12. namespace BansheeEngine
  13. {
  14. /** @cond RTTI */
  15. /** @addtogroup RTTI-Impl-Core
  16. * @{
  17. */
  18. class BS_CORE_EXPORT TextureRTTI : public RTTIType<Texture, Resource, TextureRTTI>
  19. {
  20. private:
  21. UINT32& getSize(Texture* obj) { return obj->mSize; }
  22. void setSize(Texture* obj, UINT32& val) { obj->mSize = val; }
  23. UINT32& getWidth(Texture* obj) { return obj->mProperties.mWidth; }
  24. void setWidth(Texture* obj, UINT32& val) { obj->mProperties.mWidth = val; }
  25. UINT32& getHeight(Texture* obj) { return obj->mProperties.mHeight; }
  26. void setHeight(Texture* obj, UINT32& val) { obj->mProperties.mHeight = val; }
  27. UINT32& getDepth(Texture* obj) { return obj->mProperties.mDepth; }
  28. void setDepth(Texture* obj, UINT32& val) { obj->mProperties.mDepth = val; }
  29. UINT32& getNumMipmaps(Texture* obj) { return obj->mProperties.mNumMipmaps; }
  30. void setNumMipmaps(Texture* obj, UINT32& val) { obj->mProperties.mNumMipmaps = val; }
  31. bool& getHwGamma(Texture* obj) { return obj->mProperties.mHwGamma; }
  32. void setHwGamma(Texture* obj, bool& val) { obj->mProperties.mHwGamma = val; }
  33. UINT32& getMultisampleCount(Texture* obj) { return obj->mProperties.mMultisampleCount; }
  34. void setMultisampleCount(Texture* obj, UINT32& val) { obj->mProperties.mMultisampleCount = val; }
  35. TextureType& getTextureType(Texture* obj) { return obj->mProperties.mTextureType; }
  36. void setTextureType(Texture* obj, TextureType& val) { obj->mProperties.mTextureType = val; }
  37. PixelFormat& getFormat(Texture* obj) { return obj->mProperties.mFormat; }
  38. void setFormat(Texture* obj, PixelFormat& val) { obj->mProperties.mFormat = val; }
  39. INT32& getUsage(Texture* obj) { return obj->mProperties.mUsage; }
  40. void setUsage(Texture* obj, INT32& val)
  41. {
  42. // Render target and depth stencil texture formats are for in-memory use only
  43. // and don't make sense when serialized
  44. if (val == TU_DEPTHSTENCIL || val == TU_RENDERTARGET)
  45. obj->mProperties.mUsage = TU_STATIC;
  46. else
  47. obj->mProperties.mUsage = val;
  48. }
  49. #define BS_ADD_PLAINFIELD(name, id, parentType) \
  50. addPlainField(#name, id##, &##parentType##::get##name, &##parentType##::Set##name);
  51. SPtr<PixelData> getPixelData(Texture* obj, UINT32 idx)
  52. {
  53. UINT32 face = (size_t)Math::floor(idx / (float)(obj->mProperties.getNumMipmaps() + 1));
  54. UINT32 mipmap = idx % (obj->mProperties.getNumMipmaps() + 1);
  55. UINT32 subresourceIdx = obj->mProperties.mapToSubresourceIdx(face, mipmap);
  56. SPtr<PixelData> pixelData = obj->mProperties.allocateSubresourceBuffer(subresourceIdx);
  57. obj->readSubresource(gCoreAccessor(), subresourceIdx, pixelData);
  58. gCoreAccessor().submitToCoreThread(true);
  59. return pixelData;
  60. }
  61. void setPixelData(Texture* obj, UINT32 idx, SPtr<PixelData> data)
  62. {
  63. Vector<SPtr<PixelData>>* pixelData = any_cast<Vector<SPtr<PixelData>>*>(obj->mRTTIData);
  64. (*pixelData)[idx] = data;
  65. }
  66. UINT32 getPixelDataArraySize(Texture* obj)
  67. {
  68. return obj->mProperties.getNumFaces() * (obj->mProperties.getNumMipmaps() + 1);
  69. }
  70. void setPixelDataArraySize(Texture* obj, UINT32 size)
  71. {
  72. Vector<SPtr<PixelData>>* pixelData = any_cast<Vector<SPtr<PixelData>>*>(obj->mRTTIData);
  73. pixelData->resize(size);
  74. }
  75. public:
  76. TextureRTTI()
  77. {
  78. addPlainField("mSize", 0, &TextureRTTI::getSize, &TextureRTTI::setSize);
  79. addPlainField("mHeight", 2, &TextureRTTI::getHeight, &TextureRTTI::setHeight);
  80. addPlainField("mWidth", 3, &TextureRTTI::getWidth, &TextureRTTI::setWidth);
  81. addPlainField("mDepth", 4, &TextureRTTI::getDepth, &TextureRTTI::setDepth);
  82. addPlainField("mNumMipmaps", 5, &TextureRTTI::getNumMipmaps, &TextureRTTI::setNumMipmaps);
  83. addPlainField("mHwGamma", 6, &TextureRTTI::getHwGamma, &TextureRTTI::setHwGamma);
  84. addPlainField("mMultisampleCount", 7, &TextureRTTI::getMultisampleCount, &TextureRTTI::setMultisampleCount);
  85. addPlainField("mTextureType", 9, &TextureRTTI::getTextureType, &TextureRTTI::setTextureType);
  86. addPlainField("mFormat", 10, &TextureRTTI::getFormat, &TextureRTTI::setFormat);
  87. addPlainField("mUsage", 11, &TextureRTTI::getUsage, &TextureRTTI::setUsage);
  88. addReflectablePtrArrayField("mPixelData", 12, &TextureRTTI::getPixelData, &TextureRTTI::getPixelDataArraySize,
  89. &TextureRTTI::setPixelData, &TextureRTTI::setPixelDataArraySize, RTTI_Flag_SkipInReferenceSearch);
  90. }
  91. void onDeserializationStarted(IReflectable* obj, const UnorderedMap<String, UINT64>& params) override
  92. {
  93. Texture* texture = static_cast<Texture*>(obj);
  94. texture->mRTTIData = bs_new<Vector<SPtr<PixelData>>>();
  95. }
  96. void onDeserializationEnded(IReflectable* obj, const UnorderedMap<String, UINT64>& params) override
  97. {
  98. Texture* texture = static_cast<Texture*>(obj);
  99. if(texture->mRTTIData.empty())
  100. return;
  101. TextureProperties& texProps = texture->mProperties;
  102. // Update pixel format if needed as it's possible the original texture was saved using some other render API
  103. // that has an unsupported format.
  104. PixelFormat originalFormat = texProps.mFormat;
  105. PixelFormat validFormat = TextureManager::instance().getNativeFormat(
  106. texProps.mTextureType, texProps.mFormat, texProps.mUsage, texProps.mHwGamma);
  107. Vector<SPtr<PixelData>>* pixelData = any_cast<Vector<SPtr<PixelData>>*>(texture->mRTTIData);
  108. if (originalFormat != validFormat)
  109. {
  110. texProps.mFormat = validFormat;
  111. for (size_t i = 0; i < pixelData->size(); i++)
  112. {
  113. SPtr<PixelData> origData = pixelData->at(i);
  114. SPtr<PixelData> newData = PixelData::create(origData->getWidth(), origData->getHeight(), origData->getDepth(), validFormat);
  115. PixelUtil::bulkPixelConversion(*origData, *newData);
  116. (*pixelData)[i] = newData;
  117. }
  118. }
  119. // A bit clumsy initializing with already set values, but I feel its better than complicating things and storing the values
  120. // in mRTTIData.
  121. texture->initialize();
  122. for(size_t i = 0; i < pixelData->size(); i++)
  123. {
  124. UINT32 face = (size_t)Math::floor(i / (float)(texProps.getNumMipmaps() + 1));
  125. UINT32 mipmap = i % (texProps.getNumMipmaps() + 1);
  126. UINT32 subresourceIdx = texProps.mapToSubresourceIdx(face, mipmap);
  127. texture->writeSubresource(gCoreAccessor(), subresourceIdx, pixelData->at(i), false);
  128. }
  129. bs_delete(pixelData);
  130. texture->mRTTIData = nullptr;
  131. }
  132. const String& getRTTIName() override
  133. {
  134. static String name = "Texture";
  135. return name;
  136. }
  137. UINT32 getRTTIId() override
  138. {
  139. return TID_Texture;
  140. }
  141. SPtr<IReflectable> newRTTIObject() override
  142. {
  143. return TextureManager::instance()._createEmpty();
  144. }
  145. };
  146. /** @} */
  147. /** @endcond */
  148. }