gfxD3D9TextureObject.cpp 8.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277
  1. //-----------------------------------------------------------------------------
  2. // Copyright (c) 2012 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/D3D9/gfxD3D9Device.h"
  23. #include "gfx/D3D9/gfxD3D9TextureObject.h"
  24. #include "platform/profiler.h"
  25. #ifdef TORQUE_OS_XENON
  26. #include "gfx/D3D9/360/gfx360Device.h"
  27. #include "gfx/D3D9/360/gfx360Target.h"
  28. #include "gfx/D3D9/gfxD3D9EnumTranslate.h"
  29. #endif
  30. U32 GFXD3D9TextureObject::mTexCount = 0;
  31. //*****************************************************************************
  32. // GFX D3D Texture Object
  33. //*****************************************************************************
  34. GFXD3D9TextureObject::GFXD3D9TextureObject( GFXDevice * d, GFXTextureProfile *profile)
  35. : GFXTextureObject( d, profile )
  36. {
  37. #ifdef D3D_TEXTURE_SPEW
  38. mTexCount++;
  39. Con::printf("+ texMake %d %x", mTexCount, this);
  40. #endif
  41. isManaged = false;
  42. mD3DTexture = NULL;
  43. mLocked = false;
  44. mD3DSurface = NULL;
  45. }
  46. //-----------------------------------------------------------------------------
  47. // Destructor
  48. //-----------------------------------------------------------------------------
  49. GFXD3D9TextureObject::~GFXD3D9TextureObject()
  50. {
  51. kill();
  52. #ifdef D3D_TEXTURE_SPEW
  53. mTexCount--;
  54. Con::printf("+ texkill %d %x", mTexCount, this);
  55. #endif
  56. }
  57. //-----------------------------------------------------------------------------
  58. // lock
  59. //-----------------------------------------------------------------------------
  60. GFXLockedRect *GFXD3D9TextureObject::lock(U32 mipLevel /*= 0*/, RectI *inRect /*= NULL*/)
  61. {
  62. AssertFatal( !mLocked, "GFXD3D9TextureObject::lock - The texture is already locked!" );
  63. if( mProfile->isRenderTarget() )
  64. {
  65. if( !mLockTex ||
  66. mLockTex->getWidth() != getWidth() ||
  67. mLockTex->getHeight() != getHeight() )
  68. {
  69. mLockTex.set( getWidth(), getHeight(), mFormat, &GFXSystemMemProfile, avar("%s() - mLockTex (line %d)", __FUNCTION__, __LINE__) );
  70. }
  71. PROFILE_START(GFXD3D9TextureObject_lockRT);
  72. IDirect3DSurface9 *source;
  73. D3D9Assert( get2DTex()->GetSurfaceLevel( 0, &source ), "GFXD3D9TextureObject::lock - failed to get our own texture's surface." );
  74. IDirect3DSurface9 *dest;
  75. GFXD3D9TextureObject *to = (GFXD3D9TextureObject *) &(*mLockTex);
  76. D3D9Assert( to->get2DTex()->GetSurfaceLevel( 0, &dest ), "GFXD3D9TextureObject::lock - failed to get dest texture's surface." );
  77. #ifndef TORQUE_OS_XENON
  78. LPDIRECT3DDEVICE9 D3DDevice = dynamic_cast<GFXD3D9Device *>(GFX)->getDevice();
  79. HRESULT rtLockRes = D3DDevice->GetRenderTargetData( source, dest );
  80. #else
  81. AssertFatal(false, "Use different functionality on the Xbox 360 to perform this task.");
  82. HRESULT rtLockRes = E_FAIL;
  83. #endif
  84. source->Release();
  85. if(!SUCCEEDED(rtLockRes))
  86. {
  87. // This case generally occurs if the device is lost. The lock failed
  88. // so clean up and return NULL.
  89. dest->Release();
  90. PROFILE_END();
  91. return NULL;
  92. }
  93. D3D9Assert( dest->LockRect( &mLockRect, NULL, D3DLOCK_READONLY ), NULL );
  94. dest->Release();
  95. mLocked = true;
  96. PROFILE_END();
  97. }
  98. else
  99. {
  100. RECT r;
  101. if(inRect)
  102. {
  103. r.top = inRect->point.y;
  104. r.left = inRect->point.x;
  105. r.bottom = inRect->point.y + inRect->extent.y;
  106. r.right = inRect->point.x + inRect->extent.x;
  107. }
  108. D3D9Assert( get2DTex()->LockRect(mipLevel, &mLockRect, inRect ? &r : NULL, 0),
  109. "GFXD3D9TextureObject::lock - could not lock non-RT texture!" );
  110. mLocked = true;
  111. }
  112. // GFXLockedRect is set up to correspond to D3DLOCKED_RECT, so this is ok.
  113. return (GFXLockedRect*)&mLockRect;
  114. }
  115. //-----------------------------------------------------------------------------
  116. // unLock
  117. //-----------------------------------------------------------------------------
  118. void GFXD3D9TextureObject::unlock(U32 mipLevel)
  119. {
  120. AssertFatal( mLocked, "GFXD3D9TextureObject::unlock - Attempting to unlock a surface that has not been locked" );
  121. #ifndef TORQUE_OS_XENON
  122. if( mProfile->isRenderTarget() )
  123. {
  124. IDirect3DSurface9 *dest;
  125. GFXD3D9TextureObject *to = (GFXD3D9TextureObject *) &(*mLockTex);
  126. D3D9Assert( to->get2DTex()->GetSurfaceLevel( 0, &dest ), NULL );
  127. dest->UnlockRect();
  128. dest->Release();
  129. mLocked = false;
  130. }
  131. else
  132. #endif
  133. {
  134. D3D9Assert( get2DTex()->UnlockRect(mipLevel),
  135. "GFXD3D9TextureObject::unlock - could not unlock non-RT texture." );
  136. mLocked = false;
  137. }
  138. }
  139. //------------------------------------------------------------------------------
  140. void GFXD3D9TextureObject::release()
  141. {
  142. static_cast<GFXD3D9Device *>( GFX )->destroyD3DResource( mD3DTexture );
  143. static_cast<GFXD3D9Device *>( GFX )->destroyD3DResource( mD3DSurface );
  144. mD3DTexture = NULL;
  145. mD3DSurface = NULL;
  146. }
  147. void GFXD3D9TextureObject::zombify()
  148. {
  149. // Managed textures are managed by D3D
  150. AssertFatal(!mLocked, "GFXD3D9TextureObject::zombify - Cannot zombify a locked texture!");
  151. if(isManaged)
  152. return;
  153. release();
  154. }
  155. void GFXD3D9TextureObject::resurrect()
  156. {
  157. // Managed textures are managed by D3D
  158. if(isManaged)
  159. return;
  160. static_cast<GFXD3D9TextureManager*>(TEXMGR)->refreshTexture(this);
  161. }
  162. //------------------------------------------------------------------------------
  163. bool GFXD3D9TextureObject::copyToBmp(GBitmap* bmp)
  164. {
  165. #ifdef TORQUE_OS_XENON
  166. // TODO: Implement Xenon version -patw
  167. return false;
  168. #else
  169. if (!bmp)
  170. return false;
  171. // check format limitations
  172. // at the moment we only support RGBA for the source (other 4 byte formats should
  173. // be easy to add though)
  174. AssertFatal(mFormat == GFXFormatR8G8B8A8 || mFormat == GFXFormatR8G8B8, "copyToBmp: invalid format");
  175. if (mFormat != GFXFormatR8G8B8A8 && mFormat != GFXFormatR8G8B8)
  176. return false;
  177. PROFILE_START(GFXD3D9TextureObject_copyToBmp);
  178. AssertFatal(bmp->getWidth() == getWidth(), "doh");
  179. AssertFatal(bmp->getHeight() == getHeight(), "doh");
  180. U32 width = getWidth();
  181. U32 height = getHeight();
  182. bmp->setHasTransparency(mHasTransparency);
  183. // set some constants
  184. const U32 sourceBytesPerPixel = 4;
  185. U32 destBytesPerPixel = 0;
  186. if (bmp->getFormat() == GFXFormatR8G8B8A8)
  187. destBytesPerPixel = 4;
  188. else if (bmp->getFormat() == GFXFormatR8G8B8)
  189. destBytesPerPixel = 3;
  190. else
  191. // unsupported
  192. AssertFatal(false, "unsupported bitmap format");
  193. // lock the texture
  194. D3DLOCKED_RECT* lockRect = (D3DLOCKED_RECT*) lock();
  195. // set pointers
  196. U8* srcPtr = (U8*)lockRect->pBits;
  197. U8* destPtr = bmp->getWritableBits();
  198. // we will want to skip over any D3D cache data in the source texture
  199. const S32 sourceCacheSize = lockRect->Pitch - width * sourceBytesPerPixel;
  200. AssertFatal(sourceCacheSize >= 0, "copyToBmp: cache size is less than zero?");
  201. PROFILE_START(GFXD3D9TextureObject_copyToBmp_pixCopy);
  202. // copy data into bitmap
  203. for (S32 row = 0; row < height; ++row)
  204. {
  205. for (S32 col = 0; col < width; ++col)
  206. {
  207. destPtr[0] = srcPtr[2]; // red
  208. destPtr[1] = srcPtr[1]; // green
  209. destPtr[2] = srcPtr[0]; // blue
  210. if (destBytesPerPixel == 4)
  211. destPtr[3] = srcPtr[3]; // alpha
  212. // go to next pixel in src
  213. srcPtr += sourceBytesPerPixel;
  214. // go to next pixel in dest
  215. destPtr += destBytesPerPixel;
  216. }
  217. // skip past the cache data for this row (if any)
  218. srcPtr += sourceCacheSize;
  219. }
  220. PROFILE_END();
  221. // assert if we stomped or underran memory
  222. AssertFatal(U32(destPtr - bmp->getWritableBits()) == width * height * destBytesPerPixel, "copyToBmp: doh, memory error");
  223. AssertFatal(U32(srcPtr - (U8*)lockRect->pBits) == height * lockRect->Pitch, "copyToBmp: doh, memory error");
  224. // unlock
  225. unlock();
  226. PROFILE_END();
  227. return true;
  228. #endif
  229. }