BsTextureRTTI.h 5.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184
  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. BS_BEGIN_RTTI_MEMBERS
  22. BS_RTTI_MEMBER_PLAIN(mSize, 0)
  23. BS_RTTI_MEMBER_PLAIN_NAMED(height, mProperties.mDesc.height, 2)
  24. BS_RTTI_MEMBER_PLAIN_NAMED(width, mProperties.mDesc.width, 3)
  25. BS_RTTI_MEMBER_PLAIN_NAMED(depth, mProperties.mDesc.depth, 4)
  26. BS_RTTI_MEMBER_PLAIN_NAMED(numMips, mProperties.mDesc.numMips, 5)
  27. BS_RTTI_MEMBER_PLAIN_NAMED(hwGamma, mProperties.mDesc.hwGamma, 6)
  28. BS_RTTI_MEMBER_PLAIN_NAMED(numSamples, mProperties.mDesc.numSamples, 7)
  29. BS_RTTI_MEMBER_PLAIN_NAMED(type, mProperties.mDesc.type, 9)
  30. BS_RTTI_MEMBER_PLAIN_NAMED(format, mProperties.mDesc.format, 10)
  31. BS_END_RTTI_MEMBERS
  32. INT32& getUsage(Texture* obj) { return obj->mProperties.mDesc.usage; }
  33. void setUsage(Texture* obj, INT32& val)
  34. {
  35. // Render target and depth stencil texture formats are for in-memory use only
  36. // and don't make sense when serialized
  37. if ((val & (TU_DEPTHSTENCIL | TU_RENDERTARGET)) != 0)
  38. {
  39. obj->mProperties.mDesc.usage &= ~(TU_DEPTHSTENCIL | TU_RENDERTARGET);
  40. obj->mProperties.mDesc.usage |= TU_STATIC;
  41. }
  42. else
  43. obj->mProperties.mDesc.usage = val;
  44. }
  45. #define BS_ADD_PLAINFIELD(name, id, parentType) \
  46. addPlainField(#name, id##, &##parentType##::get##name, &##parentType##::Set##name);
  47. SPtr<PixelData> getPixelData(Texture* obj, UINT32 idx)
  48. {
  49. UINT32 face = (size_t)Math::floor(idx / (float)(obj->mProperties.getNumMipmaps() + 1));
  50. UINT32 mipmap = idx % (obj->mProperties.getNumMipmaps() + 1);
  51. UINT32 subresourceIdx = obj->mProperties.mapToSubresourceIdx(face, mipmap);
  52. SPtr<PixelData> pixelData = obj->mProperties.allocateSubresourceBuffer(subresourceIdx);
  53. int usage = obj->getProperties().getUsage();
  54. if (usage & TU_CPUREADABLE || BS_EDITOR_BUILD)
  55. {
  56. obj->readSubresource(gCoreAccessor(), subresourceIdx, pixelData);
  57. gCoreAccessor().submitToCoreThread(true);
  58. return pixelData;
  59. }
  60. if(usage & TU_CPUCACHED)
  61. {
  62. obj->readData(*pixelData, mipmap, face);
  63. return pixelData;
  64. }
  65. LOGERR("Attempting to save a texture that isn't flagged with either TU_CPUCACHED OR TU_GPUREADABLE flags.");
  66. return pixelData;
  67. }
  68. void setPixelData(Texture* obj, UINT32 idx, SPtr<PixelData> data)
  69. {
  70. Vector<SPtr<PixelData>>* pixelData = any_cast<Vector<SPtr<PixelData>>*>(obj->mRTTIData);
  71. (*pixelData)[idx] = data;
  72. }
  73. UINT32 getPixelDataArraySize(Texture* obj)
  74. {
  75. return obj->mProperties.getNumFaces() * (obj->mProperties.getNumMipmaps() + 1);
  76. }
  77. void setPixelDataArraySize(Texture* obj, UINT32 size)
  78. {
  79. Vector<SPtr<PixelData>>* pixelData = any_cast<Vector<SPtr<PixelData>>*>(obj->mRTTIData);
  80. pixelData->resize(size);
  81. }
  82. public:
  83. TextureRTTI()
  84. :mInitMembers(this)
  85. {
  86. addPlainField("mUsage", 11, &TextureRTTI::getUsage, &TextureRTTI::setUsage);
  87. addReflectablePtrArrayField("mPixelData", 12, &TextureRTTI::getPixelData, &TextureRTTI::getPixelDataArraySize,
  88. &TextureRTTI::setPixelData, &TextureRTTI::setPixelDataArraySize, RTTI_Flag_SkipInReferenceSearch);
  89. }
  90. void onDeserializationStarted(IReflectable* obj, const UnorderedMap<String, UINT64>& params) override
  91. {
  92. Texture* texture = static_cast<Texture*>(obj);
  93. texture->mRTTIData = bs_new<Vector<SPtr<PixelData>>>();
  94. }
  95. void onDeserializationEnded(IReflectable* obj, const UnorderedMap<String, UINT64>& params) override
  96. {
  97. Texture* texture = static_cast<Texture*>(obj);
  98. if(texture->mRTTIData.empty())
  99. return;
  100. TextureProperties& texProps = texture->mProperties;
  101. // Update pixel format if needed as it's possible the original texture was saved using some other render API
  102. // that has an unsupported format.
  103. PixelFormat originalFormat = texProps.getFormat();
  104. PixelFormat validFormat = TextureManager::instance().getNativeFormat(
  105. texProps.getTextureType(), texProps.getFormat(), texProps.getUsage(), texProps.isHardwareGammaEnabled());
  106. Vector<SPtr<PixelData>>* pixelData = any_cast<Vector<SPtr<PixelData>>*>(texture->mRTTIData);
  107. if (originalFormat != validFormat)
  108. {
  109. texProps.mDesc.format = validFormat;
  110. for (size_t i = 0; i < pixelData->size(); i++)
  111. {
  112. SPtr<PixelData> origData = pixelData->at(i);
  113. SPtr<PixelData> newData = PixelData::create(origData->getWidth(), origData->getHeight(), origData->getDepth(), validFormat);
  114. PixelUtil::bulkPixelConversion(*origData, *newData);
  115. (*pixelData)[i] = newData;
  116. }
  117. }
  118. // A bit clumsy initializing with already set values, but I feel its better than complicating things and storing the values
  119. // in mRTTIData.
  120. texture->initialize();
  121. for(size_t i = 0; i < pixelData->size(); i++)
  122. {
  123. UINT32 face = (size_t)Math::floor(i / (float)(texProps.getNumMipmaps() + 1));
  124. UINT32 mipmap = i % (texProps.getNumMipmaps() + 1);
  125. UINT32 subresourceIdx = texProps.mapToSubresourceIdx(face, mipmap);
  126. texture->writeSubresource(gCoreAccessor(), subresourceIdx, pixelData->at(i), false);
  127. }
  128. bs_delete(pixelData);
  129. texture->mRTTIData = nullptr;
  130. }
  131. const String& getRTTIName() override
  132. {
  133. static String name = "Texture";
  134. return name;
  135. }
  136. UINT32 getRTTIId() override
  137. {
  138. return TID_Texture;
  139. }
  140. SPtr<IReflectable> newRTTIObject() override
  141. {
  142. return TextureManager::instance()._createEmpty();
  143. }
  144. };
  145. /** @} */
  146. /** @endcond */
  147. }