/Irrlicht/CD3D9Texture.cpp

http://myjeh.googlecode.com/ · C++ · 699 lines · 533 code · 113 blank · 53 comment · 108 complexity · 3a4feca75b378d87f7f5e5e7914473ef MD5 · raw file

  1. // Copyright (C) 2002-2010 Nikolaus Gebhardt
  2. // This file is part of the "Irrlicht Engine".
  3. // For conditions of distribution and use, see copyright notice in irrlicht.h
  4. #include "IrrCompileConfig.h"
  5. #ifdef _IRR_COMPILE_WITH_DIRECT3D_9_
  6. #define _IRR_DONT_DO_MEMORY_DEBUGGING_HERE
  7. #include "CD3D9Texture.h"
  8. #include "CD3D9Driver.h"
  9. #include "os.h"
  10. #include <d3dx9tex.h>
  11. #ifndef _IRR_COMPILE_WITH_DIRECT3D_8_
  12. // The D3DXFilterTexture function seems to get linked wrong when
  13. // compiling with both D3D8 and 9, causing it not to work in the D3D9 device.
  14. // So mipmapgeneration is replaced with my own bad generation in d3d 8 when
  15. // compiling with both D3D 8 and 9.
  16. // #define _IRR_USE_D3DXFilterTexture_
  17. #endif // _IRR_COMPILE_WITH_DIRECT3D_8_
  18. #ifdef _IRR_USE_D3DXFilterTexture_
  19. #pragma comment(lib, "d3dx9.lib")
  20. #endif
  21. namespace irr
  22. {
  23. namespace video
  24. {
  25. //! rendertarget constructor
  26. CD3D9Texture::CD3D9Texture(CD3D9Driver* driver, const core::dimension2d<u32>& size,
  27. const io::path& name, const ECOLOR_FORMAT format)
  28. : ITexture(name), Texture(0), RTTSurface(0), Driver(driver), DepthSurface(0),
  29. TextureSize(size), ImageSize(size), Pitch(0), ColorFormat(ECF_UNKNOWN),
  30. HasMipMaps(false), HardwareMipMaps(false), IsRenderTarget(true)
  31. {
  32. #ifdef _DEBUG
  33. setDebugName("CD3D9Texture");
  34. #endif
  35. Device=driver->getExposedVideoData().D3D9.D3DDev9;
  36. if (Device)
  37. Device->AddRef();
  38. createRenderTarget(format);
  39. }
  40. //! constructor
  41. CD3D9Texture::CD3D9Texture(IImage* image, CD3D9Driver* driver,
  42. u32 flags, const io::path& name, void* mipmapData)
  43. : ITexture(name), Texture(0), RTTSurface(0), Driver(driver), DepthSurface(0),
  44. TextureSize(0,0), ImageSize(0,0), Pitch(0), ColorFormat(ECF_UNKNOWN),
  45. HasMipMaps(false), HardwareMipMaps(false), IsRenderTarget(false)
  46. {
  47. #ifdef _DEBUG
  48. setDebugName("CD3D9Texture");
  49. #endif
  50. HasMipMaps = Driver->getTextureCreationFlag(video::ETCF_CREATE_MIP_MAPS);
  51. Device=driver->getExposedVideoData().D3D9.D3DDev9;
  52. if (Device)
  53. Device->AddRef();
  54. if (image)
  55. {
  56. if (createTexture(flags, image))
  57. {
  58. if (copyTexture(image))
  59. {
  60. regenerateMipMapLevels(mipmapData);
  61. }
  62. }
  63. else
  64. os::Printer::log("Could not create DIRECT3D9 Texture.", ELL_WARNING);
  65. }
  66. }
  67. //! destructor
  68. CD3D9Texture::~CD3D9Texture()
  69. {
  70. if (Texture)
  71. Texture->Release();
  72. if (RTTSurface)
  73. RTTSurface->Release();
  74. // if this texture was the last one using the depth buffer
  75. // we can release the surface. We only use the value of the pointer
  76. // hence it is safe to use the dropped pointer...
  77. if (DepthSurface)
  78. {
  79. if (DepthSurface->drop())
  80. Driver->removeDepthSurface(DepthSurface);
  81. }
  82. if (Device)
  83. Device->Release();
  84. }
  85. void CD3D9Texture::createRenderTarget(const ECOLOR_FORMAT format)
  86. {
  87. // are texture size restrictions there ?
  88. if(!Driver->queryFeature(EVDF_TEXTURE_NPOT))
  89. {
  90. if (TextureSize != ImageSize)
  91. os::Printer::log("RenderTarget size has to be a power of two", ELL_INFORMATION);
  92. }
  93. TextureSize = TextureSize.getOptimalSize(!Driver->queryFeature(EVDF_TEXTURE_NPOT), !Driver->queryFeature(EVDF_TEXTURE_NSQUARE), true, Driver->Caps.MaxTextureWidth);
  94. D3DFORMAT d3dformat = Driver->getD3DColorFormat();
  95. if(ColorFormat == ECF_UNKNOWN)
  96. {
  97. // get irrlicht format from backbuffer
  98. // (This will get overwritten by the custom format if it is provided, else kept.)
  99. ColorFormat = Driver->getColorFormat();
  100. setPitch(d3dformat);
  101. // Use color format if provided.
  102. if(format != ECF_UNKNOWN)
  103. {
  104. ColorFormat = format;
  105. d3dformat = Driver->getD3DFormatFromColorFormat(format);
  106. setPitch(d3dformat); // This will likely set pitch to 0 for now.
  107. }
  108. }
  109. else
  110. {
  111. d3dformat = Driver->getD3DFormatFromColorFormat(ColorFormat);
  112. }
  113. // create texture
  114. HRESULT hr;
  115. hr = Device->CreateTexture(
  116. TextureSize.Width,
  117. TextureSize.Height,
  118. 1, // mip map level count, we don't want mipmaps here
  119. D3DUSAGE_RENDERTARGET,
  120. d3dformat,
  121. D3DPOOL_DEFAULT,
  122. &Texture,
  123. NULL);
  124. if (FAILED(hr))
  125. {
  126. if (D3DERR_INVALIDCALL == hr)
  127. os::Printer::log("Could not create render target texture", "Invalid Call");
  128. else
  129. if (D3DERR_OUTOFVIDEOMEMORY == hr)
  130. os::Printer::log("Could not create render target texture", "Out of Video Memory");
  131. else
  132. if (E_OUTOFMEMORY == hr)
  133. os::Printer::log("Could not create render target texture", "Out of Memory");
  134. else
  135. os::Printer::log("Could not create render target texture");
  136. }
  137. }
  138. bool CD3D9Texture::createMipMaps(u32 level)
  139. {
  140. if (level==0)
  141. return true;
  142. if (HardwareMipMaps && Texture)
  143. {
  144. // generate mipmaps in hardware
  145. Texture->GenerateMipSubLevels();
  146. return true;
  147. }
  148. // manual mipmap generation
  149. IDirect3DSurface9* upperSurface = 0;
  150. IDirect3DSurface9* lowerSurface = 0;
  151. // get upper level
  152. HRESULT hr = Texture->GetSurfaceLevel(level-1, &upperSurface);
  153. if (FAILED(hr) || !upperSurface)
  154. {
  155. os::Printer::log("Could not get upper surface level for mip map generation", ELL_WARNING);
  156. return false;
  157. }
  158. // get lower level
  159. hr = Texture->GetSurfaceLevel(level, &lowerSurface);
  160. if (FAILED(hr) || !lowerSurface)
  161. {
  162. os::Printer::log("Could not get lower surface level for mip map generation", ELL_WARNING);
  163. upperSurface->Release();
  164. return false;
  165. }
  166. D3DSURFACE_DESC upperDesc, lowerDesc;
  167. upperSurface->GetDesc(&upperDesc);
  168. lowerSurface->GetDesc(&lowerDesc);
  169. D3DLOCKED_RECT upperlr;
  170. D3DLOCKED_RECT lowerlr;
  171. // lock upper surface
  172. if (FAILED(upperSurface->LockRect(&upperlr, NULL, 0)))
  173. {
  174. upperSurface->Release();
  175. lowerSurface->Release();
  176. os::Printer::log("Could not lock upper texture for mip map generation", ELL_WARNING);
  177. return false;
  178. }
  179. // lock lower surface
  180. if (FAILED(lowerSurface->LockRect(&lowerlr, NULL, 0)))
  181. {
  182. upperSurface->UnlockRect();
  183. upperSurface->Release();
  184. lowerSurface->Release();
  185. os::Printer::log("Could not lock lower texture for mip map generation", ELL_WARNING);
  186. return false;
  187. }
  188. if (upperDesc.Format != lowerDesc.Format)
  189. {
  190. os::Printer::log("Cannot copy mip maps with different formats.", ELL_WARNING);
  191. }
  192. else
  193. {
  194. if ((upperDesc.Format == D3DFMT_A1R5G5B5) || (upperDesc.Format == D3DFMT_R5G6B5))
  195. copy16BitMipMap((char*)upperlr.pBits, (char*)lowerlr.pBits,
  196. lowerDesc.Width, lowerDesc.Height,
  197. upperlr.Pitch, lowerlr.Pitch);
  198. else
  199. if (upperDesc.Format == D3DFMT_A8R8G8B8)
  200. copy32BitMipMap((char*)upperlr.pBits, (char*)lowerlr.pBits,
  201. lowerDesc.Width, lowerDesc.Height,
  202. upperlr.Pitch, lowerlr.Pitch);
  203. else
  204. os::Printer::log("Unsupported mipmap format, cannot copy.", ELL_WARNING);
  205. }
  206. bool result=true;
  207. // unlock
  208. if (FAILED(upperSurface->UnlockRect()))
  209. result=false;
  210. if (FAILED(lowerSurface->UnlockRect()))
  211. result=false;
  212. // release
  213. upperSurface->Release();
  214. lowerSurface->Release();
  215. if (!result || (upperDesc.Width <= 3 && upperDesc.Height <= 3))
  216. return result; // stop generating levels
  217. // generate next level
  218. return createMipMaps(level+1);
  219. }
  220. //! creates the hardware texture
  221. bool CD3D9Texture::createTexture(u32 flags, IImage * image)
  222. {
  223. ImageSize = image->getDimension();
  224. core::dimension2d<u32> optSize = ImageSize.getOptimalSize(!Driver->queryFeature(EVDF_TEXTURE_NPOT), !Driver->queryFeature(EVDF_TEXTURE_NSQUARE), true, Driver->Caps.MaxTextureWidth);
  225. D3DFORMAT format = D3DFMT_A1R5G5B5;
  226. switch(getTextureFormatFromFlags(flags))
  227. {
  228. case ETCF_ALWAYS_16_BIT:
  229. format = D3DFMT_A1R5G5B5; break;
  230. case ETCF_ALWAYS_32_BIT:
  231. format = D3DFMT_A8R8G8B8; break;
  232. case ETCF_OPTIMIZED_FOR_QUALITY:
  233. {
  234. switch(image->getColorFormat())
  235. {
  236. case ECF_R8G8B8:
  237. case ECF_A8R8G8B8:
  238. format = D3DFMT_A8R8G8B8; break;
  239. case ECF_A1R5G5B5:
  240. case ECF_R5G6B5:
  241. format = D3DFMT_A1R5G5B5; break;
  242. }
  243. }
  244. break;
  245. case ETCF_OPTIMIZED_FOR_SPEED:
  246. format = D3DFMT_A1R5G5B5;
  247. break;
  248. default:
  249. break;
  250. }
  251. if (Driver->getTextureCreationFlag(video::ETCF_NO_ALPHA_CHANNEL))
  252. {
  253. if (format == D3DFMT_A8R8G8B8)
  254. format = D3DFMT_R8G8B8;
  255. else if (format == D3DFMT_A1R5G5B5)
  256. format = D3DFMT_R5G6B5;
  257. }
  258. const bool mipmaps = Driver->getTextureCreationFlag(video::ETCF_CREATE_MIP_MAPS);
  259. DWORD usage = 0;
  260. // This enables hardware mip map generation.
  261. if (mipmaps && Driver->queryFeature(EVDF_MIP_MAP_AUTO_UPDATE))
  262. {
  263. LPDIRECT3D9 intf = Driver->getExposedVideoData().D3D9.D3D9;
  264. D3DDISPLAYMODE d3ddm;
  265. intf->GetAdapterDisplayMode(D3DADAPTER_DEFAULT, &d3ddm);
  266. if (D3D_OK==intf->CheckDeviceFormat(D3DADAPTER_DEFAULT,D3DDEVTYPE_HAL,d3ddm.Format,D3DUSAGE_AUTOGENMIPMAP,D3DRTYPE_TEXTURE,format))
  267. {
  268. usage = D3DUSAGE_AUTOGENMIPMAP;
  269. HardwareMipMaps = true;
  270. }
  271. }
  272. HRESULT hr = Device->CreateTexture(optSize.Width, optSize.Height,
  273. mipmaps ? 0 : 1, // number of mipmaplevels (0 = automatic all)
  274. usage, // usage
  275. format, D3DPOOL_MANAGED , &Texture, NULL);
  276. if (FAILED(hr))
  277. {
  278. // try brute force 16 bit
  279. HardwareMipMaps = false;
  280. if (format == D3DFMT_A8R8G8B8)
  281. format = D3DFMT_A1R5G5B5;
  282. else if (format == D3DFMT_R8G8B8)
  283. format = D3DFMT_R5G6B5;
  284. else
  285. return false;
  286. hr = Device->CreateTexture(optSize.Width, optSize.Height,
  287. mipmaps ? 0 : 1, // number of mipmaplevels (0 = automatic all)
  288. 0, format, D3DPOOL_MANAGED, &Texture, NULL);
  289. }
  290. ColorFormat = Driver->getColorFormatFromD3DFormat(format);
  291. setPitch(format);
  292. return (SUCCEEDED(hr));
  293. }
  294. //! copies the image to the texture
  295. bool CD3D9Texture::copyTexture(IImage * image)
  296. {
  297. if (Texture && image)
  298. {
  299. D3DSURFACE_DESC desc;
  300. Texture->GetLevelDesc(0, &desc);
  301. TextureSize.Width = desc.Width;
  302. TextureSize.Height = desc.Height;
  303. D3DLOCKED_RECT rect;
  304. HRESULT hr = Texture->LockRect(0, &rect, 0, 0);
  305. if (FAILED(hr))
  306. {
  307. os::Printer::log("Texture data not copied", "Could not LockRect D3D9 Texture.", ELL_ERROR);
  308. return false;
  309. }
  310. Pitch = rect.Pitch;
  311. image->copyToScaling(rect.pBits, TextureSize.Width, TextureSize.Height, ColorFormat, Pitch);
  312. hr = Texture->UnlockRect(0);
  313. if (FAILED(hr))
  314. {
  315. os::Printer::log("Texture data not copied", "Could not UnlockRect D3D9 Texture.", ELL_ERROR);
  316. return false;
  317. }
  318. }
  319. return true;
  320. }
  321. //! lock function
  322. void* CD3D9Texture::lock(bool readOnly, u32 mipmapLevel)
  323. {
  324. if (!Texture)
  325. return 0;
  326. MipLevelLocked=mipmapLevel;
  327. HRESULT hr;
  328. D3DLOCKED_RECT rect;
  329. if(!IsRenderTarget)
  330. {
  331. hr = Texture->LockRect(mipmapLevel, &rect, 0, readOnly?D3DLOCK_READONLY:0);
  332. if (FAILED(hr))
  333. {
  334. os::Printer::log("Could not lock DIRECT3D9 Texture.", ELL_ERROR);
  335. return 0;
  336. }
  337. }
  338. else
  339. {
  340. if (!RTTSurface)
  341. {
  342. // Make RTT surface large enough for all miplevels (including 0)
  343. D3DSURFACE_DESC desc;
  344. Texture->GetLevelDesc(0, &desc);
  345. hr = Device->CreateOffscreenPlainSurface(desc.Width, desc.Height, desc.Format, D3DPOOL_SYSTEMMEM, &RTTSurface, 0);
  346. if (FAILED(hr))
  347. {
  348. os::Printer::log("Could not lock DIRECT3D9 Texture", "Offscreen surface creation failed.", ELL_ERROR);
  349. return 0;
  350. }
  351. }
  352. IDirect3DSurface9 *surface = 0;
  353. hr = Texture->GetSurfaceLevel(mipmapLevel, &surface);
  354. if (FAILED(hr))
  355. {
  356. os::Printer::log("Could not lock DIRECT3D9 Texture", "Could not get surface.", ELL_ERROR);
  357. return 0;
  358. }
  359. hr = Device->GetRenderTargetData(surface, RTTSurface);
  360. surface->Release();
  361. if(FAILED(hr))
  362. {
  363. os::Printer::log("Could not lock DIRECT3D9 Texture", "Data copy failed.", ELL_ERROR);
  364. return 0;
  365. }
  366. hr = RTTSurface->LockRect(&rect, 0, readOnly?D3DLOCK_READONLY:0);
  367. if(FAILED(hr))
  368. {
  369. os::Printer::log("Could not lock DIRECT3D9 Texture", "LockRect failed.", ELL_ERROR);
  370. return 0;
  371. }
  372. }
  373. return rect.pBits;
  374. }
  375. //! unlock function
  376. void CD3D9Texture::unlock()
  377. {
  378. if (!Texture)
  379. return;
  380. if (!IsRenderTarget)
  381. Texture->UnlockRect(MipLevelLocked);
  382. else if (RTTSurface)
  383. RTTSurface->UnlockRect();
  384. }
  385. //! Returns original size of the texture.
  386. const core::dimension2d<u32>& CD3D9Texture::getOriginalSize() const
  387. {
  388. return ImageSize;
  389. }
  390. //! Returns (=size) of the texture.
  391. const core::dimension2d<u32>& CD3D9Texture::getSize() const
  392. {
  393. return TextureSize;
  394. }
  395. //! returns driver type of texture (=the driver, who created the texture)
  396. E_DRIVER_TYPE CD3D9Texture::getDriverType() const
  397. {
  398. return EDT_DIRECT3D9;
  399. }
  400. //! returns color format of texture
  401. ECOLOR_FORMAT CD3D9Texture::getColorFormat() const
  402. {
  403. return ColorFormat;
  404. }
  405. //! returns pitch of texture (in bytes)
  406. u32 CD3D9Texture::getPitch() const
  407. {
  408. return Pitch;
  409. }
  410. //! returns the DIRECT3D9 Texture
  411. IDirect3DBaseTexture9* CD3D9Texture::getDX9Texture() const
  412. {
  413. return Texture;
  414. }
  415. //! returns if texture has mipmap levels
  416. bool CD3D9Texture::hasMipMaps() const
  417. {
  418. return HasMipMaps;
  419. }
  420. void CD3D9Texture::copy16BitMipMap(char* src, char* tgt,
  421. s32 width, s32 height,
  422. s32 pitchsrc, s32 pitchtgt) const
  423. {
  424. for (s32 y=0; y<height; ++y)
  425. {
  426. for (s32 x=0; x<width; ++x)
  427. {
  428. u32 a=0, r=0, g=0, b=0;
  429. for (s32 dy=0; dy<2; ++dy)
  430. {
  431. const s32 tgy = (y*2)+dy;
  432. for (s32 dx=0; dx<2; ++dx)
  433. {
  434. const s32 tgx = (x*2)+dx;
  435. SColor c;
  436. if (ColorFormat == ECF_A1R5G5B5)
  437. c = A1R5G5B5toA8R8G8B8(*(u16*)(&src[(tgx*2)+(tgy*pitchsrc)]));
  438. else
  439. c = R5G6B5toA8R8G8B8(*(u16*)(&src[(tgx*2)+(tgy*pitchsrc)]));
  440. a += c.getAlpha();
  441. r += c.getRed();
  442. g += c.getGreen();
  443. b += c.getBlue();
  444. }
  445. }
  446. a /= 4;
  447. r /= 4;
  448. g /= 4;
  449. b /= 4;
  450. u16 c;
  451. if (ColorFormat == ECF_A1R5G5B5)
  452. c = RGBA16(r,g,b,a);
  453. else
  454. c = A8R8G8B8toR5G6B5(SColor(a,r,g,b).color);
  455. *(u16*)(&tgt[(x*2)+(y*pitchtgt)]) = c;
  456. }
  457. }
  458. }
  459. void CD3D9Texture::copy32BitMipMap(char* src, char* tgt,
  460. s32 width, s32 height,
  461. s32 pitchsrc, s32 pitchtgt) const
  462. {
  463. for (s32 y=0; y<height; ++y)
  464. {
  465. for (s32 x=0; x<width; ++x)
  466. {
  467. u32 a=0, r=0, g=0, b=0;
  468. SColor c;
  469. for (s32 dy=0; dy<2; ++dy)
  470. {
  471. const s32 tgy = (y*2)+dy;
  472. for (s32 dx=0; dx<2; ++dx)
  473. {
  474. const s32 tgx = (x*2)+dx;
  475. c = *(u32*)(&src[(tgx*4)+(tgy*pitchsrc)]);
  476. a += c.getAlpha();
  477. r += c.getRed();
  478. g += c.getGreen();
  479. b += c.getBlue();
  480. }
  481. }
  482. a /= 4;
  483. r /= 4;
  484. g /= 4;
  485. b /= 4;
  486. c.set(a, r, g, b);
  487. *(u32*)(&tgt[(x*4)+(y*pitchtgt)]) = c.color;
  488. }
  489. }
  490. }
  491. //! Regenerates the mip map levels of the texture. Useful after locking and
  492. //! modifying the texture
  493. void CD3D9Texture::regenerateMipMapLevels(void* mipmapData)
  494. {
  495. if (mipmapData)
  496. {
  497. core::dimension2du size = TextureSize;
  498. u32 level=0;
  499. do
  500. {
  501. if (size.Width>1)
  502. size.Width /=2;
  503. if (size.Height>1)
  504. size.Height /=2;
  505. ++level;
  506. IDirect3DSurface9* mipSurface = 0;
  507. HRESULT hr = Texture->GetSurfaceLevel(level, &mipSurface);
  508. if (FAILED(hr) || !mipSurface)
  509. {
  510. os::Printer::log("Could not get mipmap level", ELL_WARNING);
  511. return;
  512. }
  513. D3DSURFACE_DESC mipDesc;
  514. mipSurface->GetDesc(&mipDesc);
  515. D3DLOCKED_RECT miplr;
  516. // lock mipmap surface
  517. if (FAILED(mipSurface->LockRect(&miplr, NULL, 0)))
  518. {
  519. mipSurface->Release();
  520. os::Printer::log("Could not lock texture", ELL_WARNING);
  521. return;
  522. }
  523. memcpy(miplr.pBits, mipmapData, size.getArea()*getPitch()/TextureSize.Width);
  524. mipmapData = (u8*)mipmapData+size.getArea()*getPitch()/TextureSize.Width;
  525. // unlock
  526. mipSurface->UnlockRect();
  527. // release
  528. mipSurface->Release();
  529. } while (size.Width != 1 || size.Height != 1);
  530. }
  531. else if (HasMipMaps)
  532. {
  533. // create mip maps.
  534. #ifdef _IRR_USE_D3DXFilterTexture_
  535. // The D3DXFilterTexture function seems to get linked wrong when
  536. // compiling with both D3D8 and 9, causing it not to work in the D3D9 device.
  537. // So mipmapgeneration is replaced with my own bad generation
  538. HRESULT hr = D3DXFilterTexture(Texture, NULL, D3DX_DEFAULT, D3DX_DEFAULT);
  539. if (FAILED(hr))
  540. #endif
  541. createMipMaps();
  542. }
  543. }
  544. //! returns if it is a render target
  545. bool CD3D9Texture::isRenderTarget() const
  546. {
  547. return IsRenderTarget;
  548. }
  549. //! Returns pointer to the render target surface
  550. IDirect3DSurface9* CD3D9Texture::getRenderTargetSurface()
  551. {
  552. if (!IsRenderTarget)
  553. return 0;
  554. IDirect3DSurface9 *pRTTSurface = 0;
  555. if (Texture)
  556. Texture->GetSurfaceLevel(0, &pRTTSurface);
  557. if (pRTTSurface)
  558. pRTTSurface->Release();
  559. return pRTTSurface;
  560. }
  561. void CD3D9Texture::setPitch(D3DFORMAT d3dformat)
  562. {
  563. switch(d3dformat)
  564. {
  565. case D3DFMT_X1R5G5B5:
  566. case D3DFMT_A1R5G5B5:
  567. Pitch = TextureSize.Width * 2;
  568. break;
  569. case D3DFMT_A8B8G8R8:
  570. case D3DFMT_A8R8G8B8:
  571. case D3DFMT_X8R8G8B8:
  572. Pitch = TextureSize.Width * 4;
  573. break;
  574. case D3DFMT_R5G6B5:
  575. Pitch = TextureSize.Width * 2;
  576. break;
  577. case D3DFMT_R8G8B8:
  578. Pitch = TextureSize.Width * 3;
  579. break;
  580. default:
  581. Pitch = 0;
  582. };
  583. }
  584. } // end namespace video
  585. } // end namespace irr
  586. #endif // _IRR_COMPILE_WITH_DIRECT3D_9_