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.

5591 lines
175 KiB

  1. /*========================================================================== *
  2. *
  3. * Copyright (C) 1994-1995 Microsoft Corporation. All Rights Reserved.
  4. *
  5. * File: ddcsurf.c
  6. * Content: DirectDraw support for for create surface
  7. * History:
  8. * Date By Reason
  9. * ==== == ======
  10. * 08-jan-95 craige initial implementation
  11. * 13-jan-95 craige re-worked to updated spec + ongoing work
  12. * 21-jan-95 craige made 32-bit + ongoing work
  13. * 31-jan-95 craige and even more ongoing work...
  14. * 21-feb-95 craige work work work
  15. * 27-feb-95 craige new sync. macros
  16. * 02-mar-95 craige use pitch (not stride)
  17. * 07-mar-95 craige keep track of flippable surfaces
  18. * 08-mar-95 craige new APIs
  19. * 12-mar-95 craige clean up surfaces after process dies...
  20. * 15-mar-95 craige more HEL work
  21. * 19-mar-95 craige use HRESULTs
  22. * 20-mar-95 craige new CSECT work
  23. * 23-mar-95 craige attachment work
  24. * 29-mar-95 craige use GETCURRPID; only call emulation if
  25. * DDRAWI_EMULATIONINITIALIZED is set
  26. * 31-mar-95 craige allow setting of hwnd & ckey
  27. * 01-apr-95 craige happy fun joy updated header file
  28. * 12-apr-95 craige don't use GETCURRPID
  29. * 13-apr-95 craige EricEng's little contribution to our being late
  30. * 15-apr-95 craige added GetBltStatus
  31. * 06-may-95 craige use driver-level csects only
  32. * 15-may-95 kylej changed overlay functions in ddSurfaceCallbacks
  33. * 22-may-95 craige use MemAlloc16 to get selectors & ptrs
  34. * 24-may-95 kylej Added AddOverlayDirtyRect and UpdateOverlayDisplay
  35. * 24-may-95 craige added Restore
  36. * 04-jun-95 craige added IsLost
  37. * 11-jun-95 craige check for some
  38. * 16-jun-95 craige removed fpVidMemOrig
  39. * 17-jun-95 craige new surface structure
  40. * 18-jun-95 craige allow duplicate surfaces
  41. * 19-jun-95 craige automatically assign pitch for rectangular surfaces
  42. * 20-jun-95 craige use fpPrimaryOrig when allocating primary
  43. * 21-jun-95 craige use OBJECT_ISROOT
  44. * 25-jun-95 craige one ddraw mutex
  45. * 26-jun-95 craige reorganized surface structure
  46. * 27-jun-95 craige added BltBatch; save display mode object was created in
  47. * 28-jun-95 craige ENTER_DDRAW at very start of fns; always assign
  48. * back buffer count to first surface in flipping chain
  49. * 30-jun-95 kylej extensive changes to support multiple primary
  50. * surfaces.
  51. * 30-jun-95 craige clean pixel formats; use DDRAWI_HASPIXELFORMAT/HASOVERLAYDATA
  52. * 01-jul-95 craige fail creation of primary/flipping if not in excl. mode
  53. * alloc overlay space on primary; cmt out streaming;
  54. * bug 99
  55. * 04-jul-95 craige YEEHAW: new driver struct; SEH
  56. * 05-jul-95 craige added Initialize
  57. * 08-jul-95 craige restrict surface width to pitch
  58. * 09-jul-95 craige export ComputePitch
  59. * 11-jul-95 craige fail aggregation calls
  60. * 13-jul-95 craige allow flippable offscreen & textures
  61. * 18-jul-95 craige removed Flush
  62. * 22-jul-95 craige bug 230 - unsupported starting modes
  63. * 10-aug-95 craige misc caps combo bugs
  64. * 21-aug-95 craige mode x support
  65. * 22-aug-95 craige bug 641
  66. * 02-sep-95 craige bug 854: disable > 640x480 flippable primary for rel1
  67. * 16-sep-95 craige bug 1117: all primary surfaces were marked as root,
  68. * instead of just first one
  69. * 19-sep-95 craige bug 1185: allow any width for explicit sysmem
  70. * 09-nov-95 colinmc slightly more validation of palettized surfaces
  71. * 05-dec-95 colinmc changed DDSCAPS_TEXTUREMAP => DDSCAPS_TEXTURE for
  72. * consistency with Direct3D
  73. * 06-dec-95 colinmc added mip-map support
  74. * 09-dec-95 colinmc added execute buffer support
  75. * 14-dec-95 colinmc added shared back and z-buffer support
  76. * 18-dec-95 colinmc additional caps. bit validity checking
  77. * 22-dec-95 colinmc Direct3D support no longer conditional
  78. * 02-jan-96 kylej handle new interface structures
  79. * 10-jan-96 colinmc IUnknowns aggregated by a surface is now a list
  80. * 18-jan-96 jeffno NT hardware support in CreateSurface.
  81. * 29-jan-96 colinmc Aggregated IUnknowns now stored in additional local
  82. * surface data structure
  83. * 09-feb-96 colinmc Surface lost flag moved from global to local object
  84. * 15-feb-96 colinmc Changed message output on surface creation to make
  85. * creation of surfaces with unspecified memory caps
  86. * less frightening
  87. * 17-feb-96 colinmc Fixed execute buffer size limitation problem
  88. * 13-mar-96 jeffno Correctly examine flags when allocating NT kernel
  89. * -mode structures
  90. * 24-mar-96 colinmc Bug 14321: not possible to specify back buffer and
  91. * mip-map count in a single call
  92. * 26-mar-96 colinmc Bug 14470: Compressed surface support
  93. * 14-apr-96 colinmc Bug 17736: No driver notification of flip to GDI
  94. * 17-may-96 craige Bug 23299: non-power of 2 alignments
  95. * 23-may-96 colinmc Bug 24190: Explicit system memory surface with
  96. * no pixel format can cause heap corruption if
  97. * another app. changes display depth
  98. * 26-may-96 colinmc Bug 24552: Heap trash on emulated cards
  99. * 30-may-96 colinmc Bug 24858: Creating explicit flipping surfaces with
  100. * pixel format fails.
  101. * 11-jul-96 scottm Fixed bug in IsDifferentPixelFormat
  102. * 10-oct-96 ketand Created DDRAWSURFACE_GBL_MORE (for Physical Page table)
  103. * 12-oct-96 colinmc Improvements to Win16 locking code to reduce virtual
  104. * memory usage
  105. * 08-dec-96 colinmc Initial AGP support
  106. * 12-jan-96 colinmc More Win16 work
  107. * 18-jan-97 colinmc AGP support
  108. * 29-jan-97 jeffno Mode13 support
  109. * 30-jan-97 jeffno Allow surfaces wider than the primary
  110. * 09-feb-97 colinmc Enabled OWNDC for explicit system memory surfaces
  111. * 03-mar-97 jeffno Work item: Extended surface memory alignment
  112. * 08-mar-97 colinmc Support for DMA style AGP parts
  113. * 10-mar-97 colinmc Bug 5981 Explicit system memory surfaces with
  114. * pixel formats which match the primary don't
  115. * store thier pixel format and hence mutate on a mode
  116. * switch.
  117. * 24-mar-97 jeffno Optimized Surfaces
  118. * 03-oct-97 jeffno DDSCAPS2 and DDSURFACEDESC2
  119. * 31-oct-97 johnstep Persistent-content surfaces for Windows 9x
  120. * 18-dec-97 jvanaken CreateSurface now takes client-alloc'd surface memory.
  121. *
  122. ***************************************************************************/
  123. #include "ddrawpr.h"
  124. #include "dx8priv.h"
  125. #ifdef WINNT
  126. #include "ddrawgdi.h"
  127. #endif
  128. #include "junction.h"
  129. #include <limits.h>
  130. /*
  131. * alignPitch - compute a new pitch that works with the requested alignment
  132. */
  133. __inline DWORD alignPitch( DWORD pitch, DWORD align )
  134. {
  135. DWORD remain;
  136. /*
  137. * is it garbage we're getting?
  138. */
  139. if( align == 0 )
  140. {
  141. return pitch;
  142. }
  143. /*
  144. * is pitch already aligned properly?
  145. */
  146. remain = pitch % align;
  147. if( remain == 0 )
  148. {
  149. return pitch;
  150. }
  151. /*
  152. * align pitch to next boundary
  153. */
  154. return (pitch + (align - remain));
  155. } /* alignPitch */
  156. #define DPF_MODNAME "CreateSurface"
  157. /*
  158. * pixel formats we know we can work with...
  159. *
  160. * currently we don't included DDPF_PALETTEINDEXED1, DDPF_PALETTEINDEXED2 and
  161. * DDPF_PALETTEINDEXED4 in this list so if you want to use one of these you
  162. * must specify a valid pixel format and have a HEL/HAL that will accept such
  163. * surfaces.
  164. */
  165. #define UNDERSTOOD_PF ( \
  166. DDPF_RGB | \
  167. DDPF_PALETTEINDEXED8 | \
  168. DDPF_ALPHAPIXELS | \
  169. DDPF_ZBUFFER | \
  170. DDPF_LUMINANCE | \
  171. DDPF_BUMPDUDV | \
  172. DDPF_BUMPLUMINANCE | \
  173. DDPF_ALPHA | \
  174. DDPF_ZPIXELS)
  175. #define DRIVER_SUPPORTS_DX6_ZBUFFERS(LPDDrawI_DDraw_GBL) ((LPDDrawI_DDraw_GBL)->dwNumZPixelFormats!=0)
  176. // DP2 should always exist in a DX6 D3D driver
  177. #define IS_DX6_D3DDRIVER(pDdGbl) (((pDdGbl)->lpD3DHALCallbacks3!=NULL) && \
  178. ((pDdGbl)->lpD3DHALCallbacks3->DrawPrimitives2!=NULL))
  179. typedef struct
  180. {
  181. LPDDRAWI_DDRAWSURFACE_INT *slist_int;
  182. LPDDRAWI_DDRAWSURFACE_LCL *slist_lcl;
  183. LPDDRAWI_DDRAWSURFACE_GBL *slist;
  184. BOOL listsize;
  185. BOOL listcnt;
  186. BOOL freelist;
  187. BOOL needlink;
  188. } CSINFO;
  189. /*
  190. * isPowerOf2
  191. *
  192. * if the input (dw) is a whole power of 2 returns TRUE and
  193. * *pPower is set to the exponent.
  194. * if the input (dw) is not a whole power of 2 returns FALSE and
  195. * *pPower is undefined.
  196. * NOTE: the caller can pass NULL for pPower.
  197. */
  198. BOOL isPowerOf2(DWORD dw, int* pPower)
  199. {
  200. int n;
  201. int nBits;
  202. DWORD dwMask;
  203. nBits = 0;
  204. dwMask = 0x00000001UL;
  205. for (n = 0; n < 32; n++)
  206. {
  207. if (dw & dwMask)
  208. {
  209. if (pPower != NULL)
  210. *pPower = n;
  211. nBits++;
  212. if (nBits > 1)
  213. break;
  214. }
  215. dwMask <<= 1;
  216. }
  217. return (nBits == 1);
  218. }
  219. /*
  220. * freeSurfaceList
  221. *
  222. * free all surfaces in an associated surface list, and destroys any
  223. * resources associated with the surface struct. This function is only called
  224. * before the surfaces have been linked into the global surface list and
  225. * before they have been AddRefed.
  226. */
  227. static void freeSurfaceList( LPDDRAWI_DDRAWSURFACE_INT *slist_int,
  228. int cnt )
  229. {
  230. LPDDRAWI_DDRAWSURFACE_INT psurf_int;
  231. LPDDRAWI_DDRAWSURFACE_LCL psurf_lcl;
  232. int i;
  233. if( slist_int == NULL )
  234. {
  235. return;
  236. }
  237. for( i=0;i<cnt;i++ )
  238. {
  239. psurf_int = slist_int[i];
  240. psurf_lcl = psurf_int->lpLcl;
  241. /*
  242. * if fpVidMem = DDHAL_PLEASEALLOC_BLOCKSIZE then we didn't actually allocate any
  243. * video memory. We still need to call the driver's DestroySurface but we don't want
  244. * it to free any video memory because we haven't allocated any. So we set the
  245. * video memory pointer and the heap to NULL.
  246. */
  247. if( (psurf_lcl->lpGbl->fpVidMem == DDHAL_PLEASEALLOC_BLOCKSIZE) ||
  248. //for the 3dfx driver which fails with fpVidMem correct and blocksizes setup..
  249. //blocksize is unioned with lpVidMemHeap so we crash in vidmemfree:
  250. ((psurf_lcl->lpGbl->dwBlockSizeY == (DWORD)psurf_lcl->lpGbl->wHeight) &&
  251. (psurf_lcl->lpGbl->dwBlockSizeX == (DWORD)psurf_lcl->lpGbl->wWidth)) )
  252. {
  253. psurf_lcl->lpGbl->lpVidMemHeap = NULL;
  254. psurf_lcl->lpGbl->fpVidMem = 0;
  255. }
  256. DestroySurface( psurf_lcl );
  257. DeleteAttachedSurfaceLists( psurf_lcl );
  258. if(IsD3DManaged(psurf_lcl))
  259. {
  260. if(psurf_lcl->lpSurfMore->lpRegionList)
  261. {
  262. MemFree( psurf_lcl->lpSurfMore->lpRegionList );
  263. }
  264. }
  265. /*
  266. * NOTE: We DO NOT explicitly free the DDRAWI_DDRAWSURFACE_MORE
  267. * structure pointed to by lpSurfMore as this is allocated in
  268. * a single MemAlloc with the local surface structure.
  269. */
  270. MemFree( psurf_lcl );
  271. MemFree( psurf_int );
  272. }
  273. } /* freeSurfaceList */
  274. /*
  275. * GetBytesFromPixels
  276. */
  277. DWORD GetBytesFromPixels( DWORD pixels, UINT bpp )
  278. {
  279. DWORD bytes;
  280. bytes = pixels;
  281. switch( bpp ) {
  282. case 1:
  283. bytes = (bytes+7)/8;
  284. break;
  285. case 2:
  286. bytes = (bytes+3)/4;
  287. break;
  288. case 4:
  289. bytes = (bytes+1)/2;
  290. break;
  291. case 8:
  292. break;
  293. case 16:
  294. bytes *= 2;
  295. break;
  296. case 24:
  297. bytes *= 3;
  298. break;
  299. case 32:
  300. bytes *= 4;
  301. break;
  302. default:
  303. bytes = 0;
  304. }
  305. DPF( 5, "GetBytesFromPixels( %ld, %d ) = %d", pixels, bpp, bytes );
  306. return bytes;
  307. } /* GetBytesFromPixels */
  308. /*
  309. * getPixelsFromBytes
  310. */
  311. static DWORD getPixelsFromBytes( DWORD bytes, UINT bpp )
  312. {
  313. DWORD pixels;
  314. pixels = bytes;
  315. switch( bpp ) {
  316. case 1:
  317. pixels *= 8L;
  318. break;
  319. case 2:
  320. pixels *= 4L;
  321. break;
  322. case 4:
  323. pixels *= 2L;
  324. break;
  325. case 8:
  326. break;
  327. case 16:
  328. pixels /= 2L;
  329. break;
  330. case 24:
  331. pixels /= 3L;
  332. break;
  333. case 32:
  334. pixels /= 4L;
  335. break;
  336. default:
  337. pixels = 0;
  338. }
  339. DPF( 5, "getPixelsFromBytes( %ld, %d ) = %d", bytes, bpp, pixels );
  340. return pixels;
  341. } /* getPixelsFromBytes */
  342. DWORD
  343. GetSurfaceHandle(LPDWLIST lpSurfaceHandleList, LPDDRAWI_DDRAWSURFACE_LCL lpSurface)
  344. {
  345. DWORD handle=lpSurfaceHandleList->dwFreeList;
  346. if (0==handle)
  347. {
  348. // need to grow the dwList
  349. LPDDSURFACELISTENTRY newList;
  350. DWORD newsize;
  351. DWORD index;
  352. if (NULL != lpSurfaceHandleList->dwList)
  353. {
  354. // old size(current dwFreeList) must not be zero
  355. DDASSERT(0 != lpSurfaceHandleList->dwList[0].nextentry);
  356. // new dwFreeList is always gonna be the old dwList[0].nextentry
  357. newsize = lpSurfaceHandleList->dwList[0].nextentry + LISTGROWSIZE;
  358. newList=(LPDDSURFACELISTENTRY)MemAlloc(newsize*sizeof(DDSURFACELISTENTRY));
  359. if (NULL == newList)
  360. {
  361. DPF_ERR( "MemAlloc failure in GetSurfaceHandle()" );
  362. return 0;
  363. }
  364. lpSurfaceHandleList->dwFreeList=lpSurfaceHandleList->dwList[0].nextentry;
  365. memcpy((LPVOID)newList,(LPVOID)lpSurfaceHandleList->dwList,
  366. lpSurfaceHandleList->dwList[0].nextentry*sizeof(DDSURFACELISTENTRY));
  367. MemFree(lpSurfaceHandleList->dwList);
  368. }
  369. else
  370. {
  371. newsize = LISTGROWSIZE;
  372. newList=(LPDDSURFACELISTENTRY)MemAlloc(newsize*sizeof(DDSURFACELISTENTRY));
  373. if (NULL == newList)
  374. {
  375. DPF_ERR( "MemAlloc failure in GetSurfaceHandle()" );
  376. return 0;
  377. }
  378. // start from one as we don't want 0 as a valid handle
  379. lpSurfaceHandleList->dwFreeList = 1;
  380. }
  381. lpSurfaceHandleList->dwList=newList;
  382. lpSurfaceHandleList->dwList[0].nextentry=newsize;
  383. for(index=lpSurfaceHandleList->dwFreeList;index<newsize-1;index++)
  384. {
  385. newList[index].nextentry=index+1;
  386. }
  387. // indicate end of new FreeList
  388. newList[newsize-1].nextentry=0;
  389. // now pop up one and assign it to handle
  390. handle=lpSurfaceHandleList->dwFreeList;
  391. }
  392. // handle slot is avialable so just remove it from freeList
  393. lpSurfaceHandleList->dwFreeList=lpSurfaceHandleList->dwList[handle].nextentry;
  394. #if DBG
  395. lpSurfaceHandleList->dwList[handle].nextentry=0xDEADBEEF;
  396. #endif
  397. lpSurfaceHandleList->dwList[handle].dwFlags=0; //mark it's new
  398. lpSurfaceHandleList->dwList[handle].lpSurface=lpSurface;
  399. DDASSERT ( handle > 0);
  400. DDASSERT ( handle < lpSurfaceHandleList->dwList[0].nextentry);
  401. return handle;
  402. }
  403. void
  404. ReleaseSurfaceHandle(LPDWLIST lpSurfaceHandleList,DWORD handle)
  405. {
  406. DDASSERT ( handle > 0);
  407. DDASSERT ( NULL != lpSurfaceHandleList->dwList);
  408. DDASSERT ( handle < lpSurfaceHandleList->dwList[0].nextentry);
  409. #if DBG
  410. DDASSERT ( 0xDEADBEEF == lpSurfaceHandleList->dwList[handle].nextentry);
  411. #endif
  412. lpSurfaceHandleList->dwList[handle].nextentry = lpSurfaceHandleList->dwFreeList;
  413. lpSurfaceHandleList->dwFreeList = handle;
  414. }
  415. LPDDRAWI_DDRAWSURFACE_LCL
  416. WINAPI GetDDSurfaceLocal(LPDDRAWI_DIRECTDRAW_LCL this_lcl, DWORD handle, BOOL* isnew)
  417. {
  418. DDASSERT ( NULL != this_lcl);
  419. DDASSERT ( NULL != SURFACEHANDLELIST(this_lcl).dwList);
  420. DDASSERT ( handle > 0);
  421. DDASSERT ( handle < SURFACEHANDLELIST(this_lcl).dwList[0].nextentry);
  422. #if DBG
  423. DDASSERT ( 0xDEADBEEF == SURFACEHANDLELIST(this_lcl).dwList[handle].nextentry);
  424. #endif
  425. if (FALSE == *isnew)
  426. {
  427. // only change flag if we are called from Reference Raterizer
  428. *isnew=(SURFACEHANDLELIST(this_lcl).dwList[handle].dwFlags==0);
  429. SURFACEHANDLELIST(this_lcl).dwList[handle].dwFlags=1; //mark it's not new anymore
  430. }
  431. return SURFACEHANDLELIST(this_lcl).dwList[handle].lpSurface;
  432. }
  433. /*
  434. * AllocSurfaceMem
  435. *
  436. * Allocate the memory for all surfaces that need it...
  437. */
  438. HRESULT AllocSurfaceMem(
  439. LPDDRAWI_DIRECTDRAW_LCL this_lcl,
  440. LPDDRAWI_DDRAWSURFACE_LCL * slist_lcl,
  441. int nsurf)
  442. {
  443. LPDDRAWI_DIRECTDRAW_GBL this;
  444. DWORD vm_width;
  445. DWORD vm_height;
  446. int scnt;
  447. LPDDRAWI_DDRAWSURFACE_LCL psurf_lcl;
  448. LPDDRAWI_DDRAWSURFACE_GBL psurf;
  449. DWORD caps;
  450. FLATPTR pvidmem;
  451. LPVIDMEM pheap;
  452. BOOL do_alloc;
  453. LONG newpitch;
  454. BOOL save_pitch;
  455. DWORD newcaps;
  456. DWORD forcemem = 0;
  457. BOOL anytype;
  458. this = this_lcl->lpGbl;
  459. DDASSERT( NULL != this );
  460. /*
  461. * allocate any remaining video memory needed
  462. */
  463. for( scnt=0;scnt<nsurf;scnt++ )
  464. {
  465. /*
  466. * Stores new capabilities which are introduced depending on the memory
  467. * heap allocated from.
  468. */
  469. newcaps = 0UL;
  470. newpitch = 0;
  471. DPF( 5,V, "*** Alloc Surface %d ***", scnt );
  472. /*
  473. * get preset video memory pointer
  474. */
  475. pheap = NULL;
  476. psurf_lcl = slist_lcl[scnt];
  477. psurf = psurf_lcl->lpGbl;
  478. do_alloc = TRUE;
  479. pvidmem = psurf->fpVidMem; //If this is a Restore, this will be non-null only if it's the gdi surface...
  480. //that's the only surface that doesn't have its vram deallocated
  481. //by DestroySurface. (assumption of jeffno 960122)
  482. DPF( 5,V, "pvidmem = %08lx", pvidmem );
  483. save_pitch = FALSE;
  484. if( pvidmem != (FLATPTR) NULL )
  485. {
  486. if( pvidmem != (FLATPTR) DDHAL_PLEASEALLOC_BLOCKSIZE )
  487. {
  488. do_alloc = FALSE;
  489. #ifdef SHAREDZ
  490. /*
  491. * NOTE: Previously if we did not do the alloc we
  492. * overwrote the heap pointer with NULL. This broke
  493. * the shared surfaces stuff. So now we assume that
  494. * if the heap pointer is non-NULL we will preserve
  495. * that value.
  496. *
  497. * !!! NOTE: Will this break stuff. Need to check this
  498. * out.
  499. */
  500. if( psurf->lpVidMemHeap )
  501. pheap = psurf->lpVidMemHeap;
  502. #endif
  503. }
  504. save_pitch = TRUE;
  505. }
  506. caps = psurf_lcl->ddsCaps.dwCaps;
  507. /*
  508. * are we creating a primary surface?
  509. */
  510. if( psurf->dwGlobalFlags & DDRAWISURFGBL_ISGDISURFACE) //caps & DDSCAPS_PRIMARYSURFACE )
  511. {
  512. DPF(5,V,"allocing for primary (do_alloc==%d)",do_alloc);
  513. if( do_alloc )
  514. {
  515. pvidmem = this->fpPrimaryOrig;
  516. }
  517. /*
  518. * must be an offscreen surface of some kind
  519. */
  520. }
  521. else
  522. {
  523. /*
  524. * NT handles all memory management issues in the kernel....
  525. */
  526. #ifndef WINNT
  527. /*
  528. * get a video memory pointer if no other ptr specified
  529. */
  530. if( do_alloc )
  531. {
  532. /*
  533. * get area of surface
  534. */
  535. if( pvidmem == (FLATPTR) DDHAL_PLEASEALLOC_BLOCKSIZE )
  536. {
  537. vm_width = psurf->dwBlockSizeX;
  538. vm_height = psurf->dwBlockSizeY;
  539. DPF( 5,V, "Driver requested width=%ld, height%ld", vm_width, vm_height );
  540. }
  541. else
  542. {
  543. if( caps & DDSCAPS_EXECUTEBUFFER )
  544. {
  545. /*
  546. * Execute buffers are long, thin surfaces for the purposes
  547. * of VM allocation.
  548. */
  549. vm_width = psurf->dwLinearSize;
  550. vm_height = 1UL;
  551. }
  552. else
  553. {
  554. /*
  555. * This lPitch may have been expanded by ComputePitch
  556. * to cover global alignment restrictions.
  557. */
  558. vm_width = (DWORD) labs( psurf->lPitch );
  559. vm_height = (DWORD) psurf->wHeight;
  560. }
  561. DPF( 5,V, "width = %ld, height = %ld", vm_width, vm_height );
  562. }
  563. /*
  564. * try to allocate memory
  565. */
  566. if( caps & DDSCAPS_SYSTEMMEMORY )
  567. {
  568. pvidmem = 0;
  569. pheap = NULL;
  570. }
  571. else
  572. {
  573. DWORD dwFlags = 0;
  574. HANDLE hvxd = GETDDVXDHANDLE( this_lcl );
  575. if (psurf->dwGlobalFlags &
  576. DDRAWISURFGBL_LATEALLOCATELINEAR)
  577. {
  578. dwFlags |= DDHA_SKIPRECTANGULARHEAPS;
  579. }
  580. if (this_lcl->lpGbl->ddCaps.dwCaps2 &
  581. DDCAPS2_NONLOCALVIDMEMCAPS)
  582. {
  583. dwFlags |= DDHA_ALLOWNONLOCALMEMORY;
  584. }
  585. if (this_lcl->lpGbl->lpD3DGlobalDriverData != 0 &&
  586. (this_lcl->lpGbl->lpD3DGlobalDriverData->hwCaps.dwDevCaps &
  587. D3DDEVCAPS_TEXTURENONLOCALVIDMEM))
  588. {
  589. dwFlags |= DDHA_ALLOWNONLOCALTEXTURES;
  590. }
  591. if (forcemem)
  592. {
  593. // Force allocations to the same memory type as the first
  594. psurf_lcl->ddsCaps.dwCaps &= ~(DDSCAPS_LOCALVIDMEM | DDSCAPS_NONLOCALVIDMEM);
  595. psurf_lcl->ddsCaps.dwCaps |= forcemem;
  596. }
  597. pvidmem = DdHeapAlloc( this->vmiData.dwNumHeaps,
  598. this->vmiData.pvmList,
  599. hvxd, &this->vmiData,
  600. vm_width, vm_height, psurf_lcl,
  601. dwFlags, &pheap,
  602. &newpitch, &newcaps, NULL );
  603. if( pvidmem == (FLATPTR) NULL )
  604. {
  605. pvidmem = DdHeapAlloc( this->vmiData.dwNumHeaps,
  606. this->vmiData.pvmList,
  607. hvxd, &this->vmiData,
  608. vm_width, vm_height, psurf_lcl,
  609. dwFlags | DDHA_USEALTCAPS,
  610. &pheap, &newpitch, &newcaps, NULL );
  611. }
  612. if (forcemem == 0)
  613. {
  614. // All surfaces must be of the same type as the first so we force
  615. // that type - newcaps contains either DDSCAPS_LOCALVIDMEM or
  616. // DDSCAPS_NONLOCALVIDMEM
  617. forcemem = newcaps;
  618. // determines whether the memory type was explicit or not, so we know
  619. // if we can change it if an allocation fails
  620. anytype = !(psurf_lcl->ddsCaps.dwCaps & (DDSCAPS_LOCALVIDMEM | DDSCAPS_NONLOCALVIDMEM));
  621. }
  622. else if (!pvidmem && anytype)
  623. {
  624. // Memory type was not explicity specified, so we're going to try the
  625. // other memory type
  626. int i;
  627. for (i=0; i<scnt; i++)
  628. {
  629. LPDDRAWI_DDRAWSURFACE_GBL tsurf = slist_lcl[i]->lpGbl;
  630. DDASSERT(tsurf->lpVidMemHeap != NULL);
  631. DDASSERT(tsurf->fpVidMem != (FLATPTR)NULL);
  632. VidMemFree(tsurf->lpVidMemHeap, tsurf->fpVidMem);
  633. tsurf->fpVidMem = (FLATPTR)NULL;
  634. }
  635. // Back up to the first surface
  636. scnt = -1;
  637. // Force the other memory type
  638. forcemem = (forcemem & DDSCAPS_LOCALVIDMEM) ? DDSCAPS_NONLOCALVIDMEM : DDSCAPS_LOCALVIDMEM;
  639. // Can no longer change memory type
  640. anytype = FALSE;
  641. DPF(4,"Not all surfaces in chain fit into 1 memory type, trying another");
  642. continue;
  643. }
  644. }
  645. }
  646. #endif //!WINNT
  647. }
  648. /*
  649. * zero out overloaded fields
  650. */
  651. psurf->dwBlockSizeX = 0;
  652. if (!(psurf_lcl->lpSurfMore->ddsCapsEx.dwCaps2 & DDSCAPS2_VOLUME))
  653. {
  654. // Don't zero this for volumes because it contains the slice pitch.
  655. // We will zero it later.
  656. psurf->dwBlockSizeY = 0;
  657. }
  658. /*
  659. * if no video memory found, fail
  660. */
  661. if( pvidmem == (FLATPTR) NULL && !(psurf->dwGlobalFlags & DDRAWISURFGBL_ISGDISURFACE) )//(caps & DDSCAPS_PRIMARYSURFACE) )
  662. {
  663. #ifndef WINNT
  664. DPF( 1, "Out of Video Memory. requested block: (%ld,%ld) (%ld bytes)",
  665. vm_width, vm_height, vm_height * vm_width );
  666. // set the heap to null so we don't mistakenly try to free the memory in DestroySurface
  667. #endif //not WINNT
  668. psurf->lpVidMemHeap = NULL;
  669. return DDERR_OUTOFVIDEOMEMORY;
  670. }
  671. /*
  672. * save pointer to video memory that we are using
  673. */
  674. if (pheap)
  675. psurf->lpVidMemHeap = pheap->lpHeap;
  676. else
  677. psurf->lpVidMemHeap = 0;
  678. psurf->fpVidMem = pvidmem;
  679. if( newpitch != 0 && !save_pitch && !( caps & DDSCAPS_EXECUTEBUFFER ) )
  680. {
  681. /*
  682. * The stride is not relevant for an execute buffer so we don't
  683. * override it.
  684. */
  685. psurf->lPitch = newpitch;
  686. }
  687. /*
  688. * Need to ensure that all video memory surfaces are tagged with
  689. * either DDSCAPS_LOCALVIDMEM or DDSCAPS_NONLOCALVIDMEM even if
  690. * the driver allocated them.
  691. */
  692. psurf_lcl->ddsCaps.dwCaps |= newcaps;
  693. if( psurf_lcl->ddsCaps.dwCaps & DDSCAPS_VIDEOMEMORY )
  694. {
  695. if( !( psurf_lcl->ddsCaps.dwCaps & ( DDSCAPS_LOCALVIDMEM | DDSCAPS_NONLOCALVIDMEM ) ) )
  696. {
  697. /*
  698. * Neither of local or non-local video memory have been set. In the
  699. * case of a driver which is not AGP aware then just turn local
  700. * video memory on. We also turn it on in the case of the primary
  701. * (which we know is in local video memory).
  702. *
  703. * NOTE: AGP aware devices should set the appropriate caps bit if
  704. * they take over surface allocation. However, we assume that if
  705. * they haven't then its local video memory (taking over non-local
  706. * allocation is hard). This is a very dodgy assumption and we should
  707. * revist it.
  708. */
  709. psurf_lcl->ddsCaps.dwCaps |= DDSCAPS_LOCALVIDMEM;
  710. #ifdef DEBUG
  711. #pragma message(REMIND("Fail creation by drivers that don't set vid mem qualifiers?"))
  712. if( this_lcl->lpGbl->ddCaps.dwCaps2 & DDCAPS2_NONLOCALVIDMEM )
  713. {
  714. DDASSERT( psurf_lcl->ddsCaps.dwCaps & ( DDSCAPS_LOCALVIDMEM | DDSCAPS_NONLOCALVIDMEM ) );
  715. DPF( 1, "AGP aware driver failed to set DDSCAPS_LOCALVIDMEM or DDSCAPS_NONLOCALVIDMEM" );
  716. }
  717. #endif /* DEBUG */
  718. }
  719. #ifndef WINNT
  720. if (forcemem == 0)
  721. {
  722. // Make sure we allocate all subsequent memory from the same source as the primary
  723. forcemem = psurf_lcl->ddsCaps.dwCaps & (DDSCAPS_LOCALVIDMEM | DDSCAPS_NONLOCALVIDMEM);
  724. anytype = FALSE;
  725. }
  726. #endif
  727. }
  728. /*
  729. * If the surface has ended up in non-local video memory then we need to
  730. * compute the physical memory pointer of the surface and store this away
  731. * for driver usage.
  732. */
  733. if( psurf_lcl->ddsCaps.dwCaps & DDSCAPS_NONLOCALVIDMEM )
  734. {
  735. /*
  736. * Computing the offset is simple but it requires that we have a
  737. * heap pointer. If we don't have one we assume that the driver
  738. * has filled the physical pointer in for us (as it has taken
  739. * over surface creation from us).
  740. */
  741. if( NULL != psurf->lpVidMemHeap )
  742. {
  743. DWORD dwOffset;
  744. FLATPTR fpPhysicalVidMem;
  745. DDASSERT( 0UL != psurf->fpVidMem );
  746. DDASSERT( 0UL != psurf->lpVidMemHeap->fpGARTLin );
  747. dwOffset = (DWORD)( psurf->fpVidMem - psurf->lpVidMemHeap->fpGARTLin );
  748. fpPhysicalVidMem = psurf->lpVidMemHeap->fpGARTDev + dwOffset;
  749. GET_LPDDRAWSURFACE_GBL_MORE( psurf )->fpPhysicalVidMem = fpPhysicalVidMem;
  750. DPF( 5, "Non-local surface: fpVidmem = 0x%08x fpPhysicalVidMem = 0x%08x",
  751. psurf->fpVidMem, fpPhysicalVidMem );
  752. }
  753. }
  754. }
  755. return DD_OK;
  756. } /* AllocSurfaceMem */
  757. /*
  758. * checkCaps
  759. *
  760. * check to make sure various caps combinations are valid
  761. */
  762. static HRESULT checkCaps( DWORD caps, LPDDRAWI_DIRECTDRAW_INT pdrv_int, LPDDSCAPSEX lpCapsEx )
  763. {
  764. DDASSERT(lpCapsEx);
  765. /*
  766. * check for no caps at all!
  767. */
  768. if( caps == 0 )
  769. {
  770. DPF_ERR( "no caps specified" );
  771. return DDERR_INVALIDCAPS;
  772. }
  773. /*
  774. * check for bogus caps.
  775. */
  776. if( caps & ~DDSCAPS_VALID )
  777. {
  778. DPF_ERR( "Create surface: invalid caps specified" );
  779. return DDERR_INVALIDCAPS;
  780. }
  781. if (lpCapsEx->dwCaps2 & ~DDSCAPS2_VALID)
  782. {
  783. DPF_ERR( "Create surface: invalid caps2 specified" );
  784. return DDERR_INVALIDCAPS;
  785. }
  786. if (lpCapsEx->dwCaps3 & ~DDSCAPS3_VALID)
  787. {
  788. DPF_ERR( "Create surface: invalid caps3 specified" );
  789. return DDERR_INVALIDCAPS;
  790. }
  791. if (!(lpCapsEx->dwCaps2 & DDSCAPS2_VOLUME))
  792. {
  793. if (lpCapsEx->dwCaps4 & ~DDSCAPS4_VALID)
  794. {
  795. DPF_ERR( "Create surface: invalid caps4 specified" );
  796. return DDERR_INVALIDCAPS;
  797. }
  798. }
  799. /*
  800. * check for "read-only" caps
  801. */
  802. if( caps & (DDSCAPS_PALETTE|
  803. DDSCAPS_VISIBLE) )
  804. {
  805. DPF_ERR( "read-only cap specified" );
  806. return DDERR_INVALIDCAPS;
  807. }
  808. if ((caps & DDSCAPS_WRITEONLY) && !(caps & DDSCAPS_EXECUTEBUFFER) && !(lpCapsEx->dwCaps2 & (DDSCAPS2_TEXTUREMANAGE | DDSCAPS2_D3DTEXTUREMANAGE)))
  809. {
  810. DPF_ERR( "read-only cap specified" );
  811. return DDERR_INVALIDCAPS;
  812. }
  813. // Make sure that DONOTPERSIST is used only in texture managed surfaces
  814. if ( lpCapsEx->dwCaps2 & DDSCAPS2_DONOTPERSIST )
  815. {
  816. if ( !(lpCapsEx->dwCaps2 & (DDSCAPS2_TEXTUREMANAGE | DDSCAPS2_D3DTEXTUREMANAGE)) )
  817. {
  818. DPF_ERR( "DDSCAPS2_DONOTPERSIST can only be used with managed surfaces" );
  819. return DDERR_INVALIDCAPS;
  820. }
  821. }
  822. // Check for correct usage of texturemanage caps
  823. if ( lpCapsEx->dwCaps2 & (DDSCAPS2_TEXTUREMANAGE | DDSCAPS2_D3DTEXTUREMANAGE) )
  824. {
  825. if (0 == (caps & DDSCAPS_TEXTURE) && !(pdrv_int->lpLcl->dwLocalFlags & DDRAWILCL_DIRECTDRAW8))
  826. {
  827. DPF_ERR("Managed surfaces must be textures");
  828. return DDERR_INVALIDCAPS;
  829. }
  830. }
  831. if( !(~lpCapsEx->dwCaps2 & (DDSCAPS2_TEXTUREMANAGE | DDSCAPS2_D3DTEXTUREMANAGE)) )
  832. {
  833. DPF_ERR( "DDSCAPS2 flags DDSCAPS2_TEXTUREMANAGE and DDSCAPS2_D3DTEXTUREMANAGE are mutually exclusive" );
  834. return DDERR_INVALIDCAPS;
  835. }
  836. // Check if DDSCAPS2_HINTDYNAMIC, DDSCAPS2_HINTSTATIC, and DDSCAPS2_OPAQUE have
  837. // been correctly specified
  838. if (!(pdrv_int->lpLcl->dwLocalFlags & DDRAWILCL_DIRECTDRAW8))
  839. {
  840. if( (lpCapsEx->dwCaps2 & (DDSCAPS2_HINTDYNAMIC | DDSCAPS2_HINTSTATIC | DDSCAPS2_OPAQUE)) &&
  841. !(caps & DDSCAPS_TEXTURE) )
  842. {
  843. DPF_ERR( "DDSCAPS2 flags HINTDYNAMIC, HINTSTATIC and OPAQUE can only be used with textures" );
  844. return DDERR_INVALIDCAPS;
  845. }
  846. }
  847. if( !(~lpCapsEx->dwCaps2 & (DDSCAPS2_HINTDYNAMIC | DDSCAPS2_HINTSTATIC)) )
  848. {
  849. DPF_ERR( "DDSCAPS2 flags HINTDYNAMIC and HINTSTATIC are mutually exclusive" );
  850. return DDERR_INVALIDCAPS;
  851. }
  852. else if( !(~lpCapsEx->dwCaps2 & (DDSCAPS2_HINTDYNAMIC | DDSCAPS2_OPAQUE)) )
  853. {
  854. DPF_ERR( "DDSCAPS2 flags HINTDYNAMIC and OPAQUE are mutually exclusive" );
  855. return DDERR_INVALIDCAPS;
  856. }
  857. else if( !(~lpCapsEx->dwCaps2 & (DDSCAPS2_HINTSTATIC | DDSCAPS2_OPAQUE)) )
  858. {
  859. DPF_ERR( "DDSCAPS2 flags HINTSTATIC and OPAQUE are mutually exclusive" );
  860. return DDERR_INVALIDCAPS;
  861. }
  862. /*
  863. * Valid optimized surface caps?
  864. */
  865. if( caps & DDSCAPS_OPTIMIZED )
  866. {
  867. // ATTENTION: Potential Apps-Compat problem!!
  868. DPF_ERR("Optimized surfaces cannot be created by create-surface");
  869. return DDERR_INVALIDCAPS;
  870. #if 0 //Old code
  871. if( !(caps & DDSCAPS_TEXTURE) )
  872. {
  873. DPF_ERR("Optimized surfaces can only be textures");
  874. return DDERR_INVALIDCAPS;
  875. }
  876. if (caps & (DDSCAPS_OWNDC|DDSCAPS_3DDEVICE|DDSCAPS_ALLOCONLOAD))
  877. {
  878. DPF_ERR("Invalid caps used in conjunction with DDSCAPS_OPTIMIZED");
  879. return DDERR_INVALIDCAPS;
  880. }
  881. if ( (caps & (DDSCAPS_SYSTEMMEMORY|DDSCAPS_VIDEOMEMORY)) == 0)
  882. {
  883. DPF_ERR("Optimized surfaces must be explicitly system or video memory");
  884. return DDERR_INVALIDCAPS;
  885. }
  886. #endif //0
  887. }
  888. /*
  889. * Check for memory type qualifiers
  890. */
  891. if( caps & ( DDSCAPS_LOCALVIDMEM | DDSCAPS_NONLOCALVIDMEM ) )
  892. {
  893. /*
  894. * Neither flag is allowed with system memory.
  895. */
  896. if( caps & DDSCAPS_SYSTEMMEMORY )
  897. {
  898. DPF_ERR( "Cannot specify local or non-local video memory with DDSCAPS_SYSTEMMEMORY" );
  899. return DDERR_INVALIDCAPS;
  900. }
  901. /*
  902. * One of the other of LOCALVIDMEM or NONLOCALVIDMEM but NOT both.
  903. */
  904. if( ( caps & ( DDSCAPS_LOCALVIDMEM | DDSCAPS_NONLOCALVIDMEM ) ) ==
  905. ( DDSCAPS_LOCALVIDMEM | DDSCAPS_NONLOCALVIDMEM ) )
  906. {
  907. DPF_ERR( "Cannot specify both DDSCAPS_LOCALVIDMEM and DDSCAPS_NONLOCALVIDMEM" );
  908. return DDERR_INVALIDCAPS;
  909. }
  910. }
  911. /*
  912. * For non-v1 interfaces, FRONTBUFFER and BACKBUFFER are read-only
  913. */
  914. if( pdrv_int->lpVtbl != &ddCallbacks )
  915. {
  916. if( caps & (DDSCAPS_FRONTBUFFER | DDSCAPS_BACKBUFFER) )
  917. {
  918. DPF_ERR( "can't specify FRONTBUFFER or BACKBUFFER");
  919. return DDERR_INVALIDCAPS;
  920. }
  921. }
  922. /*
  923. * Rather than having lots of little checks for execute buffers
  924. * we simply check for what can mix with execute buffers right
  925. * up front - its not a lot - system and video memory only.
  926. */
  927. if( caps & DDSCAPS_EXECUTEBUFFER )
  928. {
  929. if( caps & ~( DDSCAPS_EXECUTEBUFFER |
  930. DDSCAPS_SYSTEMMEMORY |
  931. DDSCAPS_VIDEOMEMORY |
  932. DDSCAPS_WRITEONLY ) )
  933. {
  934. DPF_ERR( "invalid caps specified with execute buffer" );
  935. return DDERR_INVALIDCAPS;
  936. }
  937. }
  938. /*
  939. * check for caps that don't mix with complex
  940. */
  941. if( caps & DDSCAPS_COMPLEX )
  942. {
  943. if( caps & ( DDSCAPS_FRONTBUFFER) )
  944. {
  945. DPF_ERR( "DDSCAPS_FRONTBUFFER flag is with DDSCAPS_COMPLEX" );
  946. return DDERR_INVALIDCAPS;
  947. }
  948. if( caps & DDSCAPS_BACKBUFFER )
  949. {
  950. if( !(caps & DDSCAPS_ALPHA) && !(caps & DDSCAPS_ZBUFFER))
  951. {
  952. DPF_ERR( "invalid CAPS flags: complex & backbuffer, but no alpha or zbuffer" );
  953. return DDERR_INVALIDCAPS;
  954. }
  955. if( (caps & DDSCAPS_FLIP))
  956. {
  957. DPF_ERR( "invalid CAPS flags: complex & backbuffer & flip" );
  958. return DDERR_INVALIDCAPS;
  959. }
  960. }
  961. if( !(caps & (DDSCAPS_BACKBUFFER|
  962. DDSCAPS_OFFSCREENPLAIN|
  963. DDSCAPS_OVERLAY|
  964. DDSCAPS_TEXTURE|
  965. DDSCAPS_PRIMARYSURFACE)) )
  966. {
  967. DPF_ERR( "invalid CAPS flags: DDSCAPS_COMPLEX requires at least one of DDSCAPS_BACKBUFFER/DDSCAPS_OFFSCREENPLAIN/DDSCAPS_OVERLAY/DDSCAPS_TEXTURE/DDSCAPS_PRIMARYSURFACE to be set");
  968. return DDERR_INVALIDCAPS;
  969. }
  970. if( !(caps & (DDSCAPS_FLIP|DDSCAPS_ALPHA|DDSCAPS_MIPMAP|DDSCAPS_ZBUFFER) ) &&
  971. !(lpCapsEx->dwCaps2 & DDSCAPS2_CUBEMAP) )
  972. {
  973. DPF_ERR( "invalid CAPS flags: must specify at least one of FLIP, ALPHA, ZBUFFER, 2_CUBEMAP or MIPMAP with COMPLEX" );
  974. return DDERR_INVALIDCAPS;
  975. }
  976. /*
  977. * flags that can't be used if not complex
  978. */
  979. }
  980. else
  981. {
  982. // if( caps & DDSCAPS_BACKBUFFER ) {
  983. // DPF_ERR( "invalid flags: backbuffer specfied for non-complex surface" );
  984. // return DDERR_INVALIDCAPS;
  985. // }
  986. }
  987. /*
  988. * check for caps that don't mix with backbuffer
  989. */
  990. if( caps & DDSCAPS_BACKBUFFER )
  991. {
  992. if( caps & (DDSCAPS_ALPHA |
  993. DDSCAPS_FRONTBUFFER ) )
  994. {
  995. DPF_ERR( "Invalid flags with backbuffer" );
  996. return DDERR_INVALIDCAPS;
  997. }
  998. }
  999. /*
  1000. * check for flags that don't mix with a flipping surface
  1001. */
  1002. if( caps & DDSCAPS_FLIP )
  1003. {
  1004. if( !(caps & DDSCAPS_COMPLEX) )
  1005. {
  1006. DPF_ERR( "invalid flags - flip but not complex" );
  1007. return DDERR_INVALIDCAPS;
  1008. }
  1009. }
  1010. /*
  1011. * check for flags that don't mix with a primary surface
  1012. */
  1013. if( caps & DDSCAPS_PRIMARYSURFACE )
  1014. {
  1015. if( caps & (DDSCAPS_BACKBUFFER |
  1016. DDSCAPS_OFFSCREENPLAIN |
  1017. DDSCAPS_OVERLAY |
  1018. DDSCAPS_TEXTURE ) )
  1019. {
  1020. DPF_ERR( "invalid flags with primary" );
  1021. return DDERR_INVALIDCAPS;
  1022. }
  1023. /* GEE: can't allow complex attachments to the primary surface
  1024. * because of our attachment code. The user is allowed to build
  1025. * these manually.
  1026. */
  1027. #ifdef USE_ALPHA
  1028. if( (caps & DDSCAPS_ALPHA) && !(caps & DDSCAPS_FLIP) )
  1029. {
  1030. DPF_ERR( "invalid flags with primary - alpha but not flippable" );
  1031. return DDERR_INVALIDCAPS;
  1032. }
  1033. #endif
  1034. if( (caps & DDSCAPS_ZBUFFER) && !(caps & DDSCAPS_FLIP) )
  1035. {
  1036. DPF_ERR( "invalid flags with primary - z but not flippable" );
  1037. return DDERR_INVALIDCAPS;
  1038. }
  1039. }
  1040. /*
  1041. * flags that don't mix with a plain offscreen surface
  1042. */
  1043. if( caps & DDSCAPS_OFFSCREENPLAIN )
  1044. {
  1045. /*
  1046. * I see no reason not to allow offscreen plains to be created
  1047. * with alpha's and z-buffers. So they have been enabled.
  1048. */
  1049. if( caps & (DDSCAPS_BACKBUFFER |
  1050. DDSCAPS_OVERLAY |
  1051. DDSCAPS_TEXTURE ) )
  1052. {
  1053. DPF_ERR( "invalid flags with offscreenplain" );
  1054. return DDERR_INVALIDCAPS;
  1055. }
  1056. }
  1057. /*
  1058. * check for flags that don't mix with asking for an overlay
  1059. */
  1060. if( caps & DDSCAPS_OVERLAY )
  1061. {
  1062. /* GEE: should remove BACKBUFFER here for 3D stuff */
  1063. if( caps & (DDSCAPS_BACKBUFFER |
  1064. DDSCAPS_OFFSCREENPLAIN |
  1065. DDSCAPS_TEXTURE ) )
  1066. {
  1067. DPF_ERR( "invalid flags with overlay" );
  1068. return DDERR_INVALIDCAPS;
  1069. }
  1070. if( (caps & DDSCAPS_ZBUFFER) && !(caps & DDSCAPS_FLIP) )
  1071. {
  1072. DPF_ERR( "invalid flags with overlay - zbuffer but not flippable" );
  1073. return DDERR_INVALIDCAPS;
  1074. }
  1075. #ifdef USE_ALPHA
  1076. if( (caps & DDSCAPS_ALPHA) && !(caps & DDSCAPS_FLIP) )
  1077. {
  1078. DPF_ERR( "invalid flags with overlay - alpha but not flippable" );
  1079. return DDERR_INVALIDCAPS;
  1080. }
  1081. #endif
  1082. }
  1083. /*
  1084. * check for flags that don't mix with asking for an texture
  1085. */
  1086. if( caps & DDSCAPS_TEXTURE )
  1087. {
  1088. }
  1089. /*
  1090. * validate MIPMAP
  1091. */
  1092. if( caps & DDSCAPS_MIPMAP )
  1093. {
  1094. /*
  1095. * Must be used in conjunction with TEXTURE.
  1096. */
  1097. if( !( caps & DDSCAPS_TEXTURE ) )
  1098. {
  1099. DPF_ERR( "invalid flags, mip-map specified but not texture" );
  1100. return DDERR_INVALIDCAPS;
  1101. }
  1102. /*
  1103. * Can't specify Z-buffer and mip-map.
  1104. */
  1105. if( caps & DDSCAPS_ZBUFFER )
  1106. {
  1107. DPF_ERR( "invalid flags, can't specify z-buffer with mip-map" );
  1108. return DDERR_INVALIDCAPS;
  1109. }
  1110. }
  1111. /*
  1112. * check for flags that don't mix with asking for a z-buffer
  1113. */
  1114. if( caps & DDSCAPS_ZBUFFER )
  1115. {
  1116. #ifdef USE_ALPHA
  1117. if( caps & DDSCAPS_ALPHA )
  1118. {
  1119. if( !(caps & DDSCAPS_COMPLEX) )
  1120. {
  1121. DPF_ERR( "invalid flags, alpha and Z specified, but not complex" );
  1122. }
  1123. }
  1124. #endif
  1125. if( ( caps & DDSCAPS_BACKBUFFER ) && !( caps & DDSCAPS_COMPLEX ) )
  1126. {
  1127. /*
  1128. * Can't specify z-buffer and back-buffer unless you also specify
  1129. * complex.
  1130. */
  1131. DPF_ERR( "invalid flags, z-buffer and back-buffer specified but not complex" );
  1132. return DDERR_INVALIDCAPS;
  1133. }
  1134. }
  1135. #ifdef SHAREDZ
  1136. /*
  1137. * Validate SHAREDZBUFFER
  1138. */
  1139. if( caps & DDSCAPS_SHAREDZBUFFER )
  1140. {
  1141. if( !( caps & DDSCAPS_ZBUFFER ) )
  1142. {
  1143. DPF_ERR( "invalid flags, shared z-buffer specified, but not z-buffer" );
  1144. return DDERR_INVALIDCAPS;
  1145. }
  1146. }
  1147. /*
  1148. * Validate SHAREDBACKBUFFER
  1149. */
  1150. if( caps & DDSCAPS_SHAREDBACKBUFFER )
  1151. {
  1152. /*
  1153. * Either BACKBUFFER must be specified explicitly or we must be part of
  1154. * a complex flippable chain.
  1155. */
  1156. if( !( ( caps & DDSCAPS_BACKBUFFER ) ||
  1157. ( ( caps & ( DDSCAPS_COMPLEX | DDSCAPS_FLIP ) ) ==
  1158. ( DDSCAPS_COMPLEX | DDSCAPS_FLIP ) ) ) )
  1159. {
  1160. DPF_ERR("invalid flags, shared back-buffer specified but not back-buffer or flippable chain" );
  1161. return DDERR_INVALIDCAPS;
  1162. }
  1163. }
  1164. #endif
  1165. /*
  1166. * check for flags that don't mix with asking for an alpha surface
  1167. */
  1168. #ifdef USE_ALPHA
  1169. if( caps & DDSCAPS_ALPHA )
  1170. {
  1171. }
  1172. #endif
  1173. /*
  1174. * check for flags that don't mix with asking for an alloc-on-load surface
  1175. */
  1176. if( caps & DDSCAPS_ALLOCONLOAD )
  1177. {
  1178. /*
  1179. * Must be texture map currently.
  1180. */
  1181. if( !( caps & DDSCAPS_TEXTURE ) )
  1182. {
  1183. DPF_ERR( "invalid flags, allocate-on-load surfaces must be texture maps" );
  1184. return DDERR_INVALIDCAPS;
  1185. }
  1186. }
  1187. if (lpCapsEx->dwCaps2 & DDSCAPS2_CUBEMAP_ALLFACES)
  1188. {
  1189. if (0 == (lpCapsEx->dwCaps2 & DDSCAPS2_CUBEMAP) )
  1190. {
  1191. DPF_ERR("You must specify DDSCAPS2_CUBEMAP if you specify any of DDSCAPS2_CUBEMAP_*");
  1192. return DDERR_INVALIDCAPS;
  1193. }
  1194. }
  1195. /*
  1196. * What doesn't mix with cubemaps
  1197. */
  1198. if (lpCapsEx->dwCaps2 & DDSCAPS2_CUBEMAP)
  1199. {
  1200. if (
  1201. (caps & ~(
  1202. DDSCAPS_SYSTEMMEMORY |
  1203. DDSCAPS_VIDEOMEMORY |
  1204. DDSCAPS_NONLOCALVIDMEM |
  1205. DDSCAPS_LOCALVIDMEM |
  1206. DDSCAPS_TEXTURE |
  1207. DDSCAPS_3DDEVICE |
  1208. DDSCAPS_MIPMAP |
  1209. DDSCAPS_COMPLEX |
  1210. DDSCAPS_OWNDC |
  1211. DDSCAPS_ALLOCONLOAD |
  1212. DDSCAPS_WRITEONLY |
  1213. DDSCAPS_VIDEOPORT ) )
  1214. ||
  1215. (lpCapsEx->dwCaps2 & ~(
  1216. DDSCAPS2_PERSISTENTCONTENTS |
  1217. DDSCAPS2_RESERVED4 |
  1218. DDSCAPS2_HINTDYNAMIC |
  1219. DDSCAPS2_HINTSTATIC |
  1220. DDSCAPS2_TEXTUREMANAGE |
  1221. DDSCAPS2_D3DTEXTUREMANAGE |
  1222. DDSCAPS2_OPAQUE |
  1223. DDSCAPS2_CUBEMAP |
  1224. DDSCAPS2_CUBEMAP_ALLFACES |
  1225. DDSCAPS2_DONOTPERSIST |
  1226. DDSCAPS2_HINTANTIALIASING |
  1227. DDSCAPS2_DONOTCREATED3DTEXOBJECT |
  1228. DDSCAPS2_NOTUSERLOCKABLE |
  1229. DDSCAPS2_DEINTERLACE ) )
  1230. ||
  1231. lpCapsEx->dwCaps3
  1232. ||
  1233. lpCapsEx->dwCaps4
  1234. )
  1235. {
  1236. DPF_ERR("Invalid surface caps with DDSCAPS2_CUBEMAP");
  1237. DPF_ERR(" Valid additional surface caps are:");
  1238. DPF_ERR(" DDSCAPS_SYSTEMMEMORY ");
  1239. DPF_ERR(" DDSCAPS_VIDEOMEMORY ");
  1240. DPF_ERR(" DDSCAPS_NONLOCALVIDMEM ");
  1241. DPF_ERR(" DDSCAPS_LOCALVIDMEM ");
  1242. DPF_ERR(" DDSCAPS_TEXTURE ");
  1243. DPF_ERR(" DDSCAPS_3DDEVICE ");
  1244. DPF_ERR(" DDSCAPS_MIPMAP ");
  1245. DPF_ERR(" DDSCAPS_COMPLEX ");
  1246. DPF_ERR(" DDSCAPS_OWNDC ");
  1247. DPF_ERR(" DDSCAPS_ALLOCONLOAD ");
  1248. DPF_ERR(" DDSCAPS_WRITEONLY ");
  1249. DPF_ERR(" DDSCAPS_VIDEOPORT");
  1250. DPF_ERR(" DDSCAPS2_PERSISTENTCONTENTS ");
  1251. DPF_ERR(" DDSCAPS2_CUBEMAP_* ");
  1252. DPF_ERR(" DDSCAPS2_HINTDYNAMIC ");
  1253. DPF_ERR(" DDSCAPS2_HINTSTATIC ");
  1254. DPF_ERR(" DDSCAPS2_TEXTUREMANAGE ");
  1255. DPF_ERR(" DDSCAPS2_D3DTEXTUREMANAGE ");
  1256. DPF_ERR(" DDSCAPS2_OPAQUE ");
  1257. DPF_ERR(" DDSCAPS2_HINTANTIALIASING");
  1258. DPF_ERR(" DDSCAPS2_DONOTPERSIST");
  1259. DPF_ERR(" DDSCAPS2_DEINTERLACE");
  1260. return DDERR_INVALIDPARAMS;
  1261. }
  1262. /*
  1263. * Must be either a texture or a render target
  1264. */
  1265. if ( (caps & (DDSCAPS_3DDEVICE|DDSCAPS_TEXTURE)) == 0)
  1266. {
  1267. DPF_ERR("DDSCAPS2_CUBEMAP requires DDSCAPS_3DDEVICE and/or DDSCAPS_TEXTURE");
  1268. return DDERR_INVALIDPARAMS;
  1269. }
  1270. /*
  1271. * Must be complex
  1272. */
  1273. if ( (caps & DDSCAPS_COMPLEX) == 0)
  1274. {
  1275. DPF_ERR("DDSCAPS2_CUBEMAP requires DDSCAPS_COMPLEX");
  1276. return DDERR_DDSCAPSCOMPLEXREQUIRED;
  1277. }
  1278. /*
  1279. * Must specify at least one face
  1280. */
  1281. if ( (lpCapsEx->dwCaps2 & DDSCAPS2_CUBEMAP_ALLFACES) == 0)
  1282. {
  1283. DPF_ERR("DDSCAPS2_CUBEMAP requires at least one face (i.e. at least one DDSCAPS2_CUBEMAP_POSITIVE/NEGATIVE");
  1284. return DDERR_INVALIDPARAMS;
  1285. }
  1286. /*
  1287. * Device must support the caps. Note down here, we never see neither
  1288. * memory type. We are guaranteed video or system
  1289. */
  1290. {
  1291. DWORD dwCaps2 = 0;
  1292. if ( caps & DDSCAPS_VIDEOMEMORY )
  1293. {
  1294. dwCaps2 = pdrv_int->lpLcl->lpGbl->ddsCapsMore.dwCaps2;
  1295. }
  1296. else if ( caps & DDSCAPS_SYSTEMMEMORY )
  1297. {
  1298. dwCaps2 = pdrv_int->lpLcl->lpGbl->ddsHELCapsMore.dwCaps2;
  1299. }
  1300. else
  1301. {
  1302. DDASSERT(!"Neither video nor system caps set on cubemap");
  1303. }
  1304. if ( ( dwCaps2 & DDSCAPS2_CUBEMAP ) == 0 )
  1305. {
  1306. DPF(0,"CubeMaps not supported in %s memory", (caps & DDSCAPS_VIDEOMEMORY) ? "video":"system");
  1307. return DDERR_UNSUPPORTED;
  1308. }
  1309. }
  1310. }
  1311. // DX7Stereo
  1312. if (lpCapsEx->dwCaps2 & DDSCAPS2_STEREOSURFACELEFT)
  1313. {
  1314. if ((caps & DDSCAPS_PRIMARYSURFACE)==0 ||
  1315. (caps & DDSCAPS_FLIP)==0 ||
  1316. (caps & DDSCAPS_COMPLEX)==0 ||
  1317. (caps & DDSCAPS_VIDEOMEMORY)==0)
  1318. {
  1319. DPF(0,"DDSCAPS2_STEREOSURFACELEFT only supported with: ");
  1320. DPF(0," DDSCAPS_PRIMARYSURFACE & DDSCAPS_FLIP & DDSCAPS_COMPLEX & DDSCAPS_VIDEOMEMORY");
  1321. return DDERR_UNSUPPORTED;
  1322. }
  1323. }
  1324. return DD_OK;
  1325. } /* checkCaps */
  1326. #ifdef SHAREDZ
  1327. /*
  1328. * For this initial version of shared back and z support the shared back and
  1329. * z-buffers can only be full screen. We don't allow a specification of size.
  1330. */
  1331. #define CAPS_NOHEIGHT_REQUIRED ( DDSCAPS_PRIMARYSURFACE | DDSCAPS_EXECUTEBUFFER | DDSCAPS_SHAREDZBUFFER | DDSCAPS_SHAREDBACKBUFFER )
  1332. #define CAPS_NOWIDTH_REQUIRED ( DDSCAPS_PRIMARYSURFACE | DDSCAPS_SHAREDZBUFFER | DDSCAPS_SHAREDBACKBUFFER )
  1333. #else
  1334. #define CAPS_NOHEIGHT_REQUIRED ( DDSCAPS_PRIMARYSURFACE | DDSCAPS_EXECUTEBUFFER )
  1335. #define CAPS_NOWIDTH_REQUIRED ( DDSCAPS_PRIMARYSURFACE | DDSCAPS_EXECUTEBUFFER )
  1336. #endif
  1337. /*
  1338. * checkSurfaceDesc
  1339. *
  1340. * make sure a provided surface description is OK
  1341. */
  1342. HRESULT checkSurfaceDesc(
  1343. LPDDSURFACEDESC2 lpsd,
  1344. LPDDRAWI_DIRECTDRAW_GBL pdrv,
  1345. DWORD FAR *psflags,
  1346. BOOL emulation,
  1347. BOOL real_sysmem,
  1348. LPDDRAWI_DIRECTDRAW_INT pdrv_int )
  1349. {
  1350. DWORD sdflags;
  1351. DWORD pfflags;
  1352. DWORD caps;
  1353. DDSCAPSEX capsEx;
  1354. HRESULT ddrval;
  1355. DWORD bpp;
  1356. BOOL halonly;
  1357. BOOL helonly;
  1358. int wPower;
  1359. int hPower;
  1360. if( emulation )
  1361. {
  1362. helonly = TRUE;
  1363. halonly = FALSE;
  1364. } else {
  1365. helonly = FALSE;
  1366. halonly = TRUE;
  1367. }
  1368. /*
  1369. * we assume caps always - DDSD_CAPS is default
  1370. */
  1371. sdflags = lpsd->dwFlags;
  1372. caps = lpsd->ddsCaps.dwCaps;
  1373. capsEx = lpsd->ddsCaps.ddsCapsEx;
  1374. /*
  1375. * check complex
  1376. */
  1377. if( !(caps & DDSCAPS_COMPLEX) )
  1378. {
  1379. if( sdflags & DDSD_BACKBUFFERCOUNT )
  1380. {
  1381. DPF_ERR( "backbuff count on non-complex surface" );
  1382. return DDERR_INVALIDCAPS;
  1383. }
  1384. if( sdflags & DDSD_MIPMAPCOUNT )
  1385. {
  1386. DPF_ERR( "mip-map count on non-complex surface" );
  1387. return DDERR_INVALIDCAPS;
  1388. }
  1389. }
  1390. else
  1391. {
  1392. if( ( sdflags & DDSD_BACKBUFFERCOUNT ) && ( sdflags & DDSD_MIPMAPCOUNT ) )
  1393. {
  1394. DPF_ERR( "Currently can't specify both a back buffer and mip-map count" );
  1395. return DDERR_INVALIDPARAMS;
  1396. }
  1397. }
  1398. /*
  1399. * check flip
  1400. */
  1401. if( caps & DDSCAPS_FLIP )
  1402. {
  1403. if( !(caps & DDSCAPS_COMPLEX) )
  1404. {
  1405. DPF_ERR( "flip specified without complex" );
  1406. return DDERR_INVALIDCAPS;
  1407. }
  1408. if( !(sdflags & DDSD_BACKBUFFERCOUNT) || (lpsd->dwBackBufferCount == 0) )
  1409. {
  1410. DPF_ERR( "flip specified without any backbuffers" );
  1411. return DDERR_INVALIDCAPS;
  1412. }
  1413. /*
  1414. * Currently we don't allow the creating of flippable mip-map
  1415. * chains with a single call to CreateSurface(). They must be
  1416. * built manually. This will be implmented but is not in place
  1417. * as yet. Hence, for now we fail the attempt with a
  1418. * DDERR_UNSUPPORTED.
  1419. */
  1420. if( sdflags & DDSD_MIPMAPCOUNT )
  1421. {
  1422. DPF_ERR( "Creating flippable mip-map chains with a single call is not yet implemented" );
  1423. return DDERR_UNSUPPORTED;
  1424. }
  1425. }
  1426. /*
  1427. * Check hardware deinterlacing
  1428. */
  1429. if( capsEx.dwCaps2 & DDSCAPS2_RESERVED4 )
  1430. {
  1431. if( !( caps & DDSCAPS_VIDEOPORT ) || !( caps & DDSCAPS_OVERLAY ) )
  1432. {
  1433. DPF_ERR( "DDSCAPS2_RESERVED4 specified w/o video port or overlay" );
  1434. return DDERR_INVALIDCAPS;
  1435. }
  1436. if( ( pdrv->lpDDVideoPortCaps == NULL ) ||
  1437. !( pdrv->lpDDVideoPortCaps->dwCaps & DDVPCAPS_HARDWAREDEINTERLACE ) )
  1438. {
  1439. DPF_ERR( "No hardware support for DDSCAPS_RESERVED4" );
  1440. return DDERR_INVALIDCAPS;
  1441. }
  1442. if( caps & DDSCAPS_COMPLEX )
  1443. {
  1444. DPF_ERR( "DDSCAPS2_RESERVERD4 not valid w/ a complex surface" );
  1445. return DDERR_INVALIDCAPS;
  1446. }
  1447. }
  1448. /*
  1449. * check various caps combinations
  1450. */
  1451. ddrval = checkCaps( caps, pdrv_int , &capsEx);
  1452. if( ddrval != DD_OK )
  1453. {
  1454. return ddrval;
  1455. }
  1456. /*
  1457. * check alpha
  1458. */
  1459. if( (caps & DDSCAPS_ALPHA) )
  1460. {
  1461. #pragma message( REMIND( "Alpha not supported in Rev 1" ))
  1462. DPF_ERR( "Alpha not supported this release" );
  1463. return DDERR_INVALIDPARAMS;
  1464. #ifdef USE_ALPHA
  1465. if( !(sdflags & DDSD_ALPHABITDEPTH) )
  1466. {
  1467. DPF_ERR( "AlphaBitDepth required in SurfaceDesc" );
  1468. return DDERR_INVALIDPARAMS;
  1469. }
  1470. if( (lpsd->dwAlphaBitDepth > 8) ||
  1471. GetBytesFromPixels( 1, lpsd->dwAlphaBitDepth ) == 0 )
  1472. {
  1473. DPF_ERR( "Invalid AlphaBitDepth specified in SurfaceDesc" );
  1474. return DDERR_INVALIDPARAMS;
  1475. }
  1476. #endif
  1477. }
  1478. else if( sdflags & DDSD_ALPHABITDEPTH )
  1479. {
  1480. DPF_ERR( "AlphaBitDepth only valid for alpha surfaces" );
  1481. return DDERR_INVALIDPARAMS;
  1482. }
  1483. /*
  1484. * check z buffer
  1485. */
  1486. if( (caps & DDSCAPS_ZBUFFER) )
  1487. {
  1488. DDSURFACEDESC *pOldSD=(DDSURFACEDESC *)lpsd;
  1489. DWORD zbitdepth;
  1490. if(lpsd->dwSize==sizeof(DDSURFACEDESC)) {
  1491. // allow old way to request Z, using DDSD_ZBUFFERBITDEPTH field
  1492. // also allow z to be requested through pixfmt
  1493. if(sdflags & DDSD_PIXELFORMAT) {
  1494. if(lpsd->ddpfPixelFormat.dwSize!=sizeof(DDPIXELFORMAT)) {
  1495. DPF_ERR("Hey, you didn't set DDSURFACEDESC.ddpfPixelFormat.dwSize to sizeof(DDPIXELFORMAT)! Do that.");
  1496. return DDERR_INVALIDPARAMS;
  1497. }
  1498. if(pOldSD->ddpfPixelFormat.dwFlags & DDPF_STENCILBUFFER) {
  1499. DPF_ERR("Stencil ZBuffers can only be created using a SURFACEDESC2 passed to IDirectDraw4's CreateSurface");
  1500. return DDERR_INVALIDPARAMS;
  1501. }
  1502. if(pOldSD->ddpfPixelFormat.dwFlags & DDPF_ZBUFFER) {
  1503. // pixfmt overrides ddsd zbufferbitdepth.
  1504. // copy zbitdepth back to SD field because old drivers require it there
  1505. pOldSD->dwZBufferBitDepth=pOldSD->ddpfPixelFormat.dwZBufferBitDepth;
  1506. pOldSD->dwFlags|=DDSD_ZBUFFERBITDEPTH;
  1507. sdflags|=DDSD_ZBUFFERBITDEPTH;
  1508. } else {
  1509. DPF_ERR("If DDSD_PIXELFORMAT specified, DDPF_ZBUFFER flag must be too");
  1510. return DDERR_INVALIDPARAMS;
  1511. }
  1512. } else if(sdflags & DDSD_ZBUFFERBITDEPTH) {
  1513. if(!(caps & DDSCAPS_COMPLEX)) {
  1514. // setup valid zpixfmt
  1515. memset(&pOldSD->ddpfPixelFormat,0,sizeof(DDPIXELFORMAT));
  1516. pOldSD->ddpfPixelFormat.dwSize=sizeof(DDPIXELFORMAT);
  1517. pOldSD->ddpfPixelFormat.dwZBufferBitDepth=pOldSD->dwZBufferBitDepth;
  1518. pOldSD->ddpfPixelFormat.dwFlags|=DDPF_ZBUFFER;
  1519. pOldSD->dwFlags|=DDSD_PIXELFORMAT;
  1520. sdflags|=DDSD_PIXELFORMAT;
  1521. }
  1522. // for complex surfaces, cannot write zbuffer pixfmt because that would overwrite
  1523. // the main surface pixfmt
  1524. } else {
  1525. DPF_ERR("Neither DDSD_ZBUFFERBITDEPTH nor a ZBuffer ddpfPixelFormat was specified");
  1526. return DDERR_INVALIDPARAMS;
  1527. }
  1528. // fill in ZBitMask for them, so future pixfmt will be completely valid
  1529. if(!(caps & DDSCAPS_COMPLEX)) {
  1530. if(pOldSD->ddpfPixelFormat.dwZBufferBitDepth==32)
  1531. pOldSD->ddpfPixelFormat.dwZBitMask = 0xffffffff;
  1532. else pOldSD->ddpfPixelFormat.dwZBitMask = (1<<pOldSD->ddpfPixelFormat.dwZBufferBitDepth)-1;
  1533. }
  1534. } else { // SURFACEDESC2 was used (IDDraw4:CreateSurface)
  1535. if(caps & DDSCAPS_COMPLEX) {
  1536. DPF_ERR( "As of IDirectDraw4, Complex Surface Creations can no longer contain ZBuffers, must create ZBuffer separately and attach");
  1537. return DDERR_INVALIDPARAMS;
  1538. }
  1539. if(sdflags & DDSD_ZBUFFERBITDEPTH) {
  1540. DPF_ERR("DDSD_ZBUFFERBITDEPTH flag obsolete for DDSURFACEDESC2, specify ZBuffer format in ddpfPixelFormat instead");
  1541. return DDERR_INVALIDPARAMS;
  1542. }
  1543. if(!(sdflags & DDSD_PIXELFORMAT)) {
  1544. DPF_ERR("DDSD_PIXELFORMAT flag not set. For DDSURFACEDESC2, ZBuffer format must be specified in ddpfPixelFormat");
  1545. return DDERR_INVALIDPARAMS;
  1546. }
  1547. if(lpsd->ddpfPixelFormat.dwSize!=sizeof(DDPIXELFORMAT)) {
  1548. DPF_ERR("Hey, you didn't set DDSURFACEDESC2.ddpfPixelFormat.dwSize to sizeof(DDPIXELFORMAT)! Do that.");
  1549. return DDERR_INVALIDPARAMS;
  1550. }
  1551. if(!(lpsd->ddpfPixelFormat.dwFlags & DDPF_ZBUFFER)) {
  1552. DPF_ERR("DDPF_ZBUFFER flag must be set in pixfmt flags");
  1553. return DDERR_INVALIDPARAMS;
  1554. }
  1555. // not requiring this for legacy DDSURFACEDESC creations
  1556. if(lpsd->ddpfPixelFormat.dwZBitMask==0x0) {
  1557. DPF_ERR("Error: dwZBitMask must be non-0 (just copy it from the EnumZBufferFormats pixfmt)");
  1558. return DDERR_INVALIDPARAMS;
  1559. }
  1560. if(lpsd->ddpfPixelFormat.dwFlags & DDPF_STENCILBUFFER) {
  1561. // probably can't trust old drivers' CanCreateSurface to fail stencil request,
  1562. // so just fail it ourselves right here.
  1563. // if driver doesn't support EnumZBufferFormats, it can't support stencil.
  1564. // this is indicated by the 0 in pdrv->dwNumZPixelFormats
  1565. if((!emulation) && !DRIVER_SUPPORTS_DX6_ZBUFFERS(pdrv)) {
  1566. DPF_ERR("Driver doesn't support Stencil ZBuffers");
  1567. return DDERR_UNSUPPORTED;
  1568. }
  1569. } else {
  1570. // NOTE: Old drivers require the DDSURFACEDESC.dwZBufferBitDepth to be set for
  1571. // CanCreateSurface and CreateSurface. So if user asks for z-only surface, go
  1572. // ahead and set this field so creating z-only zbuffers with IDDraw4 will work with
  1573. // old drivers. I'm leaving DDSD_ZBUFFERBITDEPTH flag unset because
  1574. // I dont want to confuse driver writers into still using that field and every driver
  1575. // I've looked at keys off of DDSCAPS_ZBUFFER (which is set) and not DDSD_ZBUFFERBITDEPTH.
  1576. // Any driver that allows stenciling is a DX6 driver and should ignore the SD zbufferbitdepth,
  1577. // so no need to do this copy for them
  1578. pOldSD->dwZBufferBitDepth=lpsd->ddpfPixelFormat.dwZBufferBitDepth;
  1579. }
  1580. }
  1581. if(caps & DDSCAPS_COMPLEX)
  1582. zbitdepth=((DDSURFACEDESC*)lpsd)->dwZBufferBitDepth;
  1583. else zbitdepth=lpsd->ddpfPixelFormat.dwZBufferBitDepth;
  1584. if(zbitdepth<8) {
  1585. DPF_ERR("Invalid dwZBufferBitDepth, must be >=8 bits");
  1586. return DDERR_INVALIDPARAMS;
  1587. }
  1588. // side note for stencils: If stencils are present, dwZBufferBitDepth represents
  1589. // the total bit depth including both z and stencil bits, so z-only bits are
  1590. // dwZBufferBitDepth-dwStencilBufferBitDepth. This was done because we're afraid
  1591. // ddraw code makes too many assumptions that the total bitdepth of a surface is always
  1592. // found in the pixfmt (dwRGBBitCount/dwZBufferBitDepth) union when it does pixel computations.
  1593. if(lpsd->ddpfPixelFormat.dwFlags & DDPF_STENCILBUFFER) {
  1594. if(lpsd->ddpfPixelFormat.dwStencilBitDepth==0) {
  1595. DPF_ERR("Invalid SurfaceDesc StencilBufferBitDepth, must be non-0");
  1596. return DDERR_INVALIDPARAMS;
  1597. }
  1598. if(lpsd->ddpfPixelFormat.dwStencilBitMask==0x0) {
  1599. DPF_ERR("Error: dwStencilBitMask must be non-0 (just copy it from the EnumZBufferFormats pixfmt)");
  1600. return DDERR_INVALIDPARAMS;
  1601. }
  1602. }
  1603. } else if((sdflags & DDSD_ZBUFFERBITDEPTH) ||
  1604. ((sdflags & DDSD_PIXELFORMAT) && ((lpsd->ddpfPixelFormat.dwFlags & DDPF_ZBUFFER) ||
  1605. (lpsd->ddpfPixelFormat.dwFlags & DDPF_STENCILBUFFER)))) {
  1606. DPF_ERR("DDSD_ZBUFFERBITDEPTH, DDPF_ZBUFFER, and DDPF_STENCILBUFFER flags only valid with DDSCAPS_ZBUFFER set");
  1607. return DDERR_INVALIDPARAMS;
  1608. }
  1609. /*
  1610. * Validate height/width
  1611. */
  1612. if( sdflags & DDSD_HEIGHT )
  1613. {
  1614. if( (caps & DDSCAPS_PRIMARYSURFACE) )
  1615. {
  1616. DPF_ERR( "Height can't be specified for primary surface" );
  1617. return DDERR_INVALIDPARAMS;
  1618. }
  1619. #ifdef SHAREDZ
  1620. if( caps & ( DDSCAPS_SHAREDZBUFFER | DDSCAPS_SHAREDBACKBUFFER ) )
  1621. {
  1622. DPF_ERR( "Height can't be specified for shared back or z-buffers" );
  1623. return DDERR_INVALIDPARAMS;
  1624. }
  1625. #endif
  1626. if( lpsd->dwHeight < 1 )
  1627. {
  1628. DPF_ERR( "Invalid height specified" );
  1629. return DDERR_INVALIDPARAMS;
  1630. }
  1631. }
  1632. else
  1633. {
  1634. if( !(caps & CAPS_NOHEIGHT_REQUIRED) )
  1635. {
  1636. DPF_ERR( "Height must be specified for surface" );
  1637. return DDERR_INVALIDPARAMS;
  1638. }
  1639. }
  1640. if( sdflags & DDSD_WIDTH )
  1641. {
  1642. DWORD maxwidth;
  1643. if( (caps & DDSCAPS_PRIMARYSURFACE) )
  1644. {
  1645. DPF_ERR( "Width can't be specified for primary surface" );
  1646. return DDERR_INVALIDPARAMS;
  1647. }
  1648. #ifdef SHAREDZ
  1649. if( caps & ( DDSCAPS_SHAREDZBUFFER | DDSCAPS_SHAREDBACKBUFFER ) )
  1650. {
  1651. DPF_ERR( "Width can't be specified for shared back or z-buffers" );
  1652. return DDERR_INVALIDPARAMS;
  1653. }
  1654. #endif
  1655. if( lpsd->dwWidth < 1 )
  1656. {
  1657. DPF_ERR( "Invalid width specified" );
  1658. return DDERR_INVALIDPARAMS;
  1659. }
  1660. if( ( !real_sysmem ) && !( caps & DDSCAPS_EXECUTEBUFFER ) &&
  1661. !( caps & DDSCAPS_VIDEOPORT ) )
  1662. {
  1663. if ( (dwRegFlags & DDRAW_REGFLAGS_DISABLEWIDESURF) ||
  1664. ( !(pdrv->ddCaps.dwCaps2 & DDCAPS2_WIDESURFACES)) )
  1665. {
  1666. maxwidth = getPixelsFromBytes( pdrv->vmiData.lDisplayPitch,
  1667. pdrv->vmiData.ddpfDisplay.dwRGBBitCount );
  1668. if( lpsd->dwWidth > maxwidth )
  1669. {
  1670. DPF( 0, "Width too big: %ld reqested, max is %ld", lpsd->dwWidth, maxwidth );
  1671. return DDERR_INVALIDPARAMS;
  1672. }
  1673. }
  1674. }
  1675. }
  1676. else
  1677. {
  1678. if( !(caps & CAPS_NOWIDTH_REQUIRED) )
  1679. {
  1680. DPF_ERR( "Width must be specified for surface" );
  1681. return DDERR_INVALIDPARAMS;
  1682. }
  1683. }
  1684. /*
  1685. * Extra validation for mip-map width and height (must be a whole power of 2)
  1686. * and number of levels.
  1687. */
  1688. if( caps & DDSCAPS_MIPMAP )
  1689. {
  1690. if( sdflags & DDSD_MIPMAPCOUNT )
  1691. {
  1692. if( lpsd->dwMipMapCount == 0 )
  1693. {
  1694. DPF_ERR( "Invalid number of mip-map levels (0) specified" );
  1695. return DDERR_INVALIDPARAMS;
  1696. }
  1697. }
  1698. if( sdflags & DDSD_HEIGHT )
  1699. {
  1700. if( !isPowerOf2( lpsd->dwHeight, &hPower ) )
  1701. {
  1702. DPF_ERR( "Invalid height: height of a mip-map must be whole power of 2" );
  1703. return DDERR_INVALIDPARAMS;
  1704. }
  1705. }
  1706. if( sdflags & DDSD_WIDTH )
  1707. {
  1708. if( !isPowerOf2( lpsd->dwWidth, &wPower ) )
  1709. {
  1710. DPF_ERR( "Invalid width: width of a mip-map must be whole power of 2" );
  1711. return DDERR_INVALIDPARAMS;
  1712. }
  1713. }
  1714. if (sdflags & (DDSD_WIDTH|DDSD_HEIGHT) )
  1715. {
  1716. /*
  1717. * For deep mipmaps, we need to ensure that the supplied mipmapcount is no larger
  1718. * than the largest of the supplied dimensions. This restriction is slightly weaker
  1719. * than the DX2->DX6 restriction that the mipmapcount is no larger than either dimension.
  1720. */
  1721. int power = max ( hPower , wPower );
  1722. if( sdflags & DDSD_MIPMAPCOUNT )
  1723. {
  1724. if (lpsd->dwMipMapCount > (DWORD) ( power + 1 ))
  1725. {
  1726. DPF( 0, "Invalid number of mip-map levels (%ld) specified", lpsd->dwMipMapCount );
  1727. return DDERR_INVALIDPARAMS;
  1728. }
  1729. }
  1730. }
  1731. }
  1732. /*
  1733. * validate pixel format
  1734. */
  1735. if( sdflags & DDSD_PIXELFORMAT )
  1736. {
  1737. if( caps & DDSCAPS_PRIMARYSURFACE )
  1738. {
  1739. DPF_ERR( "Pixel format cannot be specified for primary surface" );
  1740. return DDERR_INVALIDPARAMS;
  1741. }
  1742. if(caps & DDSCAPS_ALPHA)
  1743. {
  1744. DPF_ERR( "Can't specify alpha cap with pixel format" );
  1745. return DDERR_INVALIDPIXELFORMAT;
  1746. }
  1747. pfflags = lpsd->ddpfPixelFormat.dwFlags;
  1748. if( pfflags & UNDERSTOOD_PF )
  1749. {
  1750. // Get the number of bits per pixel (dwRGBBitCount is in a union
  1751. // of fields that all mean the same thing.)
  1752. bpp = lpsd->ddpfPixelFormat.dwRGBBitCount;
  1753. if( GetBytesFromPixels( 1, bpp ) == 0 )
  1754. {
  1755. DPF_ERR( "Invalid BPP specified in pixel format" );
  1756. return DDERR_INVALIDPIXELFORMAT;
  1757. }
  1758. if( pfflags & DDPF_RGB )
  1759. {
  1760. if( pfflags & (DDPF_YUV) )
  1761. {
  1762. DPF_ERR( "Invalid flags specified in pixel format" );
  1763. return DDERR_INVALIDPIXELFORMAT;
  1764. }
  1765. }
  1766. if ( pfflags & DDPF_ALPHA )
  1767. {
  1768. //Pretty much everything else must be off
  1769. if ( pfflags & (DDPF_ALPHAPIXELS |
  1770. DDPF_FOURCC |
  1771. DDPF_PALETTEINDEXED1 |
  1772. DDPF_PALETTEINDEXED2 |
  1773. DDPF_PALETTEINDEXED4 |
  1774. DDPF_PALETTEINDEXED8 |
  1775. DDPF_RGB |
  1776. DDPF_YUV |
  1777. DDPF_ZBUFFER |
  1778. DDPF_ZPIXELS |
  1779. DDPF_STENCILBUFFER |
  1780. DDPF_LUMINANCE) )
  1781. {
  1782. DPF_ERR("DDPF_ALPHA is valid only by itself");
  1783. return DDERR_INVALIDPARAMS;
  1784. }
  1785. }
  1786. if (pfflags & DDPF_LUMINANCE )
  1787. {
  1788. if ( pfflags & ( ~ ( DDPF_LUMINANCE | DDPF_ALPHAPIXELS ) ) )
  1789. {
  1790. DPF_ERR( "DDPF_LUMINANCE set in pixel format, compatible only with DDPF_ALPHAPIXELS" );
  1791. return DDERR_INVALIDPIXELFORMAT;
  1792. }
  1793. // we don't trust pre-dx6 drivers' CanCreateSurface callback to correctly reject
  1794. // DX6 luminance/bump DDPIXELFORMATs, so reject them here
  1795. if(!IS_DX6_D3DDRIVER(pdrv) && !emulation) {
  1796. DPF_ERR("Error: Driver doesn't support Luminance surfaces");
  1797. return DDERR_UNSUPPORTED;
  1798. }
  1799. }
  1800. if (pfflags & DDPF_BUMPDUDV )
  1801. {
  1802. if (pfflags & ( ~ (DDPF_BUMPDUDV | DDPF_BUMPLUMINANCE)))
  1803. {
  1804. DPF_ERR( "DDPF_BUMPDUDV set in pixel format, compatible only with DDPF_BUMPLUMINANCE");
  1805. return DDERR_INVALIDPIXELFORMAT;
  1806. }
  1807. if(!IS_DX6_D3DDRIVER(pdrv) && !emulation) {
  1808. DPF_ERR("Error: Driver doesn't support Bump Map surfaces");
  1809. return DDERR_UNSUPPORTED;
  1810. }
  1811. }
  1812. if( pfflags & DDPF_PALETTEINDEXED8 )
  1813. {
  1814. if( pfflags & (DDPF_PALETTEINDEXED1 |
  1815. DDPF_PALETTEINDEXED2 |
  1816. DDPF_PALETTEINDEXED4 |
  1817. DDPF_PALETTEINDEXEDTO8 ) )
  1818. {
  1819. DPF_ERR( "Invalid flags specified in pixel format" );
  1820. return DDERR_INVALIDPIXELFORMAT;
  1821. }
  1822. /*
  1823. * ensure that we have zero for masks
  1824. */
  1825. lpsd->ddpfPixelFormat.dwRBitMask = 0;
  1826. lpsd->ddpfPixelFormat.dwGBitMask = 0;
  1827. lpsd->ddpfPixelFormat.dwBBitMask = 0;
  1828. if( !(pfflags & (DDPF_ZPIXELS|DDPF_ALPHAPIXELS) ) )
  1829. lpsd->ddpfPixelFormat.dwRGBZBitMask = 0;
  1830. }
  1831. lpsd->ddpfPixelFormat.dwFourCC = 0;
  1832. // Validate ZPixels
  1833. if( pfflags & DDPF_ZPIXELS )
  1834. {
  1835. if( lpsd->ddpfPixelFormat.dwRGBZBitMask == 0 )
  1836. {
  1837. DPF_ERR( "DDPF_ZPIXELS must have a dwRGBZBitMask" );
  1838. return DDERR_INVALIDPIXELFORMAT;
  1839. }
  1840. if( pfflags & (DDPF_ALPHAPIXELS | DDPF_ALPHA | DDPF_ZBUFFER) )
  1841. {
  1842. DPF_ERR( "DDPF_ZPIXELS not compatible with ALPHAPIXELS or ALPHA or ZBUFFER" );
  1843. return DDERR_INVALIDPIXELFORMAT;
  1844. }
  1845. }
  1846. }
  1847. else if (pfflags & DDPF_FOURCC)
  1848. {
  1849. DWORD width, height;
  1850. /*
  1851. * We require the width and height of DirectX compressed-texture
  1852. * surfaces (FOURCC = DXT*) to be multiples of four.
  1853. */
  1854. switch ((int)lpsd->ddpfPixelFormat.dwFourCC)
  1855. {
  1856. case MAKEFOURCC('D','X','T','1'):
  1857. case MAKEFOURCC('D','X','T','2'):
  1858. case MAKEFOURCC('D','X','T','3'):
  1859. case MAKEFOURCC('D','X','T','4'):
  1860. case MAKEFOURCC('D','X','T','5'):
  1861. width = (sdflags & DDSD_WIDTH) ? lpsd->dwWidth : pdrv->vmiData.dwDisplayWidth;
  1862. height = (sdflags & DDSD_HEIGHT) ? lpsd->dwHeight : pdrv->vmiData.dwDisplayHeight;
  1863. if ((height | width) & 3)
  1864. {
  1865. DPF_ERR("Width, height of FOURCC=DXT* surface must be multiples of 4");
  1866. return DDERR_INVALIDPARAMS;
  1867. }
  1868. break;
  1869. default:
  1870. break;
  1871. }
  1872. }
  1873. }
  1874. // ACKACK: should caps be filled in in surface desc as well as sdflags?
  1875. /*
  1876. * validate dest overlay color key
  1877. */
  1878. if( sdflags & DDSD_CKDESTOVERLAY )
  1879. {
  1880. ddrval = CheckColorKey( DDCKEY_DESTOVERLAY, pdrv,
  1881. &lpsd->ddckCKDestOverlay, psflags,
  1882. halonly, helonly );
  1883. if( ddrval != DD_OK )
  1884. {
  1885. return ddrval;
  1886. }
  1887. }
  1888. /*
  1889. * validate dest blt color key
  1890. */
  1891. if( sdflags & DDSD_CKDESTBLT )
  1892. {
  1893. ddrval = CheckColorKey( DDCKEY_DESTBLT, pdrv,
  1894. &lpsd->ddckCKDestBlt, psflags,
  1895. halonly, helonly );
  1896. if( ddrval != DD_OK )
  1897. {
  1898. return ddrval;
  1899. }
  1900. }
  1901. /*
  1902. * validate src overlay color key
  1903. */
  1904. if( sdflags & DDSD_CKSRCOVERLAY )
  1905. {
  1906. ddrval = CheckColorKey( DDCKEY_SRCOVERLAY, pdrv,
  1907. &lpsd->ddckCKSrcOverlay, psflags,
  1908. halonly, helonly );
  1909. if( ddrval != DD_OK )
  1910. {
  1911. return ddrval;
  1912. }
  1913. }
  1914. /*
  1915. * validate src blt color key
  1916. */
  1917. if( sdflags & DDSD_CKSRCBLT )
  1918. {
  1919. ddrval = CheckColorKey( DDCKEY_SRCBLT, pdrv,
  1920. &lpsd->ddckCKSrcBlt, psflags,
  1921. halonly, helonly );
  1922. if( ddrval != DD_OK )
  1923. {
  1924. return ddrval;
  1925. }
  1926. }
  1927. /*
  1928. * cube maps
  1929. */
  1930. if ( capsEx.dwCaps2 & DDSCAPS2_CUBEMAP )
  1931. {
  1932. if (LOWERTHANDDRAW7(pdrv_int))
  1933. {
  1934. DPF_ERR("DDSCAPS2_CUBEMAP is not allowed for lower than IDirectDraw7 interfaces.");
  1935. return DDERR_INVALIDPARAMS;
  1936. }
  1937. if ( (lpsd->dwFlags & (DDSD_WIDTH|DDSD_HEIGHT)) == 0)
  1938. {
  1939. DPF_ERR("dwWidth and dwHeight must be specified for a DDSCAPS2_CUBEMAP surface");
  1940. return DDERR_INVALIDPARAMS;
  1941. }
  1942. if (lpsd->dwHeight != lpsd->dwWidth)
  1943. {
  1944. DPF_ERR("dwWidth and dwHeight must be equal for a DDSCAPS2_CUBEMAP surface");
  1945. return DDERR_INVALIDPARAMS;
  1946. }
  1947. if (! isPowerOf2(lpsd->dwHeight,NULL) )
  1948. {
  1949. DPF_ERR("dwWidth and dwHeight must be a whole power of two");
  1950. return DDERR_INVALIDPARAMS;
  1951. }
  1952. if (lpsd->dwFlags & DDSD_BACKBUFFERCOUNT)
  1953. {
  1954. DPF_ERR("Cubemaps cannot have backbuffers!");
  1955. return DDERR_INVALIDPARAMS;
  1956. }
  1957. }
  1958. return DD_OK;
  1959. } /* checkSurfaceDesc */
  1960. /*
  1961. * ComputePitch
  1962. *
  1963. * compute the pitch for a given width
  1964. */
  1965. DWORD ComputePitch(
  1966. LPDDRAWI_DIRECTDRAW_GBL this,
  1967. DWORD caps,
  1968. DWORD width,
  1969. UINT bpp )
  1970. {
  1971. DWORD vm_align;
  1972. DWORD vm_pitch;
  1973. /*
  1974. * adjust area for bpp
  1975. */
  1976. vm_pitch = GetBytesFromPixels( width, bpp );
  1977. if( vm_pitch == 0 )
  1978. {
  1979. return vm_pitch;
  1980. }
  1981. /*
  1982. * Increase the pitch of the surface so that it is a
  1983. * multiple of the alignment requirement. This
  1984. * guarantees each scanline will start properly aligned.
  1985. * The alignment is no longer required to be a power of
  1986. * two but it must be divisible by 4 because of the
  1987. * BLOCK_BOUNDARY requirement in the heap management
  1988. * code.
  1989. * The alignments are all verified to be non-zero during
  1990. * driver initialization except for dwAlphaAlign.
  1991. */
  1992. /*
  1993. * system memory?
  1994. */
  1995. if( caps & DDSCAPS_SYSTEMMEMORY )
  1996. {
  1997. vm_align = sizeof( DWORD);
  1998. vm_pitch = alignPitch( vm_pitch, vm_align );
  1999. return vm_pitch;
  2000. }
  2001. /*
  2002. * If the driver exposed extended alignment, then we will simply set
  2003. * pitch=width*bpp/8 and allow that to filter down to the heap alloc
  2004. * routines which know how to align surfaces
  2005. * Note this implies that extended alignment for any heap means
  2006. * ddraw will IGNORE the legacy alignment values for all heaps.
  2007. */
  2008. if ( this->dwFlags & DDRAWI_EXTENDEDALIGNMENT )
  2009. {
  2010. return vm_pitch;
  2011. }
  2012. /*
  2013. * overlay memory
  2014. */
  2015. if( caps & DDSCAPS_OVERLAY )
  2016. {
  2017. vm_align = this->vmiData.dwOverlayAlign;
  2018. vm_pitch = alignPitch( vm_pitch, vm_align );
  2019. /*
  2020. * texture memory
  2021. */
  2022. }
  2023. else if( caps & DDSCAPS_TEXTURE )
  2024. {
  2025. vm_align = this->vmiData.dwTextureAlign;
  2026. vm_pitch = alignPitch( vm_pitch, vm_align );
  2027. /*
  2028. * z buffer memory
  2029. */
  2030. }
  2031. else if( caps & DDSCAPS_ZBUFFER )
  2032. {
  2033. vm_align = this->vmiData.dwZBufferAlign;
  2034. vm_pitch = alignPitch( vm_pitch, vm_align );
  2035. /*
  2036. * alpha memory
  2037. */
  2038. }
  2039. else if( caps & DDSCAPS_ALPHA )
  2040. {
  2041. vm_align = this->vmiData.dwAlphaAlign;
  2042. vm_pitch = alignPitch( vm_pitch, vm_align );
  2043. /*
  2044. * regular video memory
  2045. */
  2046. }
  2047. else
  2048. {
  2049. vm_align = this->vmiData.dwOffscreenAlign;
  2050. vm_pitch = alignPitch( vm_pitch, vm_align );
  2051. }
  2052. return vm_pitch;
  2053. } /* ComputePitch */
  2054. #define FIX_SLIST_CNT 16 // number of surfaces before malloc reqd
  2055. /*
  2056. * initMipMapDim
  2057. *
  2058. * If we have a mip-map description then we can fill in some
  2059. * fields for the caller. This function needs to be invoked
  2060. * before the checkSurfaceDesc is called as it may put in
  2061. * place some fields checked by that function.
  2062. *
  2063. * NOTE: This function may modify the surface description.
  2064. */
  2065. static HRESULT initMipMapDim( LPDDSURFACEDESC2 lpsd, BOOL bDeepMipmaps )
  2066. {
  2067. DWORD sdflags;
  2068. DWORD caps;
  2069. int heightPower;
  2070. int widthPower;
  2071. DDASSERT( lpsd != NULL );
  2072. DDASSERT( lpsd->ddsCaps.dwCaps & DDSCAPS_MIPMAP );
  2073. sdflags = lpsd->dwFlags;
  2074. caps = lpsd->ddsCaps.dwCaps;
  2075. /*
  2076. * This stuff is only relevant for complex, non-flipable
  2077. * mip-maps.
  2078. */
  2079. if( ( caps & DDSCAPS_COMPLEX ) && !( caps & DDSCAPS_FLIP ) )
  2080. {
  2081. if( ( ( sdflags & DDSD_HEIGHT ) && ( sdflags & DDSD_WIDTH ) ) &&
  2082. !( sdflags & DDSD_MIPMAPCOUNT ) )
  2083. {
  2084. /*
  2085. * Width and height but no number of levels so compute the
  2086. * maximum number of mip-map levels supported by the given
  2087. * width and height.
  2088. */
  2089. if( !isPowerOf2( lpsd->dwHeight, &heightPower ) )
  2090. {
  2091. DPF_ERR( "Invalid height: height of a mip-map must be whole power of 2" );
  2092. return DDERR_INVALIDPARAMS;
  2093. }
  2094. if( !isPowerOf2( lpsd->dwWidth, &widthPower ) )
  2095. {
  2096. DPF_ERR( "Invalid width: width of a mip-map must be whole powers of 2" );
  2097. return DDERR_INVALIDPARAMS;
  2098. }
  2099. /*
  2100. * Deep mipmaps are those that clamp their smaller dimension at 1 as
  2101. * the larger dimension ramps down to 1
  2102. */
  2103. if ( bDeepMipmaps )
  2104. lpsd->dwMipMapCount = (DWORD)(max(heightPower, widthPower) + 1);
  2105. else
  2106. lpsd->dwMipMapCount = (DWORD)(min(heightPower, widthPower) + 1);
  2107. lpsd->dwFlags |= DDSD_MIPMAPCOUNT;
  2108. }
  2109. else if( ( sdflags & DDSD_MIPMAPCOUNT ) &&
  2110. !( ( sdflags & DDSD_WIDTH ) || ( sdflags & DDSD_HEIGHT ) ) )
  2111. {
  2112. /*
  2113. * We have been given a mip-map count but no width
  2114. * and height so compute the width and height assuming
  2115. * the smallest map is 1x1.
  2116. * NOTE: We don't help out if they supply a width or height but
  2117. * not both.
  2118. */
  2119. if( lpsd->dwMipMapCount == 0 )
  2120. {
  2121. DPF_ERR( "Invalid number of mip-map levels (0) specified" );
  2122. return DDERR_INVALIDPARAMS;
  2123. }
  2124. else
  2125. {
  2126. lpsd->dwWidth = lpsd->dwHeight = 1 << (lpsd->dwMipMapCount - 1);
  2127. lpsd->dwFlags |= (DDSD_HEIGHT | DDSD_WIDTH);
  2128. }
  2129. }
  2130. }
  2131. return DD_OK;
  2132. }
  2133. HRESULT createsurfaceEx( LPDDRAWI_DDRAWSURFACE_LCL lpSurfLcl )
  2134. {
  2135. LPDDRAWI_DIRECTDRAW_LCL lpDDLcl=lpSurfLcl->lpSurfMore->lpDD_lcl;
  2136. if (
  2137. (0 != lpSurfLcl->lpSurfMore->dwSurfaceHandle)
  2138. && (NULL != lpDDLcl->lpGbl->lpDDCBtmp->HALDDMiscellaneous2.CreateSurfaceEx)
  2139. )
  2140. {
  2141. DDHAL_CREATESURFACEEXDATA csdex;
  2142. DWORD rc;
  2143. csdex.ddRVal = DDERR_GENERIC;
  2144. csdex.dwFlags = 0;
  2145. csdex.lpDDLcl = lpDDLcl;
  2146. csdex.lpDDSLcl = lpSurfLcl;
  2147. rc = lpDDLcl->lpGbl->lpDDCBtmp->HALDDMiscellaneous2.CreateSurfaceEx(&csdex);
  2148. if( DDHAL_DRIVER_HANDLED == rc )
  2149. {
  2150. if( ( DD_OK != csdex.ddRVal ) &&
  2151. !( lpSurfLcl->ddsCaps.dwCaps & DDSCAPS_SYSTEMMEMORY ) )
  2152. {
  2153. DPF_ERR("Driver failed CreateSurfaceEx callback in createSurface");
  2154. return csdex.ddRVal;
  2155. }
  2156. }
  2157. else
  2158. {
  2159. DPF_ERR("Driver failed to handle CreateSurfaceEx callback in createSurface");
  2160. return DDERR_GENERIC;
  2161. }
  2162. }
  2163. return DD_OK;
  2164. }
  2165. #ifdef WINNT
  2166. LPDDRAWI_DDRAWSURFACE_LCL GetTopLevel(LPDDRAWI_DDRAWSURFACE_LCL lpLcl);
  2167. BOOL WINAPI CompleteCreateSysmemSurface( LPDDRAWI_DDRAWSURFACE_LCL lpSurfLcl )
  2168. {
  2169. DDASSERT(lpSurfLcl
  2170. && (DDSCAPS_SYSTEMMEMORY & lpSurfLcl->ddsCaps.dwCaps)
  2171. && (0 == lpSurfLcl->hDDSurface));
  2172. if (lpSurfLcl->lpSurfMore->lpDD_lcl->lpGbl->hDD)
  2173. {
  2174. BOOL bRet;
  2175. int scnt;
  2176. int nsurf;
  2177. LPDDRAWI_DDRAWSURFACE_LCL *slist;
  2178. lpSurfLcl = GetTopLevel(lpSurfLcl);
  2179. slist=lpSurfLcl->lpSurfMore->slist;
  2180. if (slist)
  2181. {
  2182. DWORD caps=lpSurfLcl->ddsCaps.dwCaps;
  2183. DWORD caps2=lpSurfLcl->lpSurfMore->ddsCapsEx.dwCaps2;
  2184. nsurf=lpSurfLcl->lpSurfMore->cSurfaces;
  2185. DDASSERT(nsurf);
  2186. if (DDSCAPS2_CUBEMAP & caps2)
  2187. {
  2188. int dwCubeMapFaceCount;
  2189. int surf_from;
  2190. int perfacecnt;
  2191. DDASSERT(lpSurfLcl->lpSurfMore->pCreatedDDSurfaceDesc2);
  2192. // to calculate dwCubeMapFaceCount we must use this caps2
  2193. caps2 = lpSurfLcl->lpSurfMore->pCreatedDDSurfaceDesc2->ddsCaps.dwCaps2;
  2194. dwCubeMapFaceCount =
  2195. (( caps2 & DDSCAPS2_CUBEMAP_POSITIVEX ) ? 1 : 0 )+
  2196. (( caps2 & DDSCAPS2_CUBEMAP_NEGATIVEX ) ? 1 : 0 )+
  2197. (( caps2 & DDSCAPS2_CUBEMAP_POSITIVEY ) ? 1 : 0 )+
  2198. (( caps2 & DDSCAPS2_CUBEMAP_NEGATIVEY ) ? 1 : 0 )+
  2199. (( caps2 & DDSCAPS2_CUBEMAP_POSITIVEZ ) ? 1 : 0 )+
  2200. (( caps2 & DDSCAPS2_CUBEMAP_NEGATIVEZ ) ? 1 : 0 );
  2201. DDASSERT(dwCubeMapFaceCount);
  2202. DDASSERT(nsurf >= dwCubeMapFaceCount);
  2203. DDASSERT(0 == (nsurf % dwCubeMapFaceCount));
  2204. perfacecnt = nsurf/ dwCubeMapFaceCount;
  2205. DDASSERT(perfacecnt == 1 || ((perfacecnt>1) && (caps & DDSCAPS_MIPMAP)) );
  2206. /*
  2207. * Every (perfacecnt)th surface needs to be linked to the very first
  2208. * Otherwise, it's a mip level that needs linking to its parent
  2209. */
  2210. for (scnt = 1; scnt < nsurf; scnt++)
  2211. {
  2212. if ( (scnt % perfacecnt) == 0 )
  2213. surf_from = 0;
  2214. else
  2215. surf_from = scnt - 1;
  2216. if ( !DdAttachSurface(slist[surf_from], slist[scnt]) )
  2217. DPF(0,"DdAttachSurface CUBEMAP %d from %d failed!",surf_from,scnt);
  2218. }
  2219. }
  2220. else if (DDSCAPS_MIPMAP & caps)
  2221. {
  2222. for (scnt = 1; scnt < nsurf; scnt++)
  2223. {
  2224. if ( !DdAttachSurface(slist[scnt-1], slist[scnt]) )
  2225. DPF(0,"DdAttachSurface MIPMAP %d failed!",scnt);
  2226. }
  2227. }
  2228. }
  2229. else
  2230. {
  2231. slist=&lpSurfLcl;
  2232. nsurf = 1;
  2233. }
  2234. for (scnt = 0; scnt < nsurf; scnt++)
  2235. {
  2236. bRet = DdCreateSurfaceObject(slist[scnt], FALSE);
  2237. if (!bRet)
  2238. {
  2239. // cleanup is needed as hDDSurface could be created partially
  2240. // by DdAttachSurface,
  2241. for (scnt = 0; scnt < nsurf; scnt++)
  2242. {
  2243. if (slist[scnt]->hDDSurface)
  2244. {
  2245. if (!DdDeleteSurfaceObject(slist[scnt]))
  2246. DPF(5,"DdDeleteSurfaceObject failed");
  2247. }
  2248. }
  2249. break;
  2250. }
  2251. }
  2252. // we only allow system surface being created w/o succeeding Kernel side
  2253. if (bRet)
  2254. {
  2255. DDASSERT(lpSurfLcl->hDDSurface);
  2256. createsurfaceEx(lpSurfLcl);
  2257. }
  2258. else
  2259. {
  2260. DPF_ERR("Fail to complete SYSTEM surface w/ Kernel Object");
  2261. return FALSE;
  2262. }
  2263. }
  2264. return TRUE;
  2265. }
  2266. #endif
  2267. /*
  2268. * createSurface
  2269. *
  2270. * Create a surface, without linking it into the chain.
  2271. * We could potentially create multiple surfaces here, if we get a
  2272. * request to create a page flipped surface and/or attached alpha or
  2273. * z buffer surfaces
  2274. */
  2275. static HRESULT createSurface( LPDDRAWI_DIRECTDRAW_LCL this_lcl,
  2276. LPDDSURFACEDESC2 lpDDSurfaceDesc,
  2277. CSINFO *pcsinfo,
  2278. BOOL emulation,
  2279. BOOL real_sysmem,
  2280. BOOL probe_driver,
  2281. LPDDRAWI_DIRECTDRAW_INT this_int,
  2282. LPDDSURFACEINFO pSysMemInfo,
  2283. DWORD DX8Flags)
  2284. {
  2285. LPDDRAWI_DIRECTDRAW_GBL this;
  2286. LPDDRAWI_DDRAWSURFACE_INT psurf_int;
  2287. LPDDRAWI_DDRAWSURFACE_LCL psurf_lcl;
  2288. LPDDRAWI_DDRAWSURFACE_GBL psurf;
  2289. DWORD caps;
  2290. int surf_size;
  2291. int surf_size_lcl;
  2292. int surf_size_lcl_more;
  2293. HRESULT ddrval;
  2294. int bbcnt;
  2295. int scnt;
  2296. int nsurf;
  2297. BOOL do_abuffer;
  2298. DWORD abuff_depth;
  2299. BOOL do_zbuffer;
  2300. BOOL firstbbuff;
  2301. LPDDRAWI_DDRAWSURFACE_INT *slist_int;
  2302. LPDDRAWI_DDRAWSURFACE_LCL *slist_lcl;
  2303. LPDDRAWI_DDRAWSURFACE_GBL *slist;
  2304. int bbuffoff;
  2305. int zbuffoff;
  2306. DWORD rc;
  2307. DDPIXELFORMAT ddpf;
  2308. LPDDPIXELFORMAT pddpf;
  2309. BOOL is_primary_chain;
  2310. UINT bpp = 0;
  2311. LONG vm_pitch;
  2312. BOOL is_flip;
  2313. BOOL is_diff;
  2314. BOOL is_mipmap;
  2315. DDHAL_CREATESURFACEDATA csd;
  2316. DDHAL_CANCREATESURFACEDATA ccsd;
  2317. DWORD sflags;
  2318. BOOL is_curr_diff;
  2319. BOOL understood_pf;
  2320. DWORD nsflags;
  2321. LPDDSCAPS pdrv_ddscaps;
  2322. LPDDHAL_CANCREATESURFACE ccsfn;
  2323. LPDDHAL_CREATESURFACE csfn;
  2324. LPDDHAL_CANCREATESURFACE ccshalfn;
  2325. LPDDHAL_CREATESURFACE cshalfn;
  2326. BOOL is_excl;
  2327. BOOL excl_exists;
  2328. DWORD sdflags;
  2329. #ifdef WIN95
  2330. DWORD ptr16;
  2331. #endif
  2332. DWORD pid;
  2333. LPDDRAWI_DDRAWSURFACE_GBL lpGlobalSurface;
  2334. DDSURFACEDESC2 sd;
  2335. BOOL existing_global;
  2336. DWORD caps2;
  2337. BOOL is_cubemap;
  2338. BOOL is_stereo;
  2339. #ifdef SHAREDZ
  2340. BOOL do_shared_z;
  2341. BOOL do_shared_back;
  2342. #endif
  2343. this = this_lcl->lpGbl;
  2344. #ifdef WINNT
  2345. // Update DDraw handle in driver GBL object.
  2346. this->hDD = this_lcl->hDD;
  2347. #endif //WINNT
  2348. /*
  2349. * validate surface description
  2350. */
  2351. nsflags = 0;
  2352. sd = *lpDDSurfaceDesc;
  2353. lpDDSurfaceDesc = &sd;
  2354. /*
  2355. * This new (DX7) caps bit is added to mipmap sublevels. Squish it in case old apps do the
  2356. * GetSurfaceDesc, CreateSurface thing.
  2357. */
  2358. sd.ddsCaps.dwCaps2 &= ~DDSCAPS2_MIPMAPSUBLEVEL;
  2359. /*
  2360. * If we have a mip-map then we potentially can fill in some
  2361. * blanks for the caller.
  2362. */
  2363. if( lpDDSurfaceDesc->ddsCaps.dwCaps & DDSCAPS_MIPMAP )
  2364. {
  2365. /*
  2366. * We allow deep mipmaps only for ddraw7 and above interfaces
  2367. * and for DX7 and above class drivers.
  2368. */
  2369. ddrval = initMipMapDim( lpDDSurfaceDesc , !LOWERTHANDDRAW7(this_int) && this->lpDDCBtmp->HALDDMiscellaneous2.GetDriverState != NULL );
  2370. if( ddrval != DD_OK )
  2371. return ddrval;
  2372. }
  2373. // Volume textures can only be created using the DX8 interfaces
  2374. if ((lpDDSurfaceDesc->ddsCaps.dwCaps2 & DDSCAPS2_VOLUME) &&
  2375. !(DX8Flags & DX8SFLAG_DX8))
  2376. {
  2377. DPF_ERR("Volume textures cannot be created using the ddraw interfaces");
  2378. return DDERR_INVALIDCAPS;
  2379. }
  2380. // Image surfaces can be in Z formats that CheckSurfaceDesc will fail since
  2381. // the surface isn't a Z buffer. Also, all image surface descs are filled in
  2382. // the thunk layer, so we shouldn't have to check them anyway.
  2383. if (!(DX8Flags & DX8SFLAG_IMAGESURF))
  2384. {
  2385. ddrval = checkSurfaceDesc( lpDDSurfaceDesc, this, &nsflags, emulation, real_sysmem, this_int );
  2386. if( ddrval != DD_OK )
  2387. {
  2388. return ddrval;
  2389. }
  2390. }
  2391. sdflags = lpDDSurfaceDesc->dwFlags;
  2392. pid = GetCurrentProcessId();
  2393. caps = lpDDSurfaceDesc->ddsCaps.dwCaps;
  2394. caps2 = lpDDSurfaceDesc->ddsCaps.dwCaps2;
  2395. /*
  2396. * set up for emulation vs driver
  2397. *
  2398. * NOTE: There are different HAL entry points for creating execute buffers
  2399. * and conventional surfaces (to keep the driver writing simpler and because,
  2400. * potentially, there may be different semantics for creating execute buffers
  2401. * and conventional surfaces) so we need to set up the HAL call differently
  2402. * here.
  2403. */
  2404. if( emulation )
  2405. {
  2406. pdrv_ddscaps = &this->ddHELCaps.ddsCaps;
  2407. if( caps & DDSCAPS_EXECUTEBUFFER )
  2408. {
  2409. ccsfn = this_lcl->lpDDCB->HELDDExeBuf.CanCreateExecuteBuffer;
  2410. csfn = this_lcl->lpDDCB->HELDDExeBuf.CreateExecuteBuffer;
  2411. }
  2412. else
  2413. {
  2414. ccsfn = this_lcl->lpDDCB->HELDD.CanCreateSurface;
  2415. csfn = this_lcl->lpDDCB->HELDD.CreateSurface;
  2416. }
  2417. ccshalfn = ccsfn;
  2418. cshalfn = csfn;
  2419. }
  2420. else
  2421. {
  2422. pdrv_ddscaps = &this->ddCaps.ddsCaps;
  2423. if( caps & DDSCAPS_EXECUTEBUFFER )
  2424. {
  2425. ccsfn = this_lcl->lpDDCB->HALDDExeBuf.CanCreateExecuteBuffer;
  2426. csfn = this_lcl->lpDDCB->HALDDExeBuf.CreateExecuteBuffer;
  2427. ccshalfn = this_lcl->lpDDCB->cbDDExeBufCallbacks.CanCreateExecuteBuffer;
  2428. cshalfn = this_lcl->lpDDCB->cbDDExeBufCallbacks.CreateExecuteBuffer;
  2429. if ( DDSCAPS2_COMMANDBUFFER & caps2 )
  2430. {
  2431. // Asheron's Call(a DX6 app) will fail if we allow Video Command buffer
  2432. // it's not interesting anyway, let's fail it
  2433. DPF(4,"Command buffer is not supported in video-memory.");
  2434. return DDERR_OUTOFVIDEOMEMORY;
  2435. }
  2436. }
  2437. else
  2438. {
  2439. ccsfn = this_lcl->lpDDCB->HALDD.CanCreateSurface;
  2440. csfn = this_lcl->lpDDCB->HALDD.CreateSurface;
  2441. ccshalfn = this_lcl->lpDDCB->cbDDCallbacks.CanCreateSurface;
  2442. cshalfn = this_lcl->lpDDCB->cbDDCallbacks.CreateSurface;
  2443. }
  2444. }
  2445. /*
  2446. * get some frequently used fields
  2447. */
  2448. if( sdflags & DDSD_BACKBUFFERCOUNT )
  2449. {
  2450. bbcnt = (int) lpDDSurfaceDesc->dwBackBufferCount;
  2451. if( bbcnt < 0 )
  2452. {
  2453. DPF( 0, "Invalid back buffer count %ld", bbcnt );
  2454. return DDERR_INVALIDPARAMS;
  2455. }
  2456. }
  2457. else if( sdflags & DDSD_MIPMAPCOUNT )
  2458. {
  2459. /*
  2460. * Unlike the back-buffer count which can be 0
  2461. * the mip-map level count must be at least one
  2462. * if specified.
  2463. */
  2464. bbcnt = (int) lpDDSurfaceDesc->dwMipMapCount - 1;
  2465. if( bbcnt < 0 )
  2466. {
  2467. DPF( 0, "Invalid mip-map count %ld", bbcnt + 1);
  2468. return DDERR_INVALIDPARAMS;
  2469. }
  2470. }
  2471. else
  2472. {
  2473. bbcnt = 0;
  2474. }
  2475. /*
  2476. * make sure the driver supports these caps
  2477. */
  2478. if( (caps & DDSCAPS_ALPHA) && !(pdrv_ddscaps->dwCaps & DDSCAPS_ALPHA) )
  2479. {
  2480. if( probe_driver )
  2481. DPF( 2, "Alpha not supported in hardware. Trying emulation..." );
  2482. else
  2483. DPF( 0, "Alpha not supported in %s", (emulation ? "emulation" : "hardware") );
  2484. return DDERR_NOALPHAHW;
  2485. }
  2486. // DX7Stereo
  2487. if (caps2 & DDSCAPS2_STEREOSURFACELEFT)
  2488. {
  2489. DPF(4,"validating driver caps for stereo flipping chain");
  2490. DPF(5,"driver stereo caps dwCaps2: %08lx",this->ddCaps.dwCaps2);
  2491. DPF(5," dwSVCaps:%08lx",this->ddCaps.dwSVCaps);
  2492. DPF(5," ddsCapsMore.dwCaps2: %08lx",this->ddsCapsMore.dwCaps2);
  2493. if (!(this->ddCaps.dwCaps2 & DDCAPS2_STEREO))
  2494. {
  2495. DPF(0,"DDSCAPS2_STEREOSURFACELEFT invalid, hardware does not support DDCAPS2_STEREO");
  2496. return DDERR_NOSTEREOHARDWARE;
  2497. }
  2498. if (!(this->ddCaps.dwSVCaps & (DDSVCAPS_STEREOSEQUENTIAL)))
  2499. {
  2500. DPF(0,"DDSCAPS2_STEREOSURFACELEFT invalid, hardware must support DDSVCAPS_STEREOSEQUENTIAL");
  2501. return DDERR_NOSTEREOHARDWARE;
  2502. }
  2503. if (!(this->ddsCapsMore.dwCaps2 & DDSCAPS2_STEREOSURFACELEFT))
  2504. {
  2505. DPF(0,"DDSCAPS2_STEREOSURFACELEFT invalid, hardware does not support DDSCAPS2_STEREOSURFACELEFT");
  2506. return DDERR_NOSURFACELEFT;
  2507. }
  2508. }
  2509. #if 0
  2510. if( (caps & DDSCAPS_FLIP) && !(pdrv_ddscaps->dwCaps & DDSCAPS_FLIP))
  2511. {
  2512. if( probe_driver )
  2513. DPF( 2, "Flip not supported in hardware. Trying emulation..." );
  2514. else
  2515. DPF( 0, "Flip not supported in %s", (emulation ? "emulation" : "hardware") );
  2516. return DDERR_NOFLIPHW;
  2517. }
  2518. #endif
  2519. if((caps & DDSCAPS_ZBUFFER) && !(pdrv_ddscaps->dwCaps & DDSCAPS_ZBUFFER))
  2520. {
  2521. if( probe_driver )
  2522. DPF( 2, "Z Buffer not supported in hardware. Trying emulation..." );
  2523. else
  2524. DPF( 0, "Z Buffer not supported in %s", (emulation ? "emulation" : "hardware") );
  2525. return DDERR_NOZBUFFERHW;
  2526. }
  2527. if((caps & DDSCAPS_TEXTURE) && !(pdrv_ddscaps->dwCaps & DDSCAPS_TEXTURE))
  2528. {
  2529. if( probe_driver )
  2530. DPF( 2, "Textures not supported in hardware. Trying emulation..." );
  2531. else
  2532. DPF( 0, "Textures not supported in %s", (emulation ? "emulation" : "hardware") );
  2533. return DDERR_NOTEXTUREHW;
  2534. }
  2535. if((caps & DDSCAPS_MIPMAP) && !(pdrv_ddscaps->dwCaps & DDSCAPS_MIPMAP))
  2536. {
  2537. if( probe_driver )
  2538. DPF( 2, "Mip-maps not supported in hardware. Trying emulation..." );
  2539. else
  2540. DPF( 0, "Mip-maps not supported in %s", (emulation ? "emulation" : "hardware") );
  2541. return DDERR_NOMIPMAPHW;
  2542. }
  2543. if((caps & DDSCAPS_EXECUTEBUFFER) && !(pdrv_ddscaps->dwCaps & DDSCAPS_EXECUTEBUFFER))
  2544. {
  2545. if( probe_driver )
  2546. DPF( 2, "Execute buffers not supported in hardware. Trying emulation..." );
  2547. else
  2548. DPF( 2, "Execute buffers not supported in %s", (emulation ? "emulation" : "hardware") );
  2549. return DDERR_NOEXECUTEBUFFERHW;
  2550. }
  2551. #ifdef SHAREDZ
  2552. if((caps & DDSCAPS_SHAREDZBUFFER) && !(pdrv_ddscaps->dwCaps & DDSCAPS_SHAREDZBUFFER))
  2553. {
  2554. if( probe_driver )
  2555. DPF( 2, "Shared Z-buffer not supported in hardware. Trying emulation..." );
  2556. else
  2557. DPF( 0, "Shared Z-buffer not supported in %s", (emulation ? "emulation" : "hardware") );
  2558. return DDERR_NOSHAREDZBUFFERHW;
  2559. }
  2560. if((caps & DDSCAPS_SHAREDBACKBUFFER) && !(pdrv_ddscaps->dwCaps & DDSCAPS_SHAREDBACKBUFFER))
  2561. {
  2562. if( probe_driver )
  2563. DPF( 2, "Shared back-buffer not supported in hardware. Trying emulation..." );
  2564. else
  2565. DPF( 0, "Shared back-buffer not supported in %s", (emulation ? "emulation" : "hardware") );
  2566. return DDERR_NOSHAREDBACKBUFFERHW;
  2567. }
  2568. #endif
  2569. if(caps & DDSCAPS_OVERLAY)
  2570. {
  2571. if( emulation )
  2572. {
  2573. if( 0 == (this->ddHELCaps.dwCaps & DDCAPS_OVERLAY) )
  2574. {
  2575. DPF_ERR( "No overlay hardware emulation" );
  2576. return DDERR_NOOVERLAYHW;
  2577. }
  2578. }
  2579. else
  2580. {
  2581. if( 0 == (this->ddCaps.dwCaps & DDCAPS_OVERLAY) )
  2582. {
  2583. if( probe_driver )
  2584. DPF( 2, "No overlay hardware. Trying emulation..." );
  2585. else
  2586. DPF_ERR( "No overlay hardware" );
  2587. return DDERR_NOOVERLAYHW;
  2588. }
  2589. }
  2590. }
  2591. if(caps2 & DDSCAPS2_DEINTERLACE)
  2592. {
  2593. if( emulation )
  2594. {
  2595. DPF_ERR( "No deinterlacing hardware emulation" );
  2596. return DDERR_INVALIDPARAMS;
  2597. }
  2598. else
  2599. {
  2600. if( 0 == (this->ddsCapsMore.dwCaps2 & DDSCAPS2_DEINTERLACE) )
  2601. {
  2602. if( probe_driver )
  2603. DPF( 2, "No deinterlace hardware. Trying emulation..." );
  2604. else
  2605. DPF_ERR( "No deinterlace hardware" );
  2606. return DDERR_INVALIDPARAMS;
  2607. }
  2608. }
  2609. }
  2610. #ifdef DEBUG
  2611. if( (caps & DDSCAPS_FLIP) && !emulation && GetProfileInt("DirectDraw","nohwflip",0))
  2612. {
  2613. DPF(1,"pretending flip not supported in HW (due to nohwflip in [DirectDraw] of win.ini" );
  2614. return DDERR_NOFLIPHW;
  2615. }
  2616. #endif
  2617. /*
  2618. * fail requests for non-local video memory allocations if the driver does not
  2619. * support non-local video memory.
  2620. *
  2621. * NOTE: Should we really do this or just let the allocation fail from natural
  2622. * causes?
  2623. *
  2624. * ALSO NOTE: Don't have to worry about emulation as no emulated surface should
  2625. * ever get this far with DDSCAPS_NONLOCALVIDMEM set.
  2626. *
  2627. * ALSO ALSO NOTE: Should we also fail DDSCAPS_LOCALVIDMEM if the driver does
  2628. * not support DDSCAPS_NONLOCALVIDMEM. My feeling is that we should allow.
  2629. * DDSCAPS_LOCALVIDMEM is legal with a non AGP driver - redundant but legal.
  2630. */
  2631. if( caps & DDSCAPS_NONLOCALVIDMEM )
  2632. {
  2633. if( !( this->ddCaps.dwCaps2 & DDCAPS2_NONLOCALVIDMEM ) )
  2634. {
  2635. DPF_ERR( "Driver does not support non-local video memory" );
  2636. return DDERR_NONONLOCALVIDMEM;
  2637. }
  2638. }
  2639. #if 0 //Old code
  2640. //ATTENTION: Potential Apps compat problem!!
  2641. /*
  2642. * Optimized surfaces in video memory are only allowed if the HAL supports
  2643. * them. We won't send a legacy driver create surface HAL calls for optimized
  2644. * surfaces.
  2645. */
  2646. if( caps & DDSCAPS_OPTIMIZED )
  2647. {
  2648. if( caps & DDSCAPS_VIDEOMEMORY )
  2649. {
  2650. if ( !(this->ddCaps.ddsCaps.dwCaps & DDSCAPS_OPTIMIZED) )
  2651. {
  2652. DPF_ERR("Can't specify video memory optimized surface... Driver doesn't support optimized surfaces");
  2653. return DDERR_NOOPTIMIZEHW;
  2654. }
  2655. }
  2656. if( caps & DDSCAPS_SYSTEMMEMORY )
  2657. {
  2658. if ( !(this->ddHELCaps.ddsCaps.dwCaps & DDSCAPS_OPTIMIZED) )
  2659. {
  2660. DPF_ERR("Can't specify system memory optimized surface... HEL doesn't support optimized surfaces");
  2661. return DDERR_INVALIDPARAMS;
  2662. }
  2663. }
  2664. }
  2665. #endif //0
  2666. CheckExclusiveMode(this_lcl, &excl_exists, &is_excl, FALSE, NULL, FALSE);
  2667. if (!is_excl || !(this->dwFlags & DDRAWI_FULLSCREEN) )
  2668. {
  2669. if( (caps & DDSCAPS_FLIP) && (caps & DDSCAPS_PRIMARYSURFACE) )
  2670. {
  2671. DPF_ERR( "Must be in full-screen exclusive mode to create a flipping primary surface" );
  2672. return DDERR_NOEXCLUSIVEMODE;
  2673. }
  2674. }
  2675. /*
  2676. * see if we are creating the primary surface; if we are, see if
  2677. * we can allow its creation
  2678. */
  2679. if( (caps & DDSCAPS_PRIMARYSURFACE) )
  2680. {
  2681. LPDDRAWI_DDRAWSURFACE_INT pprim_int;
  2682. pprim_int = this_lcl->lpPrimary;
  2683. if( pprim_int )
  2684. {
  2685. DPF_ERR( "Can't create primary, already created by this process" );
  2686. return DDERR_PRIMARYSURFACEALREADYEXISTS;
  2687. }
  2688. if( (excl_exists) && (is_excl) )
  2689. {
  2690. /*
  2691. * we are the exclusive mode process invalidate everyone
  2692. * else's primary surfaces and create our own
  2693. */
  2694. InvalidateAllPrimarySurfaces( this );
  2695. }
  2696. else if( excl_exists )
  2697. {
  2698. /*
  2699. * we are not the exclusive mode process but someone else is
  2700. */
  2701. DPF(1, "Can't create primary, exclusive mode not owned" );
  2702. return DDERR_NOEXCLUSIVEMODE;
  2703. }
  2704. else
  2705. {
  2706. /*
  2707. * no one has exclusive mode
  2708. */
  2709. if( !MatchPrimary( this, lpDDSurfaceDesc ) )
  2710. {
  2711. DPF_ERR( "Can't create primary, incompatible with current primary" );
  2712. return DDERR_INCOMPATIBLEPRIMARY;
  2713. }
  2714. /*
  2715. * otherwise, it is possible to create a primary surface
  2716. */
  2717. }
  2718. }
  2719. #ifdef SHAREDZ
  2720. if( caps & DDSCAPS_SHAREDZBUFFER )
  2721. {
  2722. if( this_lcl->lpSharedZ != NULL )
  2723. {
  2724. DPF_ERR( "Can't create shared Z, already created by this process" );
  2725. return DDERR_SHAREDZBUFFERALREADYEXISTS;
  2726. }
  2727. if( !MatchSharedZBuffer( this, lpDDSurfaceDesc ) )
  2728. {
  2729. DPF_ERR( "Can't create shared Z buffer, incompatible with existing Z buffer" );
  2730. return DDERR_INCOMPATIBLESHAREDZBUFFER;
  2731. }
  2732. }
  2733. if( caps & DDSCAPS_SHAREDBACKBUFFER )
  2734. {
  2735. if( this_lcl->lpSharedBack != NULL )
  2736. {
  2737. DPF_ERR( "Can't create shared back-buffer, already created by this process" );
  2738. return DDERR_SHAREDBACKBUFFERALREADYEXISTS;
  2739. }
  2740. if( !MatchSharedBackBuffer( this, lpDDSurfaceDesc ) )
  2741. {
  2742. DPF_ERR( "Can't create shared back buffer, incompatible with existing back buffer" );
  2743. return DDERR_INCOMPATIBLESHAREDBACKBUFFER;
  2744. }
  2745. }
  2746. #endif
  2747. /*
  2748. * make sure the driver wants this to happen...
  2749. */
  2750. if(caps & DDSCAPS_ZBUFFER) {
  2751. //NOTE: In DX5, DDSD_PIXELFORMAT was never set for ZBuffers (except maybe for complex surfs)
  2752. // so drivers came to expect ccsd.bIsDifferentPixelFormat to be FALSE for ZBuffers,
  2753. // even though it should really be TRUE by definition and the spec. Changing it to TRUE
  2754. // breaks CanCreateSurface in these old drivers (they return DRIVER_HANDLED+DDERR_INVALIDPIXELFORMAT)
  2755. // Sooo, I'm forcing it to be false for zbuffers, except for if zpixelformats is non-zero, which
  2756. // implies a DX6 driver which should be written to handle that field correctly.
  2757. if(DRIVER_SUPPORTS_DX6_ZBUFFERS(this)) {
  2758. // See manbug 27011.
  2759. // Setting is_diff TRUE here makes it TRUE for typical DX5 primary creates.
  2760. // This causes us to fault later on because we assume is_diff => pddpf is non-null.
  2761. // is_diff == TRUE in this case also causes the nv4, nv10 drivers to fail cancreate.
  2762. // The solution is to set is_diff false if it's a complex DX5 chain with Z
  2763. //
  2764. //DDASSERT((caps & DDSCAPS_COMPLEX)==0); // shouldve already forbidden complex surf creation w/stencil
  2765. if ( caps & DDSCAPS_COMPLEX )
  2766. {
  2767. is_diff=FALSE;
  2768. }
  2769. else
  2770. {
  2771. is_diff=TRUE;
  2772. }
  2773. } else is_diff=FALSE;
  2774. } else if( sdflags & DDSD_PIXELFORMAT )
  2775. {
  2776. is_diff = IsDifferentPixelFormat( &this->vmiData.ddpfDisplay, &lpDDSurfaceDesc->ddpfPixelFormat );
  2777. }
  2778. else
  2779. {
  2780. is_diff = FALSE;
  2781. }
  2782. DPF( 5, "is_diff = %d", is_diff );
  2783. rc = DDHAL_DRIVER_NOTHANDLED;
  2784. if( ccshalfn != NULL )
  2785. {
  2786. DPF(4,"Calling HAL for create surface, emulation == %d",emulation);
  2787. ccsd.CanCreateSurface = ccshalfn;
  2788. ccsd.lpDD = this;
  2789. ccsd.lpDDSurfaceDesc = (LPDDSURFACEDESC)lpDDSurfaceDesc;
  2790. ccsd.bIsDifferentPixelFormat = is_diff;
  2791. /*
  2792. * This hack breaks Sundown (passing a pointer in an HRESULT).
  2793. * No longer necessary following a change to ddhel.c (in myCanCreateSurface).
  2794. * If that change gets backed out, we'll need a real fix here.
  2795. if(emulation) {
  2796. // slight hack: need to sneak this ptr to HEL's myCanCreateSurface because it might
  2797. // need to LoadLib d3dim.dll and set this_lcl->hD3DInstance, if a Zbuffer is created
  2798. ccsd.ddRVal=(LONG_PTR) this_lcl; // **** needs to be fixed.
  2799. }
  2800. */
  2801. /*
  2802. * !!! NOTE: Currently we don't support 16-bit versions of the HAL
  2803. * execute buffer members. If this is so do we need to use DOHALCALL?
  2804. */
  2805. if( caps & DDSCAPS_EXECUTEBUFFER )
  2806. {
  2807. DOHALCALL( CanCreateExecuteBuffer, ccsfn, ccsd, rc, emulation );
  2808. }
  2809. else
  2810. {
  2811. DOHALCALL( CanCreateSurface, ccsfn, ccsd, rc, emulation );
  2812. }
  2813. if( rc == DDHAL_DRIVER_HANDLED )
  2814. {
  2815. if( ccsd.ddRVal != DD_OK )
  2816. {
  2817. DPF(2, "Driver says surface can't be created" );
  2818. return ccsd.ddRVal;
  2819. }
  2820. }
  2821. }
  2822. /*
  2823. * if the driver didn't handle it, then fail any requests to create a
  2824. * surface that differs in format from the primary surface, except for
  2825. * z buffer and alpha
  2826. */
  2827. if( rc == DDHAL_DRIVER_NOTHANDLED )
  2828. {
  2829. if( is_diff && !(caps & (DDSCAPS_ZBUFFER|DDSCAPS_ALPHA)) )
  2830. {
  2831. return DDERR_INVALIDPIXELFORMAT;
  2832. }
  2833. }
  2834. /*
  2835. * is this a primary surface chain?
  2836. */
  2837. if( caps & DDSCAPS_PRIMARYSURFACE )
  2838. {
  2839. is_primary_chain = TRUE;
  2840. }
  2841. else
  2842. {
  2843. is_primary_chain = FALSE;
  2844. }
  2845. #ifdef SHAREDZ
  2846. do_shared_z = FALSE;
  2847. do_shared_back = FALSE;
  2848. #endif
  2849. /*
  2850. * see if we are looking for a z-buffer with our surface
  2851. */
  2852. if( (caps & DDSCAPS_ZBUFFER) )
  2853. {
  2854. do_zbuffer = TRUE;
  2855. #ifdef SHAREDZ
  2856. if( caps & DDSCAPS_SHAREDZBUFFER )
  2857. do_shared_z = TRUE;
  2858. #endif
  2859. if( (caps & DDSCAPS_COMPLEX) )
  2860. {
  2861. caps &= ~DDSCAPS_ZBUFFER;
  2862. #ifdef SHAREDZ
  2863. caps &= ~DDSCAPS_SHAREDZBUFFER;
  2864. #endif
  2865. }
  2866. }
  2867. else
  2868. {
  2869. do_zbuffer = FALSE;
  2870. }
  2871. /*
  2872. * see if we are looking for an alpha buffer with our surface
  2873. */
  2874. if( (caps & DDSCAPS_ALPHA) )
  2875. {
  2876. do_abuffer = TRUE;
  2877. abuff_depth = lpDDSurfaceDesc->dwAlphaBitDepth;
  2878. if( (caps & DDSCAPS_COMPLEX) )
  2879. {
  2880. caps &= ~DDSCAPS_ALPHA;
  2881. }
  2882. }
  2883. else
  2884. {
  2885. do_abuffer = FALSE;
  2886. abuff_depth = 0;
  2887. }
  2888. #ifdef SHAREDZ
  2889. /*
  2890. * See if we looking for a shared back-buffer with our surface
  2891. */
  2892. if( caps & DDSCAPS_SHAREDBACKBUFFER )
  2893. do_shared_back = TRUE;
  2894. #endif
  2895. /*
  2896. * number of surfaces we need
  2897. */
  2898. nsurf = 1 + bbcnt;
  2899. // DX7stereo
  2900. is_stereo = (BOOL)(caps2 & DDSCAPS2_STEREOSURFACELEFT);
  2901. if ( is_stereo )
  2902. {
  2903. nsurf *= 2;
  2904. nsflags |= DDRAWISURF_STEREOSURFACELEFT;
  2905. caps2 &= ~DDSCAPS2_STEREOSURFACELEFT;
  2906. DPF( 3, "doubling surfaces for stereo support" );
  2907. }
  2908. if( do_zbuffer && (caps & DDSCAPS_COMPLEX) )
  2909. {
  2910. nsurf++;
  2911. DPF( 3, "adding one for zbuffer" );
  2912. }
  2913. if( do_abuffer && (caps & DDSCAPS_COMPLEX) )
  2914. {
  2915. nsurf++;
  2916. DPF( 3, "adding one for alpha" );
  2917. }
  2918. is_cubemap = (BOOL)(caps2 & DDSCAPS2_CUBEMAP);
  2919. if ( is_cubemap )
  2920. {
  2921. //Count the number of real surfaces we're making for the cube map
  2922. DWORD dwCubeMapFaceCount =
  2923. (( caps2 & DDSCAPS2_CUBEMAP_POSITIVEX ) ? 1 : 0 )+
  2924. (( caps2 & DDSCAPS2_CUBEMAP_NEGATIVEX ) ? 1 : 0 )+
  2925. (( caps2 & DDSCAPS2_CUBEMAP_POSITIVEY ) ? 1 : 0 )+
  2926. (( caps2 & DDSCAPS2_CUBEMAP_NEGATIVEY ) ? 1 : 0 )+
  2927. (( caps2 & DDSCAPS2_CUBEMAP_POSITIVEZ ) ? 1 : 0 )+
  2928. (( caps2 & DDSCAPS2_CUBEMAP_NEGATIVEZ ) ? 1 : 0 );
  2929. /*
  2930. * If it's a mipmap, then we add the back buffer count
  2931. * to each face in the cube
  2932. * If no mipmap, then bbcnt==0
  2933. */
  2934. DDASSERT(bbcnt == 0 || (bbcnt && (caps & DDSCAPS_MIPMAP)) ); //If we have nonzero backbuffercount, then it has to be mipmaps
  2935. DDASSERT(!do_zbuffer);
  2936. DDASSERT(!do_abuffer);
  2937. nsurf = dwCubeMapFaceCount * (bbcnt+1);
  2938. DPF( 5, "I count %d cubemap faces",dwCubeMapFaceCount);
  2939. }
  2940. DPF( 5, "bbcnt=%d,nsurf=%d", bbcnt, nsurf );
  2941. DPF( 5, "do_abuffer=%d,do_zbuffer=%d,is_stereo=%d", do_abuffer, do_zbuffer, is_stereo );
  2942. /*
  2943. * Compute offsets into the surface list of the various distinguished
  2944. * surface types.
  2945. */
  2946. /*
  2947. * are we creating a non-flipping complex surface?
  2948. */
  2949. if( nsurf > 1 )
  2950. {
  2951. if( (caps & DDSCAPS_COMPLEX) && !(caps & DDSCAPS_FLIP) )
  2952. {
  2953. bbuffoff = 0;
  2954. }
  2955. else
  2956. {
  2957. bbuffoff = 1;
  2958. }
  2959. if( do_zbuffer )
  2960. {
  2961. if( do_abuffer )
  2962. zbuffoff = (nsurf - 2);
  2963. else
  2964. zbuffoff = (nsurf - 1);
  2965. }
  2966. }
  2967. else
  2968. {
  2969. bbuffoff = 0;
  2970. if( do_zbuffer )
  2971. zbuffoff = 0;
  2972. }
  2973. /*
  2974. * is this a flipping surface?
  2975. */
  2976. if( caps & DDSCAPS_FLIP )
  2977. {
  2978. is_flip = TRUE;
  2979. }
  2980. else
  2981. {
  2982. is_flip = FALSE;
  2983. }
  2984. /*
  2985. * Are we creating a mip-map chain?
  2986. */
  2987. if( ( ( caps & ( DDSCAPS_COMPLEX | DDSCAPS_MIPMAP ) ) ==
  2988. ( DDSCAPS_COMPLEX | DDSCAPS_MIPMAP ) ) &&
  2989. ( sdflags & DDSD_MIPMAPCOUNT ) )
  2990. {
  2991. is_mipmap = TRUE;
  2992. }
  2993. else
  2994. {
  2995. is_mipmap = FALSE;
  2996. }
  2997. /*
  2998. * The creation of flipping optimized mipmaps has a different semantic from that of
  2999. * non-optimized mipmap chains.
  3000. * Since a single optimized mipmap represents the entire mipmap chain, a request to create
  3001. * a complex optimized mipmap must be interpreted as meaning "please create me n mipmap chains
  3002. * each represented by a single optimized surface."
  3003. * In this case we need to turn off the is_mipmap flag to prevent the sizes of the subsequent
  3004. * backbuffers from being cut in half (as would happen for a non-optimized mipmap).
  3005. */
  3006. #if 0 //Old code
  3007. if (caps & DDSCAPS_OPTIMIZED)
  3008. {
  3009. is_mipmap = FALSE;
  3010. }
  3011. #endif //0
  3012. /*
  3013. * set up the list array
  3014. */
  3015. if( nsurf <= pcsinfo->listsize )
  3016. {
  3017. slist_int = pcsinfo->slist_int;
  3018. slist_lcl = pcsinfo->slist_lcl;
  3019. slist = pcsinfo->slist;
  3020. }
  3021. else
  3022. {
  3023. slist_int = MemAlloc( nsurf * sizeof( LPDDRAWI_DDRAWSURFACE_INT ) );
  3024. if( NULL == slist_int )
  3025. {
  3026. return DDERR_OUTOFMEMORY;
  3027. }
  3028. slist_lcl = MemAlloc( nsurf * sizeof( LPDDRAWI_DDRAWSURFACE_LCL ) );
  3029. if( slist_lcl == NULL )
  3030. {
  3031. MemFree(slist_int);
  3032. return DDERR_OUTOFMEMORY;
  3033. }
  3034. slist = MemAlloc( nsurf * sizeof( LPDDRAWI_DDRAWSURFACE_GBL ) );
  3035. if( slist == NULL )
  3036. {
  3037. MemFree(slist_int);
  3038. MemFree(slist_lcl);
  3039. return DDERR_OUTOFMEMORY;
  3040. }
  3041. pcsinfo->slist_int = slist_int;
  3042. pcsinfo->slist_lcl = slist_lcl;
  3043. pcsinfo->slist = slist;
  3044. pcsinfo->listsize = nsurf;
  3045. }
  3046. pcsinfo->listcnt = nsurf;
  3047. /*
  3048. * Create all needed surface structures.
  3049. *
  3050. * The callback fns, caps, and other misc things are filled in.
  3051. * Memory for the surface is allocated later.
  3052. */
  3053. pcsinfo->needlink = TRUE;
  3054. firstbbuff = TRUE;
  3055. if( is_primary_chain )
  3056. {
  3057. nsflags |= DDRAWISURF_PARTOFPRIMARYCHAIN;
  3058. if( this->dwFlags & DDRAWI_MODEX )
  3059. {
  3060. if( this->dwFlags & DDRAWI_STANDARDVGA )
  3061. {
  3062. caps |= DDSCAPS_STANDARDVGAMODE;
  3063. }
  3064. else
  3065. {
  3066. caps |= DDSCAPS_MODEX;
  3067. }
  3068. }
  3069. }
  3070. for( scnt=0;scnt<nsurf;scnt++ )
  3071. {
  3072. DPF( 4, "*** Structs Surface %d ***", scnt );
  3073. is_curr_diff = is_diff;
  3074. understood_pf = FALSE;
  3075. sflags = nsflags;
  3076. pddpf = NULL;
  3077. /*
  3078. * get the base pixel format
  3079. */
  3080. if( is_primary_chain || !(sdflags & DDSD_PIXELFORMAT) )
  3081. {
  3082. #ifdef USE_ALPHA
  3083. if( (caps & DDSCAPS_ALPHA) && !(caps & DDSCAPS_COMPLEX) )
  3084. {
  3085. memset( &ddpf, 0, sizeof( ddpf ) );
  3086. ddpf.dwSize = sizeof( ddpf );
  3087. pddpf = &ddpf;
  3088. pddpf->dwAlphaBitDepth = lpDDSurfaceDesc->dwAlphaBitDepth;
  3089. pddpf->dwFlags = DDPF_ALPHAPIXELS;
  3090. is_curr_diff = TRUE;
  3091. understood_pf = TRUE;
  3092. }
  3093. else
  3094. #endif
  3095. {
  3096. /*
  3097. * If this surface has been explicitly requested in system
  3098. * memory then we will force the allocation of a pixel
  3099. * format. Why? because explicit system memory surfaces
  3100. * don't get lost when a mode switches. This is a problem
  3101. * if the surface has no pixel format as we will pick up
  3102. * the pixel format of the current mode instead. Trouble
  3103. * is that the surface was not created in that mode so
  3104. * we end up with a bad bit depth - very dangerous. Heap
  3105. * corruption follows.
  3106. */
  3107. if( real_sysmem && !( caps & DDSCAPS_EXECUTEBUFFER ) )
  3108. {
  3109. DPF( 3, "Forcing pixel format for explicit system memory surface" );
  3110. ddpf = this->vmiData.ddpfDisplay;
  3111. pddpf = &ddpf;
  3112. is_curr_diff = TRUE;
  3113. }
  3114. /*
  3115. * If no pixel format is specified then we use the pixel format
  3116. * of the primary. So if we understand the pixel format of the
  3117. * primary then we understand the pixel format of this surface.
  3118. * With one notable exception. We always understand the pixel
  3119. * format of an execute buffer - it hasn't got one.
  3120. */
  3121. if( ( this->vmiData.ddpfDisplay.dwFlags & UNDERSTOOD_PF ) ||
  3122. ( caps & DDSCAPS_EXECUTEBUFFER ) )
  3123. {
  3124. understood_pf = TRUE;
  3125. }
  3126. }
  3127. }
  3128. else
  3129. {
  3130. /*
  3131. * If we have an explicit system memory surface with a pixel format
  3132. * I don't care whether the specifed pixel format is the same as the
  3133. * primary. We are going to store it anyway. This is vital as
  3134. * explicit system memory surfaces survive mode switches so they must
  3135. * carry their pixel format with them.
  3136. */
  3137. if( real_sysmem && !( caps & DDSCAPS_EXECUTEBUFFER ) )
  3138. {
  3139. DPF( 3, "Forcing pixel format for explicit system memory surface" );
  3140. is_curr_diff = TRUE;
  3141. }
  3142. if( is_curr_diff )
  3143. {
  3144. pddpf = &ddpf;
  3145. ddpf = lpDDSurfaceDesc->ddpfPixelFormat;
  3146. if( pddpf->dwFlags & UNDERSTOOD_PF )
  3147. {
  3148. understood_pf = TRUE;
  3149. }
  3150. }
  3151. else
  3152. {
  3153. if( this->vmiData.ddpfDisplay.dwFlags & UNDERSTOOD_PF )
  3154. {
  3155. understood_pf = TRUE;
  3156. }
  3157. }
  3158. }
  3159. if((caps & DDSCAPS_ZBUFFER) && !(caps & DDSCAPS_COMPLEX)) {
  3160. DDASSERT(nsurf==1);
  3161. understood_pf = is_curr_diff = TRUE;
  3162. pddpf = &ddpf;
  3163. // proper pixfmt will have been set in checkSurfaceDesc
  3164. ddpf=lpDDSurfaceDesc->ddpfPixelFormat;
  3165. }
  3166. /*
  3167. * set up caps for each surface
  3168. */
  3169. if( scnt > 0 )
  3170. {
  3171. /*
  3172. * mark implicitly created surfaces as such
  3173. */
  3174. sflags |= DDRAWISURF_IMPLICITCREATE;
  3175. /*
  3176. * eliminated unwanted caps.
  3177. * NOTE: If we are creating a flipping chain for a mip-mapped
  3178. * texture then we don't propagate the MIPMAP cap to the back
  3179. * buffers, only the front buffer is tagged as a mip-map.
  3180. */
  3181. caps &= ~(DDSCAPS_PRIMARYSURFACE |
  3182. DDSCAPS_FRONTBUFFER | DDSCAPS_VISIBLE |
  3183. DDSCAPS_ALPHA | DDSCAPS_ZBUFFER |
  3184. DDSCAPS_BACKBUFFER );
  3185. caps2 &= ~DDSCAPS2_STEREOSURFACELEFT;
  3186. #ifdef SHAREDZ
  3187. caps &= ~(DDSCAPS_SHAREDZBUFFER | DDSCAPS_SHAREDBACKBUFFER);
  3188. #endif
  3189. /*
  3190. * Complex optimized mipmaps actually keep the mipmap tags on their back buffers
  3191. * since each surface represents a whole chain of mipmaps
  3192. */
  3193. #if 0 //Old code
  3194. if ((caps & DDSCAPS_OPTIMIZED) == 0)
  3195. {
  3196. if( is_flip )
  3197. caps &= ~DDSCAPS_MIPMAP;
  3198. }
  3199. #endif //0
  3200. #ifdef USE_ALPHA
  3201. /*
  3202. * caps for an alpha buffer
  3203. */
  3204. if( (do_abuffer && do_zbuffer && (scnt == nsurf-1) ) ||
  3205. (do_abuffer && (scnt == nsurf-1)) )
  3206. {
  3207. DPF( 4, "TRY ALPHA" );
  3208. caps &= ~(DDSCAPS_TEXTURE | DDSCAPS_FLIP | DDSCAPS_OVERLAY | DDSCAPS_OFFSCREENPLAIN);
  3209. caps |= DDSCAPS_ALPHA;
  3210. memset( &ddpf, 0, sizeof( ddpf ) );
  3211. ddpf.dwSize = sizeof( ddpf );
  3212. pddpf = &ddpf;
  3213. pddpf->dwAlphaBitDepth = lpDDSurfaceDesc->dwAlphaBitDepth;
  3214. pddpf->dwFlags = DDPF_ALPHA;
  3215. understood_pf = TRUE;
  3216. is_curr_diff = TRUE;
  3217. /*
  3218. * caps for a z buffer
  3219. */
  3220. }
  3221. else
  3222. #endif
  3223. if( do_zbuffer && ( scnt == zbuffoff ) )
  3224. {
  3225. caps &= ~(DDSCAPS_TEXTURE | DDSCAPS_FLIP | DDSCAPS_OVERLAY | DDSCAPS_OFFSCREENPLAIN | DDSCAPS_3DDEVICE);
  3226. caps |= DDSCAPS_ZBUFFER;
  3227. #ifdef SHAREDZ
  3228. if( do_shared_z )
  3229. caps |= DDSCAPS_SHAREDZBUFFER;
  3230. #endif
  3231. pddpf = &ddpf;
  3232. DDASSERT(caps & DDSCAPS_COMPLEX); // scnt>0, so this must be true
  3233. // must construct a valid z pixfmt in ddpf since DDSurfaceDesc one is being used
  3234. // be primary surface. note complex surfdescs will never be able to create stencil zbufs
  3235. memset(&ddpf, 0, sizeof(DDPIXELFORMAT));
  3236. ddpf.dwSize=sizeof(DDPIXELFORMAT);
  3237. ddpf.dwFlags|=DDPF_ZBUFFER;
  3238. ddpf.dwZBufferBitDepth = ((DDSURFACEDESC *)lpDDSurfaceDesc)->dwZBufferBitDepth;
  3239. ddpf.dwZBitMask = (1 << ((DDSURFACEDESC *)lpDDSurfaceDesc)->dwZBufferBitDepth)-1;
  3240. is_curr_diff = TRUE;
  3241. understood_pf = TRUE;
  3242. /*
  3243. * set up for offscreen surfaces
  3244. */
  3245. }
  3246. else
  3247. {
  3248. if( (!is_mipmap) && (!is_cubemap) )
  3249. {
  3250. /*
  3251. * Flip and back buffer don't apply to mip-map chains or cubemaps.
  3252. */
  3253. // DX7Stereo spec case for stereo
  3254. // mark odd backbuffers only as surfaceleft
  3255. if (is_stereo && ((scnt & 1)!=0))
  3256. {
  3257. caps2 |= DDSCAPS2_STEREOSURFACELEFT;
  3258. } else
  3259. {
  3260. caps |= DDSCAPS_FLIP;
  3261. if( firstbbuff )
  3262. {
  3263. caps |= DDSCAPS_BACKBUFFER;
  3264. sflags |= DDRAWISURF_BACKBUFFER;
  3265. #ifdef SHAREDZ
  3266. if( do_shared_back )
  3267. caps |= DDSCAPS_SHAREDBACKBUFFER;
  3268. #endif
  3269. firstbbuff = FALSE;
  3270. }
  3271. }
  3272. }
  3273. }
  3274. /*
  3275. * the first surface...
  3276. */
  3277. }
  3278. else
  3279. {
  3280. if( caps & DDSCAPS_PRIMARYSURFACE )
  3281. {
  3282. caps |= DDSCAPS_VISIBLE;
  3283. }
  3284. if( caps & DDSCAPS_FLIP )
  3285. {
  3286. caps |= DDSCAPS_FRONTBUFFER;
  3287. sflags |= DDRAWISURF_FRONTBUFFER;
  3288. }
  3289. if( nsurf > 1 )
  3290. {
  3291. sflags |= DDRAWISURF_IMPLICITROOT;
  3292. }
  3293. if( caps & DDSCAPS_BACKBUFFER )
  3294. {
  3295. sflags |= DDRAWISURF_BACKBUFFER;
  3296. }
  3297. }
  3298. /*
  3299. * if it isn't a pixel format we grok, then it is different...
  3300. */
  3301. if( !understood_pf )
  3302. {
  3303. is_curr_diff = TRUE;
  3304. }
  3305. /*
  3306. * pick size of structure we need to allocate...
  3307. */
  3308. if( (caps & DDSCAPS_OVERLAY) ||
  3309. ((caps & DDSCAPS_PRIMARYSURFACE) &&
  3310. ((this->ddCaps.dwCaps & DDCAPS_OVERLAY) ||
  3311. (this->ddHELCaps.dwCaps & DDCAPS_OVERLAY))) )
  3312. {
  3313. sflags |= DDRAWISURF_HASOVERLAYDATA;
  3314. }
  3315. /*
  3316. * Execute buffers should NEVER have pixel formats.
  3317. */
  3318. if( is_curr_diff && !( caps & DDSCAPS_EXECUTEBUFFER ) )
  3319. {
  3320. sflags |= DDRAWISURF_HASPIXELFORMAT;
  3321. }
  3322. /*
  3323. * allocate the surface struct, allowing for overlay and pixel
  3324. * format data
  3325. *
  3326. * NOTE: This single allocation can allocate space for local surface
  3327. * structure (DDRAWI_DDRAWSURFACE_LCL), the additional local surface
  3328. * structure (DDRAWI_DDRAWSURFACE_MORE) and the global surface structure
  3329. * (DDRAWI_DDRAWSURFACE_GBL). (And now the global surface more structure too
  3330. * (DDRAWI_DDRAWSURFACE_GBL_MORE). As both the local and global objects
  3331. * can be variable sized this can get pretty complex. Additionally, we have
  3332. * 4 bytes just before the surface_gbl that points to the surface_gbl_more.
  3333. *
  3334. * CAVEAT: All future surfaces that share this global all point to this
  3335. * allocation. The last surface's release has to free it. During
  3336. * InternalSurfaceRelease (in ddsiunk.c) a calculation is made to determine
  3337. * the start of this memory allocation. If the surface being released is
  3338. * the first one, then freeing "this_lcl" will free the whole thing. If
  3339. * not, then "this_lcl->lpGbl - (Surface_lcl + surface_more + more_ptr)"
  3340. * is computed. Keep this layout in synch with code in ddsiunk.c.
  3341. *
  3342. * The layout of the various objects in the allocation is as follows:
  3343. *
  3344. * +-----------------+---------------+----+------------+-----------------+
  3345. * | SURFACE_LCL | SURFACE_MORE |More| SURFACE_GBL| SURFACE_GBL_MORE|
  3346. * | (variable) | |Ptr | (variable) | |
  3347. * +-----------------+---------------+----+------------+-----------------+
  3348. * <- surf_size_lcl -> | |
  3349. * <- surf_size_lcl_more ------------> |
  3350. * <- surf_size --------------------------------------------------------->
  3351. *
  3352. */
  3353. if( sflags & DDRAWISURF_HASOVERLAYDATA )
  3354. {
  3355. surf_size_lcl = sizeof( DDRAWI_DDRAWSURFACE_LCL );
  3356. DPF( 5, "OVERLAY DATA SPACE" );
  3357. }
  3358. else
  3359. {
  3360. surf_size_lcl = offsetof( DDRAWI_DDRAWSURFACE_LCL, ddckCKSrcOverlay );
  3361. }
  3362. surf_size_lcl_more = surf_size_lcl + sizeof( DDRAWI_DDRAWSURFACE_MORE );
  3363. if( ( sflags & DDRAWISURF_HASPIXELFORMAT ) || ( caps & DDSCAPS_PRIMARYSURFACE ) )
  3364. {
  3365. DPF( 5, "PIXEL FORMAT SPACE" );
  3366. surf_size = surf_size_lcl_more + sizeof( DDRAWI_DDRAWSURFACE_GBL );
  3367. }
  3368. else
  3369. {
  3370. surf_size = surf_size_lcl_more +
  3371. offsetof( DDRAWI_DDRAWSURFACE_GBL, ddpfSurface );
  3372. }
  3373. // Need to allocate a pointer just before the SURFACE_GBL to
  3374. // point to the beginning of the GBL_MORE.
  3375. surf_size += sizeof( LPDDRAWI_DDRAWSURFACE_GBL_MORE );
  3376. // Need to allocate a SURFACE_GBL_MORE too
  3377. surf_size += sizeof( DDRAWI_DDRAWSURFACE_GBL_MORE );
  3378. DPF( 5, "Allocating struct (%ld)", surf_size );
  3379. existing_global = FALSE;
  3380. if( caps & DDSCAPS_PRIMARYSURFACE )
  3381. {
  3382. // attempt to find existing global primary surface
  3383. lpGlobalSurface = FindGlobalPrimary( this );
  3384. }
  3385. #ifdef SHAREDZ
  3386. else if( caps & DDSCAPS_SHAREDZBUFFER )
  3387. {
  3388. DPF( 4, "Searching for shared Z-buffer" );
  3389. lpGlobalSurface = FindGlobalZBuffer( this );
  3390. }
  3391. else if( caps & DDSCAPS_SHAREDBACKBUFFER )
  3392. {
  3393. DPF( 4, "Searching for shared back-buffer" );
  3394. lpGlobalSurface = FindGlobalBackBuffer( this );
  3395. }
  3396. #endif
  3397. else
  3398. {
  3399. lpGlobalSurface = NULL;
  3400. }
  3401. if( lpGlobalSurface )
  3402. {
  3403. DPF( 4, "Using shared global surface" );
  3404. #ifdef WIN95
  3405. psurf_lcl = (LPDDRAWI_DDRAWSURFACE_LCL) MemAlloc16( surf_size_lcl_more, &ptr16 );
  3406. #else
  3407. psurf_lcl = (LPDDRAWI_DDRAWSURFACE_LCL) MemAlloc( surf_size_lcl_more );
  3408. #endif
  3409. if( psurf_lcl != NULL )
  3410. {
  3411. psurf_lcl->lpGbl = lpGlobalSurface;
  3412. }
  3413. existing_global = TRUE;
  3414. }
  3415. else
  3416. {
  3417. #ifdef WIN95
  3418. psurf_lcl = (LPDDRAWI_DDRAWSURFACE_LCL) MemAlloc16( surf_size, &ptr16 );
  3419. #else
  3420. psurf_lcl = (LPDDRAWI_DDRAWSURFACE_LCL) MemAlloc( surf_size );
  3421. #endif
  3422. if( psurf_lcl != NULL )
  3423. {
  3424. LPVOID *ppsurf_gbl_more;
  3425. // Initialize SURFACE_GBL pointer
  3426. // skipping 4 bytes for a pointer to the GBL_MORE
  3427. psurf_lcl->lpGbl = (LPVOID) (((LPSTR) psurf_lcl) +
  3428. surf_size_lcl_more + sizeof( LPVOID ) );
  3429. // Initialize GBL_MORE pointer
  3430. ppsurf_gbl_more = (LPVOID *)((LPBYTE)psurf_lcl->lpGbl - sizeof( LPVOID ));
  3431. *ppsurf_gbl_more = (LPVOID)
  3432. ((LPBYTE)psurf_lcl + surf_size
  3433. - sizeof( DDRAWI_DDRAWSURFACE_GBL_MORE ));
  3434. // Sanity Check
  3435. DDASSERT( *ppsurf_gbl_more == (LPVOID)GET_LPDDRAWSURFACE_GBL_MORE( psurf_lcl->lpGbl ) );
  3436. // Initialize GBL_MORE structure
  3437. GET_LPDDRAWSURFACE_GBL_MORE( psurf_lcl->lpGbl )->dwSize = sizeof( DDRAWI_DDRAWSURFACE_GBL_MORE );
  3438. /*
  3439. * Init the contents stamp to 0 means the surface's contents can change at
  3440. * any time.
  3441. */
  3442. if ( caps & (DDSCAPS_VIDEOPORT|DDSCAPS_OWNDC) )
  3443. {
  3444. GET_LPDDRAWSURFACE_GBL_MORE( psurf_lcl->lpGbl )->dwContentsStamp = 0;
  3445. }
  3446. else
  3447. {
  3448. GET_LPDDRAWSURFACE_GBL_MORE( psurf_lcl->lpGbl )->dwContentsStamp = 1;
  3449. }
  3450. }
  3451. }
  3452. if( psurf_lcl == NULL )
  3453. {
  3454. freeSurfaceList( slist_int, scnt );
  3455. return DDERR_OUTOFMEMORY;
  3456. }
  3457. psurf = psurf_lcl->lpGbl;
  3458. /*
  3459. * allocate surface interface
  3460. */
  3461. psurf_int = (LPDDRAWI_DDRAWSURFACE_INT) MemAlloc( sizeof( DDRAWI_DDRAWSURFACE_INT ));
  3462. if( NULL == psurf_int )
  3463. {
  3464. freeSurfaceList( slist_int, scnt );
  3465. MemFree( psurf_lcl );
  3466. return DDERR_OUTOFMEMORY;
  3467. }
  3468. /*
  3469. * fill surface specific stuff
  3470. */
  3471. psurf_int->lpLcl = psurf_lcl;
  3472. if (LOWERTHANDDRAW4(this_int))
  3473. {
  3474. psurf_int->lpVtbl = &ddSurfaceCallbacks;
  3475. }
  3476. else if (this_int->lpVtbl == &dd4Callbacks)
  3477. {
  3478. psurf_int->lpVtbl = &ddSurface4Callbacks;
  3479. }
  3480. else
  3481. {
  3482. psurf_int->lpVtbl = &ddSurface7Callbacks;
  3483. }
  3484. if( existing_global )
  3485. {
  3486. psurf_lcl->dwLocalRefCnt = 0;
  3487. }
  3488. else
  3489. {
  3490. psurf_lcl->dwLocalRefCnt = OBJECT_ISROOT;
  3491. }
  3492. psurf_lcl->dwProcessId = pid;
  3493. slist_int[scnt] = psurf_int;
  3494. slist_lcl[scnt] = psurf_lcl;
  3495. slist[scnt] = psurf;
  3496. /*
  3497. * fill in misc stuff
  3498. */
  3499. psurf->lpDD = this;
  3500. psurf_lcl->dwFlags = sflags;
  3501. /*
  3502. * initialize extended fields if necessary
  3503. */
  3504. if( sflags & DDRAWISURF_HASOVERLAYDATA )
  3505. {
  3506. psurf_lcl->lpSurfaceOverlaying = NULL;
  3507. }
  3508. /*
  3509. * Initialize the additional local surface data structure
  3510. */
  3511. psurf_lcl->lpSurfMore = (LPDDRAWI_DDRAWSURFACE_MORE) (((LPSTR) psurf_lcl) + surf_size_lcl );
  3512. psurf_lcl->lpSurfMore->dwSize = sizeof( DDRAWI_DDRAWSURFACE_MORE );
  3513. psurf_lcl->lpSurfMore->lpIUnknowns = NULL;
  3514. psurf_lcl->lpSurfMore->lpDD_lcl = this_lcl;
  3515. psurf_lcl->lpSurfMore->lpDD_int = this_int;
  3516. psurf_lcl->lpSurfMore->dwMipMapCount = 0UL;
  3517. psurf_lcl->lpSurfMore->lpddOverlayFX = NULL;
  3518. psurf_lcl->lpSurfMore->lpD3DDevIList = NULL;
  3519. psurf_lcl->lpSurfMore->dwPFIndex = PFINDEX_UNINITIALIZED;
  3520. #ifdef WIN95
  3521. psurf_lcl->dwModeCreatedIn = this->dwModeIndex;
  3522. #else
  3523. psurf_lcl->lpSurfMore->dmiCreated = this->dmiCurrent;
  3524. #endif
  3525. /*
  3526. * fill in the current caps
  3527. */
  3528. psurf_lcl->lpSurfMore->ddsCapsEx = sd.ddsCaps.ddsCapsEx;
  3529. if (DDSD_TEXTURESTAGE & sd.dwFlags) //hack here to pass the flag too as dwTextureStage is [0,7]
  3530. psurf_lcl->lpSurfMore->dwTextureStage = sd.dwTextureStage | DDSD_TEXTURESTAGE;
  3531. psurf_lcl->ddsCaps.dwCaps = caps;
  3532. psurf_lcl->lpSurfMore->lpbDirty=NULL; //initialized
  3533. psurf_lcl->lpSurfMore->dwSurfaceHandle=0; //initialized
  3534. psurf_lcl->lpSurfMore->qwBatch.QuadPart=0;
  3535. if (sd.dwFlags & DDSD_FVF)
  3536. psurf_lcl->lpSurfMore->dwFVF = sd.dwFVF; //just stuff it in no matter what the surface type
  3537. else
  3538. psurf_lcl->lpSurfMore->dwFVF = 0;
  3539. /*
  3540. * Mark surface as driver managed if the surface is marked with
  3541. * DDSCAPS2_TEXTUREMANAGE *and* if the driver claims it can manage textures
  3542. */
  3543. if((psurf_lcl->lpSurfMore->lpDD_lcl->dwLocalFlags & DDRAWILCL_DIRECTDRAW7) &&
  3544. !(psurf_lcl->lpSurfMore->lpDD_lcl->dwLocalFlags & DDRAWILCL_DIRECTDRAW8) &&
  3545. (psurf_lcl->lpSurfMore->ddsCapsEx.dwCaps2 & DDSCAPS2_TEXTUREMANAGE) &&
  3546. (psurf_lcl->lpSurfMore->lpDD_lcl->lpGbl->ddCaps.dwCaps2 & DDCAPS2_CANMANAGETEXTURE))
  3547. {
  3548. psurf_lcl->dwFlags |= DDRAWISURF_DRIVERMANAGED;
  3549. }
  3550. else if((psurf_lcl->lpSurfMore->lpDD_lcl->dwLocalFlags & DDRAWILCL_DIRECTDRAW8) &&
  3551. (psurf_lcl->lpSurfMore->ddsCapsEx.dwCaps2 & DDSCAPS2_TEXTUREMANAGE))
  3552. {
  3553. DDASSERT((psurf_lcl->lpSurfMore->lpDD_lcl->lpGbl->ddCaps.dwCaps2 & DDCAPS2_CANMANAGERESOURCE));
  3554. psurf_lcl->dwFlags |= DDRAWISURF_DRIVERMANAGED;
  3555. }
  3556. /*
  3557. * If it's a cubemap, then we need to mark up the surface's caps accordingly
  3558. *
  3559. * Cubemaps are laid out in the surface list such that the 0th and every subsequent
  3560. * (bbcnt+1)th surface are the top levels of the mipmap. Surfaces in between these
  3561. * are the mip levels. All surfaces in the map are tagged with their face cap.
  3562. */
  3563. if (is_cubemap)
  3564. {
  3565. int i;
  3566. DWORD dwOrderedFaces[6] = {
  3567. DDSCAPS2_CUBEMAP_POSITIVEX,
  3568. DDSCAPS2_CUBEMAP_NEGATIVEX,
  3569. DDSCAPS2_CUBEMAP_POSITIVEY,
  3570. DDSCAPS2_CUBEMAP_NEGATIVEY,
  3571. DDSCAPS2_CUBEMAP_POSITIVEZ,
  3572. DDSCAPS2_CUBEMAP_NEGATIVEZ
  3573. };
  3574. int n;
  3575. /*
  3576. * Now we find the nth cubemap face in our ordered list.
  3577. * This is the ordering, but some may be missing from the surfacedesc:
  3578. * DDSCAPS2_CUBEMAP_POSITIVEX
  3579. * DDSCAPS2_CUBEMAP_NEGATIVEX
  3580. * DDSCAPS2_CUBEMAP_POSITIVEY
  3581. * DDSCAPS2_CUBEMAP_NEGATIVEY
  3582. * DDSCAPS2_CUBEMAP_POSITIVEZ
  3583. * DDSCAPS2_CUBEMAP_NEGATIVEZ
  3584. */
  3585. n = (int) (scnt/(bbcnt+1));
  3586. DDASSERT(n<=5);
  3587. i=0;
  3588. do
  3589. {
  3590. if (dwOrderedFaces[i] & sd.ddsCaps.dwCaps2)
  3591. n--;
  3592. }
  3593. while (n>=0 && i++<6);
  3594. psurf_lcl->lpSurfMore->ddsCapsEx.dwCaps2 &= ~DDSCAPS2_CUBEMAP_ALLFACES;
  3595. psurf_lcl->lpSurfMore->ddsCapsEx.dwCaps2 |= dwOrderedFaces[i];
  3596. /*
  3597. * Every top-level face is marked as a cubemap
  3598. */
  3599. psurf_lcl->lpSurfMore->ddsCapsEx.dwCaps2 |= DDSCAPS2_CUBEMAP;
  3600. }
  3601. if (is_stereo)
  3602. {
  3603. psurf_lcl->lpSurfMore->ddsCapsEx.dwCaps2 = caps2;
  3604. }
  3605. /*
  3606. * Allocate memory to hold region list for D3D texture management
  3607. */
  3608. if(IsD3DManaged(psurf_lcl))
  3609. {
  3610. LPREGIONLIST lpRegionList;
  3611. lpRegionList = (LPREGIONLIST)MemAlloc(sizeof(REGIONLIST));
  3612. if(lpRegionList == NULL)
  3613. {
  3614. DPF_ERR("Out of memory allocating region list");
  3615. freeSurfaceList( slist_int, scnt );
  3616. psurf_lcl->lpSurfMore->lpRegionList = 0;
  3617. MemFree( psurf_lcl );
  3618. MemFree( psurf_int );
  3619. return DDERR_OUTOFMEMORY;
  3620. }
  3621. lpRegionList->rdh.dwSize = sizeof(RGNDATAHEADER);
  3622. lpRegionList->rdh.iType = RDH_RECTANGLES;
  3623. lpRegionList->rdh.nCount = 0;
  3624. lpRegionList->rdh.nRgnSize = 0;
  3625. lpRegionList->rdh.rcBound.left = LONG_MAX;
  3626. lpRegionList->rdh.rcBound.right = 0;
  3627. lpRegionList->rdh.rcBound.top = LONG_MAX;
  3628. lpRegionList->rdh.rcBound.bottom = 0;
  3629. psurf_lcl->lpSurfMore->lpRegionList = lpRegionList;
  3630. }
  3631. else
  3632. {
  3633. psurf_lcl->lpSurfMore->lpRegionList = 0;
  3634. }
  3635. /*
  3636. * set up format info
  3637. *
  3638. * are we creating a primary surface?
  3639. */
  3640. if( caps & DDSCAPS_PRIMARYSURFACE )
  3641. {
  3642. /*
  3643. * NOTE: Previously we set ISGDISURFACE for all primary surfaces
  3644. * We now set it only for primarys hanging off display drivers.
  3645. * This is to better support drivers which are not GDI display
  3646. * drivers.
  3647. */
  3648. if( this->dwFlags & DDRAWI_DISPLAYDRV )
  3649. psurf->dwGlobalFlags |= DDRAWISURFGBL_ISGDISURFACE;
  3650. psurf->wHeight = (WORD) this->vmiData.dwDisplayHeight;
  3651. psurf->wWidth = (WORD) this->vmiData.dwDisplayWidth;
  3652. psurf->lPitch = this->vmiData.lDisplayPitch;
  3653. DPF(5,"Primary Surface get's display size:%dx%d",psurf->wWidth,psurf->wHeight);
  3654. if( !understood_pf && (pddpf == NULL) )
  3655. {
  3656. ddpf = this->vmiData.ddpfDisplay;
  3657. pddpf = &ddpf;
  3658. }
  3659. bpp = this->vmiData.ddpfDisplay.dwRGBBitCount;
  3660. }
  3661. else
  3662. {
  3663. /*
  3664. * process a plain ol' non-primary surface
  3665. */
  3666. /*
  3667. * set up surface attributes
  3668. */
  3669. if( scnt > 0 )
  3670. {
  3671. /*
  3672. * NOTE: Don't have to worry about execute buffers here as
  3673. * execute buffers can never be created as part of a complex
  3674. * surface and hence scnt will never be > 0 for an execute
  3675. * buffer.
  3676. */
  3677. DDASSERT( !( caps & DDSCAPS_EXECUTEBUFFER ) );
  3678. /*
  3679. * If we are doing a mip-map chain then the width and height
  3680. * of each surface is half that of the preceeding surface.
  3681. * If we are doing cubemaps, then we need to reset every
  3682. * (bbcnt+1)th surface to the supplied size
  3683. */
  3684. if( !is_mipmap || (is_cubemap && ((scnt%(bbcnt+1))==0) ) )
  3685. {
  3686. psurf->wWidth = slist[0]->wWidth;
  3687. psurf->wHeight = slist[0]->wHeight;
  3688. }
  3689. else
  3690. {
  3691. psurf->wWidth = max ( slist[scnt - 1]->wWidth / 2 , 1);
  3692. psurf->wHeight = max ( slist[scnt - 1]->wHeight / 2 , 1);
  3693. }
  3694. }
  3695. else
  3696. {
  3697. if( caps & DDSCAPS_EXECUTEBUFFER )
  3698. {
  3699. /*
  3700. * NOTE: Execute buffers are a special case. They are
  3701. * linear and not rectangular. We therefore store zero
  3702. * for width and height, they have no pitch and store
  3703. * their linear size in dwLinerSize (in union with lPitch).
  3704. * The linear size is given by the width of the surface
  3705. * description (the width MUST be specified - the height
  3706. * MUST NOT be).
  3707. */
  3708. DDASSERT( lpDDSurfaceDesc->dwFlags & DDSD_WIDTH );
  3709. DDASSERT( !( lpDDSurfaceDesc->dwFlags & DDSD_HEIGHT ) );
  3710. psurf->wWidth = 0;
  3711. psurf->wHeight = 0;
  3712. psurf->dwLinearSize = lpDDSurfaceDesc->dwWidth;
  3713. }
  3714. else
  3715. {
  3716. if( sdflags & DDSD_HEIGHT )
  3717. {
  3718. psurf->wHeight = (WORD) lpDDSurfaceDesc->dwHeight;
  3719. }
  3720. else
  3721. {
  3722. psurf->wHeight = (WORD) this->vmiData.dwDisplayHeight;
  3723. }
  3724. if( sdflags & DDSD_WIDTH )
  3725. {
  3726. psurf->wWidth = (WORD) lpDDSurfaceDesc->dwWidth;
  3727. }
  3728. else
  3729. {
  3730. psurf->wWidth = (WORD) this->vmiData.dwDisplayWidth;
  3731. }
  3732. }
  3733. }
  3734. /*
  3735. * set pixel format and pitch for surfaces we understand
  3736. */
  3737. if( lpDDSurfaceDesc->dwFlags & DDSD_PITCH )
  3738. {
  3739. /*
  3740. * Client has alloc'd surface memory and specified its pitch.
  3741. */
  3742. psurf->lPitch = lpDDSurfaceDesc->lPitch;
  3743. }
  3744. else if( caps & DDSCAPS_EXECUTEBUFFER )
  3745. {
  3746. /*
  3747. * Execute buffers need to be handled differently from
  3748. * other surfaces. They never have pixel formats and
  3749. * BPP is a bit meaningless. You might wonder why we call
  3750. * ComputePitch at all for execute buffers. Well, they
  3751. * may also have alignment requirements and so it we
  3752. * need to give ComputePitch a chance to enlarge the
  3753. * size of the execute buffer.
  3754. *
  3755. * NOTE: For the purposes of this calculation. Execute
  3756. * buffers are 8-bits per pixel.
  3757. */
  3758. psurf->dwLinearSize = ComputePitch( this, caps, psurf->dwLinearSize, 8U );
  3759. if( psurf->dwLinearSize == 0UL )
  3760. {
  3761. DPF_ERR( "Computed linear size of execute buffer as zero" );
  3762. MemFree(psurf_lcl->lpSurfMore->lpRegionList);
  3763. MemFree( psurf_lcl );
  3764. MemFree( psurf_int ); //oops, someone forgot these (jeffno 960118)
  3765. freeSurfaceList( slist_int, scnt );
  3766. return DDERR_INVALIDPARAMS;
  3767. }
  3768. }
  3769. else
  3770. {
  3771. if( understood_pf )
  3772. {
  3773. LPDDPIXELFORMAT pcurr_ddpf;
  3774. pcurr_ddpf = NULL;
  3775. if( is_curr_diff )
  3776. {
  3777. if( (caps & DDSCAPS_FLIP) && scnt > 0 )
  3778. {
  3779. GET_PIXEL_FORMAT( slist_lcl[0], slist[0], pcurr_ddpf );
  3780. pddpf->dwRGBBitCount = pcurr_ddpf->dwRGBBitCount;
  3781. bpp = pddpf->dwRGBBitCount;
  3782. }
  3783. else
  3784. {
  3785. if(pddpf->dwFlags & DDPF_ZBUFFER) {
  3786. // note dwZBufferBitDepth includes any stencil bits too
  3787. bpp = (UINT)pddpf->dwZBufferBitDepth;
  3788. } else {
  3789. bpp = (UINT) pddpf->dwRGBBitCount;
  3790. }
  3791. if( bpp == 0 )
  3792. {
  3793. bpp = (UINT) this->vmiData.ddpfDisplay.dwRGBBitCount;
  3794. pddpf->dwRGBBitCount = (DWORD) bpp;
  3795. }
  3796. }
  3797. }
  3798. else
  3799. {
  3800. bpp = (UINT) this->vmiData.ddpfDisplay.dwRGBBitCount;
  3801. }
  3802. vm_pitch = (LONG) ComputePitch( this, caps,
  3803. (DWORD) psurf->wWidth, bpp );
  3804. if( vm_pitch == 0 )
  3805. {
  3806. DPF_ERR( "Computed pitch of 0" );
  3807. MemFree(psurf_lcl->lpSurfMore->lpRegionList);
  3808. MemFree( psurf_lcl );
  3809. MemFree( psurf_int ); //oops, someone forgot these (jeffno 960118)
  3810. freeSurfaceList( slist_int, scnt );
  3811. return DDERR_INVALIDPARAMS;
  3812. }
  3813. }
  3814. else
  3815. {
  3816. vm_pitch = -1;
  3817. }
  3818. psurf->lPitch = vm_pitch;
  3819. }
  3820. }
  3821. /*
  3822. * If this is a sysmem surface used for DX8, we need to use the memory
  3823. * that has already been allocated for this surface
  3824. */
  3825. if( (DX8Flags & DX8SFLAG_DX8) && real_sysmem && pSysMemInfo != NULL )
  3826. {
  3827. psurf->dwGlobalFlags |= DDRAWISURFGBL_DX8SURFACE;
  3828. psurf->lPitch = pSysMemInfo[scnt].iPitch;
  3829. psurf->fpVidMem = (ULONG_PTR) pSysMemInfo[scnt].pbPixels;
  3830. }
  3831. /*
  3832. * If it's a volume texture, set that up
  3833. */
  3834. if ((DX8Flags & DX8SFLAG_DX8) && (lpDDSurfaceDesc->ddsCaps.dwCaps2 & DDSCAPS2_VOLUME))
  3835. {
  3836. if (scnt > 0)
  3837. {
  3838. psurf_lcl->lpSurfMore->ddsCapsEx.dwCaps2 |= DDSCAPS2_MIPMAPSUBLEVEL;
  3839. }
  3840. psurf_lcl->lpSurfMore->ddsCapsEx.dwCaps4 =
  3841. MAKELONG((WORD)(pSysMemInfo[scnt].cpDepth),0);
  3842. psurf->lSlicePitch = pSysMemInfo[scnt].iSlicePitch;
  3843. }
  3844. /*
  3845. * Figure out what Blitting tables to use
  3846. */
  3847. /*
  3848. * Initialize junctions if necessary
  3849. */
  3850. if( g_rgjunc8 == NULL )
  3851. {
  3852. HRESULT hr = InitializeJunctions( dwRegFlags & DDRAW_REGFLAGS_DISABLEMMX );
  3853. if( FAILED( hr ) )
  3854. {
  3855. DPF_ERR( "InitializeJunctions failed" );
  3856. return hr;
  3857. }
  3858. }
  3859. /*
  3860. * Figure out what blitting table to use
  3861. */
  3862. switch( bpp )
  3863. {
  3864. case 8:
  3865. psurf_lcl->lpSurfMore->rgjunc = (VOID *) g_rgjunc8;
  3866. break;
  3867. case 16:
  3868. psurf_lcl->lpSurfMore->rgjunc = (VOID *) g_rgjunc565;
  3869. break;
  3870. case 24:
  3871. psurf_lcl->lpSurfMore->rgjunc = (VOID *) g_rgjunc24;
  3872. break;
  3873. case 32:
  3874. psurf_lcl->lpSurfMore->rgjunc = (VOID *) g_rgjunc32;
  3875. break;
  3876. case 0:
  3877. // DX7: Handle YUY2 and UYVY FourCC as just being 16bpp for the
  3878. // purposes of bltting
  3879. if (pddpf &&
  3880. (pddpf->dwFlags & DDPF_FOURCC) &&
  3881. ((pddpf->dwFourCC == MAKEFOURCC('Y', 'U', 'Y', '2')) ||
  3882. (pddpf->dwFourCC == MAKEFOURCC('U', 'Y', 'V', 'Y'))))
  3883. {
  3884. psurf_lcl->lpSurfMore->rgjunc = (VOID *) g_rgjunc565;
  3885. }
  3886. else
  3887. {
  3888. // No junction table support for other FOURCCs
  3889. psurf_lcl->lpSurfMore->rgjunc = (VOID *) NULL;
  3890. }
  3891. break;
  3892. default:
  3893. // No table? Must be something weird like 1, 2, or 4 bits
  3894. psurf_lcl->lpSurfMore->rgjunc = (VOID *) NULL;
  3895. break;
  3896. }
  3897. /*
  3898. * first surface in flippable chain gets a back buffer count
  3899. */
  3900. if( (scnt == 0) && (caps & DDSCAPS_FLIP) )
  3901. {
  3902. psurf_lcl->dwBackBufferCount = lpDDSurfaceDesc->dwBackBufferCount;
  3903. }
  3904. else
  3905. {
  3906. psurf_lcl->dwBackBufferCount = 0;
  3907. }
  3908. /*
  3909. * Each surface in the mip-map chain gets the number of levels
  3910. * in the map (including this level).
  3911. */
  3912. if( caps & DDSCAPS_MIPMAP )
  3913. {
  3914. if( is_mipmap )
  3915. {
  3916. /*
  3917. * Part of complex mip-map chain.
  3918. * If it's a cube map, then its mip level is how far we are into the list
  3919. * away from the last top-level face. Top level faces are every bbcnt+1.
  3920. */
  3921. if (is_cubemap)
  3922. {
  3923. psurf_lcl->lpSurfMore->dwMipMapCount = ((nsurf - scnt -1) % (bbcnt+1) ) + 1;
  3924. }
  3925. else
  3926. {
  3927. psurf_lcl->lpSurfMore->dwMipMapCount = (nsurf - scnt);
  3928. }
  3929. /*
  3930. * Set sublevel cap for any non-top-level (if we are not at a (bbcnt+1)th level)
  3931. */
  3932. psurf_lcl->lpSurfMore->ddsCapsEx.dwCaps2 &= ~DDSCAPS2_MIPMAPSUBLEVEL;
  3933. if ( scnt%(bbcnt+1) )
  3934. psurf_lcl->lpSurfMore->ddsCapsEx.dwCaps2 |= DDSCAPS2_MIPMAPSUBLEVEL;
  3935. DPF( 5, "Assigning mip-map level %d to mip-map %d", psurf_lcl->lpSurfMore->dwMipMapCount, scnt );
  3936. }
  3937. else
  3938. {
  3939. /*
  3940. * Single level map - not part of a chain.
  3941. */
  3942. DPF( 5, "Assign mip-map level of 1 to single level mip-map" );
  3943. psurf_lcl->lpSurfMore->dwMipMapCount = 1UL;
  3944. }
  3945. }
  3946. /*
  3947. * assign pixel format...
  3948. */
  3949. if( is_curr_diff )
  3950. {
  3951. /*
  3952. * Execute buffers should NEVER have a pixel format.
  3953. */
  3954. DDASSERT( !( caps & DDSCAPS_EXECUTEBUFFER ) );
  3955. psurf->ddpfSurface=*pddpf;
  3956. if( understood_pf )
  3957. {
  3958. DPF( 5, "pitch=%ld, bpp = %d, (%hu,%hu)", psurf->lPitch,
  3959. (UINT) psurf->ddpfSurface.dwRGBBitCount,
  3960. psurf->wWidth, psurf->wHeight );
  3961. }
  3962. }
  3963. else
  3964. {
  3965. if( !( caps & DDSCAPS_EXECUTEBUFFER ) )
  3966. {
  3967. /*
  3968. * Somewhat misleading message for an execute buffer.
  3969. */
  3970. DPF( 5, "pitch=%ld, WAS THE SAME PIXEL FORMAT AS PRIMARY", psurf->lPitch );
  3971. }
  3972. }
  3973. /*
  3974. * FINALLY: set up attached surfaces: back buffers + alpha + Z
  3975. *
  3976. * NOTE: Z & alpha get attached to the back buffer
  3977. */
  3978. if( nsurf > 1 )
  3979. {
  3980. #ifdef USE_ALPHA
  3981. if( do_zbuffer && do_abuffer && (scnt == nsurf-1) )
  3982. {
  3983. DPF( 5, "linking alpha buffer to back buffer" );
  3984. AddAttachedSurface( slist_lcl[bbuffoff], psurf_lcl, TRUE );
  3985. }
  3986. else if( do_zbuffer && do_abuffer && (scnt == nsurf-2) )
  3987. {
  3988. DPF( 5, "linking Z buffer to back buffer" );
  3989. AddAttachedSurface( slist_lcl[bbuffoff], psurf_lcl, TRUE );
  3990. }
  3991. else if( do_abuffer && (scnt == nsurf-1) )
  3992. {
  3993. DPF( 5, "linking alpha buffer to back buffer" );
  3994. AddAttachedSurface( slist_lcl[bbuffoff], psurf_lcl, TRUE );
  3995. }
  3996. else
  3997. #endif
  3998. if( do_zbuffer && (scnt == nsurf-1) )//DX7Stereo: adjust this for stereo
  3999. {
  4000. DPF( 5, "linking Z buffer to back buffer" );
  4001. AddAttachedSurface( slist_int[bbuffoff], psurf_int, TRUE );
  4002. }
  4003. // DX7Stereo: for stereo, exclude this case and handle it later
  4004. else if(!is_stereo && (is_flip && ((scnt == nsurf-1) ||
  4005. #ifndef USE_ALPHA
  4006. (do_zbuffer && do_abuffer && (scnt == nsurf-3)) ||
  4007. (do_abuffer && (scnt == nsurf-2)) ||
  4008. #endif
  4009. (do_zbuffer && (scnt == nsurf-2)))) )
  4010. {
  4011. /*
  4012. * NOTE: For mip-maps we don't chain the last surface back
  4013. * to the first.
  4014. */
  4015. DPF( 5, "linking buffer %d to buffer %d", scnt-1, scnt );
  4016. AddAttachedSurface( slist_int[scnt-1], psurf_int, TRUE );
  4017. /*
  4018. * link last surface to front buffer
  4019. */
  4020. DPF( 5, "linking last buffer (%d) to front buffer", scnt );
  4021. AddAttachedSurface( slist_int[scnt], slist_int[0], TRUE );
  4022. }
  4023. else if( is_cubemap)
  4024. {
  4025. /*
  4026. * Every (bbcnt+1)th surface needs to be linked to the very first
  4027. * Otherwise, it's a mip level that needs linking to its parent
  4028. */
  4029. if ( scnt>0 )
  4030. {
  4031. if ( (scnt % (bbcnt+1)) == 0 )
  4032. {
  4033. DPF( 5, "linking cubemap surface #%d to root", scnt );
  4034. AddAttachedSurface( slist_int[0], psurf_int, TRUE );
  4035. }
  4036. else
  4037. {
  4038. DPF( 5, "linking cubemap mip surface #%d to buffer #%d", scnt-1, scnt );
  4039. AddAttachedSurface( slist_int[scnt-1], psurf_int, TRUE );
  4040. }
  4041. }
  4042. }
  4043. else if( ( is_flip || is_mipmap ) && (scnt > 0) )
  4044. {
  4045. if (!is_stereo) // DX7Stereo
  4046. {
  4047. DPF( 5, "linking buffer %d to buffer %d", scnt-1, scnt );
  4048. AddAttachedSurface( slist_int[scnt-1], psurf_int, TRUE );
  4049. } else
  4050. {
  4051. if (scnt & 1)
  4052. {
  4053. DPF( 5, "linking left buffer %d to buffer %d", scnt-1, scnt );
  4054. AddAttachedSurface( slist_int[scnt-1], psurf_int, TRUE );
  4055. } else
  4056. {
  4057. DPF( 5, "linking back buffer %d to buffer %d", scnt-2, scnt );
  4058. AddAttachedSurface( slist_int[scnt-2], psurf_int, TRUE );
  4059. }
  4060. if (scnt==nsurf-1)
  4061. {
  4062. DPF( 5, "linking last back buffer %d to primary buffer", scnt-1);
  4063. AddAttachedSurface( slist_int[scnt-1], slist_int[0], TRUE );
  4064. }
  4065. }
  4066. }
  4067. DPF( 4, "after addattached" );
  4068. }
  4069. } //end for(surfaces)
  4070. DPF( 4, "**************************" );
  4071. if ((caps &
  4072. (DDSCAPS_TEXTURE |
  4073. DDSCAPS_EXECUTEBUFFER |
  4074. DDSCAPS_3DDEVICE |
  4075. DDSCAPS_ZBUFFER)) &&
  4076. !(DX8Flags & DX8SFLAG_IMAGESURF)
  4077. )
  4078. {
  4079. int i;
  4080. for (i=0; i < nsurf; i++)
  4081. {
  4082. slist_lcl[i]->lpSurfMore->dwSurfaceHandle=
  4083. GetSurfaceHandle(&SURFACEHANDLELIST(this_lcl),slist_lcl[i]);
  4084. //DPF(0,"Got slist_lcl[0]->lpSurfMore->dwSurfaceHandle=%08lx",slist_lcl[0]->lpSurfMore->dwSurfaceHandle);
  4085. }
  4086. }
  4087. /*
  4088. * OK, now create the physical surface(s)
  4089. *
  4090. * First, see if the driver wants to do it.
  4091. */
  4092. if( cshalfn != NULL )
  4093. {
  4094. DPF(4,"Calling driver to see if it wants to say something about create surface");
  4095. csd.CreateSurface = cshalfn;
  4096. csd.lpDD = this;
  4097. csd.lpDDSurfaceDesc = (LPDDSURFACEDESC)lpDDSurfaceDesc;
  4098. csd.lplpSList = slist_lcl;
  4099. csd.dwSCnt = nsurf;
  4100. //
  4101. // record the creation stuff for dx7 drivers so we can do an atomic restore
  4102. // with exactly the same parameters
  4103. //
  4104. if (NULL != this->lpDDCBtmp->HALDDMiscellaneous2.CreateSurfaceEx &&
  4105. (nsurf > 1))
  4106. {
  4107. DDASSERT(slist_lcl[0]->lpSurfMore->cSurfaces == 0);
  4108. DDASSERT(slist_lcl[0]->lpSurfMore->pCreatedDDSurfaceDesc2 == 0);
  4109. DDASSERT(slist_lcl[0]->lpSurfMore->slist == 0);
  4110. slist_lcl[0]->lpSurfMore->slist = MemAlloc( sizeof(slist_lcl[0]) * nsurf );
  4111. if( slist_lcl[0]->lpSurfMore->slist )
  4112. {
  4113. slist_lcl[0]->lpSurfMore->cSurfaces = nsurf;
  4114. memcpy(slist_lcl[0]->lpSurfMore->slist , slist_lcl, sizeof(slist_lcl[0]) * nsurf );
  4115. //
  4116. // we don't need to waste all this goo on mipmaps
  4117. //
  4118. if ((0 == (slist_lcl[0]->ddsCaps.dwCaps & DDSCAPS_MIPMAP)) ||
  4119. (slist_lcl[0]->lpSurfMore->ddsCapsEx.dwCaps2 & DDSCAPS2_CUBEMAP) )
  4120. {
  4121. slist_lcl[0]->lpSurfMore->pCreatedDDSurfaceDesc2 = MemAlloc(sizeof(*lpDDSurfaceDesc));
  4122. if ( slist_lcl[0]->lpSurfMore->pCreatedDDSurfaceDesc2 )
  4123. {
  4124. memcpy(slist_lcl[0]->lpSurfMore->pCreatedDDSurfaceDesc2, lpDDSurfaceDesc, sizeof(*lpDDSurfaceDesc) );
  4125. }
  4126. else
  4127. {
  4128. MemFree(slist_lcl[0]->lpSurfMore->slist);
  4129. slist_lcl[0]->lpSurfMore->slist=0;
  4130. }
  4131. }
  4132. }
  4133. }
  4134. /*
  4135. * NOTE: Different HAL entry points for execute buffers and
  4136. * conventional surfaces.
  4137. */
  4138. if( caps & DDSCAPS_EXECUTEBUFFER )
  4139. {
  4140. DOHALCALL( CreateExecuteBuffer, csfn, csd, rc, emulation );\
  4141. }
  4142. else
  4143. {
  4144. #ifdef WIN95
  4145. /* Copy the VXD handle from the per process local structure to global.
  4146. * This handle will be used by DDHAL32_VidMemAlloc(), rather than creating
  4147. * a new one using GetDXVxdHandle(). The assumptions here are:
  4148. * 1) Only one process can enter createSurface(), 2) Deferred calls to
  4149. * DDHAL32_VidMemAlloc() will result in the slow path, ie getting
  4150. * the VXD handle using GetDXVxdHandle().
  4151. * (snene 2/23/98)
  4152. */
  4153. this->hDDVxd = this_lcl->hDDVxd;
  4154. #endif /* WIN95 */
  4155. DOHALCALL( CreateSurface, csfn, csd, rc, emulation );
  4156. #ifdef WIN95
  4157. /* Restore the handle to INVALID_HANDLE_VALUE so that non-createSurface()
  4158. * calls using DDHAL32_VidMemAlloc() or deferred calls (possibly from other
  4159. * processes) will correctly recreate the handle using GetDXVxdHandle().
  4160. * (snene 2/23/98)
  4161. */
  4162. this->hDDVxd = (DWORD)INVALID_HANDLE_VALUE;
  4163. #endif /* WIN95 */
  4164. }
  4165. if( rc == DDHAL_DRIVER_HANDLED )
  4166. {
  4167. if( csd.ddRVal != DD_OK )
  4168. {
  4169. int i;
  4170. #ifdef DEBUG
  4171. if( emulation )
  4172. {
  4173. DPF( 1, "Emulation won't let surface be created, rc=%08lx (%ld)",
  4174. csd.ddRVal, LOWORD( csd.ddRVal ) );
  4175. }
  4176. else
  4177. {
  4178. DPF( 1, "Driver won't let surface be created, rc=%08lx (%ld)",
  4179. csd.ddRVal, LOWORD( csd.ddRVal ) );
  4180. }
  4181. #endif
  4182. for (i=0; i < nsurf; i++)
  4183. {
  4184. if (slist_lcl[i]->lpSurfMore->dwSurfaceHandle)
  4185. ReleaseSurfaceHandle(&SURFACEHANDLELIST(this_lcl),
  4186. slist_lcl[i]->lpSurfMore->dwSurfaceHandle);
  4187. }
  4188. if (slist_lcl[0]->lpSurfMore->slist)
  4189. {
  4190. MemFree(slist_lcl[0]->lpSurfMore->slist);
  4191. }
  4192. if (slist_lcl[0]->lpSurfMore->pCreatedDDSurfaceDesc2)
  4193. {
  4194. MemFree(slist_lcl[0]->lpSurfMore->pCreatedDDSurfaceDesc2);
  4195. }
  4196. freeSurfaceList( slist_int, nsurf );
  4197. //
  4198. // If this routine returns either of these error values, then the calling routine
  4199. // (createandlinksurfaces) will assume that something was wrong with the ddsurfacedesc
  4200. // and return the error code to the app. This messes up the case where the app didn't
  4201. // specify a memory type (sys/vid), since if the driver returns one of these codes on
  4202. // the vidmem attempt, we will bail to the app and not try the sysmem attempt.
  4203. //
  4204. if ((csd.ddRVal == DDERR_INVALIDPARAMS || csd.ddRVal == DDERR_INVALIDCAPS) &&
  4205. (caps & DDSCAPS_VIDEOMEMORY) )
  4206. {
  4207. csd.ddRVal = DDERR_INVALIDPIXELFORMAT;
  4208. DPF( 2, "Mutating driver's DDERR_INVALIDPARAMS/INVALIDCAPS into DDERR_INVALIDPIXELFORMAT!");
  4209. }
  4210. return csd.ddRVal;
  4211. }
  4212. }
  4213. }
  4214. #if 0 //Old code
  4215. if ( (slist_lcl[0]->ddsCaps.dwCaps & DDSCAPS_OPTIMIZED)!= 0)
  4216. {
  4217. for( scnt=0;scnt<nsurf;scnt++ )
  4218. {
  4219. /*
  4220. * Optimized surfaces get neither memory nor aliases at creation time.
  4221. * (In fact they'll never be aliased because they can't be locked.)
  4222. */
  4223. /*
  4224. * Optimized surfaces are born free!
  4225. */
  4226. if (slist_lcl[scnt]->ddsCaps.dwCaps & DDSCAPS_SYSTEMMEMORY)
  4227. {
  4228. //HEL should have done this
  4229. DDASSERT(slist_lcl[scnt]->lpGbl->dwGlobalFlags & DDRAWISURFGBL_MEMFREE);
  4230. }
  4231. slist_lcl[scnt]->lpGbl->dwGlobalFlags |= DDRAWISURFGBL_MEMFREE;
  4232. }
  4233. }
  4234. else //else not optimized surface
  4235. {
  4236. #endif //0
  4237. /*
  4238. * now, allocate any unallocated surfaces
  4239. */
  4240. ddrval = AllocSurfaceMem( this_lcl, slist_lcl, nsurf );
  4241. if( ddrval != DD_OK )
  4242. {
  4243. int i;
  4244. for (i=0; i < nsurf; i++)
  4245. {
  4246. if (slist_lcl[i]->lpSurfMore->dwSurfaceHandle)
  4247. ReleaseSurfaceHandle(&SURFACEHANDLELIST(this_lcl),
  4248. slist_lcl[i]->lpSurfMore->dwSurfaceHandle);
  4249. }
  4250. if (slist_lcl[0]->lpSurfMore->slist)
  4251. {
  4252. MemFree(slist_lcl[0]->lpSurfMore->slist);
  4253. }
  4254. if (slist_lcl[0]->lpSurfMore->pCreatedDDSurfaceDesc2)
  4255. {
  4256. MemFree(slist_lcl[0]->lpSurfMore->pCreatedDDSurfaceDesc2);
  4257. }
  4258. freeSurfaceList( slist_int, nsurf );
  4259. return ddrval;
  4260. }
  4261. #ifdef USE_ALIAS
  4262. /*
  4263. * If this device has heap aliases then precompute the pointer
  4264. * alias for the video memory returned at creation time. This
  4265. * is by far the most likely pointer we are going to be handing
  4266. * out at lock time so we are going to make lock a lot faster
  4267. * by precomputing this then at lock time all we need to do is
  4268. * compare the pointer we got from the driver with fpVidMem. If
  4269. * they are equal then we can just return this cached pointer.
  4270. */
  4271. for( scnt=0;scnt<nsurf;scnt++ )
  4272. {
  4273. LPDDRAWI_DDRAWSURFACE_GBL_MORE lpGblMore;
  4274. lpGblMore = GET_LPDDRAWSURFACE_GBL_MORE( slist_lcl[scnt]->lpGbl );
  4275. if( slist_lcl[scnt]->ddsCaps.dwCaps & DDSCAPS_VIDEOMEMORY )
  4276. {
  4277. lpGblMore->fpAliasedVidMem = GetAliasedVidMem( this_lcl, slist_lcl[scnt],
  4278. slist_lcl[scnt]->lpGbl->fpVidMem );
  4279. // If we succeeded in getting an alias, cache it for future use. Also store the original
  4280. // fpVidMem to compare with before using the cached pointer to make sure the cached value
  4281. // is still valid
  4282. if (lpGblMore->fpAliasedVidMem)
  4283. lpGblMore->fpAliasOfVidMem = slist_lcl[scnt]->lpGbl->fpVidMem;
  4284. else
  4285. lpGblMore->fpAliasOfVidMem = 0;
  4286. }
  4287. else
  4288. {
  4289. lpGblMore->fpAliasedVidMem = 0UL;
  4290. lpGblMore->fpAliasOfVidMem = 0UL;
  4291. }
  4292. }
  4293. #endif /* USE_ALIAS */
  4294. #if 0 //Old code
  4295. } //if optimized surface
  4296. #endif //0
  4297. /*
  4298. * remember the primary surface...
  4299. */
  4300. if( lpDDSurfaceDesc->ddsCaps.dwCaps & DDSCAPS_PRIMARYSURFACE )
  4301. {
  4302. this_lcl->lpPrimary = slist_int[0];
  4303. }
  4304. #ifdef SHAREDZ
  4305. /*
  4306. * remember the shared back and z-buffers (if any).
  4307. */
  4308. if( lpDDSurfaceDesc->ddsCaps.dwCaps & DDSCAPS_SHAREDZBUFFER )
  4309. {
  4310. this_lcl->lpSharedZ = slist_int[zbuffoff];
  4311. /*
  4312. * It is possible that the an existing shared z-buffer we found
  4313. * was lost. If it was then the creation process we went through
  4314. * above has rendered it "found" so clear the lost surface flags.
  4315. */
  4316. this_lcl->lpSharedZ->lpGbl->dwGlobalFlags &= ~DDRAWISURFGBL_MEMFREE;
  4317. }
  4318. if( lpDDSurfaceDesc->ddsCaps.dwCaps & DDSCAPS_SHAREDBACKBUFFER )
  4319. {
  4320. this_lcl->lpSharedBack = slist_int[bbuffoff];
  4321. /*
  4322. * It is possible that the an existing shared back-buffer we found
  4323. * was lost. If it was then the creation process we went through
  4324. * above has rendered it "found" so clear the lost surface flags.
  4325. */
  4326. this_lcl->lpSharedBack->lpGbl->dwGlobalFlags &= ~DDRAWISURFGBL_MEMFREE;
  4327. }
  4328. #endif
  4329. if (
  4330. #ifdef WINNT
  4331. // on NT side, we still call CreateSurfaceEx if HW driver isn't called
  4332. emulation && slist_lcl[0]->hDDSurface &&
  4333. #endif //WINNT
  4334. !(DX8Flags & DX8SFLAG_ISLOST)
  4335. )
  4336. {
  4337. DDASSERT(this_lcl == slist_lcl[0]->lpSurfMore->lpDD_lcl);
  4338. return createsurfaceEx(slist_lcl[0]);
  4339. }
  4340. return DD_OK;
  4341. } /* createSurface */
  4342. /*
  4343. * createAndLinkSurfaces
  4344. *
  4345. * Really create the surface. Also used by EnumSurfaces
  4346. * Assumes the lock on the driver object has been taken.
  4347. */
  4348. HRESULT createAndLinkSurfaces(
  4349. LPDDRAWI_DIRECTDRAW_LCL this_lcl,
  4350. LPDDSURFACEDESC2 lpDDSurfaceDesc,
  4351. BOOL emulation,
  4352. LPDIRECTDRAWSURFACE FAR *lplpDDSurface,
  4353. BOOL real_sysmem,
  4354. BOOL probe_driver,
  4355. LPDDRAWI_DIRECTDRAW_INT this_int,
  4356. LPDDSURFACEINFO pSysMemInfo,
  4357. DWORD DX8Flags)
  4358. {
  4359. LPDDRAWI_DDRAWSURFACE_INT curr_int;
  4360. LPDDRAWI_DDRAWSURFACE_LCL curr_lcl;
  4361. LPDDRAWI_DDRAWSURFACE_GBL curr;
  4362. HRESULT ddrval;
  4363. CSINFO csinfo;
  4364. LPDDRAWI_DDRAWSURFACE_INT fix_slist_int[FIX_SLIST_CNT];
  4365. LPDDRAWI_DDRAWSURFACE_LCL fix_slist_lcl[FIX_SLIST_CNT];
  4366. LPDDRAWI_DDRAWSURFACE_GBL fix_slist[FIX_SLIST_CNT];
  4367. int i;
  4368. LPDDRAWI_DIRECTDRAW_GBL this;
  4369. this = this_lcl->lpGbl;
  4370. /*
  4371. * try to create the surface
  4372. */
  4373. csinfo.needlink = FALSE;
  4374. csinfo.slist_int = fix_slist_int;
  4375. csinfo.slist_lcl = fix_slist_lcl;
  4376. csinfo.slist = fix_slist;
  4377. csinfo.listsize = FIX_SLIST_CNT;
  4378. ddrval = createSurface( this_lcl, lpDDSurfaceDesc, &csinfo, emulation, real_sysmem, probe_driver, this_int, pSysMemInfo, DX8Flags );
  4379. /*
  4380. * if it worked, update the structures
  4381. */
  4382. if( ddrval == DD_OK )
  4383. {
  4384. /*
  4385. * link surface(s) into chain, increment refcnt
  4386. */
  4387. for( i=0;i<csinfo.listcnt; i++ )
  4388. {
  4389. curr_int = csinfo.slist_int[i];
  4390. curr_lcl = csinfo.slist_lcl[i];
  4391. curr = curr_lcl->lpGbl;
  4392. if( real_sysmem )
  4393. {
  4394. curr->dwGlobalFlags |= DDRAWISURFGBL_SYSMEMREQUESTED;
  4395. }
  4396. if( csinfo.needlink )
  4397. {
  4398. if( curr_lcl->ddsCaps.dwCaps & DDSCAPS_OVERLAY )
  4399. {
  4400. // This surface is an overlay. Insert it into the overlay
  4401. // Z order list. By inserting this node into the head of
  4402. // the list, it is the highest priority overlay,
  4403. // obscuring all others.
  4404. // The Z order list is implemented as a doubly linked list.
  4405. // The node for each surface exists in its
  4406. // DDRAWI_DDRAWSURFACE_GBL structure. The root node
  4407. // exists in the direct draw object. The next pointer of
  4408. // the root node points to the top-most overlay. The prev
  4409. // pointer points to the bottom-most overlay. The list
  4410. // may be traversed from back to front by following the
  4411. // prev pointers. It may be traversed from front to back
  4412. // by following the next pointers.
  4413. curr_lcl->dbnOverlayNode.next =
  4414. this->dbnOverlayRoot.next;
  4415. curr_lcl->dbnOverlayNode.prev =
  4416. (LPVOID)(&(this->dbnOverlayRoot));
  4417. this->dbnOverlayRoot.next =
  4418. (LPVOID)(&(curr_lcl->dbnOverlayNode));
  4419. curr_lcl->dbnOverlayNode.next->prev =
  4420. (LPVOID)(&(curr_lcl->dbnOverlayNode));
  4421. curr_lcl->dbnOverlayNode.object_int = curr_int;
  4422. curr_lcl->dbnOverlayNode.object = curr_lcl;
  4423. }
  4424. /*
  4425. * link into list of all surfaces
  4426. */
  4427. if (!(DX8Flags & DX8SFLAG_DX8) ||
  4428. (curr_lcl->dwFlags & DDRAWISURF_PARTOFPRIMARYCHAIN))
  4429. {
  4430. curr_int->lpLink = this->dsList;
  4431. this->dsList = curr_int;
  4432. }
  4433. }
  4434. DD_Surface_AddRef( (LPDIRECTDRAWSURFACE) curr_int );
  4435. }
  4436. *lplpDDSurface = (LPDIRECTDRAWSURFACE) csinfo.slist_int[0];
  4437. }
  4438. /*
  4439. * free allocated list if needed
  4440. */
  4441. if( csinfo.listsize > FIX_SLIST_CNT )
  4442. {
  4443. MemFree( csinfo.slist_int );
  4444. MemFree( csinfo.slist_lcl );
  4445. MemFree( csinfo.slist );
  4446. }
  4447. return ddrval;
  4448. } /* createAndLinkSurfaces */
  4449. /*
  4450. * InternalCreateSurface
  4451. *
  4452. * Create the surface.
  4453. * This is the internal way of doing this; used by EnumSurfaces.
  4454. * Assumes the directdraw lock has been taken.
  4455. */
  4456. HRESULT InternalCreateSurface(
  4457. LPDDRAWI_DIRECTDRAW_LCL this_lcl,
  4458. LPDDSURFACEDESC2 lpDDSurfaceDesc,
  4459. LPDIRECTDRAWSURFACE FAR *lplpDDSurface,
  4460. LPDDRAWI_DIRECTDRAW_INT this_int,
  4461. LPDDSURFACEINFO pSysMemInfo,
  4462. DWORD DX8Flags)
  4463. {
  4464. DDSCAPS2 caps;
  4465. HRESULT ddrval;
  4466. LPDDRAWI_DIRECTDRAW_GBL this;
  4467. this = this_lcl->lpGbl;
  4468. /*
  4469. * valid memory caps?
  4470. */
  4471. caps = lpDDSurfaceDesc->ddsCaps;
  4472. if( (caps.dwCaps & DDSCAPS_SYSTEMMEMORY) && (caps.dwCaps & DDSCAPS_VIDEOMEMORY) )
  4473. {
  4474. DPF_ERR( "Can't specify SYSTEMMEMORY and VIDEOMEMORY" );
  4475. return DDERR_INVALIDCAPS;
  4476. }
  4477. if (LOWERTHANDDRAW4(this_int))
  4478. {
  4479. lpDDSurfaceDesc->dwFlags &= ~(DDSD_PITCH | DDSD_LINEARSIZE); // clear DDSD_LPSURFACE too?
  4480. }
  4481. // Has the client already allocated the surface memory?
  4482. if( lpDDSurfaceDesc->dwFlags & DDSD_LPSURFACE )
  4483. {
  4484. LPDDPIXELFORMAT pddpf;
  4485. /*
  4486. * The client has allocated the memory for this surface. This is
  4487. * legal only if the surface's storage is explicitly specified to
  4488. * be in system memory.
  4489. */
  4490. if( !(caps.dwCaps & DDSCAPS_SYSTEMMEMORY) )
  4491. {
  4492. DPF_ERR( "DDSD_LPSURFACE flag valid only with DDSCAPS_SYSTEMMEMORY flag" );
  4493. return DDERR_INVALIDCAPS;
  4494. }
  4495. if( !VALIDEX_PTR(lpDDSurfaceDesc->lpSurface,sizeof(DWORD)) )
  4496. {
  4497. DPF_ERR( "DDSD_LPSURFACE flag requires valid lpSurface ptr" );
  4498. return DDERR_INVALIDPARAMS;
  4499. }
  4500. if( caps.dwCaps & DDSCAPS_OPTIMIZED ) // what about DDSCAPS_ALLOCONLOAD?
  4501. {
  4502. DPF_ERR( "DDSD_LPSURFACE flag illegal with optimized surface" );
  4503. return DDERR_INVALIDCAPS;
  4504. }
  4505. if( caps.dwCaps & DDSCAPS_COMPLEX )
  4506. {
  4507. DPF_ERR( "DDSD_LPSURFACE flag illegal with complex surface" );
  4508. return DDERR_INVALIDCAPS;
  4509. }
  4510. if( caps.dwCaps & DDSCAPS_EXECUTEBUFFER )
  4511. {
  4512. DPF_ERR( "DDSD_LPSURFACE flag illegal with execute-buffer surface" );
  4513. return DDERR_INVALIDCAPS;
  4514. }
  4515. if( caps.dwCaps & (DDSCAPS_PRIMARYSURFACE | DDSCAPS_PRIMARYSURFACELEFT | DDSCAPS_OVERLAY) )
  4516. {
  4517. DPF_ERR( "DDSD_LPSURFACE flag illegal with primary surface or overlay surface" );
  4518. return DDERR_INVALIDCAPS;
  4519. }
  4520. if( caps.dwCaps & DDSCAPS_VIDEOPORT )
  4521. {
  4522. DPF_ERR( "DDSD_LPSURFACE flag illegal with video-port surface" );
  4523. return DDERR_INVALIDCAPS;
  4524. }
  4525. if( ~lpDDSurfaceDesc->dwFlags & (DDSD_HEIGHT | DDSD_WIDTH) )
  4526. {
  4527. DPF_ERR( "DDSD_LPSURFACE flag requires valid height and width" );
  4528. return DDERR_INVALIDPARAMS;
  4529. }
  4530. if ((ULONG_PTR)lpDDSurfaceDesc->lpSurface & 3)
  4531. {
  4532. if (this_int->lpVtbl != &dd4Callbacks)
  4533. {
  4534. DPF_ERR( "Surface memory must be aligned to DWORD boundary" );
  4535. return DDERR_INVALIDPARAMS;
  4536. }
  4537. // Avoid regression error with DX6 IDD4 interface.
  4538. DPF(1, "Client-allocated surface memory is not DWORD-aligned" );
  4539. }
  4540. // Get a pointer to the pixel format for this surface.
  4541. if( lpDDSurfaceDesc->dwFlags & DDSD_PIXELFORMAT )
  4542. {
  4543. // The pixel format is specified in the DDSURFACEDESC2 structure.
  4544. pddpf = &lpDDSurfaceDesc->ddpfPixelFormat;
  4545. }
  4546. else
  4547. {
  4548. // The pixel format is the same as the primary surface's.
  4549. pddpf = &this->vmiData.ddpfDisplay;
  4550. }
  4551. // Validate specified pitch or linear size.
  4552. if (!(pddpf->dwFlags & DDPF_FOURCC))
  4553. {
  4554. long minpitch;
  4555. /*
  4556. * Verify that the pitch is an even multiple of 4 and that the pitch
  4557. * is large enough to accommodate the surface width.
  4558. */
  4559. if (!(lpDDSurfaceDesc->dwFlags & DDSD_PITCH))
  4560. {
  4561. DPF_ERR( "DDSD_LPSURFACE flag requires valid pitch" );
  4562. return DDERR_INVALIDPARAMS;
  4563. }
  4564. minpitch = (lpDDSurfaceDesc->dwWidth*pddpf->dwRGBBitCount + 7) >> 3;
  4565. if( lpDDSurfaceDesc->lPitch < minpitch || lpDDSurfaceDesc->lPitch & 3 )
  4566. {
  4567. DPF_ERR( "Bad value specified for surface pitch" );
  4568. return DDERR_INVALIDPARAMS;
  4569. }
  4570. }
  4571. else
  4572. {
  4573. DWORD blksize;
  4574. DWORD dx, dy;
  4575. /*
  4576. * The client allocated memory for a surface with a FOURCC format.
  4577. * The only FOURCC formats we support in system memory are the
  4578. * DXT formats.
  4579. */
  4580. blksize = GetDxtBlkSize(pddpf->dwFourCC); // returns 0 if not DXT
  4581. if (!blksize)
  4582. {
  4583. DPF_ERR( "Specified FOURCC format is not supported in system memory" );
  4584. return DDERR_UNSUPPORTED;
  4585. }
  4586. dx = (lpDDSurfaceDesc->dwWidth + 3) >> 2; // surface width in blocks
  4587. dy = (lpDDSurfaceDesc->dwHeight + 3) >> 2; // surface height in blocks
  4588. if (lpDDSurfaceDesc->dwFlags & DDSD_PITCH)
  4589. {
  4590. if (this_int->lpVtbl != &dd4Callbacks)
  4591. {
  4592. DPF_ERR( "DXT surface requires DDSD_LINEARSIZE, not DDSD_PITCH" );
  4593. return DDERR_INVALIDPARAMS;
  4594. }
  4595. // Avoid regression error with DX6 IDD4 interface.
  4596. DPF(1, "DXT surface requires DDSD_LINEARSIZE, not DDSD_PITCH" );
  4597. lpDDSurfaceDesc->dwFlags &= ~DDSD_PITCH;
  4598. lpDDSurfaceDesc->dwFlags |= DDSD_LINEARSIZE;
  4599. lpDDSurfaceDesc->dwLinearSize = dx*dy*blksize;
  4600. }
  4601. /*
  4602. * The surface does have a DXT format. Verify that the specified linear
  4603. * size is large enough to accommodate the specified width and height.
  4604. */
  4605. if (!(lpDDSurfaceDesc->dwFlags & DDSD_LINEARSIZE))
  4606. {
  4607. DPF_ERR( "DDSD_LPSURFACE flag requires valid linear size for DXT surface" );
  4608. return DDERR_INVALIDPARAMS;
  4609. }
  4610. if (lpDDSurfaceDesc->dwLinearSize < dx*dy*blksize)
  4611. {
  4612. DPF_ERR( "Bad value specified for linear size" );
  4613. return DDERR_INVALIDPARAMS;
  4614. }
  4615. }
  4616. }
  4617. else if (lpDDSurfaceDesc->dwFlags & (DDSD_PITCH | DDSD_LINEARSIZE))
  4618. {
  4619. // Avoid regression error with DX6 IDD4 interface.
  4620. DPF(1, "DDSD_PITCH and DDSD_LINEARSIZE flags ignored if DDSD_LPSURFACE=0" );
  4621. lpDDSurfaceDesc->dwFlags &= ~(DDSD_PITCH | DDSD_LINEARSIZE);
  4622. }
  4623. #if 0 // DDSCAPS2_LOCALALLOC, DDSCAPS2_COTASKMEM and DDRAWISURFGBL_DDFREESCLIENTMEM are gone
  4624. // Will DirectDraw be responsible for freeing client-allocated surface memory?
  4625. if( caps.dwCaps2 & (DDSCAPS2_LOCALALLOC | DDSCAPS2_COTASKMEM) )
  4626. {
  4627. if( !(lpDDSurfaceDesc->dwFlags & DDSD_LPSURFACE) )
  4628. {
  4629. DPF_ERR( "DDSCAPS2 flags LOCALALLOC and COTASKMEM require DDSD_LPSURFACE flag" );
  4630. return DDERR_INVALIDCAPS;
  4631. }
  4632. if( !(~caps.dwCaps2 & (DDSCAPS2_LOCALALLOC | DDSCAPS2_COTASKMEM)) )
  4633. {
  4634. DPF_ERR( "DDSCAPS2 flags LOCALALLOC and COTASKMEM are mutually exclusive" );
  4635. return DDERR_INVALIDCAPS;
  4636. }
  4637. }
  4638. #endif // 0
  4639. //
  4640. // Check persistent-content caps
  4641. //
  4642. if (caps.dwCaps2 & DDSCAPS2_PERSISTENTCONTENTS)
  4643. {
  4644. #ifdef WIN95
  4645. //
  4646. // Primary surface contents can only persist if exclusive mode.
  4647. //
  4648. if ((caps.dwCaps & DDSCAPS_PRIMARYSURFACE) &&
  4649. !(this_lcl->dwLocalFlags & DDRAWILCL_HASEXCLUSIVEMODE))
  4650. {
  4651. DPF_ERR("Non-exclusive primary surface contents cannot persist");
  4652. return DDERR_NOEXCLUSIVEMODE;
  4653. }
  4654. //
  4655. // DDSCAPS_OWNDC and DDSCAPS_VIDEOPORT imply volatile surfaces.
  4656. // Also, optimized surfaces are a special case which will be handled
  4657. // later by deferring memory allocation.
  4658. //
  4659. // ATTENTION: Optimized surfaces can only be Persistent ?
  4660. if ((caps.dwCaps & (DDSCAPS_OWNDC | DDSCAPS_VIDEOPORT | DDSCAPS_OPTIMIZED)))
  4661. {
  4662. DPF_ERR("Surface is volatile, contents cannot persist");
  4663. return DDERR_INVALIDCAPS;
  4664. }
  4665. //
  4666. // We don't have enough information to backup FourCC surface contents.
  4667. //
  4668. if (lpDDSurfaceDesc->dwFlags & DDSD_PIXELFORMAT)
  4669. {
  4670. if (lpDDSurfaceDesc->ddpfPixelFormat.dwFlags & DDPF_FOURCC)
  4671. {
  4672. DPF_ERR("FourCC video memory surface contents cannot persist");
  4673. return DDERR_INVALIDCAPS;
  4674. }
  4675. }
  4676. #else
  4677. DPF_ERR("Persistent content surfaces not implemented");
  4678. return DDERR_INVALIDCAPS;
  4679. #endif
  4680. }
  4681. /*
  4682. * If DDSCAPS_LOCALVIDMEM or DDSCAPS_NONLOCALVIDMEM are specified
  4683. * then DDSCAPS_VIDOEMEMORY must be explicity specified. Note, we
  4684. * can't dely this check until checkCaps() as by that time the heap
  4685. * scanning software may well have turned on DDSCAPS_VIDOEMEMORY.
  4686. */
  4687. if( ( caps.dwCaps & ( DDSCAPS_LOCALVIDMEM | DDSCAPS_NONLOCALVIDMEM ) ) &&
  4688. !( caps.dwCaps & DDSCAPS_VIDEOMEMORY ) )
  4689. {
  4690. DPF_ERR( "DDSCAPS_VIDEOMEMORY must be specified with DDSCAPS_LOCALVIDMEM or DDSCAPS_NONLOCALVIDMEM" );
  4691. return DDERR_INVALIDCAPS;
  4692. }
  4693. /*
  4694. * valid memory caps?
  4695. */
  4696. if( caps.dwCaps & DDSCAPS_OWNDC )
  4697. {
  4698. if( !( caps.dwCaps & DDSCAPS_SYSTEMMEMORY ) )
  4699. {
  4700. DPF_ERR( "OWNDC only support for explicit system memory surfaces" );
  4701. return DDERR_UNSUPPORTED;
  4702. }
  4703. }
  4704. /*
  4705. * managed texture?
  4706. */
  4707. if( caps.dwCaps2 & DDSCAPS2_D3DTEXTUREMANAGE )
  4708. {
  4709. if ( caps.dwCaps & (DDSCAPS_SYSTEMMEMORY | DDSCAPS_VIDEOMEMORY | DDSCAPS_NONLOCALVIDMEM | DDSCAPS_LOCALVIDMEM) )
  4710. {
  4711. DPF_ERR("Memory type can't be specified upon creation of managed surfaces ");
  4712. return DDERR_INVALIDCAPS;
  4713. }
  4714. if ( (caps.dwCaps2 & DDSCAPS2_DONOTPERSIST) && (caps.dwCaps & DDSCAPS_WRITEONLY) &&
  4715. (this_lcl->dwLocalFlags & DDRAWILCL_DIRECTDRAW7) && (this->ddCaps.dwCaps2 & DDCAPS2_NONLOCALVIDMEM) &&
  4716. !(this->dwFlags & DDRAWI_NOHARDWARE) &&
  4717. ((this->ddCaps.dwCaps2 & DDCAPS2_TEXMANINNONLOCALVIDMEM) || (dwRegFlags & DDRAW_REGFLAGS_USENONLOCALVIDMEM)) )
  4718. {
  4719. lpDDSurfaceDesc->ddsCaps.dwCaps &= ~DDSCAPS_WRITEONLY;
  4720. lpDDSurfaceDesc->ddsCaps.dwCaps2 &= ~DDSCAPS2_DONOTPERSIST;
  4721. lpDDSurfaceDesc->ddsCaps.dwCaps |= (DDSCAPS_VIDEOMEMORY | DDSCAPS_NONLOCALVIDMEM);
  4722. DPF(2, "Creating managed surface in non-local vidmem");
  4723. ddrval = createAndLinkSurfaces( this_lcl, lpDDSurfaceDesc, FALSE,
  4724. lplpDDSurface, FALSE, FALSE, this_int,
  4725. pSysMemInfo, DX8Flags);
  4726. lpDDSurfaceDesc->ddsCaps = caps;
  4727. if(ddrval == DDERR_OUTOFVIDEOMEMORY)
  4728. {
  4729. if( this->dwFlags & DDRAWI_NOEMULATION )
  4730. {
  4731. DPF_ERR( "No emulation support" );
  4732. return DDERR_NOEMULATION;
  4733. }
  4734. DPF(1, "Surface creation failed (out of memory). Now creating in system memory");
  4735. lpDDSurfaceDesc->ddsCaps.dwCaps &= ~DDSCAPS_WRITEONLY;
  4736. lpDDSurfaceDesc->ddsCaps.dwCaps2 &= ~DDSCAPS2_DONOTPERSIST;
  4737. lpDDSurfaceDesc->ddsCaps.dwCaps |= DDSCAPS_SYSTEMMEMORY;
  4738. ddrval = createAndLinkSurfaces( this_lcl, lpDDSurfaceDesc, TRUE,
  4739. lplpDDSurface, TRUE, FALSE, this_int,
  4740. pSysMemInfo, DX8Flags);
  4741. lpDDSurfaceDesc->ddsCaps = caps;
  4742. }
  4743. }
  4744. else
  4745. {
  4746. if( this->dwFlags & DDRAWI_NOEMULATION )
  4747. {
  4748. DPF_ERR( "No emulation support" );
  4749. return DDERR_NOEMULATION;
  4750. }
  4751. lpDDSurfaceDesc->ddsCaps.dwCaps &= ~DDSCAPS_WRITEONLY;
  4752. lpDDSurfaceDesc->ddsCaps.dwCaps2 &= ~DDSCAPS2_DONOTPERSIST;
  4753. lpDDSurfaceDesc->ddsCaps.dwCaps |= DDSCAPS_SYSTEMMEMORY;
  4754. ddrval = createAndLinkSurfaces( this_lcl, lpDDSurfaceDesc, TRUE,
  4755. lplpDDSurface, TRUE, FALSE, this_int,
  4756. pSysMemInfo, DX8Flags);
  4757. lpDDSurfaceDesc->ddsCaps = caps;
  4758. }
  4759. }
  4760. else if( (caps.dwCaps2 & DDSCAPS2_TEXTUREMANAGE) && !(this_lcl->dwLocalFlags & DDRAWILCL_DIRECTDRAW8) )
  4761. {
  4762. if ( caps.dwCaps & (DDSCAPS_SYSTEMMEMORY | DDSCAPS_VIDEOMEMORY | DDSCAPS_NONLOCALVIDMEM | DDSCAPS_LOCALVIDMEM) )
  4763. {
  4764. DPF_ERR("Memory type can't be specified upon creation of managed surfaces ");
  4765. return DDERR_INVALIDCAPS;
  4766. }
  4767. if( (this_lcl->lpGbl->ddCaps.dwCaps2 & DDCAPS2_CANMANAGETEXTURE)
  4768. && (this_lcl->dwLocalFlags & DDRAWILCL_DIRECTDRAW7) )
  4769. {
  4770. if( this->dwFlags & DDRAWI_NOHARDWARE )
  4771. {
  4772. DPF_ERR( "No hardware support" );
  4773. return DDERR_NODIRECTDRAWHW;
  4774. }
  4775. lpDDSurfaceDesc->ddsCaps.dwCaps |= DDSCAPS_VIDEOMEMORY;
  4776. ddrval = createAndLinkSurfaces( this_lcl, lpDDSurfaceDesc, FALSE,
  4777. lplpDDSurface, FALSE, FALSE, this_int,
  4778. pSysMemInfo, DX8Flags);
  4779. lpDDSurfaceDesc->ddsCaps = caps;
  4780. }
  4781. else
  4782. {
  4783. if ( (caps.dwCaps2 & DDSCAPS2_DONOTPERSIST) && (caps.dwCaps & DDSCAPS_WRITEONLY) &&
  4784. (this_lcl->dwLocalFlags & DDRAWILCL_DIRECTDRAW7) && (this->ddCaps.dwCaps2 & DDCAPS2_NONLOCALVIDMEM) &&
  4785. !(this->dwFlags & DDRAWI_NOHARDWARE) &&
  4786. ((this->ddCaps.dwCaps2 & DDCAPS2_TEXMANINNONLOCALVIDMEM) || (dwRegFlags & DDRAW_REGFLAGS_USENONLOCALVIDMEM)) )
  4787. {
  4788. lpDDSurfaceDesc->ddsCaps.dwCaps &= ~DDSCAPS_WRITEONLY;
  4789. lpDDSurfaceDesc->ddsCaps.dwCaps2 &= ~DDSCAPS2_DONOTPERSIST;
  4790. lpDDSurfaceDesc->ddsCaps.dwCaps |= (DDSCAPS_VIDEOMEMORY | DDSCAPS_NONLOCALVIDMEM);
  4791. DPF(2, "Creating managed surface in non-local vidmem");
  4792. ddrval = createAndLinkSurfaces( this_lcl, lpDDSurfaceDesc, FALSE,
  4793. lplpDDSurface, FALSE, FALSE, this_int,
  4794. pSysMemInfo, DX8Flags);
  4795. lpDDSurfaceDesc->ddsCaps = caps;
  4796. if(ddrval == DDERR_OUTOFVIDEOMEMORY)
  4797. {
  4798. if( this->dwFlags & DDRAWI_NOEMULATION )
  4799. {
  4800. DPF_ERR( "No emulation support" );
  4801. return DDERR_NOEMULATION;
  4802. }
  4803. DPF(2, "CreateSurface failed (out of memory). Now creating in system memory");
  4804. lpDDSurfaceDesc->ddsCaps.dwCaps &= ~DDSCAPS_WRITEONLY;
  4805. lpDDSurfaceDesc->ddsCaps.dwCaps2 &= ~DDSCAPS2_DONOTPERSIST;
  4806. lpDDSurfaceDesc->ddsCaps.dwCaps |= DDSCAPS_SYSTEMMEMORY;
  4807. ddrval = createAndLinkSurfaces( this_lcl, lpDDSurfaceDesc, TRUE,
  4808. lplpDDSurface, TRUE, FALSE, this_int,
  4809. pSysMemInfo, DX8Flags);
  4810. lpDDSurfaceDesc->ddsCaps = caps;
  4811. }
  4812. }
  4813. else
  4814. {
  4815. if( this->dwFlags & DDRAWI_NOEMULATION )
  4816. {
  4817. DPF_ERR( "No emulation support" );
  4818. return DDERR_NOEMULATION;
  4819. }
  4820. lpDDSurfaceDesc->ddsCaps.dwCaps &= ~DDSCAPS_WRITEONLY;
  4821. lpDDSurfaceDesc->ddsCaps.dwCaps2 &= ~DDSCAPS2_DONOTPERSIST;
  4822. lpDDSurfaceDesc->ddsCaps.dwCaps |= DDSCAPS_SYSTEMMEMORY;
  4823. ddrval = createAndLinkSurfaces( this_lcl, lpDDSurfaceDesc, TRUE,
  4824. lplpDDSurface, TRUE, FALSE, this_int,
  4825. pSysMemInfo, DX8Flags);
  4826. lpDDSurfaceDesc->ddsCaps = caps;
  4827. }
  4828. }
  4829. /*
  4830. * want in video memory only?
  4831. */
  4832. }
  4833. else if( caps.dwCaps & DDSCAPS_VIDEOMEMORY )
  4834. {
  4835. if( this->dwFlags & DDRAWI_NOHARDWARE )
  4836. {
  4837. DPF_ERR( "No hardware support" );
  4838. return DDERR_NODIRECTDRAWHW;
  4839. }
  4840. ddrval = createAndLinkSurfaces( this_lcl, lpDDSurfaceDesc, FALSE,
  4841. lplpDDSurface, FALSE, FALSE, this_int,
  4842. pSysMemInfo, DX8Flags);
  4843. /*
  4844. * want in system memory only?
  4845. */
  4846. }
  4847. else if( caps.dwCaps & DDSCAPS_SYSTEMMEMORY )
  4848. {
  4849. if( this->dwFlags & DDRAWI_NOEMULATION )
  4850. {
  4851. DPF_ERR( "No emulation support" );
  4852. return DDERR_NOEMULATION;
  4853. }
  4854. ddrval = createAndLinkSurfaces( this_lcl, lpDDSurfaceDesc, TRUE,
  4855. lplpDDSurface, TRUE, FALSE, this_int,
  4856. pSysMemInfo, DX8Flags);
  4857. /*
  4858. * don't care where it goes? Try video memory first...
  4859. */
  4860. }
  4861. else
  4862. {
  4863. if( !(this->dwFlags & DDRAWI_NOHARDWARE) )
  4864. {
  4865. lpDDSurfaceDesc->ddsCaps.dwCaps |= DDSCAPS_VIDEOMEMORY;
  4866. ddrval = createAndLinkSurfaces( this_lcl, lpDDSurfaceDesc, FALSE,
  4867. lplpDDSurface, FALSE, TRUE, this_int,
  4868. pSysMemInfo, DX8Flags);
  4869. lpDDSurfaceDesc->ddsCaps.dwCaps &= ~DDSCAPS_VIDEOMEMORY;
  4870. }
  4871. else
  4872. {
  4873. ddrval = DDERR_NOEMULATION;
  4874. }
  4875. if( ddrval != DD_OK && ddrval != DDERR_INVALIDCAPS &&
  4876. ddrval != DDERR_INVALIDPARAMS )
  4877. {
  4878. if( !(this->dwFlags & DDRAWI_NOEMULATION) &&
  4879. (this->dwFlags & DDRAWI_EMULATIONINITIALIZED) )
  4880. {
  4881. lpDDSurfaceDesc->ddsCaps.dwCaps |= DDSCAPS_SYSTEMMEMORY;
  4882. ddrval = createAndLinkSurfaces( this_lcl, lpDDSurfaceDesc, TRUE,
  4883. lplpDDSurface, FALSE, FALSE, this_int,
  4884. pSysMemInfo, DX8Flags);
  4885. lpDDSurfaceDesc->ddsCaps.dwCaps &= ~DDSCAPS_SYSTEMMEMORY;
  4886. }
  4887. else
  4888. {
  4889. DPF_ERR( "Couldn't allocate a surface at all" );
  4890. }
  4891. }
  4892. }
  4893. // any color keys specified?
  4894. if( (ddrval == DD_OK) &&
  4895. (lpDDSurfaceDesc->dwFlags & (DDSD_CKSRCOVERLAY|DDSD_CKDESTOVERLAY|
  4896. DDSD_CKSRCBLT|DDSD_CKDESTBLT) ) )
  4897. {
  4898. /*
  4899. * Attempt to set the specified color keys
  4900. */
  4901. if( lpDDSurfaceDesc->dwFlags & DDSD_CKSRCBLT )
  4902. ddrval = DD_Surface_SetColorKey((LPDIRECTDRAWSURFACE)*lplpDDSurface,
  4903. DDCKEY_SRCBLT, &(lpDDSurfaceDesc->ddckCKSrcBlt) );
  4904. if(ddrval == DD_OK)
  4905. {
  4906. if( lpDDSurfaceDesc->dwFlags & DDSD_CKDESTBLT )
  4907. ddrval = DD_Surface_SetColorKey((LPDIRECTDRAWSURFACE)*lplpDDSurface,
  4908. DDCKEY_DESTBLT, &(lpDDSurfaceDesc->ddckCKDestBlt) );
  4909. if(ddrval == DD_OK)
  4910. {
  4911. if( lpDDSurfaceDesc->dwFlags & DDSD_CKSRCOVERLAY )
  4912. ddrval = DD_Surface_SetColorKey((LPDIRECTDRAWSURFACE)*lplpDDSurface,
  4913. DDCKEY_SRCOVERLAY, &(lpDDSurfaceDesc->ddckCKSrcOverlay) );
  4914. if(ddrval == DD_OK)
  4915. {
  4916. if( lpDDSurfaceDesc->dwFlags & DDSD_CKDESTOVERLAY )
  4917. ddrval = DD_Surface_SetColorKey((LPDIRECTDRAWSURFACE)*lplpDDSurface,
  4918. DDCKEY_DESTOVERLAY, &(lpDDSurfaceDesc->ddckCKDestOverlay) );
  4919. }
  4920. }
  4921. }
  4922. if( ddrval != DD_OK )
  4923. {
  4924. DPF_ERR("Surface Creation failed because color key set failed.");
  4925. DD_Surface_Release((LPDIRECTDRAWSURFACE)*lplpDDSurface);
  4926. *lplpDDSurface = NULL;
  4927. }
  4928. }
  4929. #ifdef WIN95
  4930. //
  4931. // Allocate persistent-content surface memory, if specified
  4932. //
  4933. if (SUCCEEDED(ddrval) && (lpDDSurfaceDesc->ddsCaps.dwCaps2 & DDSCAPS2_PERSISTENTCONTENTS))
  4934. {
  4935. if (FAILED(AllocSurfaceContents(((LPDDRAWI_DDRAWSURFACE_INT) *lplpDDSurface)->lpLcl)))
  4936. {
  4937. DD_Surface_Release((LPDIRECTDRAWSURFACE) *lplpDDSurface);
  4938. *lplpDDSurface = NULL;
  4939. ddrval = DDERR_OUTOFMEMORY;
  4940. }
  4941. }
  4942. #endif
  4943. return ddrval;
  4944. } /* InternalCreateSurface */
  4945. void CopyDDSurfDescToDDSurfDesc2(DDSURFACEDESC2* ddsd2, DDSURFACEDESC* ddsd)
  4946. {
  4947. memcpy(ddsd2, ddsd, sizeof(*ddsd));
  4948. ddsd2->ddsCaps.dwCaps2 = 0;
  4949. ddsd2->ddsCaps.dwCaps3 = 0;
  4950. ddsd2->ddsCaps.dwCaps4 = 0;
  4951. ddsd2->dwTextureStage = 0;
  4952. }
  4953. HRESULT DDAPI DD_CreateSurface4_Main(LPDIRECTDRAW lpDD,LPDDSURFACEDESC2 lpDDSurfaceDesc,
  4954. LPDIRECTDRAWSURFACE FAR *lplpDDSurface,IUnknown FAR *pUnkOuter,BOOL bDoSurfaceDescCheck,
  4955. LPDDSURFACEINFO pSysMemInfo, DWORD DX8Flags);
  4956. /*
  4957. * DD_CreateSurface
  4958. *
  4959. * Create a surface.
  4960. * This is the method visible to the outside world.
  4961. */
  4962. #undef DPF_MODNAME
  4963. #define DPF_MODNAME "CreateSurface"
  4964. HRESULT DDAPI DD_CreateSurface(
  4965. LPDIRECTDRAW lpDD,
  4966. LPDDSURFACEDESC lpDDSurfaceDesc,
  4967. LPDIRECTDRAWSURFACE FAR *lplpDDSurface,
  4968. IUnknown FAR *pUnkOuter )
  4969. {
  4970. LPDDRAWI_DIRECTDRAW_INT this_int;
  4971. LPDDRAWI_DIRECTDRAW_LCL this_lcl;
  4972. LPDDRAWI_DIRECTDRAW_GBL this;
  4973. DDSURFACEDESC2 ddsd2;
  4974. HRESULT hr = DD_OK;
  4975. ENTER_DDRAW();
  4976. DPF(2,A,"ENTERAPI: DD_CreateSurface");
  4977. ZeroMemory(&ddsd2,sizeof(ddsd2));
  4978. TRY
  4979. {
  4980. this_int = (LPDDRAWI_DIRECTDRAW_INT) lpDD;
  4981. if( !VALID_DIRECTDRAW_PTR( this_int ) )
  4982. {
  4983. DPF_ERR( "Invalid driver object passed" );
  4984. DPF_APIRETURNS(DDERR_INVALIDOBJECT);
  4985. LEAVE_DDRAW();
  4986. return DDERR_INVALIDOBJECT;
  4987. }
  4988. this_lcl = this_int->lpLcl;
  4989. this = this_lcl->lpGbl;
  4990. /*
  4991. * verify that cooperative level is set
  4992. */
  4993. if( !(this_lcl->dwLocalFlags & DDRAWILCL_SETCOOPCALLED) )
  4994. {
  4995. DPF_ERR( "Must call SetCooperativeLevel before calling Create functions" );
  4996. LEAVE_DDRAW();
  4997. DPF_APIRETURNS(DDERR_NOCOOPERATIVELEVELSET);
  4998. return DDERR_NOCOOPERATIVELEVELSET;
  4999. }
  5000. if( !VALID_DDSURFACEDESC_PTR( lpDDSurfaceDesc ) )
  5001. {
  5002. DPF_ERR( "Invalid DDSURFACEDESC. Did you set the dwSize member?" );
  5003. DPF_APIRETURNS(DDERR_INVALIDPARAMS);
  5004. LEAVE_DDRAW();
  5005. return DDERR_INVALIDPARAMS;
  5006. }
  5007. if( (this->dwModeIndex == DDUNSUPPORTEDMODE)
  5008. #ifdef WINNT
  5009. && !(DDSCAPS_SYSTEMMEMORY & lpDDSurfaceDesc->ddsCaps.dwCaps)
  5010. #endif
  5011. )
  5012. {
  5013. DPF_ERR( "Driver is in an unsupported mode" );
  5014. LEAVE_DDRAW();
  5015. DPF_APIRETURNS(DDERR_UNSUPPORTEDMODE);
  5016. return DDERR_UNSUPPORTEDMODE;
  5017. }
  5018. CopyDDSurfDescToDDSurfDesc2(&ddsd2, lpDDSurfaceDesc);
  5019. }
  5020. EXCEPT( EXCEPTION_EXECUTE_HANDLER )
  5021. {
  5022. DPF_ERR( "Exception encountered validating parameters: Bad LPDDSURFACEDESC" );
  5023. DPF_APIRETURNS(DDERR_INVALIDPARAMS);
  5024. LEAVE_DDRAW();
  5025. return DDERR_INVALIDPARAMS;
  5026. }
  5027. // must leave dwSize intact so checkSurfaceDesc can distinguish DDSURFACEDESC from DDSURFACEDESC2,
  5028. // ddsd2.dwSize = sizeof(ddsd2);
  5029. hr = DD_CreateSurface4_Main(lpDD,&ddsd2,lplpDDSurface,pUnkOuter,FALSE, NULL, 0);
  5030. LEAVE_DDRAW();
  5031. return hr;
  5032. }
  5033. HRESULT DDAPI DD_CreateSurface4(
  5034. LPDIRECTDRAW lpDD,
  5035. LPDDSURFACEDESC2 lpDDSurfaceDesc,
  5036. LPDIRECTDRAWSURFACE FAR *lplpDDSurface,
  5037. IUnknown FAR *pUnkOuter ) {
  5038. DPF(2,A,"ENTERAPI: DD_CreateSurface4");
  5039. return DD_CreateSurface4_Main(lpDD,lpDDSurfaceDesc,lplpDDSurface,pUnkOuter,TRUE, NULL, 0);
  5040. }
  5041. HRESULT DDAPI DD_CreateSurface4_Main(
  5042. LPDIRECTDRAW lpDD,
  5043. LPDDSURFACEDESC2 lpDDSurfaceDesc,
  5044. LPDIRECTDRAWSURFACE FAR *lplpDDSurface,
  5045. IUnknown FAR *pUnkOuter,
  5046. BOOL bDoSurfaceDescCheck,
  5047. LPDDSURFACEINFO pSysMemInfo,
  5048. DWORD DX8Flags)
  5049. {
  5050. LPDDRAWI_DIRECTDRAW_INT this_int;
  5051. LPDDRAWI_DIRECTDRAW_LCL this_lcl;
  5052. LPDDRAWI_DIRECTDRAW_GBL this;
  5053. HRESULT ddrval;
  5054. if( pUnkOuter != NULL )
  5055. {
  5056. return CLASS_E_NOAGGREGATION;
  5057. }
  5058. ENTER_DDRAW();
  5059. DPF(2,A,"ENTERAPI: DD_CreateSurface4_Main");
  5060. /* DPF_ENTERAPI(lpDD); */
  5061. TRY
  5062. {
  5063. this_int = (LPDDRAWI_DIRECTDRAW_INT) lpDD;
  5064. if( !VALID_DIRECTDRAW_PTR( this_int ) )
  5065. {
  5066. DPF_ERR( "Invalid driver object passed" );
  5067. DPF_APIRETURNS(DDERR_INVALIDOBJECT);
  5068. LEAVE_DDRAW();
  5069. return DDERR_INVALIDOBJECT;
  5070. }
  5071. this_lcl = this_int->lpLcl;
  5072. this = this_lcl->lpGbl;
  5073. /*
  5074. * verify that cooperative level is set
  5075. */
  5076. if( !(this_lcl->dwLocalFlags & DDRAWILCL_SETCOOPCALLED) )
  5077. {
  5078. DPF_ERR( "Must call SetCooperativeLevel before calling Create functions" );
  5079. LEAVE_DDRAW();
  5080. DPF_APIRETURNS(DDERR_NOCOOPERATIVELEVELSET);
  5081. return DDERR_NOCOOPERATIVELEVELSET;
  5082. }
  5083. if( bDoSurfaceDescCheck && !VALID_DDSURFACEDESC2_PTR( lpDDSurfaceDesc ) )
  5084. {
  5085. DPF(0, "Invalid DDSURFACEDESC2. Did you set the dwSize member? (%d should be %d)", lpDDSurfaceDesc->dwSize, sizeof(DDSURFACEDESC2) );
  5086. LEAVE_DDRAW();
  5087. DPF_APIRETURNS(DDERR_INVALIDPARAMS);
  5088. return DDERR_INVALIDPARAMS;
  5089. }
  5090. if( (this->dwModeIndex == DDUNSUPPORTEDMODE)
  5091. #ifdef WINNT
  5092. && !(DDSCAPS_SYSTEMMEMORY & lpDDSurfaceDesc->ddsCaps.dwCaps)
  5093. #endif
  5094. )
  5095. {
  5096. DPF_ERR( "Driver is in an unsupported mode" );
  5097. LEAVE_DDRAW();
  5098. DPF_APIRETURNS(DDERR_UNSUPPORTEDMODE);
  5099. return DDERR_UNSUPPORTEDMODE;
  5100. }
  5101. *lplpDDSurface = NULL;
  5102. }
  5103. EXCEPT( EXCEPTION_EXECUTE_HANDLER )
  5104. {
  5105. DPF_ERR( "Exception encountered validating parameters" );
  5106. LEAVE_DDRAW();
  5107. DPF_APIRETURNS(DDERR_INVALIDPARAMS);
  5108. return DDERR_INVALIDPARAMS;
  5109. }
  5110. if( this_lcl->dwProcessId != GetCurrentProcessId() )
  5111. {
  5112. DPF_ERR( "Process does not have access to object" );
  5113. LEAVE_DDRAW();
  5114. DPF_APIRETURNS(DDERR_INVALIDOBJECT);
  5115. return DDERR_INVALIDOBJECT;
  5116. }
  5117. ddrval = InternalCreateSurface( this_lcl, lpDDSurfaceDesc,
  5118. lplpDDSurface, this_int, pSysMemInfo, DX8Flags );
  5119. if( ddrval == DD_OK )
  5120. {
  5121. /*
  5122. * If this is DX7, then we need to create a D3D texture object
  5123. * if the surface is marked with DDSCAPS_TEXTURE. If the
  5124. * createsurface is call is before creating a Direct3D7 object,
  5125. * then we will create a Direct3D7 ourselves.
  5126. */
  5127. if( ( this_lcl->dwLocalFlags & DDRAWILCL_DIRECTDRAW7 ) && !(DX8Flags & DX8SFLAG_DX8))
  5128. {
  5129. LPDDRAWI_DDRAWSURFACE_INT pInt = (LPDDRAWI_DDRAWSURFACE_INT) (*lplpDDSurface);
  5130. if((pInt->lpLcl->ddsCaps.dwCaps & DDSCAPS_TEXTURE) &&
  5131. !(pInt->lpLcl->lpSurfMore->ddsCapsEx.dwCaps2 & DDSCAPS2_DONOTCREATED3DTEXOBJECT))
  5132. {
  5133. if( !D3D_INITIALIZED( this_lcl ) )
  5134. {
  5135. /*
  5136. * No Direct3D interface yet so try and create one.
  5137. */
  5138. DPF(3, "No Direct3D interface yet, creating one");
  5139. ddrval = InitD3D( this_int );
  5140. if( FAILED( ddrval ) )
  5141. {
  5142. DPF_APIRETURNS(ddrval);
  5143. LEAVE_DDRAW();
  5144. return ddrval;
  5145. }
  5146. }
  5147. DDASSERT( D3D_INITIALIZED( this_lcl ) );
  5148. DPF(4, "Calling D3D to create texture");
  5149. ddrval = this_lcl->pD3DCreateTexture((LPDIRECTDRAWSURFACE7)pInt);
  5150. if(ddrval != DD_OK)
  5151. {
  5152. DPF_APIRETURNS(ddrval);
  5153. LEAVE_DDRAW();
  5154. return ddrval;
  5155. }
  5156. }
  5157. }
  5158. else
  5159. {
  5160. ((LPDDRAWI_DDRAWSURFACE_INT)(*lplpDDSurface))->lpLcl->lpSurfMore->lpTex = NULL;
  5161. }
  5162. /*
  5163. * If this ddraw object generates independent child objects, then this surface takes
  5164. * a ref count on that ddraw object.
  5165. * Note how we don't take an addref of the ddraw object for implicitly created
  5166. * surfaces.
  5167. */
  5168. if (CHILD_SHOULD_TAKE_REFCNT(this_int))
  5169. {
  5170. LPDDRAWI_DDRAWSURFACE_INT pInt = (LPDDRAWI_DDRAWSURFACE_INT) (*lplpDDSurface);
  5171. lpDD->lpVtbl->AddRef(lpDD);
  5172. pInt->lpLcl->lpSurfMore->pAddrefedThisOwner = (IUnknown*) lpDD;
  5173. }
  5174. // FillDDSurfaceDesc( (LPDDRAWI_DDRAWSURFACE_LCL) *lplpDDSurface, lpDDSurfaceDesc );
  5175. }
  5176. DPF_APIRETURNS(ddrval);
  5177. LEAVE_DDRAW();
  5178. return ddrval;
  5179. } /* DD_CreateSurface4_Main */