Leaked source code of windows server 2003
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

1135 lines
35 KiB

  1. ///////////////////////////////////////////////////////////////////////////////
  2. // Copyright (C) Microsoft Corporation, 1998.
  3. //
  4. // texmap.cpp
  5. //
  6. // Direct3D Reference Rasterizer - Texture Map Access Methods
  7. //
  8. ///////////////////////////////////////////////////////////////////////////////
  9. #include "pch.cpp"
  10. #pragma hdrstop
  11. //----------------------------------------------------------------------------
  12. //
  13. // FindOutSurfFormat
  14. //
  15. // Converts a DDPIXELFORMAT to RDSurfaceFormat.
  16. //
  17. //----------------------------------------------------------------------------
  18. HRESULT FASTCALL
  19. FindOutSurfFormat(LPDDPIXELFORMAT pDdPixFmt,
  20. RDSurfaceFormat* pFmt,
  21. BOOL* pbIsDepth)
  22. {
  23. if( pbIsDepth ) *pbIsDepth = FALSE;
  24. if (pDdPixFmt->dwFourCC == D3DFMT_Q8W8V8U8 )
  25. {
  26. *pFmt = RD_SF_U8V8W8Q8;
  27. }
  28. else if (pDdPixFmt->dwFourCC == D3DFMT_W11V11U10 )
  29. {
  30. *pFmt = RD_SF_U10V11W11;
  31. }
  32. else if (pDdPixFmt->dwFourCC == D3DFMT_V16U16 )
  33. {
  34. *pFmt = RD_SF_U16V16;
  35. }
  36. else if (pDdPixFmt->dwFourCC == D3DFMT_R8G8B8 )
  37. {
  38. *pFmt = RD_SF_B8G8R8;
  39. }
  40. else if (pDdPixFmt->dwFourCC == D3DFMT_A8 )
  41. {
  42. *pFmt = RD_SF_A8;
  43. }
  44. else if (pDdPixFmt->dwFourCC == D3DFMT_A8P8 )
  45. {
  46. *pFmt = RD_SF_P8A8;
  47. }
  48. else if (pDdPixFmt->dwFourCC == D3DFMT_X4R4G4B4 )
  49. {
  50. *pFmt = RD_SF_B4G4R4X4;
  51. }
  52. else if (pDdPixFmt->dwFourCC == D3DFMT_A2B10G10R10)
  53. {
  54. *pFmt = RD_SF_R10G10B10A2;
  55. }
  56. #if 0
  57. else if (pDdPixFmt->dwFourCC == D3DFMT_A8B8G8R8)
  58. {
  59. *pFmt = RD_SF_R8G8B8A8;
  60. }
  61. else if (pDdPixFmt->dwFourCC == D3DFMT_X8B8G8R8)
  62. {
  63. *pFmt = RD_SF_R8G8B8X8;
  64. }
  65. else if (pDdPixFmt->dwFourCC == D3DFMT_W10V11U11)
  66. {
  67. *pFmt = RD_SF_U11V11W10;
  68. }
  69. else if (pDdPixFmt->dwFourCC == D3DFMT_A8X8V8U8)
  70. {
  71. *pFmt = RD_SF_U8V8X8A8;
  72. }
  73. else if (pDdPixFmt->dwFourCC == D3DFMT_L8X8V8U8)
  74. {
  75. *pFmt = RD_SF_U8V8X8L8;
  76. }
  77. #endif
  78. else if (pDdPixFmt->dwFourCC == D3DFMT_G16R16)
  79. {
  80. *pFmt = RD_SF_R16G16;
  81. }
  82. else if (pDdPixFmt->dwFourCC == D3DFMT_A2W10V10U10)
  83. {
  84. *pFmt = RD_SF_U10V10W10A2;
  85. }
  86. else if (pDdPixFmt->dwFourCC == MAKEFOURCC('U', 'Y', 'V', 'Y'))
  87. {
  88. *pFmt = RD_SF_UYVY;
  89. }
  90. else if (pDdPixFmt->dwFourCC == MAKEFOURCC('Y', 'U', 'Y', '2'))
  91. {
  92. *pFmt = RD_SF_YUY2;
  93. }
  94. else if (pDdPixFmt->dwFourCC == MAKEFOURCC('D', 'X', 'T', '1'))
  95. {
  96. *pFmt = RD_SF_DXT1;
  97. }
  98. else if (pDdPixFmt->dwFourCC == MAKEFOURCC('D', 'X', 'T', '2'))
  99. {
  100. *pFmt = RD_SF_DXT2;
  101. }
  102. else if (pDdPixFmt->dwFourCC == MAKEFOURCC('D', 'X', 'T', '3'))
  103. {
  104. *pFmt = RD_SF_DXT3;
  105. }
  106. else if (pDdPixFmt->dwFourCC == MAKEFOURCC('D', 'X', 'T', '4'))
  107. {
  108. *pFmt = RD_SF_DXT4;
  109. }
  110. else if (pDdPixFmt->dwFourCC == MAKEFOURCC('D', 'X', 'T', '5'))
  111. {
  112. *pFmt = RD_SF_DXT5;
  113. }
  114. else if (pDdPixFmt->dwFourCC == 0xFF000004)
  115. {
  116. // This is an example of a IHV-specific format
  117. // The HIWORD must be the PCI-ID of the IHV
  118. // and the third byte must be zero.
  119. // In this case, we're using a sample PCI-ID of
  120. // FF00, and we're denoting the 4th format
  121. // by that PCI-ID
  122. *pFmt = RD_SF_Z32S0;
  123. }
  124. else if (pDdPixFmt->dwFlags & DDPF_ZBUFFER)
  125. {
  126. if( pbIsDepth ) *pbIsDepth = TRUE;
  127. switch(pDdPixFmt->dwZBitMask)
  128. {
  129. default:
  130. case 0x0000FFFF: *pFmt = RD_SF_Z16S0; break;
  131. case 0xFFFFFF00:
  132. switch(pDdPixFmt->dwStencilBitMask)
  133. {
  134. default:
  135. case 0x00000000: *pFmt = RD_SF_Z24X8; break;
  136. case 0x000000FF: *pFmt = RD_SF_Z24S8; break;
  137. case 0x0000000F: *pFmt = RD_SF_Z24X4S4; break;
  138. }
  139. break;
  140. case 0x00FFFFFF:
  141. switch(pDdPixFmt->dwStencilBitMask)
  142. {
  143. default:
  144. case 0x00000000: *pFmt = RD_SF_X8Z24; break;
  145. case 0xFF000000: *pFmt = RD_SF_S8Z24; break;
  146. case 0x0F000000: *pFmt = RD_SF_X4S4Z24; break;
  147. }
  148. break;
  149. case 0x0000FFFE: *pFmt = RD_SF_Z15S1; break;
  150. case 0x00007FFF: *pFmt = RD_SF_S1Z15; break;
  151. case 0xFFFFFFFF: *pFmt = RD_SF_Z32S0; break;
  152. }
  153. }
  154. else if (pDdPixFmt->dwFlags & DDPF_BUMPDUDV)
  155. {
  156. UINT uFmt = pDdPixFmt->dwBumpDvBitMask;
  157. switch (uFmt)
  158. {
  159. case 0x0000ff00:
  160. switch (pDdPixFmt->dwRGBBitCount)
  161. {
  162. case 32:
  163. *pFmt = RD_SF_U8V8L8X8;
  164. break;
  165. case 16:
  166. *pFmt = RD_SF_U8V8;
  167. break;
  168. }
  169. break;
  170. case 0x000003e0:
  171. *pFmt = RD_SF_U5V5L6;
  172. break;
  173. }
  174. }
  175. else if (pDdPixFmt->dwFlags & DDPF_PALETTEINDEXED8)
  176. {
  177. if (pDdPixFmt->dwFlags & DDPF_ALPHAPIXELS)
  178. {
  179. *pFmt = RD_SF_P8A8;
  180. }
  181. else
  182. {
  183. *pFmt = RD_SF_PALETTE8;
  184. }
  185. }
  186. else if (pDdPixFmt->dwFlags & DDPF_PALETTEINDEXED4)
  187. {
  188. *pFmt = RD_SF_PALETTE4;
  189. }
  190. else if (pDdPixFmt->dwFlags & DDPF_ALPHA)
  191. {
  192. if (pDdPixFmt->dwAlphaBitDepth == 8)
  193. {
  194. *pFmt = RD_SF_A8;
  195. }
  196. else
  197. {
  198. *pFmt = RD_SF_NULL;
  199. }
  200. }
  201. else
  202. {
  203. UINT uFmt = pDdPixFmt->dwGBitMask | pDdPixFmt->dwRBitMask;
  204. if (pDdPixFmt->dwFlags & DDPF_ALPHAPIXELS)
  205. {
  206. uFmt |= pDdPixFmt->dwRGBAlphaBitMask;
  207. }
  208. switch (uFmt)
  209. {
  210. case 0x00ffff00:
  211. switch (pDdPixFmt->dwRGBBitCount)
  212. {
  213. case 32:
  214. *pFmt = RD_SF_B8G8R8X8;
  215. break;
  216. case 24:
  217. *pFmt = RD_SF_B8G8R8;
  218. break;
  219. }
  220. break;
  221. case 0xffffff00:
  222. *pFmt = RD_SF_B8G8R8A8;
  223. break;
  224. case 0xffe0:
  225. if (pDdPixFmt->dwFlags & DDPF_ALPHAPIXELS)
  226. {
  227. *pFmt = RD_SF_B5G5R5A1;
  228. }
  229. else
  230. {
  231. *pFmt = RD_SF_B5G6R5;
  232. }
  233. break;
  234. case 0x07fe0:
  235. *pFmt = RD_SF_B5G5R5X1;
  236. break;
  237. case 0xff0:
  238. *pFmt = RD_SF_B4G4R4X4;
  239. break;
  240. case 0xfff0:
  241. *pFmt = RD_SF_B4G4R4A4;
  242. break;
  243. case 0xff:
  244. if (pDdPixFmt->dwFlags & DDPF_ALPHAPIXELS)
  245. {
  246. *pFmt = RD_SF_L4A4;
  247. }
  248. else
  249. {
  250. *pFmt = RD_SF_L8;
  251. }
  252. break;
  253. case 0xffff:
  254. *pFmt = RD_SF_L8A8;
  255. break;
  256. case 0xfc:
  257. *pFmt = RD_SF_B2G3R3;
  258. break;
  259. case 0xfffc:
  260. *pFmt = RD_SF_B2G3R3A8;
  261. break;
  262. default:
  263. *pFmt = RD_SF_NULL;
  264. break;
  265. }
  266. }
  267. return D3D_OK;
  268. }
  269. //----------------------------------------------------------------------------
  270. //
  271. // ValidMipmapSize
  272. //
  273. // Computes size of next smallest mipmap level, clamping at 1
  274. //
  275. //----------------------------------------------------------------------------
  276. BOOL FASTCALL
  277. ValidMipmapSize(INT16 iPreSize, INT16 iSize)
  278. {
  279. if (iPreSize == 1)
  280. {
  281. if (iSize == 1)
  282. {
  283. return TRUE;
  284. }
  285. else
  286. {
  287. return FALSE;
  288. }
  289. }
  290. else
  291. {
  292. return ((iPreSize >> 1) == iSize);
  293. }
  294. }
  295. //////////////////////////////////////////////////////////////////////////////
  296. //
  297. // RDPalette
  298. //
  299. //////////////////////////////////////////////////////////////////////////////
  300. const DWORD RDPalette::RDPAL_ALPHAINPALETTE = (1 << 0);
  301. const DWORD RDPalette::m_dwNumEntries = 256;
  302. HRESULT
  303. RDPalette::Update( WORD StartIndex, WORD wNumEntries, PALETTEENTRY* pEntries )
  304. {
  305. _ASSERT( StartIndex < m_dwNumEntries, "Bad StartIndex\n" );
  306. _ASSERT( StartIndex+wNumEntries <= m_dwNumEntries, "Too many entries\n" );
  307. for( WORD i = 0; i < wNumEntries; i++ )
  308. {
  309. m_Entries[StartIndex+i] = D3DCOLOR_ARGB( pEntries[i].peFlags,
  310. pEntries[i].peRed,
  311. pEntries[i].peGreen,
  312. pEntries[i].peBlue );
  313. }
  314. return S_OK;
  315. }
  316. //-----------------------------------------------------------------------------
  317. //
  318. // Constructor/Destructor
  319. //
  320. //-----------------------------------------------------------------------------
  321. RDSurface2D::RDSurface2D( void )
  322. {
  323. m_pRefDev = NULL;
  324. m_uFlags = 0;
  325. m_iWidth = 0;
  326. m_iHeight = 0;
  327. m_iDepth = 0;
  328. m_cLOD = 0;
  329. m_SurfFormat = RD_SF_NULL;
  330. m_dwColorKey = 0;
  331. m_dwEmptyFaceColor = 0;
  332. m_pPalette = 0;
  333. m_pPalObj = NULL;
  334. m_cLODDDS = 0;
  335. m_hTex = 0;
  336. m_bHasAlpha = 0;
  337. memset(m_pBits, 0, sizeof(m_pBits));
  338. memset(m_iPitch, 0, sizeof(m_iPitch));
  339. memset(m_iSlicePitch, 0, sizeof(m_iSlicePitch));
  340. memset(m_pDDSLcl, 0, sizeof(m_pDDSLcl));
  341. m_cDimension = 0;
  342. memset(m_fTexels, 0, sizeof(m_fTexels));
  343. memset(m_cTexels, 0, sizeof(m_cTexels));
  344. }
  345. //-----------------------------------------------------------------------------
  346. RDSurface2D::~RDSurface2D( void )
  347. {
  348. }
  349. DWORD
  350. RDSurface2D::ComputePitch( LPDDRAWI_DDRAWSURFACE_LCL pLcl,
  351. RDSurfaceFormat SurfFormat,
  352. DWORD width, DWORD height ) const
  353. {
  354. if ((SurfFormat == RD_SF_DXT1) ||
  355. (SurfFormat == RD_SF_DXT2) ||
  356. (SurfFormat == RD_SF_DXT3) ||
  357. (SurfFormat == RD_SF_DXT4) ||
  358. (SurfFormat == RD_SF_DXT5))
  359. {
  360. // Note, here is the assumption that:
  361. // 1) width and height are reported correctly by the runtime.
  362. // 2) The allocation of the memory is contiguous (as done by hel)
  363. return (((width+3)>>2) *
  364. g_DXTBlkSize[(int)SurfFormat - (int)RD_SF_DXT1]);
  365. }
  366. #if 0
  367. else if( (SurfFormat == RD_SF_YUY2) ||
  368. (SurfFormat == RD_SF_UYVY) )
  369. {
  370. // Same assumptions as for DXTn.
  371. return (DDSurf_Pitch(pLcl)/height);
  372. }
  373. #endif
  374. else
  375. {
  376. return DDSurf_Pitch(pLcl);
  377. }
  378. }
  379. DWORD
  380. RDSurface2D::ComputePitch( LPDDRAWI_DDRAWSURFACE_LCL pLcl ) const
  381. {
  382. return ComputePitch( pLcl, m_SurfFormat, m_iWidth, m_iHeight );
  383. }
  384. //-----------------------------------------------------------------------------
  385. //
  386. // RDSurface2D::Initialize()
  387. //
  388. //-----------------------------------------------------------------------------
  389. HRESULT
  390. RDSurface2D::Initialize( LPDDRAWI_DDRAWSURFACE_LCL pLcl )
  391. {
  392. HRESULT hr = D3D_OK;
  393. RDSurfaceFormat SurfFormat;
  394. DDSCAPS2 ddscaps;
  395. LPDDRAWI_DDRAWSURFACE_GBL pGbl = pLcl->lpGbl;
  396. LPDDRAWI_DDRAWSURFACE_MORE pMore = pLcl->lpSurfMore;
  397. memset(&ddscaps, 0, sizeof(ddscaps));
  398. UINT wMultiSampleCount = 0xfL & pMore->ddsCapsEx.dwCaps3;
  399. //Older than DX8 runtimes place a zero in this field
  400. if (wMultiSampleCount == 0)
  401. wMultiSampleCount = 1;
  402. if( pLcl->ddsCaps.dwCaps & DDSCAPS_TEXTURE )
  403. m_SurfType |= RR_ST_TEXTURE;
  404. if( pLcl->ddsCaps.dwCaps & DDSCAPS_ZBUFFER )
  405. {
  406. m_iSamples = wMultiSampleCount;
  407. m_SurfType |= RR_ST_RENDERTARGETDEPTH;
  408. }
  409. if( pLcl->ddsCaps.dwCaps & DDSCAPS_3DDEVICE )
  410. {
  411. m_iSamples = wMultiSampleCount;
  412. m_SurfType |= RR_ST_RENDERTARGETCOLOR;
  413. }
  414. m_iWidth = DDSurf_Width(pLcl);
  415. m_iHeight = DDSurf_Height(pLcl);
  416. HR_RET(FindOutSurfFormat(&(DDSurf_PixFmt(pLcl)), &SurfFormat, NULL));
  417. m_SurfFormat = SurfFormat;
  418. if (pMore->ddsCapsEx.dwCaps2 & DDSCAPS2_VOLUME)
  419. {
  420. // low word of ddsCaps.ddsCapsEx.dwCaps4 has depth
  421. // (volume texture only).
  422. m_iDepth = LOWORD(pMore->ddsCapsEx.dwCaps4);
  423. }
  424. else
  425. {
  426. m_iDepth = 0;
  427. }
  428. m_cTexels[0][0] = m_iWidth;
  429. m_cTexels[0][1] = m_iHeight;
  430. m_cTexels[0][2] = m_iDepth;
  431. m_fTexels[0][0] = (float)m_cTexels[0][0];
  432. m_fTexels[0][1] = (float)m_cTexels[0][1];
  433. m_fTexels[0][2] = (float)m_cTexels[0][2];
  434. m_cLOD = 0;
  435. if( wMultiSampleCount > 1 )
  436. {
  437. RDCREATESURFPRIVATE* pPriv = (RDCREATESURFPRIVATE*)pGbl->dwReserved1;
  438. m_pBits[0] = pPriv->pMultiSampleBits;
  439. m_iPitch[0] = pPriv->dwMultiSamplePitch;
  440. }
  441. else
  442. {
  443. m_pBits[0] = (BYTE *)SURFACE_MEMORY(pLcl);
  444. m_iPitch[0] = ComputePitch( pLcl );
  445. }
  446. if (pMore->ddsCapsEx.dwCaps2 & DDSCAPS2_VOLUME)
  447. {
  448. // set slice pitch (volume texture only).
  449. m_iSlicePitch[0] = pGbl->lSlicePitch;
  450. }
  451. else
  452. {
  453. m_iSlicePitch[0] = 0;
  454. }
  455. // If the surface is not a texture early out.
  456. if( (pLcl->ddsCaps.dwCaps & DDSCAPS_TEXTURE) == 0 )
  457. {
  458. SetInitialized();
  459. return S_OK;
  460. }
  461. // Set the transparent bit and the transparent color with pDDS[0]
  462. if ((pLcl->dwFlags & DDRAWISURF_HASCKEYSRCBLT) != 0)
  463. {
  464. m_uFlags |= RR_TEXTURE_HAS_CK;
  465. m_dwColorKey = pLcl->ddckCKSrcBlt.dwColorSpaceLowValue;
  466. }
  467. else
  468. {
  469. m_uFlags &= ~RR_TEXTURE_HAS_CK;
  470. }
  471. // set the empty face color with pDDS[0]
  472. // note that ddckCKDestOverlay is unioned with dwEmptyFaceColor,
  473. // but not in the internal structure
  474. m_dwEmptyFaceColor = pLcl->ddckCKDestOverlay.dwColorSpaceLowValue;
  475. if (pMore->ddsCapsEx.dwCaps2 & DDSCAPS2_VOLUME)
  476. {
  477. m_uFlags |= RR_TEXTURE_VOLUME;
  478. m_cDimension = 3;
  479. }
  480. else
  481. {
  482. m_cDimension = 2;
  483. }
  484. // Compute sizes and pitches
  485. // We need to gather info on all surfaces under the top-level
  486. // mipmap face (This test is DX7+ runtime dependent)
  487. if ((0 == (pMore->ddsCapsEx.dwCaps2 & DDSCAPS2_MIPMAPSUBLEVEL)) &&
  488. (pMore->ddsCapsEx.dwCaps2 & DDSCAPS2_CUBEMAP_POSITIVEX) )
  489. {
  490. m_uFlags |= RR_TEXTURE_CUBEMAP;
  491. LPDDRAWI_DDRAWSURFACE_LCL pDDSNextLcl;
  492. ddscaps.dwCaps = DDSCAPS_TEXTURE;
  493. m_pDDSLcl[0] = pLcl;
  494. m_pBits[0] = (BYTE *)SURFACE_MEMORY(m_pDDSLcl[0]);
  495. m_iPitch[0] = ComputePitch( m_pDDSLcl[0] );
  496. m_iSlicePitch[0] = 0;
  497. // get rest of top level surfaces, in order
  498. for (INT i = 1; i < 6; i++)
  499. {
  500. switch(i)
  501. {
  502. case 1: ddscaps.dwCaps2 = DDSCAPS2_CUBEMAP_NEGATIVEX; break;
  503. case 2: ddscaps.dwCaps2 = DDSCAPS2_CUBEMAP_POSITIVEY; break;
  504. case 3: ddscaps.dwCaps2 = DDSCAPS2_CUBEMAP_NEGATIVEY; break;
  505. case 4: ddscaps.dwCaps2 = DDSCAPS2_CUBEMAP_POSITIVEZ; break;
  506. case 5: ddscaps.dwCaps2 = DDSCAPS2_CUBEMAP_NEGATIVEZ; break;
  507. }
  508. ddscaps.dwCaps2 |= DDSCAPS2_CUBEMAP;
  509. pDDSNextLcl = NULL;
  510. hr = DDGetAttachedSurfaceLcl( pLcl, &ddscaps, &pDDSNextLcl);
  511. if ((hr != D3D_OK) && (hr != DDERR_NOTFOUND))
  512. {
  513. return hr;
  514. }
  515. if (hr == DDERR_NOTFOUND)
  516. {
  517. m_pDDSLcl[i] = NULL;
  518. return hr;
  519. }
  520. else
  521. {
  522. m_pDDSLcl[i] = pDDSNextLcl;
  523. }
  524. m_pBits[i] = (BYTE *)SURFACE_MEMORY(m_pDDSLcl[i]);
  525. m_iPitch[i] = ComputePitch( m_pDDSLcl[i] );
  526. m_iSlicePitch[i] = 0;
  527. m_cTexels[i][0] = DDSurf_Width(m_pDDSLcl[i]);
  528. m_cTexels[i][1] = DDSurf_Height(m_pDDSLcl[i]);
  529. m_fTexels[i][0] = (float)m_cTexels[i][0];
  530. m_fTexels[i][1] = (float)m_cTexels[i][1];
  531. }
  532. for (i = 0; i < 6; i++)
  533. {
  534. pLcl = m_pDDSLcl[i];
  535. m_cLOD = 0;
  536. if (pLcl)
  537. {
  538. // Check for mipmap if any.
  539. LPDDRAWI_DDRAWSURFACE_LCL pTmpSLcl;
  540. // iPreSizeU and iPreSizeV store the size(u and v) of the
  541. // previous level mipmap. They are init'ed with the first
  542. // texture size.
  543. INT16 iPreSizeU = (INT16)m_iWidth;
  544. INT16 iPreSizeV = (INT16)m_iHeight;
  545. for (;;)
  546. {
  547. ddscaps.dwCaps = DDSCAPS_TEXTURE;
  548. ddscaps.dwCaps2 = DDSCAPS2_MIPMAPSUBLEVEL;
  549. pTmpSLcl = NULL;
  550. hr = DDGetAttachedSurfaceLcl( pLcl, &ddscaps, &pTmpSLcl);
  551. if (hr != D3D_OK && hr != DDERR_NOTFOUND)
  552. {
  553. return hr;
  554. }
  555. if (hr == DDERR_NOTFOUND)
  556. {
  557. break;
  558. }
  559. pLcl = pTmpSLcl;
  560. pGbl = pLcl->lpGbl;
  561. pMore = pLcl->lpSurfMore;
  562. m_cLOD ++;
  563. INT iMap = m_cLOD*6+i;
  564. m_pDDSLcl[iMap] = pLcl;
  565. m_pBits[iMap] = (BYTE *)SURFACE_MEMORY(pLcl);
  566. m_iPitch[iMap] = ComputePitch( pLcl, m_SurfFormat,
  567. m_iWidth>>m_cLOD,
  568. m_iHeight>>m_cLOD );
  569. if (pMore->ddsCapsEx.dwCaps2 & DDSCAPS2_VOLUME)
  570. {
  571. // set slice pitch
  572. // (volume texture only).
  573. m_iSlicePitch[iMap] = pGbl->lSlicePitch;
  574. }
  575. else
  576. {
  577. m_iSlicePitch[iMap] = 0;
  578. }
  579. m_cTexels[iMap][0] = DDSurf_Width(pLcl);
  580. m_cTexels[iMap][1] = DDSurf_Height(pLcl);
  581. m_fTexels[iMap][0] = (float)m_cTexels[iMap][0];
  582. m_fTexels[iMap][1] = (float)m_cTexels[iMap][1];
  583. // Check for invalid mipmap texture size
  584. if (!ValidMipmapSize(iPreSizeU,
  585. (INT16)DDSurf_Width(pLcl)) ||
  586. !ValidMipmapSize(iPreSizeV,
  587. (INT16)DDSurf_Height(pLcl)))
  588. {
  589. return DDERR_INVALIDPARAMS;
  590. }
  591. iPreSizeU = (INT16)DDSurf_Width(pLcl);
  592. iPreSizeV = (INT16)DDSurf_Height(pLcl);
  593. }
  594. }
  595. }
  596. }
  597. else if ((0 == (pMore->ddsCapsEx.dwCaps2 & DDSCAPS2_MIPMAPSUBLEVEL) &&
  598. (0 == (pMore->ddsCapsEx.dwCaps2 & DDSCAPS2_CUBEMAP))) )
  599. {
  600. //This surface is not a top-level cubemap.
  601. //Maybe it's a top-level mipmap. Go find its sublevels.
  602. m_pDDSLcl[0] = pLcl;
  603. // Check for mipmap if any.
  604. LPDDRAWI_DDRAWSURFACE_LCL pTmpSLcl;
  605. // iPreSizeU and iPreSizeV store the size(u and v) of the previous
  606. // level mipmap. They are init'ed with the first texture size.
  607. INT16 iPreSizeU = (INT16)m_iWidth;
  608. INT16 iPreSizeV = (INT16)m_iHeight;
  609. for (;;)
  610. {
  611. ddscaps.dwCaps = DDSCAPS_TEXTURE;
  612. ddscaps.dwCaps2 = DDSCAPS2_MIPMAPSUBLEVEL;
  613. pTmpSLcl = NULL;
  614. hr = DDGetAttachedSurfaceLcl( pLcl, &ddscaps, &pTmpSLcl);
  615. if (hr != D3D_OK && hr != DDERR_NOTFOUND)
  616. {
  617. return hr;
  618. }
  619. if (hr == DDERR_NOTFOUND)
  620. {
  621. break;
  622. }
  623. pLcl = pTmpSLcl;
  624. pGbl = pLcl->lpGbl;
  625. pMore = pLcl->lpSurfMore;
  626. m_cLOD ++;
  627. m_pDDSLcl[m_cLOD] = pLcl;
  628. // Save the pointer to the real bits and the pitch.
  629. m_pBits[m_cLOD] = (BYTE *)SURFACE_MEMORY(pLcl);
  630. m_iPitch[m_cLOD] = ComputePitch( pLcl, m_SurfFormat,
  631. m_iWidth>>m_cLOD,
  632. m_iHeight>>m_cLOD );
  633. if (pMore->ddsCapsEx.dwCaps2 & DDSCAPS2_VOLUME)
  634. {
  635. // set slice pitch (volume texture only).
  636. m_iSlicePitch[m_cLOD] = pGbl->lSlicePitch;
  637. }
  638. else
  639. {
  640. m_iSlicePitch[m_cLOD] = 0;
  641. }
  642. // Check for invalid mipmap texture size
  643. if (!ValidMipmapSize(iPreSizeU, (INT16)DDSurf_Width(pLcl)) ||
  644. !ValidMipmapSize(iPreSizeV, (INT16)DDSurf_Height(pLcl)))
  645. {
  646. return DDERR_INVALIDPARAMS;
  647. }
  648. iPreSizeU = (INT16)DDSurf_Width(pLcl);
  649. iPreSizeV = (INT16)DDSurf_Height(pLcl);
  650. m_cTexels[m_cLOD][0] = DDSurf_Width(pLcl);
  651. m_cTexels[m_cLOD][1] = DDSurf_Height(pLcl);
  652. if (pMore->ddsCapsEx.dwCaps2 & DDSCAPS2_VOLUME)
  653. m_cTexels[m_cLOD][2] = LOWORD(pMore->ddsCapsEx.dwCaps4);
  654. else
  655. m_cTexels[m_cLOD][2] = 0;
  656. m_fTexels[m_cLOD][0] = (float)m_cTexels[m_cLOD][0];
  657. m_fTexels[m_cLOD][1] = (float)m_cTexels[m_cLOD][1];
  658. m_fTexels[m_cLOD][2] = (float)m_cTexels[m_cLOD][2];
  659. }
  660. }
  661. // Copy the palette
  662. // UpdatePalette();
  663. m_cLODDDS = m_cLOD;
  664. if ( !(Validate()) )
  665. {
  666. return DDERR_GENERIC;
  667. }
  668. SetInitialized();
  669. return D3D_OK;
  670. }
  671. //----------------------------------------------------------------------------
  672. //
  673. // UpdatePalette
  674. //
  675. //----------------------------------------------------------------------------
  676. void
  677. RDSurface2D::UpdatePalette()
  678. {
  679. // Update palette
  680. if (m_SurfFormat == RD_SF_PALETTE8 || m_SurfFormat == RD_SF_PALETTE4 || m_SurfFormat == RD_SF_P8A8 )
  681. {
  682. #if 0
  683. // This code needs to be revived in case the DX6 DDI
  684. // emulation is ever implemented in RefDev.
  685. if (m_pDDSLcl[0]->lpDDPalette)
  686. {
  687. LPDDRAWI_DDRAWPALETTE_GBL pPal =
  688. m_pDDSLcl[0]->lpDDPalette->lpLcl->lpGbl;
  689. m_pPalette = (DWORD*)pPal->lpColorTable;
  690. if (pPal->dwFlags & DDRAWIPAL_ALPHA)
  691. {
  692. m_uFlags |= RR_TEXTURE_ALPHAINPALETTE;
  693. }
  694. else
  695. {
  696. m_uFlags &= ~RR_TEXTURE_ALPHAINPALETTE;
  697. }
  698. }
  699. #endif
  700. _ASSERT( m_pPalObj, "No Palette set for this paletted texture\n" );
  701. m_pPalette = m_pPalObj->GetEntries();
  702. if( m_SurfFormat == RD_SF_PALETTE8 || m_SurfFormat == RD_SF_PALETTE4 )
  703. {
  704. if( m_pPalObj->HasAlpha() )
  705. {
  706. m_uFlags |= RR_TEXTURE_ALPHAINPALETTE;
  707. }
  708. else
  709. {
  710. m_uFlags &= ~RR_TEXTURE_ALPHAINPALETTE;
  711. }
  712. }
  713. }
  714. }
  715. //-----------------------------------------------------------------------------
  716. //
  717. // Validate - Updates private data. Must be called anytime public data is
  718. // altered.
  719. //
  720. //-----------------------------------------------------------------------------
  721. BOOL
  722. RDSurface2D::Validate( void )
  723. {
  724. // validate inputs
  725. if ( m_cLOD >= RD_MAX_CLOD ) // too many LODs
  726. {
  727. DPFRR(1,"RDSurface2D::Validate failed. Too many LODs");
  728. return FALSE;
  729. }
  730. // compute the 'has alpha' flag
  731. m_bHasAlpha = FALSE;
  732. switch ( m_SurfFormat )
  733. {
  734. case RD_SF_A8:
  735. case RD_SF_P8A8:
  736. case RD_SF_B8G8R8A8:
  737. case RD_SF_B5G5R5A1:
  738. case RD_SF_B4G4R4A4:
  739. case RD_SF_L8A8:
  740. case RD_SF_L4A4:
  741. case RD_SF_B2G3R3A8:
  742. case RD_SF_DXT1:
  743. case RD_SF_DXT2:
  744. case RD_SF_DXT3:
  745. case RD_SF_DXT4:
  746. case RD_SF_DXT5:
  747. m_bHasAlpha = TRUE;
  748. break;
  749. case RD_SF_PALETTE4:
  750. case RD_SF_PALETTE8:
  751. m_bHasAlpha = ( m_uFlags & RR_TEXTURE_ALPHAINPALETTE ) ? TRUE : FALSE;
  752. break;
  753. }
  754. return TRUE;
  755. }
  756. //-----------------------------------------------------------------------------
  757. //
  758. //-----------------------------------------------------------------------------
  759. inline UINT8 CLAMP_BYTE(double f)
  760. {
  761. if (f > 255.0) return 255;
  762. if (f < 0.0) return 0;
  763. return (BYTE) f;
  764. }
  765. //-----------------------------------------------------------------------------
  766. // TexelFromBlock - decompress a color block and obtain texel color
  767. //-----------------------------------------------------------------------------
  768. UINT32 TexelFromBlock(RDSurfaceFormat surfType, char *pblockSrc,
  769. int x, int y)
  770. {
  771. UINT32 index = ((y & 0x3)<<2) + (x & 0x3);
  772. DDRGBA colorDst[DXT_BLOCK_PIXELS];
  773. switch(surfType)
  774. {
  775. case RD_SF_DXT1:
  776. DecodeBlockRGB((DXTBlockRGB *)pblockSrc, (DXT_COLOR *)colorDst);
  777. break;
  778. case RD_SF_DXT2:
  779. case RD_SF_DXT3:
  780. DecodeBlockAlpha4((DXTBlockAlpha4 *)pblockSrc,
  781. (DXT_COLOR *)colorDst);
  782. break;
  783. case RD_SF_DXT4:
  784. case RD_SF_DXT5:
  785. DecodeBlockAlpha3((DXTBlockAlpha3 *)pblockSrc,
  786. (DXT_COLOR *)colorDst);
  787. break;
  788. }
  789. return RGBA_MAKE(colorDst[index].red,
  790. colorDst[index].green,
  791. colorDst[index].blue,
  792. colorDst[index].alpha);
  793. }
  794. //-----------------------------------------------------------------------------
  795. //
  796. // ReadTexelColor - Reads texel from texture map at given LOD; converts to
  797. // RDColor format, applying palette if necessary; also performs colorkey by
  798. // returning match information
  799. //
  800. //-----------------------------------------------------------------------------
  801. void
  802. RDSurface2D::ReadColor(
  803. INT32 iX, INT32 iY, INT32 iZ, INT32 iLOD,
  804. RDColor& Texel, BOOL &bColorKeyKill )
  805. {
  806. if ( (iLOD > m_cLOD) && !(m_uFlags & RR_TEXTURE_CUBEMAP) )
  807. {
  808. return;
  809. }
  810. if ( NULL == m_pBits[iLOD] ) { return; }
  811. char* pSurfaceBits =
  812. PixelAddress( iX, iY, iZ, m_pBits[iLOD],
  813. m_iPitch[iLOD], m_iSlicePitch[iLOD], m_SurfFormat );
  814. switch ( m_SurfFormat )
  815. {
  816. default:
  817. Texel.ConvertFrom( m_SurfFormat, pSurfaceBits );
  818. break;
  819. case RD_SF_P8A8:
  820. {
  821. UINT8 uIndex = *((UINT8*)pSurfaceBits);
  822. Texel.ConvertFrom( RD_SF_B8G8R8A8, (char*)((UINT32*)m_pPalette + uIndex) );
  823. Texel.A = *((UINT8*)pSurfaceBits+1)/255.f;
  824. }
  825. break;
  826. case RD_SF_PALETTE8:
  827. {
  828. UINT8 uIndex = *((UINT8*)pSurfaceBits);
  829. Texel.ConvertFrom( RD_SF_B8G8R8A8, (char*)((UINT32*)m_pPalette + uIndex) );
  830. if ( !( m_uFlags & RR_TEXTURE_ALPHAINPALETTE ) ) Texel.A = 1.f;
  831. }
  832. break;
  833. case RD_SF_PALETTE4:
  834. {
  835. UINT8 uIndex = *((INT8*)pSurfaceBits);
  836. if ((iX & 1) == 0) { uIndex &= 0xf; }
  837. else { uIndex >>= 4; }
  838. Texel.ConvertFrom( RD_SF_B8G8R8A8, (char*)((UINT32*)m_pPalette + uIndex) );
  839. if ( !( m_uFlags & RR_TEXTURE_ALPHAINPALETTE ) ) Texel.A = 1.f;
  840. }
  841. break;
  842. case RD_SF_UYVY:
  843. case RD_SF_YUY2:
  844. // Converts a given YUV (8bits each) to RGB scaled between 0 and 255
  845. // These are using the YCrCb to RGB algorithms given on page 30
  846. // in "VIDEO DEMYSTIFIED" by Keith Jack
  847. // ISBN#: 1-878707-09-4
  848. // IN PC graphics, even though they call it YUV, it is really YCrCb
  849. // formats that are used by most framegrabbers etc. Hence the pixel
  850. // data we will obtain in these YUV surfaces will most likely be this
  851. // and not the original YUV which is actually used in PAL broadcast
  852. // only (NTSC uses YIQ). So really, U should be called Cb (Blue color
  853. // difference) and V should be called Cr (Red color difference)
  854. //
  855. // These equations are meant to handle the following ranges
  856. // (from the same book):
  857. // Y (16 to 235), U and V (16 to 240, 128 = zero)
  858. // -----------
  859. // Y U V
  860. // -----------
  861. // White : 180 128 128
  862. // Black : 16 128 128
  863. // Red : 65 100 212
  864. // Green : 112 72 58
  865. // Blue : 35 212 114
  866. // Yellow : 162 44 142
  867. // Cyan : 131 156 44
  868. // Magenta: 84 184 198
  869. // -----------
  870. // It is assumed that the gamma corrected RGB range is (0 - 255)
  871. //
  872. // UYVY: U0Y0 V0Y1 U2Y2 V2Y3 (low byte always has current Y)
  873. // If iX is even, hight-byte has current U (Cb)
  874. // If iX is odd, hight-byte has previous V (Cr)
  875. //
  876. // YUY2: Y0U0 Y1V0 Y2U2 Y3V2 (high byte always has current Y)
  877. // (UYVY bytes flipped)
  878. //
  879. // In this algorithm, we use U and V values from two neighboring
  880. // pixels
  881. {
  882. UINT8 Y, U, V;
  883. UINT16 u16Curr = *((UINT16*)pSurfaceBits);
  884. UINT16 u16ForU = 0; // Extract U from this
  885. UINT16 u16ForV = 0; // Extract V from this
  886. // By default we assume YUY2. Change it later if it is UYVY
  887. int uvShift = 8;
  888. int yShift = 0;
  889. if (m_SurfFormat == RD_SF_UYVY)
  890. {
  891. uvShift = 0;
  892. yShift = 8;
  893. }
  894. if ((iX & 1) == 0)
  895. {
  896. // For even numbered pixels:
  897. // Current U is available.
  898. // Current V is available in the next pixel.
  899. u16ForU = u16Curr;
  900. // Obtain V from the next pixel
  901. u16ForV = *((UINT16*)PixelAddress( iX+1, iY, iZ,
  902. m_pBits[iLOD],
  903. m_iPitch[iLOD],
  904. m_iSlicePitch[iLOD],
  905. m_SurfFormat ));
  906. U = (u16ForU >> uvShift) & 0xff;
  907. V = (u16ForV >> uvShift) & 0xff;
  908. }
  909. else
  910. {
  911. UINT16 u16ForU1 = 0, u16ForU2 = 0;
  912. UINT16 u16ForV1 = 0, u16ForV2 = 0;
  913. // For odd numbered pixels. Neither current U nor V are
  914. // available.
  915. // Obtain U by interpolating U from i-1 and i+1 pixels.
  916. _ASSERT( iX > 0, "iX is negative" );
  917. u16ForU1 = *((UINT16*)PixelAddress( iX-1, iY, iZ,
  918. m_pBits[iLOD],
  919. m_iPitch[iLOD],
  920. m_iSlicePitch[iLOD],
  921. m_SurfFormat ));
  922. if( (iX+1) < (m_iWidth >> iLOD) )
  923. {
  924. u16ForU2 = *((UINT16*)PixelAddress( iX+1, iY, iZ,
  925. m_pBits[iLOD],
  926. m_iPitch[iLOD],
  927. m_iSlicePitch[iLOD],
  928. m_SurfFormat ));
  929. U = (((u16ForU1 >> uvShift) & 0xff) +
  930. ((u16ForU2 >> uvShift) & 0xff)) >> 1;
  931. }
  932. else
  933. {
  934. U = (u16ForU1 >> uvShift) & 0xff;
  935. }
  936. // Obtain V by interpolating V from i and i+2 pixels.
  937. u16ForV1 = u16Curr;
  938. if( (iX+2) < (m_iWidth >> iLOD) )
  939. {
  940. u16ForV2 = *((UINT16*)PixelAddress( iX+2, iY, iZ,
  941. m_pBits[iLOD],
  942. m_iPitch[iLOD],
  943. m_iSlicePitch[iLOD],
  944. m_SurfFormat ));
  945. V = (((u16ForV1 >> uvShift) & 0xff) +
  946. ((u16ForV2 >> uvShift) & 0xff)) >> 1;
  947. }
  948. else
  949. {
  950. V = (u16ForV1 >> uvShift) & 0xff;
  951. }
  952. }
  953. Y = (u16Curr >> yShift) & 0xff;
  954. Texel = RGB_MAKE(
  955. CLAMP_BYTE(1.164*(Y-16) + 1.596*(V-128)),
  956. CLAMP_BYTE(1.164*(Y-16) - 0.813*(V-128) - 0.391*(U-128)),
  957. CLAMP_BYTE(1.164*(Y-16) + 2.018*(U-128))
  958. );
  959. Texel.A = 1.f;
  960. }
  961. break;
  962. // DXTn compressed formats:
  963. // We have the address to the block, now extract the actual color
  964. case RD_SF_DXT1:
  965. case RD_SF_DXT2:
  966. case RD_SF_DXT3:
  967. case RD_SF_DXT4:
  968. case RD_SF_DXT5:
  969. Texel = TexelFromBlock(m_SurfFormat, pSurfaceBits, iX, iY);
  970. break;
  971. }
  972. // colorkey
  973. if ( m_pRefDev->ColorKeyEnabled() )
  974. {
  975. DWORD dwBits;
  976. switch ( m_SurfFormat )
  977. {
  978. default:
  979. case RD_SF_NULL:
  980. return; // don't colorkey unknown or null surfaces
  981. case RD_SF_PALETTE4:
  982. {
  983. UINT8 uIndex = *((INT8*)pSurfaceBits);
  984. if ((iX & 1) == 0) { uIndex &= 0xf; }
  985. else { uIndex >>= 4; }
  986. dwBits = (DWORD)uIndex;
  987. }
  988. break;
  989. case RD_SF_L8:
  990. case RD_SF_A8:
  991. case RD_SF_PALETTE8:
  992. case RD_SF_B2G3R3:
  993. case RD_SF_L4A4:
  994. {
  995. UINT8 uBits = *((UINT8*)pSurfaceBits);
  996. dwBits = (DWORD)uBits;
  997. }
  998. break;
  999. case RD_SF_B5G6R5:
  1000. case RD_SF_B5G5R5X1:
  1001. case RD_SF_B5G5R5A1:
  1002. case RD_SF_B4G4R4A4:
  1003. case RD_SF_B4G4R4X4:
  1004. case RD_SF_L8A8:
  1005. case RD_SF_P8A8:
  1006. case RD_SF_B2G3R3A8:
  1007. {
  1008. UINT16 uBits = *((UINT16*)pSurfaceBits);
  1009. dwBits = (DWORD)uBits;
  1010. }
  1011. break;
  1012. case RD_SF_B8G8R8:
  1013. {
  1014. UINT32 uBits = 0;
  1015. uBits |= ( *((UINT8*)pSurfaceBits+0) ) << 0;
  1016. uBits |= ( *((UINT8*)pSurfaceBits+1) ) << 8;
  1017. uBits |= ( *((UINT8*)pSurfaceBits+2) ) << 16;
  1018. dwBits = (DWORD)uBits;
  1019. }
  1020. break;
  1021. case RD_SF_B8G8R8A8:
  1022. case RD_SF_B8G8R8X8:
  1023. {
  1024. UINT32 uBits = *((UINT32*)pSurfaceBits);
  1025. dwBits = (DWORD)uBits;
  1026. }
  1027. break;
  1028. }
  1029. DWORD ColorKey = m_dwColorKey;
  1030. if ( dwBits == ColorKey )
  1031. {
  1032. if (m_pRefDev->GetRS()[D3DRENDERSTATE_COLORKEYENABLE])
  1033. {
  1034. bColorKeyKill = TRUE;
  1035. }
  1036. if (m_pRefDev->GetRS()[D3DRENDERSTATE_COLORKEYBLENDENABLE])
  1037. {
  1038. Texel.R = 0.F;
  1039. Texel.G = 0.F;
  1040. Texel.B = 0.F;
  1041. Texel.A = 0.F;
  1042. }
  1043. }
  1044. }
  1045. }
  1046. ///////////////////////////////////////////////////////////////////////////////
  1047. // end