Source code of Windows XP (NT5)
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.

545 lines
14 KiB

  1. /******************************Module*Header*******************************\
  2. * Module Name: ddtex.c
  3. *
  4. * wgl DirectDraw texture support
  5. *
  6. * Created: 02-10-1997
  7. * Author: Drew Bliss [drewb]
  8. *
  9. * Copyright (c) 1993-1997 Microsoft Corporation
  10. \**************************************************************************/
  11. #include "precomp.h"
  12. #pragma hdrstop
  13. #include "gencx.h"
  14. // Simple surface description for supported texture formats
  15. #define DDTF_BGRA 0
  16. #define DDTF_BGR 1
  17. #define DDTF_PALETTED 2
  18. typedef struct _DDTEXFORMAT
  19. {
  20. int iFormat;
  21. int cColorBits;
  22. } DDTEXFORMAT;
  23. // Supported formats
  24. static DDTEXFORMAT ddtfFormats[] =
  25. {
  26. DDTF_BGRA, 32,
  27. DDTF_BGR, 32,
  28. DDTF_PALETTED, 8
  29. };
  30. #define NDDTF (sizeof(ddtfFormats)/sizeof(ddtfFormats[0]))
  31. /******************************Public*Routine******************************\
  32. *
  33. * DescribeDdtf
  34. *
  35. * Fill out a DDSURFACEDESC from a DDTEXFORMAT
  36. *
  37. * History:
  38. * Tue Sep 03 18:16:50 1996 -by- Drew Bliss [drewb]
  39. * Created
  40. *
  41. \**************************************************************************/
  42. void DescribeDdtf(DDTEXFORMAT *pddtf, DDSURFACEDESC *pddsd)
  43. {
  44. memset(pddsd, 0, sizeof(*pddsd));
  45. pddsd->dwSize = sizeof(*pddsd);
  46. pddsd->dwFlags = DDSD_CAPS | DDSD_PIXELFORMAT;
  47. pddsd->ddsCaps.dwCaps = DDSCAPS_MIPMAP | DDSCAPS_TEXTURE;
  48. pddsd->ddpfPixelFormat.dwFlags = DDPF_RGB;
  49. pddsd->ddpfPixelFormat.dwRGBBitCount = pddtf->cColorBits;
  50. switch(pddtf->iFormat)
  51. {
  52. case DDTF_BGRA:
  53. pddsd->dwFlags |= DDSD_ALPHABITDEPTH;
  54. pddsd->dwAlphaBitDepth = pddtf->cColorBits/4;
  55. pddsd->ddsCaps.dwCaps |= DDSCAPS_ALPHA;
  56. pddsd->ddpfPixelFormat.dwFlags |= DDPF_ALPHAPIXELS;
  57. // Fall through
  58. case DDTF_BGR:
  59. switch(pddtf->cColorBits)
  60. {
  61. case 32:
  62. pddsd->ddpfPixelFormat.dwRBitMask = 0xff0000;
  63. pddsd->ddpfPixelFormat.dwGBitMask = 0xff00;
  64. pddsd->ddpfPixelFormat.dwBBitMask = 0xff;
  65. if (pddtf->iFormat == DDTF_BGRA)
  66. {
  67. pddsd->ddpfPixelFormat.dwRGBAlphaBitMask = 0xff000000;
  68. }
  69. break;
  70. }
  71. break;
  72. case DDTF_PALETTED:
  73. switch(pddtf->cColorBits)
  74. {
  75. case 1:
  76. pddsd->ddpfPixelFormat.dwFlags |= DDPF_PALETTEINDEXED1;
  77. break;
  78. case 2:
  79. pddsd->ddpfPixelFormat.dwFlags |= DDPF_PALETTEINDEXED2;
  80. break;
  81. case 4:
  82. pddsd->ddpfPixelFormat.dwFlags |= DDPF_PALETTEINDEXED4;
  83. break;
  84. case 8:
  85. pddsd->ddpfPixelFormat.dwFlags |= DDPF_PALETTEINDEXED8;
  86. break;
  87. }
  88. break;
  89. }
  90. }
  91. /******************************Public*Routine******************************\
  92. *
  93. * CacheTextureFormats
  94. *
  95. * Creates list of valid texture formats for a context
  96. *
  97. * History:
  98. * Fri Sep 27 16:14:29 1996 -by- Drew Bliss [drewb]
  99. * Created
  100. *
  101. \**************************************************************************/
  102. BOOL CacheTextureFormats(PLRC plrc)
  103. {
  104. int i;
  105. int nFmts;
  106. int nMcdFmts;
  107. DDTEXFORMAT *pddtf;
  108. DDSURFACEDESC *pddsdAlloc, *pddsd;
  109. __GLGENcontext *gengc;
  110. ASSERTOPENGL(plrc->pddsdTexFormats == NULL,
  111. "CacheTextureFormats overwriting cache\n");
  112. if (plrc->dhrc != 0)
  113. {
  114. // Call the ICD
  115. if (plrc->pGLDriver->pfnDrvEnumTextureFormats == NULL)
  116. {
  117. nFmts = 0;
  118. }
  119. else
  120. {
  121. nFmts = plrc->pGLDriver->pfnDrvEnumTextureFormats(0, NULL);
  122. if (nFmts < 0)
  123. {
  124. return FALSE;
  125. }
  126. }
  127. }
  128. else
  129. {
  130. gengc = (__GLGENcontext *)GLTEB_SRVCONTEXT();
  131. ASSERTOPENGL(gengc != NULL, "No server context\n");
  132. nFmts = NDDTF;
  133. nMcdFmts = 0;
  134. #if MCD_VER_MAJOR >= 2 || (MCD_VER_MAJOR == 1 && MCD_VER_MINOR >= 0x10)
  135. if (gengc->pMcdState != NULL &&
  136. McdDriverInfo.mcdDriver.pMCDrvGetTextureFormats != NULL)
  137. {
  138. nMcdFmts = GenMcdGetTextureFormats(gengc, 0, NULL);
  139. if (nMcdFmts < 0)
  140. {
  141. SetLastError(ERROR_NOT_ENOUGH_MEMORY);
  142. return FALSE;
  143. }
  144. nFmts += nMcdFmts;
  145. }
  146. #endif // 1.1
  147. }
  148. pddsdAlloc = (DDSURFACEDESC *)ALLOC(sizeof(DDSURFACEDESC)*nFmts);
  149. if (pddsdAlloc == NULL)
  150. {
  151. return FALSE;
  152. }
  153. if (plrc->dhrc != 0)
  154. {
  155. if (nFmts > 0)
  156. {
  157. nFmts = plrc->pGLDriver->pfnDrvEnumTextureFormats(nFmts,
  158. pddsdAlloc);
  159. if (nFmts < 0)
  160. {
  161. FREE(pddsdAlloc);
  162. return FALSE;
  163. }
  164. }
  165. }
  166. else
  167. {
  168. pddsd = pddsdAlloc;
  169. pddtf = ddtfFormats;
  170. for (i = 0; i < NDDTF; i++)
  171. {
  172. DescribeDdtf(pddtf, pddsd);
  173. pddtf++;
  174. pddsd++;
  175. }
  176. if (gengc->pMcdState != NULL && nMcdFmts > 0)
  177. {
  178. nMcdFmts = GenMcdGetTextureFormats(gengc, nMcdFmts, pddsd);
  179. if (nMcdFmts < 0)
  180. {
  181. FREE(pddsdAlloc);
  182. SetLastError(ERROR_NOT_ENOUGH_MEMORY);
  183. return FALSE;
  184. }
  185. }
  186. }
  187. plrc->pddsdTexFormats = pddsdAlloc;
  188. plrc->nDdTexFormats = nFmts;
  189. return TRUE;
  190. }
  191. /******************************Public*Routine******************************\
  192. *
  193. * wglEnumTextureFormats
  194. *
  195. * Enumerates texture formats supported for DirectDraw surfaces
  196. *
  197. * History:
  198. * Tue Sep 03 17:52:17 1996 -by- Drew Bliss [drewb]
  199. * Created
  200. *
  201. \**************************************************************************/
  202. #ifdef ALLOW_DDTEX
  203. BOOL WINAPI wglEnumTextureFormats(WGLENUMTEXTUREFORMATSCALLBACK pfnCallback,
  204. LPVOID pvUser)
  205. {
  206. int i;
  207. DDSURFACEDESC *pddsd;
  208. BOOL bRet = TRUE;
  209. PLRC plrc;
  210. plrc = GLTEB_CLTCURRENTRC();
  211. if (plrc == NULL)
  212. {
  213. SetLastError(ERROR_INVALID_FUNCTION);
  214. return FALSE;
  215. }
  216. glFlush();
  217. if (plrc->pddsdTexFormats == NULL &&
  218. !CacheTextureFormats(plrc))
  219. {
  220. return FALSE;
  221. }
  222. pddsd = plrc->pddsdTexFormats;
  223. for (i = 0; i < plrc->nDdTexFormats; i++)
  224. {
  225. if (!pfnCallback(pddsd, pvUser))
  226. {
  227. break;
  228. }
  229. pddsd++;
  230. }
  231. // Should this return FALSE if the enumeration was terminated?
  232. return bRet;
  233. }
  234. #endif
  235. /******************************Public*Routine******************************\
  236. *
  237. * wglBindDirectDrawTexture
  238. *
  239. * Makes a DirectDraw surface the current 2D texture source
  240. *
  241. * History:
  242. * Tue Sep 03 17:53:43 1996 -by- Drew Bliss [drewb]
  243. * Created
  244. *
  245. \**************************************************************************/
  246. BOOL WINAPI wglBindDirectDrawTexture(LPDIRECTDRAWSURFACE pdds)
  247. {
  248. DDSURFACEDESC ddsd;
  249. int i;
  250. DDSURFACEDESC *pddsd;
  251. __GLcontext *gc;
  252. int iLev = 0;
  253. PLRC plrc;
  254. LPDIRECTDRAWSURFACE apdds[__GL_WGL_MAX_MIPMAP_LEVEL];
  255. GLuint ulFlags;
  256. plrc = GLTEB_CLTCURRENTRC();
  257. if (plrc == NULL)
  258. {
  259. SetLastError(ERROR_INVALID_FUNCTION);
  260. return FALSE;
  261. }
  262. glFlush();
  263. if (plrc->dhrc != 0)
  264. {
  265. if (plrc->pGLDriver->pfnDrvBindDirectDrawTexture == NULL)
  266. {
  267. SetLastError(ERROR_INVALID_FUNCTION);
  268. return FALSE;
  269. }
  270. }
  271. else
  272. {
  273. gc = (__GLcontext *)GLTEB_SRVCONTEXT();
  274. ASSERTOPENGL(gc != NULL, "No server context\n");
  275. }
  276. if (pdds == NULL)
  277. {
  278. // Clear any previous binding
  279. if (plrc->dhrc != 0)
  280. {
  281. return plrc->pGLDriver->pfnDrvBindDirectDrawTexture(pdds);
  282. }
  283. else
  284. {
  285. glsrvUnbindDirectDrawTexture(gc);
  286. // If we're just unbinding, we're done
  287. return TRUE;
  288. }
  289. }
  290. memset(&ddsd, 0, sizeof(ddsd));
  291. ddsd.dwSize = sizeof(ddsd);
  292. if (pdds->lpVtbl->GetSurfaceDesc(pdds, &ddsd) != DD_OK)
  293. {
  294. return FALSE;
  295. }
  296. // Surface must be a texture
  297. // Surface must have a width and height which are powers of two
  298. if ((ddsd.dwFlags & (DDSD_CAPS | DDSD_PIXELFORMAT | DDSD_WIDTH |
  299. DDSD_HEIGHT)) !=
  300. (DDSD_CAPS | DDSD_PIXELFORMAT | DDSD_WIDTH | DDSD_HEIGHT) ||
  301. (ddsd.ddsCaps.dwCaps & DDSCAPS_TEXTURE) == 0 ||
  302. (ddsd.dwWidth & (ddsd.dwWidth-1)) != 0 ||
  303. (ddsd.dwHeight & (ddsd.dwHeight-1)) != 0)
  304. {
  305. return FALSE;
  306. }
  307. // Surface must match a supported format
  308. if (plrc->pddsdTexFormats == NULL &&
  309. !CacheTextureFormats(plrc))
  310. {
  311. return FALSE;
  312. }
  313. pddsd = plrc->pddsdTexFormats;
  314. for (i = 0; i < plrc->nDdTexFormats; i++)
  315. {
  316. if (ddsd.ddpfPixelFormat.dwFlags & DDPF_RGB)
  317. {
  318. if (ddsd.ddpfPixelFormat.dwRGBBitCount ==
  319. (DWORD)pddsd->ddpfPixelFormat.dwRGBBitCount)
  320. {
  321. if (ddsd.ddpfPixelFormat.dwRBitMask !=
  322. pddsd->ddpfPixelFormat.dwRBitMask ||
  323. ddsd.ddpfPixelFormat.dwGBitMask !=
  324. pddsd->ddpfPixelFormat.dwGBitMask ||
  325. ddsd.ddpfPixelFormat.dwBBitMask !=
  326. pddsd->ddpfPixelFormat.dwBBitMask)
  327. {
  328. return FALSE;
  329. }
  330. else
  331. {
  332. break;
  333. }
  334. }
  335. }
  336. else
  337. {
  338. if ((ddsd.ddpfPixelFormat.dwFlags & (DDPF_PALETTEINDEXED1 |
  339. DDPF_PALETTEINDEXED2 |
  340. DDPF_PALETTEINDEXED4 |
  341. DDPF_PALETTEINDEXED8)) !=
  342. (pddsd->ddpfPixelFormat.dwFlags & (DDPF_PALETTEINDEXED1 |
  343. DDPF_PALETTEINDEXED2 |
  344. DDPF_PALETTEINDEXED4 |
  345. DDPF_PALETTEINDEXED8)))
  346. {
  347. return FALSE;
  348. }
  349. else
  350. {
  351. break;
  352. }
  353. }
  354. pddsd++;
  355. }
  356. if (i == plrc->nDdTexFormats)
  357. {
  358. return FALSE;
  359. }
  360. ulFlags = 0;
  361. if (i < NDDTF)
  362. {
  363. ulFlags |= DDTEX_GENERIC_FORMAT;
  364. }
  365. if (plrc->dhrc != 0)
  366. {
  367. return plrc->pGLDriver->pfnDrvBindDirectDrawTexture(pdds);
  368. }
  369. pdds->lpVtbl->AddRef(pdds);
  370. // Track whether the texture is in video memory or not.
  371. ulFlags |= DDTEX_VIDEO_MEMORY;
  372. if ((ddsd.ddsCaps.dwCaps & DDSCAPS_VIDEOMEMORY) == 0)
  373. {
  374. ulFlags &= ~DDTEX_VIDEO_MEMORY;
  375. }
  376. // If mipmaps are given, all mipmaps must be present
  377. if (ddsd.ddsCaps.dwCaps & DDSCAPS_MIPMAP)
  378. {
  379. DWORD dwWidth;
  380. DWORD dwHeight;
  381. LONG lPitch;
  382. int cColorBits;
  383. LPDIRECTDRAWSURFACE pddsMipmap, pddsNext;
  384. DDSCAPS ddscaps;
  385. DDSURFACEDESC ddsdMipmap;
  386. // Determine pixel depth
  387. if (ddsd.ddpfPixelFormat.dwFlags & DDPF_PALETTEINDEXED1)
  388. {
  389. cColorBits = 1;
  390. }
  391. else if (ddsd.ddpfPixelFormat.dwFlags & DDPF_PALETTEINDEXED2)
  392. {
  393. cColorBits = 2;
  394. }
  395. else if (ddsd.ddpfPixelFormat.dwFlags & DDPF_PALETTEINDEXED4)
  396. {
  397. cColorBits = 4;
  398. }
  399. else if (ddsd.ddpfPixelFormat.dwFlags & DDPF_PALETTEINDEXED8)
  400. {
  401. cColorBits = 8;
  402. }
  403. else
  404. {
  405. ASSERTOPENGL(ddsd.ddpfPixelFormat.dwFlags & DDPF_RGB,
  406. "DDPF_RGB expected\n");
  407. cColorBits =
  408. DdPixDepthToCount(pddsd->ddpfPixelFormat.dwRGBBitCount);
  409. }
  410. dwWidth = ddsd.dwWidth;
  411. dwHeight = ddsd.dwHeight;
  412. // Compute pitch from pixel depth. The generic texturing code
  413. // doesn't support a pitch that differs from the natural pitch
  414. // given the width and depth of the surface.
  415. lPitch = (cColorBits*dwWidth+7)/8;
  416. if (ddsd.lPitch != lPitch)
  417. {
  418. goto CleanMipmap;
  419. }
  420. pddsMipmap = pdds;
  421. ddscaps.dwCaps = DDSCAPS_TEXTURE | DDSCAPS_MIPMAP;
  422. ddsdMipmap.dwSize = sizeof(DDSURFACEDESC);
  423. for (;;)
  424. {
  425. apdds[iLev++] = pddsMipmap;
  426. if (pddsMipmap->lpVtbl->
  427. GetSurfaceDesc(pddsMipmap, &ddsdMipmap) != DD_OK ||
  428. ((ddsdMipmap.ddpfPixelFormat.dwFlags & DDPF_RGB) &&
  429. ddsdMipmap.ddpfPixelFormat.dwRGBBitCount !=
  430. ddsd.ddpfPixelFormat.dwRGBBitCount) ||
  431. ((ddsdMipmap.ddpfPixelFormat.dwFlags & DDPF_RGB) == 0 &&
  432. (ddsdMipmap.ddpfPixelFormat.dwFlags & (DDPF_PALETTEINDEXED1 |
  433. DDPF_PALETTEINDEXED2 |
  434. DDPF_PALETTEINDEXED4 |
  435. DDPF_PALETTEINDEXED8)) !=
  436. (ddsd.ddpfPixelFormat.dwFlags & (DDPF_PALETTEINDEXED1 |
  437. DDPF_PALETTEINDEXED2 |
  438. DDPF_PALETTEINDEXED4 |
  439. DDPF_PALETTEINDEXED8))) ||
  440. ddsdMipmap.dwWidth != dwWidth ||
  441. ddsdMipmap.dwHeight != dwHeight ||
  442. ddsdMipmap.lPitch != lPitch)
  443. {
  444. goto CleanMipmap;
  445. }
  446. if ((ddsdMipmap.ddsCaps.dwCaps & DDSCAPS_VIDEOMEMORY) == 0)
  447. {
  448. ulFlags &= ~DDTEX_VIDEO_MEMORY;
  449. }
  450. if (iLev > gc->constants.maxMipMapLevel ||
  451. (dwWidth == 1 && dwHeight == 1))
  452. {
  453. break;
  454. }
  455. if (pddsMipmap->lpVtbl->
  456. GetAttachedSurface(pddsMipmap, &ddscaps, &pddsNext) != DD_OK)
  457. {
  458. goto CleanMipmap;
  459. }
  460. pddsMipmap = pddsNext;
  461. if (dwWidth != 1)
  462. {
  463. dwWidth >>= 1;
  464. lPitch >>= 1;
  465. }
  466. if (dwHeight != 1)
  467. {
  468. dwHeight >>= 1;
  469. }
  470. }
  471. }
  472. else
  473. {
  474. apdds[iLev++] = pdds;
  475. }
  476. if (glsrvBindDirectDrawTexture(gc, iLev, apdds, &ddsd, ulFlags))
  477. {
  478. return TRUE;
  479. }
  480. CleanMipmap:
  481. while (--iLev >= 0)
  482. {
  483. apdds[iLev]->lpVtbl->Release(apdds[iLev]);
  484. }
  485. return FALSE;
  486. }