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.

1072 lines
37 KiB

  1. /******************************Module*Header**********************************\
  2. *
  3. * **************************
  4. * * DirectDraw SAMPLE CODE *
  5. * **************************
  6. *
  7. * Module Name: ddsurf.c
  8. *
  9. * Content:
  10. *
  11. * Copyright (c) 1994-1998 3Dlabs Inc. Ltd. All rights reserved.
  12. * Copyright (c) 1995-1999 Microsoft Corporation. All rights reserved.
  13. \*****************************************************************************/
  14. #include "precomp.h"
  15. #include "directx.h"
  16. #include "dd.h"
  17. #include "heap.h"
  18. #include "d3dtxman.h"
  19. #define ALLOC_TAG ALLOC_TAG_US2P
  20. // Texture tables defined in the D3D side of the driver (d3d.c)
  21. // TODO: move to dd.h or d3d.h
  22. extern ULONG gD3DNumberOfTextureFormats;
  23. extern DDSURFACEDESC gD3DTextureFormats[];
  24. //---------------------------------------------------------------------------
  25. // BOOL bComparePixelFormat
  26. //
  27. // Function used to compare 2 pixels formats for equality. This is a
  28. // helper function to bCheckTextureFormat. A return value of TRUE indicates
  29. // equality
  30. //
  31. //---------------------------------------------------------------------------
  32. BOOL
  33. bComparePixelFormat(LPDDPIXELFORMAT lpddpf1, LPDDPIXELFORMAT lpddpf2)
  34. {
  35. if (lpddpf1->dwFlags != lpddpf2->dwFlags)
  36. {
  37. return FALSE;
  38. }
  39. // same bitcount for non-YUV surfaces?
  40. if (!(lpddpf1->dwFlags & (DDPF_YUV | DDPF_FOURCC)))
  41. {
  42. if (lpddpf1->dwRGBBitCount != lpddpf2->dwRGBBitCount )
  43. {
  44. return FALSE;
  45. }
  46. }
  47. // same RGB properties?
  48. if (lpddpf1->dwFlags & DDPF_RGB)
  49. {
  50. if ((lpddpf1->dwRBitMask != lpddpf2->dwRBitMask) ||
  51. (lpddpf1->dwGBitMask != lpddpf2->dwGBitMask) ||
  52. (lpddpf1->dwBBitMask != lpddpf2->dwBBitMask) ||
  53. (lpddpf1->dwRGBAlphaBitMask != lpddpf2->dwRGBAlphaBitMask))
  54. {
  55. return FALSE;
  56. }
  57. }
  58. // same YUV properties?
  59. if (lpddpf1->dwFlags & DDPF_YUV)
  60. {
  61. if ((lpddpf1->dwFourCC != lpddpf2->dwFourCC) ||
  62. (lpddpf1->dwYUVBitCount != lpddpf2->dwYUVBitCount) ||
  63. (lpddpf1->dwYBitMask != lpddpf2->dwYBitMask) ||
  64. (lpddpf1->dwUBitMask != lpddpf2->dwUBitMask) ||
  65. (lpddpf1->dwVBitMask != lpddpf2->dwVBitMask) ||
  66. (lpddpf1->dwYUVAlphaBitMask != lpddpf2->dwYUVAlphaBitMask))
  67. {
  68. return FALSE;
  69. }
  70. }
  71. else if (lpddpf1->dwFlags & DDPF_FOURCC)
  72. {
  73. if (lpddpf1->dwFourCC != lpddpf2->dwFourCC)
  74. {
  75. return FALSE;
  76. }
  77. }
  78. // If Interleaved Z then check Z bit masks are the same
  79. if (lpddpf1->dwFlags & DDPF_ZPIXELS)
  80. {
  81. if (lpddpf1->dwRGBZBitMask != lpddpf2->dwRGBZBitMask)
  82. {
  83. return FALSE;
  84. }
  85. }
  86. return TRUE;
  87. } // bComparePixelFormat
  88. //---------------------------------------------------------------------------
  89. //
  90. // BOOL bCheckTextureFormat
  91. //
  92. // Function used to determine if a texture format is supported. It traverses
  93. // the deviceTextureFormats list. We use this in DdCanCreateSurface32. A
  94. // return value of TRUE indicates that we do support the requested texture
  95. // format.
  96. //
  97. //---------------------------------------------------------------------------
  98. BOOL
  99. bCheckTextureFormat(LPDDPIXELFORMAT lpddpf)
  100. {
  101. DWORD i;
  102. // Run the list for a matching format
  103. for (i=0; i < gD3DNumberOfTextureFormats; i++)
  104. {
  105. if (bComparePixelFormat(lpddpf,
  106. &gD3DTextureFormats[i].ddpfPixelFormat))
  107. {
  108. return TRUE;
  109. }
  110. }
  111. return FALSE;
  112. } // bCheckTextureFormat
  113. //-----------------------------------------------------------------------------
  114. //
  115. // DdCanCreateSurface32
  116. //
  117. // This entry point is called after parameter validation but before
  118. // any object creation. You can decide here if it is possible for
  119. // you to create this surface. For example, if the person is trying
  120. // to create an overlay, and you already have the maximum number of
  121. // overlays created, this is the place to fail the call.
  122. //
  123. // You also need to check if the pixel format specified can be supported.
  124. //
  125. //-----------------------------------------------------------------------------
  126. DWORD CALLBACK
  127. DdCanCreateSurface(LPDDHAL_CANCREATESURFACEDATA pccsd)
  128. {
  129. PPDev ppdev=(PPDev)pccsd->lpDD->dhpdev;
  130. PERMEDIA_DEFS(ppdev);
  131. PDD_SURFACEDESC lpDDS=pccsd->lpDDSurfaceDesc;
  132. DBG_DD((2,"DDraw:DdCanCreateSurface"));
  133. if(lpDDS->dwLinearSize == 0)
  134. {
  135. // rectangular surface
  136. // Reject all widths larger than we can create partial products for.
  137. DUMPSURFACE(10, NULL, lpDDS);
  138. if (lpDDS->dwWidth > (ULONG)(2 << MAX_PARTIAL_PRODUCT_P2))
  139. {
  140. DBG_DD((1,"DDraw:DdCanCreateSurface: Surface rejected:"));
  141. DBG_DD((1," Width Requested: %ld (max. %ld)",
  142. lpDDS->dwWidth,(2 << MAX_PARTIAL_PRODUCT_P2)));
  143. pccsd->ddRVal = DDERR_INVALIDPIXELFORMAT;
  144. return DDHAL_DRIVER_HANDLED;
  145. }
  146. }
  147. // We only support 16bits & 15bits (for stencils) Z-Buffer on PERMEDIA
  148. if ((lpDDS->ddsCaps.dwCaps & DDSCAPS_ZBUFFER) &&
  149. (lpDDS->ddsCaps.dwCaps & DDSCAPS_VIDEOMEMORY))
  150. {
  151. DWORD dwBitDepth;
  152. // verify where the right z buffer bit depth is
  153. if (DDSD_ZBUFFERBITDEPTH & lpDDS->dwFlags)
  154. dwBitDepth = lpDDS->dwZBufferBitDepth;
  155. else
  156. dwBitDepth = lpDDS->ddpfPixelFormat.dwZBufferBitDepth;
  157. // Notice we have to check for a BitDepth of 16 even if a stencil
  158. // buffer is present. dwZBufferBitDepth in this case will be the
  159. // sum of the z buffer and the stencil buffer bit depth.
  160. if (dwBitDepth == 16)
  161. {
  162. pccsd->ddRVal = DD_OK;
  163. }
  164. else
  165. {
  166. DBG_DD((2,"DDraw:DdCanCreateSurface: ERROR: "
  167. "Depth buffer not 16Bits! - %d", dwBitDepth));
  168. pccsd->ddRVal = DDERR_INVALIDPIXELFORMAT;
  169. }
  170. return DDHAL_DRIVER_HANDLED;
  171. }
  172. // pccsd->bIsDifferentPixelFormat tells us if the pixel format of the
  173. // surface being created matches that of the primary surface. It can be
  174. // true for Z buffer and alpha buffers, so don't just reject it out of
  175. // hand...
  176. if (pccsd->bIsDifferentPixelFormat)
  177. {
  178. DBG_DD((3," Pixel Format is different to primary"));
  179. if(lpDDS->ddpfPixelFormat.dwFlags & DDPF_FOURCC)
  180. {
  181. DBG_DD((3, " FourCC requested (%4.4hs, 0x%08lx)", (LPSTR)
  182. &lpDDS->ddpfPixelFormat.dwFourCC,
  183. lpDDS->ddpfPixelFormat.dwFourCC ));
  184. switch (lpDDS->ddpfPixelFormat.dwFourCC)
  185. {
  186. case FOURCC_YUV422:
  187. DBG_DD((3," Surface requested is YUV422"));
  188. if (ppdev->iBitmapFormat == BMF_8BPP)
  189. {
  190. pccsd->ddRVal = DDERR_INVALIDPIXELFORMAT;
  191. } else
  192. {
  193. lpDDS->ddpfPixelFormat.dwYUVBitCount = 16;
  194. pccsd->ddRVal = DD_OK;
  195. }
  196. return DDHAL_DRIVER_HANDLED;
  197. default:
  198. DBG_DD((3," ERROR: Invalid FOURCC requested, refusing"));
  199. pccsd->ddRVal = DDERR_INVALIDPIXELFORMAT;
  200. return DDHAL_DRIVER_HANDLED;
  201. }
  202. }
  203. else if((lpDDS->ddsCaps.dwCaps & DDSCAPS_TEXTURE))
  204. {
  205. if (bCheckTextureFormat(&pccsd->lpDDSurfaceDesc->ddpfPixelFormat))
  206. {
  207. // texture surface is in one or our supported texture formats
  208. DBG_DD((3, " Texture Surface - OK" ));
  209. pccsd->ddRVal = DD_OK;
  210. return DDHAL_DRIVER_HANDLED;
  211. }
  212. else
  213. {
  214. // we don't support this kind of texture format
  215. DBG_DD((3, " ERROR: Texture Surface - NOT OK" ));
  216. pccsd->ddRVal = DDERR_INVALIDPIXELFORMAT;
  217. return DDHAL_DRIVER_HANDLED;
  218. }
  219. }
  220. //@@BEGIN_DDKSPLIT
  221. #if DX7_ALPHABLT
  222. else if (ValidRGBAlphaSurfaceformat(
  223. &lpDDS->ddpfPixelFormat,
  224. NULL))
  225. {
  226. DBG_DD((3, " RGB alpha Surface - OK" ));
  227. if (lpDDS->ddpfPixelFormat.dwRGBBitCount!=24)
  228. {
  229. pccsd->ddRVal = DD_OK;
  230. return DDHAL_DRIVER_HANDLED;
  231. }
  232. }
  233. #endif
  234. //@@END_DDKSPLIT
  235. pccsd->ddRVal = DDERR_INVALIDPIXELFORMAT;
  236. return DDHAL_DRIVER_HANDLED;
  237. }
  238. pccsd->ddRVal = DD_OK;
  239. return DDHAL_DRIVER_HANDLED;
  240. } // DdCanCreateSurface32
  241. //-----------------------------------------------------------------------------
  242. //
  243. // DdCreateSurface
  244. //
  245. // This function is called by DirectDraw if a new surface is created. If the
  246. // driver has its own memory manager, here is the place to allocate the
  247. // videomemory or to fail the call. Note that we return
  248. // DDHAL_DRIVER_NOTHANDLED here to indicate that we do not manage the heap.
  249. // fpVidMem is set to DDHAL_PLEASEALLOC_BLOCKSIZE, and the DDraw memory
  250. // manager wll allocate the memory for us.
  251. //
  252. // Note that the Permedia chip requires a partial product
  253. // to be setup for each surface. They also limit the widths to a multiple
  254. // of 32 for the Partial Products to work. The below code adjusts the
  255. // surfaces to meet this requirement. Note that if we are using a
  256. // rectangular allocation scheme, the surface is already OK as the desktop
  257. // is a good width anyway. This code also handles YUV 16 Bit colour space
  258. // compressed format (FOURCC_YUV422) which will always be 16 bits, regardless
  259. // of the desktop resolution/requested depth.
  260. //
  261. //-----------------------------------------------------------------------------
  262. DWORD CALLBACK
  263. DdCreateSurface(PDD_CREATESURFACEDATA lpCreateSurface)
  264. {
  265. PPDev ppdev= (PPDev)lpCreateSurface->lpDD->dhpdev;
  266. PERMEDIA_DEFS(ppdev);
  267. DWORD dwBitDepth;
  268. DD_SURFACE_LOCAL* lpSurfaceLocal;
  269. DD_SURFACE_GLOBAL* lpSurfaceGlobal;
  270. LPDDSURFACEDESC lpSurfaceDesc;
  271. BOOL bYUV = FALSE;
  272. BOOL bResize = FALSE;
  273. DWORD dwExtraBytes;
  274. PermediaSurfaceData*pPrivateData = NULL;
  275. DBG_DD((2, "DdCreateSurface called"));
  276. //
  277. // See if any of these surfaces are Z buffers. If they are, ensure that the
  278. // pitch is a valid LB width. The minimum partial product is 32 words or
  279. // 32 pixels on Permedia 2
  280. //
  281. // On Windows NT, dwSCnt will always be 1, so there will only ever
  282. // be one entry in the 'lplpSList' array:
  283. //
  284. ASSERTDD(lpCreateSurface->dwSCnt == 1,
  285. "DdCreateSurface: Unexpected dwSCnt value not equal to one");
  286. lpSurfaceLocal = lpCreateSurface->lplpSList[0];
  287. lpSurfaceGlobal = lpSurfaceLocal->lpGbl;
  288. lpSurfaceDesc = lpCreateSurface->lpDDSurfaceDesc;
  289. //
  290. // We repeat the same checks we did in 'DdCanCreateSurface' because
  291. // it's possible that an application doesn't call 'DdCanCreateSurface'
  292. // before calling 'DdCreateSurface'.
  293. //
  294. ASSERTDD(lpSurfaceGlobal->ddpfSurface.dwSize == sizeof(DDPIXELFORMAT),
  295. "NT is supposed to guarantee that ddpfSurface.dwSize is valid");
  296. //
  297. // If the surface has already been allocated, don't reallocate it, just
  298. // reset it. This will happen if the surface is the primary surface.
  299. //
  300. if ( lpSurfaceGlobal->dwReserved1 != 0 )
  301. {
  302. pPrivateData = (PermediaSurfaceData*)lpSurfaceGlobal->dwReserved1;
  303. if ( CHECK_P2_SURFACEDATA_VALIDITY(pPrivateData) )
  304. {
  305. DBG_DD((0, " Already allocated Private Surface data 0x%x",
  306. pPrivateData));
  307. memset(pPrivateData, 0, sizeof(PermediaSurfaceData));
  308. }
  309. else
  310. {
  311. pPrivateData = NULL;
  312. }
  313. }
  314. //
  315. // If the data isn't valid allocate it.
  316. //
  317. if ( pPrivateData == NULL )
  318. {
  319. pPrivateData = (PermediaSurfaceData *)
  320. ENGALLOCMEM(FL_ZERO_MEMORY,
  321. sizeof(PermediaSurfaceData),
  322. ALLOC_TAG);
  323. if ( pPrivateData == NULL )
  324. {
  325. DBG_DD((0, "DDraw:DdCreateSurface: "
  326. "Not enough memory for private surface data!"));
  327. lpCreateSurface->ddRVal = DDERR_OUTOFMEMORY;
  328. return DDHAL_DRIVER_HANDLED;
  329. }
  330. }
  331. //
  332. // Store the pointer to the new data
  333. //
  334. lpSurfaceGlobal->dwReserved1 = (UINT_PTR)pPrivateData;
  335. DBG_DD((3,"DDraw:DdCreateSurface privatedata=0x%x lpGbl=0x%x lpLcl=0x%x "
  336. "dwFlags=%08lx &dwReserved1=0x%x", pPrivateData, lpSurfaceGlobal,
  337. lpSurfaceLocal, lpSurfaceLocal->dwFlags,
  338. &lpSurfaceGlobal->dwReserved1));
  339. //
  340. // Set the magic number
  341. //
  342. pPrivateData->MagicNo = SURF_MAGIC_NO;
  343. //
  344. // Store away the important information
  345. //
  346. SetupPrivateSurfaceData(ppdev, pPrivateData, lpSurfaceLocal);
  347. if ( pPrivateData->SurfaceFormat.PixelSize != __PERMEDIA_24BITPIXEL )
  348. {
  349. dwBitDepth = (8 << pPrivateData->SurfaceFormat.PixelSize);
  350. }
  351. else
  352. {
  353. dwBitDepth = 24;
  354. }
  355. //
  356. // If the surface is a Z Buffer, then we always need to check the
  357. // pitch/partial products, and we need to get the depth from the
  358. // dwZBufferBitDepth field.
  359. //
  360. bYUV = FALSE;
  361. bResize = FALSE;
  362. dwExtraBytes = 0;
  363. //
  364. // get correct bit depth for Z buffers
  365. //
  366. if ( (lpSurfaceLocal->dwFlags & DDRAWISURF_HASPIXELFORMAT)
  367. &&(lpSurfaceGlobal->ddpfSurface.dwFlags & DDPF_ZBUFFER) )
  368. {
  369. DBG_DD((5," Surface is Z Buffer - Adjusting"));
  370. dwBitDepth = lpSurfaceGlobal->ddpfSurface.dwZBufferBitDepth;
  371. }
  372. if ( lpSurfaceGlobal->ddpfSurface.dwFlags & DDPF_FOURCC )
  373. {
  374. //
  375. // The surface is a YUV format surface or we fail
  376. //
  377. switch ( lpSurfaceGlobal->ddpfSurface.dwFourCC )
  378. {
  379. case FOURCC_YUV422:
  380. DBG_DD((3," Surface is YUV422 - Adjusting"));
  381. lpSurfaceGlobal->ddpfSurface.dwYUVBitCount = 16;
  382. dwBitDepth = 16;
  383. bYUV = TRUE;
  384. break;
  385. default:
  386. //
  387. // We should never get here, as CanCreateSurface will
  388. // validate the YUV format for us.
  389. //
  390. ASSERTDD(0, "Trying to create an invalid YUV surface!");
  391. break;
  392. }
  393. }
  394. //
  395. // If the surface is a p2 texture and it is using a LUT, then we need to
  396. // allocate extra local buffer memory for the LUT entries (only on p2).
  397. //
  398. if ( (lpSurfaceLocal->ddsCaps.dwCaps & DDSCAPS_TEXTURE)
  399. &&(pPrivateData->SurfaceFormat.Format == PERMEDIA_8BIT_PALETTEINDEX) )
  400. {
  401. DBG_DD((7," Texture is a P2 8Bit LUT"));
  402. bResize = TRUE;
  403. dwExtraBytes = (256 * sizeof(DWORD));
  404. }
  405. DBG_DD((5," Surface Pitch is: 0x%x", lpSurfaceGlobal->lPitch));
  406. //
  407. // Width is in pixels/texels
  408. //
  409. LONG lPitch;
  410. lPitch = lpSurfaceGlobal->wWidth;
  411. DBG_DD((4," Source Surface is %d texels/depth values across",
  412. lpSurfaceGlobal->wWidth));
  413. // align before hand to a DWPORD boundary
  414. if (pPrivateData->SurfaceFormat.PixelSize == __PERMEDIA_4BITPIXEL)
  415. {
  416. lPitch = ((lPitch >> 1) + 31) & ~31;
  417. }
  418. else
  419. {
  420. lPitch = (lPitch + 31) & ~31;
  421. }
  422. ULONG ulPackedPP;
  423. vCalcPackedPP( lPitch, &lPitch, &ulPackedPP);
  424. DBG_DD((7," Surface is 0x%x bits deep", dwBitDepth));
  425. if ( pPrivateData->SurfaceFormat.PixelSize != __PERMEDIA_4BITPIXEL )
  426. {
  427. //
  428. // Convert back to BYTES
  429. //
  430. if ( dwBitDepth != 24 )
  431. {
  432. lPitch <<= ((int)dwBitDepth) >> 4;
  433. }
  434. else
  435. {
  436. lPitch *= 3;
  437. }
  438. }
  439. pPrivateData->dwFlags |= P2_PPVALID;
  440. DWORD dwExtraLines = 0;
  441. if ( !bYUV )
  442. {
  443. //
  444. // PM Textures must be at least 32 high
  445. //
  446. if ( lpSurfaceGlobal->wHeight < 32 )
  447. {
  448. dwExtraLines = 32 - lpSurfaceGlobal->wHeight;
  449. }
  450. }
  451. lpSurfaceGlobal->dwBlockSizeX =
  452. lPitch * (DWORD)(lpSurfaceGlobal->wHeight + dwExtraLines);
  453. lpSurfaceGlobal->dwBlockSizeY = 1;
  454. lpSurfaceGlobal->lPitch = lPitch;
  455. //
  456. // Store the partial productes in the structure
  457. //
  458. pPrivateData->ulPackedPP = ulPackedPP;
  459. DBG_DD((4, " New Width of surface in Bytes: %d", lPitch));
  460. //
  461. // This flag is set if the surface needs resizing. This is currently only
  462. // used for the P2 LUT based textures.
  463. //
  464. if ( bResize )
  465. {
  466. DWORD dwExtraScanlines = 0;
  467. LONG lExtraRemaining = (LONG)dwExtraBytes;
  468. //
  469. // ExtraScanlines is the count x, which * pitch is what we need to get
  470. // enough memory to hold the LUT. This algorithm will ensure that even
  471. // requests for sizes less than a pitch length will get allocated.
  472. //
  473. do
  474. {
  475. dwExtraScanlines++;
  476. lExtraRemaining -= (LONG)lpSurfaceGlobal->lPitch;
  477. } while ( lExtraRemaining > 0 );
  478. DBG_DD((4, "Calculated extra Pitch lines = %d", dwExtraScanlines));
  479. //
  480. // Stretch the surface a little more in multiples of pitch.
  481. //
  482. lpSurfaceGlobal->dwBlockSizeX +=dwExtraScanlines *
  483. lpSurfaceGlobal->lPitch;
  484. }// if ( bResize )
  485. //
  486. // Modify surface descriptions as appropriate and let Direct
  487. // Draw perform the allocation if the surface was not the primary
  488. //
  489. if (lpSurfaceLocal->ddsCaps.dwCaps & DDSCAPS_PRIMARYSURFACE)
  490. {
  491. lpSurfaceGlobal->fpVidMem = NULL;
  492. }
  493. else
  494. {
  495. lpSurfaceGlobal->fpVidMem = DDHAL_PLEASEALLOC_BLOCKSIZE;
  496. }
  497. lpSurfaceDesc->lPitch = lpSurfaceGlobal->lPitch;
  498. lpSurfaceDesc->dwFlags |= DDSD_PITCH;
  499. if (lpSurfaceLocal->lpSurfMore->ddsCapsEx.dwCaps2 & DDSCAPS2_TEXTUREMANAGE)
  500. {
  501. if (lpSurfaceDesc->dwFlags & DDSD_PIXELFORMAT)
  502. {
  503. lPitch =
  504. lpSurfaceDesc->lPitch =
  505. lpSurfaceGlobal->lPitch =
  506. ((lpSurfaceDesc->ddpfPixelFormat.dwRGBBitCount*
  507. lpSurfaceGlobal->wWidth+31)/32)*4; //make it DWORD aligned
  508. }
  509. lpSurfaceGlobal->dwUserMemSize = lPitch *
  510. (DWORD)(lpSurfaceGlobal->wHeight);
  511. lpSurfaceGlobal->fpVidMem = DDHAL_PLEASEALLOC_USERMEM;
  512. }
  513. lpCreateSurface->ddRVal = DD_OK;
  514. return DDHAL_DRIVER_NOTHANDLED;
  515. }// DdCreateSurface()
  516. //-----------------------------------------------------------------------------
  517. //
  518. // DdDestroySurface
  519. //
  520. // Frees up the private memory allocated with this surface. Note that
  521. // we return DDHAL_DRIVER_NOTHANDLED indicating that we didn't actually
  522. // free the surface, since the heap is managed by DDraw.
  523. //
  524. //-----------------------------------------------------------------------------
  525. extern TextureCacheManager P2TextureManager;
  526. DWORD CALLBACK
  527. DdDestroySurface( LPDDHAL_DESTROYSURFACEDATA psdd )
  528. {
  529. PermediaSurfaceData *pPrivateData=
  530. (PermediaSurfaceData*)psdd->lpDDSurface->lpGbl->dwReserved1;
  531. DBG_DD((3,"DDraw:DdDestroySurface pPrivateData=0x%x "
  532. "lpGbl=0x%x lpLcl=0x%x dwFlags=%08lx &dwReserved1=0x%x",
  533. pPrivateData, psdd->lpDDSurface->lpGbl, psdd->lpDDSurface,
  534. psdd->lpDDSurface->dwFlags, &psdd->lpDDSurface->lpGbl->dwReserved1));
  535. if (CHECK_P2_SURFACEDATA_VALIDITY(pPrivateData))
  536. {
  537. PPERMEDIA_D3DTEXTURE pTexture=NULL;
  538. if ((psdd->lpDDSurface->lpSurfMore->dwSurfaceHandle) &&
  539. (HandleList[psdd->lpDDSurface->dwReserved1].dwSurfaceList) &&
  540. (psdd->lpDDSurface->lpSurfMore->dwSurfaceHandle <
  541. PtrToUlong(HandleList[psdd->lpDDSurface->dwReserved1].
  542. dwSurfaceList[0])))
  543. pTexture=HandleList[psdd->lpDDSurface->dwReserved1].dwSurfaceList
  544. [psdd->lpDDSurface->lpSurfMore->dwSurfaceHandle];
  545. DBG_DD((3,"psdd->lpDDSurface->lpSurfMore->ddsCapsEx.dwCaps2=%08lx",
  546. psdd->lpDDSurface->lpSurfMore->ddsCapsEx.dwCaps2));
  547. if (psdd->lpDDSurface->lpSurfMore->ddsCapsEx.dwCaps2 &
  548. DDSCAPS2_TEXTUREMANAGE)
  549. {
  550. DBG_D3D((3, "free fpVidMem=%08lx fpVidMem=%08lx",
  551. pPrivateData->fpVidMem,psdd->lpDDSurface->lpGbl->fpVidMem));
  552. if ((pPrivateData->fpVidMem) && pTexture)
  553. {
  554. ASSERTDD(CHECK_D3DSURFACE_VALIDITY(pTexture),
  555. "Invalid pTexture in DdDestroySurface");
  556. TextureCacheManagerRemove(&P2TextureManager,pTexture);
  557. }
  558. if (DDRAWISURF_INVALID & psdd->lpDDSurface->dwFlags)
  559. {
  560. // indicate that driver takes care of the lost surface already
  561. psdd->ddRVal = DD_OK;
  562. return DDHAL_DRIVER_HANDLED;
  563. }
  564. }
  565. if (pTexture)
  566. {
  567. ENGFREEMEM(pTexture);
  568. HandleList[psdd->lpDDSurface->dwReserved1].dwSurfaceList
  569. [psdd->lpDDSurface->lpSurfMore->dwSurfaceHandle]=0;
  570. }
  571. pPrivateData->MagicNo = NULL;
  572. ENGFREEMEM(pPrivateData);
  573. psdd->lpDDSurface->lpGbl->dwReserved1 = 0;
  574. }
  575. #if DBG
  576. else
  577. {
  578. if (pPrivateData) {
  579. ASSERTDD(0, "DDraw:DdDestroySurface:ERROR:"
  580. "Private Surface data not valid??");
  581. }
  582. DBG_DD((0, "DDraw:DdDestroySurface:WARNING:"
  583. "No Private data in destroyed surface"));
  584. }
  585. #endif
  586. return DDHAL_DRIVER_NOTHANDLED;
  587. } // DdDestroySurface
  588. //-----------------------------------------------------------------------------
  589. //
  590. // SetupPrivateSurfaceData
  591. //
  592. // Function to get info about DDRAW surface and store it away in the
  593. // private structure. Useful for partial products, pixel depths,
  594. // texture setup (patching/formats), etc.
  595. //
  596. //-----------------------------------------------------------------------------
  597. VOID
  598. SetupPrivateSurfaceData( PPDev ppdev,
  599. PermediaSurfaceData* pPrivateData,
  600. LPDDRAWI_DDRAWSURFACE_LCL pSurface)
  601. {
  602. DDPIXELFORMAT* pPixFormat = NULL;
  603. ASSERTDD(CHECK_P2_SURFACEDATA_VALIDITY(pPrivateData),
  604. "SetupPrivateSurfaceData: Private Surface data pointer invalid!!");
  605. ASSERTDD(pSurface, "SetupPrivateSurfaceData: Surface pointer invalid");
  606. DBG_DD((5,"DDraw:SetupPrivateSurfaceData"));
  607. DBG_DD((6," Width: %d, Height: %d",
  608. pSurface->lpGbl->wWidth, pSurface->lpGbl->wHeight));
  609. // Surface is the primary surface
  610. if (pSurface->ddsCaps.dwCaps & DDSCAPS_PRIMARYSURFACE)
  611. {
  612. DBG_DD((6," Surface is Primary"));
  613. pPrivateData->dwFlags |= P2_SURFACE_PRIMARY;
  614. pPixFormat = &ppdev->ddpfDisplay;
  615. } // Either the surface is a texture or it has a valid pixel format.
  616. else
  617. {
  618. DUMPSURFACE(6, pSurface, NULL);
  619. pPixFormat = &pSurface->lpGbl->ddpfSurface;
  620. }
  621. // At surface creation the surface has not been patched.
  622. pPrivateData->dwFlags &= ~P2_ISPATCHED;
  623. if (pSurface->ddsCaps.dwCaps & DDSCAPS_TEXTURE)
  624. {
  625. // If the user has chosen the normal mechanism, then patch the surface.
  626. if (pSurface->ddsCaps.dwCaps & DDSCAPS_ALLOCONLOAD)
  627. {
  628. DBG_DD((6," Remembering to patch this surface"));
  629. pPrivateData->dwFlags |= P2_CANPATCH;
  630. }
  631. else
  632. {
  633. pPrivateData->dwFlags &= ~P2_CANPATCH;
  634. }
  635. }
  636. // Initially assume no Alpha
  637. pPrivateData->SurfaceFormat.bAlpha = FALSE;
  638. if (pPixFormat != NULL)
  639. {
  640. if (pPixFormat->dwFlags & DDPF_FOURCC)
  641. {
  642. pPrivateData->dwFlags |= P2_SURFACE_FORMAT_VALID;
  643. switch( pPixFormat->dwFourCC )
  644. {
  645. case FOURCC_YUV422:
  646. DBG_DD((6," Surface is 4:2:2 YUV"));
  647. pPrivateData->SurfaceFormat.Format = PERMEDIA_YUV422;
  648. pPrivateData->SurfaceFormat.FormatExtension =
  649. PERMEDIA_YUV422_EXTENSION;
  650. pPrivateData->SurfaceFormat.PixelSize = __PERMEDIA_16BITPIXEL;
  651. pPrivateData->SurfaceFormat.FBReadPixel= __PERMEDIA_16BITPIXEL;
  652. pPrivateData->SurfaceFormat.PixelMask = 1;
  653. pPrivateData->SurfaceFormat.PixelShift= 1;
  654. pPrivateData->SurfaceFormat.ColorComponents = 2;
  655. pPrivateData->SurfaceFormat.logPixelSize = log2(16);
  656. pPrivateData->SurfaceFormat.ColorOrder = 0;
  657. break;
  658. }
  659. }
  660. else if (pPixFormat->dwFlags & DDPF_PALETTEINDEXED4)
  661. {
  662. DBG_DD((6," Surface is 4-Bit Palette"));
  663. pPrivateData->dwFlags |= P2_SURFACE_FORMAT_VALID;
  664. pPrivateData->dwFlags |= P2_SURFACE_FORMAT_PALETTE;
  665. pPrivateData->SurfaceFormat.Format = PERMEDIA_4BIT_PALETTEINDEX;
  666. pPrivateData->SurfaceFormat.FormatExtension = 0;
  667. pPrivateData->SurfaceFormat.PixelSize = __PERMEDIA_4BITPIXEL;
  668. pPrivateData->SurfaceFormat.FBReadPixel= __PERMEDIA_8BITPIXEL;
  669. pPrivateData->SurfaceFormat.PixelMask = 7;
  670. pPrivateData->SurfaceFormat.PixelShift= 0;
  671. pPrivateData->SurfaceFormat.ColorComponents = 3;
  672. pPrivateData->SurfaceFormat.logPixelSize = log2(4);
  673. pPrivateData->SurfaceFormat.ColorOrder = 0;
  674. pPrivateData->dwFlags &= ~P2_CANPATCH;
  675. }
  676. else if (pPixFormat->dwFlags & DDPF_PALETTEINDEXED8)
  677. {
  678. DBG_DD((6," Surface is 8-Bit Palette"));
  679. pPrivateData->dwFlags |= P2_SURFACE_FORMAT_VALID;
  680. pPrivateData->dwFlags |= P2_SURFACE_FORMAT_PALETTE;
  681. pPrivateData->SurfaceFormat.Format = PERMEDIA_8BIT_PALETTEINDEX;
  682. pPrivateData->SurfaceFormat.FormatExtension = 0;
  683. pPrivateData->SurfaceFormat.PixelSize = __PERMEDIA_8BITPIXEL;
  684. pPrivateData->SurfaceFormat.FBReadPixel= __PERMEDIA_8BITPIXEL;
  685. pPrivateData->SurfaceFormat.PixelMask = 3;
  686. pPrivateData->SurfaceFormat.PixelShift= 0;
  687. pPrivateData->SurfaceFormat.ColorComponents = 3;
  688. pPrivateData->SurfaceFormat.Texture16BitMode = 1;
  689. pPrivateData->SurfaceFormat.logPixelSize = log2(8);
  690. pPrivateData->SurfaceFormat.ColorOrder = 0;
  691. }
  692. else
  693. {
  694. if (SetRGBAlphaSurfaceFormat( pPixFormat,
  695. &pPrivateData->SurfaceFormat))
  696. {
  697. pPrivateData->dwFlags |= P2_SURFACE_FORMAT_VALID;
  698. } else
  699. {
  700. pPrivateData->dwFlags &= ~P2_SURFACE_FORMAT_VALID;
  701. }
  702. }
  703. }
  704. else
  705. {
  706. ASSERTDD(0, "SetupPrivateSurfaceData:"
  707. "Can't get valid surface format pointer");
  708. }
  709. } // SetupPrivateSurfaceData
  710. //-----------------------------------------------------------------------------
  711. //
  712. // list all valid pixel formats for Permedia 2
  713. // The P2 supports BGR for all formats, so these formats are not
  714. // explicitely listed here, also formats having no alpha channel are permitted
  715. //
  716. //-----------------------------------------------------------------------------
  717. DDPIXELFORMAT Permedia2PixelFormats[] = {
  718. // 32 bit RGBa
  719. {PERMEDIA_8888_RGB,0,0,32,0x000000ff,0x0000ff00,0x00ff0000,0xff000000},
  720. // 16 bit 5:6:5, RGB
  721. {PERMEDIA_565_RGB ,0,0,16,0x0000001f,0x000007e0,0x0000f800,0x00000000},
  722. // 16 bit 4:4:4:4RGBa
  723. {PERMEDIA_444_RGB ,0,0,16,0x0000000f,0x000000f0,0x00000f00,0x0000f000},
  724. // 15 bit 5:5:5, RGBa
  725. {PERMEDIA_5551_RGB,0,0,16,0x0000001f,0x000003e0,0x00007c00,0x00008000},
  726. // 8 bit 3:3:2 RGB
  727. // 332 format is not symmetric. Its listed twice for BGR/RGB case
  728. {PERMEDIA_332_RGB ,1,0, 8,0x00000007,0x00000038,0x000000c0,0x00000000},
  729. {PERMEDIA_332_RGB ,0,0, 8,0x00000003,0x0000001c,0x000000e0,0x00000000},
  730. //@@BEGIN_DDKSPLIT
  731. // there are no testcases against the 2321 format, so disable it for now
  732. // 8 bit 2:3:2:1RGBa
  733. // {PERMEDIA_2321_RGB,0,0, 8,0x00000003,0x0000001c,0x00000060,0x00000080},
  734. //@@END_DDKSPLIT
  735. // 24 bit RGB
  736. {PERMEDIA_888_RGB ,0,0,24,0x000000ff,0x0000ff00,0x00ff0000,0x00000000}
  737. };
  738. #define N_PERMEDIA2PIXELFORMATS \
  739. (sizeof(Permedia2PixelFormats)/sizeof(DDPIXELFORMAT))
  740. BOOL
  741. ValidRGBAlphaSurfaceformat( DDPIXELFORMAT *pPixFormat, INT *pIndex)
  742. {
  743. INT i;
  744. if (pPixFormat==NULL)
  745. return FALSE;
  746. if (pPixFormat->dwSize < sizeof(DDPIXELFORMAT))
  747. return FALSE;
  748. // The Z-Buffer is a special case. Its basically a 16 bit surface
  749. if (pPixFormat->dwFlags & DDPF_ZBUFFER)
  750. {
  751. if (pIndex!=0) *pIndex=1;
  752. return TRUE;
  753. }
  754. if ((pPixFormat->dwFlags & DDPF_RGB)==0)
  755. return FALSE;
  756. for ( i=0; i<N_PERMEDIA2PIXELFORMATS; i++)
  757. {
  758. // check if the RGB and alpha masks fit.
  759. // on Permedia we can swap R and B, so allow also BGR formats
  760. if ((((pPixFormat->dwRBitMask ==
  761. Permedia2PixelFormats[i].dwRBitMask) &&
  762. (pPixFormat->dwBBitMask ==
  763. Permedia2PixelFormats[i].dwBBitMask)) ||
  764. ((pPixFormat->dwRBitMask ==
  765. Permedia2PixelFormats[i].dwBBitMask) &&
  766. (pPixFormat->dwBBitMask ==
  767. Permedia2PixelFormats[i].dwRBitMask))) &&
  768. (pPixFormat->dwGBitMask ==
  769. Permedia2PixelFormats[i].dwGBitMask) &&
  770. ((pPixFormat->dwRGBAlphaBitMask ==
  771. Permedia2PixelFormats[i].dwRGBAlphaBitMask) ||
  772. (pPixFormat->dwRGBAlphaBitMask == 0) ||
  773. ((pPixFormat->dwFlags&DDPF_ALPHAPIXELS)==0)) &&
  774. (pPixFormat->dwRGBBitCount==
  775. Permedia2PixelFormats[i].dwRGBBitCount)
  776. )
  777. {
  778. if (pIndex!=NULL)
  779. {
  780. *pIndex = i;
  781. }
  782. return TRUE;
  783. }
  784. }
  785. // no pixel format matched...
  786. return FALSE;
  787. } // ValidRGBAlphaSurfaceformat
  788. //-----------------------------------------------------------------------------
  789. //
  790. // SetRGBAlphaSurfaceFormat
  791. //
  792. // Store away pixel format information of a surface in the Permedia native
  793. // format
  794. //
  795. //-----------------------------------------------------------------------------
  796. BOOL
  797. SetRGBAlphaSurfaceFormat(DDPIXELFORMAT *pPixFormat,
  798. PERMEDIA_SURFACE *pSurfaceFormat)
  799. {
  800. INT iFormatIndex;
  801. if (!ValidRGBAlphaSurfaceformat( pPixFormat, &iFormatIndex))
  802. {
  803. DBG_DD((1,"couldn't set SurfaceFormat"));
  804. return FALSE;
  805. }
  806. DBG_DD((6," Surface RGB Data Valid"));
  807. pSurfaceFormat->RedMask = pPixFormat->dwRBitMask;
  808. pSurfaceFormat->GreenMask = pPixFormat->dwGBitMask;
  809. pSurfaceFormat->BlueMask = pPixFormat->dwBBitMask;
  810. pSurfaceFormat->bPreMult = FALSE;
  811. if (pPixFormat->dwFlags & DDPF_ALPHAPIXELS)
  812. {
  813. pSurfaceFormat->AlphaMask = pPixFormat->dwRGBAlphaBitMask;
  814. if (pSurfaceFormat->AlphaMask!=0)
  815. {
  816. pSurfaceFormat->bAlpha = TRUE;
  817. }
  818. if (pPixFormat->dwFlags & DDPF_ALPHAPREMULT)
  819. {
  820. pSurfaceFormat->bPreMult = TRUE;
  821. }
  822. }
  823. pSurfaceFormat->ColorOrder = Permedia2PixelFormats[iFormatIndex].dwFlags;
  824. // check for the BGR case
  825. if (pPixFormat->dwRBitMask ==
  826. Permedia2PixelFormats[iFormatIndex].dwRBitMask)
  827. pSurfaceFormat->ColorOrder = !pSurfaceFormat->ColorOrder;
  828. switch (pPixFormat->dwRGBBitCount)
  829. {
  830. case 24:
  831. DBG_DD((6," Surface is 8:8:8 Packed 24 Bit"));
  832. pSurfaceFormat->Format = PERMEDIA_888_RGB;
  833. pSurfaceFormat->FormatExtension = PERMEDIA_888_RGB_EXTENSION;
  834. pSurfaceFormat->PixelSize = __PERMEDIA_24BITPIXEL;
  835. pSurfaceFormat->FBReadPixel= __PERMEDIA_24BITPIXEL;
  836. pSurfaceFormat->PixelMask = 0; // not valid for 24 bit
  837. pSurfaceFormat->PixelShift= 0;
  838. pSurfaceFormat->logPixelSize = 0;
  839. pSurfaceFormat->ColorComponents = 3;
  840. break;
  841. case 32:
  842. DBG_DD((6," Surface is 8:8:8:8"));
  843. pSurfaceFormat->Format = PERMEDIA_8888_RGB;
  844. pSurfaceFormat->FormatExtension = PERMEDIA_8888_RGB_EXTENSION;
  845. pSurfaceFormat->PixelSize = __PERMEDIA_32BITPIXEL;
  846. pSurfaceFormat->FBReadPixel= __PERMEDIA_32BITPIXEL;
  847. pSurfaceFormat->PixelMask = 0;
  848. pSurfaceFormat->PixelShift= 2;
  849. pSurfaceFormat->logPixelSize = log2(32);
  850. pSurfaceFormat->ColorComponents = 3;
  851. break;
  852. case 16:
  853. pSurfaceFormat->logPixelSize = log2(16);
  854. pSurfaceFormat->PixelSize = __PERMEDIA_16BITPIXEL;
  855. pSurfaceFormat->FBReadPixel= __PERMEDIA_16BITPIXEL;
  856. pSurfaceFormat->PixelMask = 1; // not valid for 24 bit
  857. pSurfaceFormat->PixelShift= 1;
  858. switch (Permedia2PixelFormats[iFormatIndex].dwSize)
  859. {
  860. case PERMEDIA_565_RGB:
  861. pSurfaceFormat->Texture16BitMode = 0;
  862. pSurfaceFormat->Format = PERMEDIA_565_RGB;
  863. pSurfaceFormat->FormatExtension = PERMEDIA_565_RGB_EXTENSION;
  864. pSurfaceFormat->ColorComponents = 2;
  865. DBG_DD((6," Surface is 5:6:5"));
  866. break;
  867. case PERMEDIA_444_RGB:
  868. pSurfaceFormat->Format = PERMEDIA_444_RGB;
  869. pSurfaceFormat->FormatExtension = 0;
  870. pSurfaceFormat->ColorComponents = 3;
  871. if (pPixFormat->dwRGBAlphaBitMask != 0)
  872. {
  873. DBG_DD((6," Surface is 4:4:4:4"));
  874. } else
  875. {
  876. DBG_DD((6," Surface is 4:4:4:0"));
  877. }
  878. break;
  879. case PERMEDIA_5551_RGB:
  880. pSurfaceFormat->Texture16BitMode = 1;
  881. pSurfaceFormat->Format = PERMEDIA_5551_RGB;
  882. pSurfaceFormat->FormatExtension = PERMEDIA_5551_RGB_EXTENSION;
  883. if (pPixFormat->dwRGBAlphaBitMask != 0)
  884. {
  885. DBG_DD((6," Surface is 5:5:5:1"));
  886. pSurfaceFormat->ColorComponents = 3;
  887. }
  888. else
  889. {
  890. DBG_DD((6," Surface is 5:5:5"));
  891. pSurfaceFormat->ColorComponents = 2;
  892. }
  893. break;
  894. default:
  895. ASSERTDD( FALSE, " 16 bit Surface has unknown format");
  896. break;
  897. }
  898. break;
  899. case 8:
  900. pSurfaceFormat->PixelSize = __PERMEDIA_8BITPIXEL;
  901. pSurfaceFormat->FBReadPixel= __PERMEDIA_8BITPIXEL;
  902. pSurfaceFormat->PixelMask = 3;
  903. pSurfaceFormat->PixelShift= 0;
  904. pSurfaceFormat->logPixelSize = log2(8);
  905. if (Permedia2PixelFormats[iFormatIndex].dwSize==PERMEDIA_2321_RGB)
  906. {
  907. pSurfaceFormat->Format = PERMEDIA_2321_RGB;
  908. pSurfaceFormat->FormatExtension = PERMEDIA_2321_RGB_EXTENSION;
  909. pSurfaceFormat->ColorComponents = 3;
  910. }
  911. else if (Permedia2PixelFormats[iFormatIndex].dwSize==PERMEDIA_332_RGB)
  912. {
  913. pSurfaceFormat->Format = PERMEDIA_332_RGB;
  914. pSurfaceFormat->FormatExtension = PERMEDIA_332_RGB_EXTENSION;
  915. pSurfaceFormat->ColorComponents = 2;
  916. } else
  917. {
  918. ASSERTDD( FALSE, " Surface (8bit) has unknown format");
  919. }
  920. break;
  921. case 0:
  922. DBG_DD((6," Surface is palleted"));
  923. pSurfaceFormat->Format = PERMEDIA_8BIT_PALETTEINDEX;
  924. pSurfaceFormat->FormatExtension = PERMEDIA_8BIT_PALETTEINDEX_EXTENSION;
  925. pSurfaceFormat->PixelSize = __PERMEDIA_8BITPIXEL;
  926. pSurfaceFormat->FBReadPixel= __PERMEDIA_8BITPIXEL;
  927. pSurfaceFormat->PixelMask = 3; // not valid for 24 bit
  928. pSurfaceFormat->PixelShift= 0;
  929. pSurfaceFormat->logPixelSize = log2(8);
  930. pSurfaceFormat->ColorComponents = 0;
  931. break;
  932. default:
  933. ASSERTDD( FALSE, " Surface has unknown pixelformat");
  934. return FALSE;
  935. }
  936. return TRUE;
  937. } // SetRGBAlphaSurfaceFormat