gfxD3D11TextureObject.cpp 8.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281
  1. //-----------------------------------------------------------------------------
  2. // Copyright (c) 2015 GarageGames, LLC
  3. //
  4. // Permission is hereby granted, free of charge, to any person obtaining a copy
  5. // of this software and associated documentation files (the "Software"), to
  6. // deal in the Software without restriction, including without limitation the
  7. // rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
  8. // sell copies of the Software, and to permit persons to whom the Software is
  9. // furnished to do so, subject to the following conditions:
  10. //
  11. // The above copyright notice and this permission notice shall be included in
  12. // all copies or substantial portions of the Software.
  13. //
  14. // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
  15. // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
  16. // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
  17. // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
  18. // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
  19. // FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
  20. // IN THE SOFTWARE.
  21. //-----------------------------------------------------------------------------
  22. #include "gfx/D3D11/gfxD3D11Device.h"
  23. #include "gfx/D3D11/gfxD3D11TextureObject.h"
  24. #include "platform/profiler.h"
  25. #include "console/console.h"
  26. #ifdef TORQUE_DEBUG
  27. U32 GFXD3D11TextureObject::mTexCount = 0;
  28. #endif
  29. // GFXFormatR8G8B8 has now the same behaviour as GFXFormatR8G8B8X8.
  30. // This is because 24 bit format are now deprecated by microsoft, for data alignment reason there's no changes beetween 24 and 32 bit formats.
  31. // DirectX 10-11 both have 24 bit format no longer.
  32. GFXD3D11TextureObject::GFXD3D11TextureObject( GFXDevice * d, GFXTextureProfile *profile) : GFXTextureObject( d, profile )
  33. {
  34. #ifdef D3D11_DEBUG_SPEW
  35. mTexCount++;
  36. Con::printf("+ texMake %d %x", mTexCount, this);
  37. #endif
  38. mD3DTexture = NULL;
  39. mLocked = false;
  40. mD3DSurface = NULL;
  41. mLockedSubresource = 0;
  42. mDSView = NULL;
  43. mRTView = NULL;
  44. mSRView = NULL;
  45. }
  46. GFXD3D11TextureObject::~GFXD3D11TextureObject()
  47. {
  48. kill();
  49. #ifdef D3D11_DEBUG_SPEW
  50. mTexCount--;
  51. Con::printf("+ texkill %d %x", mTexCount, this);
  52. #endif
  53. }
  54. GFXLockedRect *GFXD3D11TextureObject::lock(U32 mipLevel /*= 0*/, RectI *inRect /*= NULL*/)
  55. {
  56. AssertFatal( !mLocked, "GFXD3D11TextureObject::lock - The texture is already locked!" );
  57. D3D11_MAPPED_SUBRESOURCE mapInfo;
  58. if( mProfile->isRenderTarget() )
  59. {
  60. //AssertFatal( 0, "GFXD3D11TextureObject::lock - Need to handle mapping render targets" );
  61. if( !mLockTex ||
  62. mLockTex->getWidth() != getWidth() ||
  63. mLockTex->getHeight() != getHeight() )
  64. {
  65. mLockTex.set( getWidth(), getHeight(), mFormat, &GFXSystemMemTextureProfile, avar("%s() - mLockTex (line %d)", __FUNCTION__, __LINE__) );
  66. }
  67. PROFILE_START(GFXD3D11TextureObject_lockRT);
  68. GFXD3D11Device* dev = D3D11;
  69. GFXD3D11TextureObject* to = (GFXD3D11TextureObject*) &(*mLockTex);
  70. dev->getDeviceContext()->CopyResource(to->get2DTex(), mD3DTexture);
  71. mLockedSubresource = D3D11CalcSubresource(0, 0, 1);
  72. HRESULT hr = dev->getDeviceContext()->Map(to->get2DTex(), mLockedSubresource, D3D11_MAP_READ, 0, &mapInfo);
  73. if (FAILED(hr))
  74. AssertFatal(false, "GFXD3D11TextureObject:lock- failed to map render target resource!");
  75. mLocked = true;
  76. PROFILE_END();
  77. }
  78. else
  79. {
  80. RECT r;
  81. if(inRect)
  82. {
  83. r.top = inRect->point.y;
  84. r.left = inRect->point.x;
  85. r.bottom = inRect->point.y + inRect->extent.y;
  86. r.right = inRect->point.x + inRect->extent.x;
  87. }
  88. mLockedSubresource = D3D11CalcSubresource(mipLevel, 0, getMipLevels());
  89. HRESULT hr = D3D11DEVICECONTEXT->Map(mD3DTexture, mLockedSubresource, D3D11_MAP_WRITE_DISCARD, 0, &mapInfo);
  90. if ( FAILED(hr) )
  91. AssertFatal(false, "GFXD3D11TextureObject::lock - Failed to map subresource.");
  92. mLocked = true;
  93. }
  94. mLockRect.pBits = static_cast<U8*>(mapInfo.pData);
  95. mLockRect.Pitch = mapInfo.RowPitch;
  96. return (GFXLockedRect*)&mLockRect;
  97. }
  98. void GFXD3D11TextureObject::unlock(U32 mipLevel)
  99. {
  100. AssertFatal( mLocked, "GFXD3D11TextureObject::unlock - Attempting to unlock a surface that has not been locked" );
  101. if( mProfile->isRenderTarget() )
  102. {
  103. //AssertFatal( 0, "GFXD3D11TextureObject::unlock - Need to handle mapping render targets" );
  104. GFXD3D11TextureObject* to = (GFXD3D11TextureObject*)&(*mLockTex);
  105. D3D11->getDeviceContext()->Unmap(to->get2DTex(), mLockedSubresource);
  106. mLockedSubresource = 0;
  107. mLocked = false;
  108. }
  109. else
  110. {
  111. D3D11DEVICECONTEXT->Unmap(get2DTex(), mLockedSubresource);
  112. mLockedSubresource = 0;
  113. mLocked = false;
  114. }
  115. }
  116. void GFXD3D11TextureObject::release()
  117. {
  118. SAFE_RELEASE(mSRView);
  119. SAFE_RELEASE(mRTView);
  120. SAFE_RELEASE(mDSView);
  121. SAFE_RELEASE(mD3DTexture);
  122. SAFE_RELEASE(mD3DSurface);
  123. }
  124. void GFXD3D11TextureObject::zombify()
  125. {
  126. // Managed textures are managed by D3D
  127. AssertFatal(!mLocked, "GFXD3D11TextureObject::zombify - Cannot zombify a locked texture!");
  128. if(isManaged)
  129. return;
  130. release();
  131. }
  132. void GFXD3D11TextureObject::resurrect()
  133. {
  134. // Managed textures are managed by D3D
  135. if(isManaged)
  136. return;
  137. static_cast<GFXD3D11TextureManager*>(TEXMGR)->refreshTexture(this);
  138. }
  139. bool GFXD3D11TextureObject::copyToBmp(GBitmap* bmp)
  140. {
  141. if (!bmp)
  142. return false;
  143. // check format limitations
  144. // at the moment we only support RGBA for the source (other 4 byte formats should
  145. // be easy to add though)
  146. AssertFatal(mFormat == GFXFormatR8G8B8A8 || mFormat == GFXFormatR8G8B8A8_LINEAR_FORCE || mFormat == GFXFormatR8G8B8A8_SRGB, "copyToBmp: invalid format");
  147. if (mFormat != GFXFormatR8G8B8A8 && mFormat != GFXFormatR8G8B8A8_LINEAR_FORCE && mFormat != GFXFormatR8G8B8A8_SRGB)
  148. return false;
  149. PROFILE_START(GFXD3D11TextureObject_copyToBmp);
  150. AssertFatal(bmp->getWidth() == getWidth(), "doh");
  151. AssertFatal(bmp->getHeight() == getHeight(), "doh");
  152. U32 width = getWidth();
  153. U32 height = getHeight();
  154. bmp->setHasTransparency(mHasTransparency);
  155. // set some constants
  156. const U32 sourceBytesPerPixel = 4;
  157. U32 destBytesPerPixel = 0;
  158. const GFXFormat fmt = bmp->getFormat();
  159. if (fmt == GFXFormatR8G8B8A8 || fmt == GFXFormatR8G8B8A8_LINEAR_FORCE || fmt == GFXFormatR8G8B8A8_SRGB)
  160. destBytesPerPixel = 4;
  161. else if(bmp->getFormat() == GFXFormatR8G8B8)
  162. destBytesPerPixel = 3;
  163. else
  164. // unsupported
  165. AssertFatal(false, "unsupported bitmap format");
  166. // lock the texture
  167. DXGI_MAPPED_RECT* lockRect = (DXGI_MAPPED_RECT*) lock();
  168. // set pointers
  169. U8* srcPtr = (U8*)lockRect->pBits;
  170. U8* destPtr = bmp->getWritableBits();
  171. // we will want to skip over any D3D cache data in the source texture
  172. const S32 sourceCacheSize = lockRect->Pitch - width * sourceBytesPerPixel;
  173. AssertFatal(sourceCacheSize >= 0, "copyToBmp: cache size is less than zero?");
  174. PROFILE_START(GFXD3D11TextureObject_copyToBmp_pixCopy);
  175. // copy data into bitmap
  176. for (U32 row = 0; row < height; ++row)
  177. {
  178. for (U32 col = 0; col < width; ++col)
  179. {
  180. destPtr[0] = srcPtr[2]; // red
  181. destPtr[1] = srcPtr[1]; // green
  182. destPtr[2] = srcPtr[0]; // blue
  183. if (destBytesPerPixel == 4)
  184. destPtr[3] = srcPtr[3]; // alpha
  185. // go to next pixel in src
  186. srcPtr += sourceBytesPerPixel;
  187. // go to next pixel in dest
  188. destPtr += destBytesPerPixel;
  189. }
  190. // skip past the cache data for this row (if any)
  191. srcPtr += sourceCacheSize;
  192. }
  193. PROFILE_END();
  194. // assert if we stomped or underran memory
  195. AssertFatal(U32(destPtr - bmp->getWritableBits()) == width * height * destBytesPerPixel, "copyToBmp: doh, memory error");
  196. AssertFatal(U32(srcPtr - (U8*)lockRect->pBits) == height * lockRect->Pitch, "copyToBmp: doh, memory error");
  197. // unlock
  198. unlock();
  199. PROFILE_END();
  200. return true;
  201. }
  202. ID3D11ShaderResourceView* GFXD3D11TextureObject::getSRView()
  203. {
  204. return mSRView;
  205. }
  206. ID3D11RenderTargetView* GFXD3D11TextureObject::getRTView()
  207. {
  208. return mRTView;
  209. }
  210. ID3D11DepthStencilView* GFXD3D11TextureObject::getDSView()
  211. {
  212. return mDSView;
  213. }
  214. ID3D11ShaderResourceView** GFXD3D11TextureObject::getSRViewPtr()
  215. {
  216. return &mSRView;
  217. }
  218. ID3D11RenderTargetView** GFXD3D11TextureObject::getRTViewPtr()
  219. {
  220. return &mRTView;
  221. }
  222. ID3D11DepthStencilView** GFXD3D11TextureObject::getDSViewPtr()
  223. {
  224. return &mDSView;
  225. }