1*c2c66affSColin Finck /*
2*c2c66affSColin Finck * COPYRIGHT: See COPYING in the top level directory
3*c2c66affSColin Finck * PROJECT: ReactOS DirectX
4*c2c66affSColin Finck * FILE: dll/directx/ddraw/Surface/createsurface.c
5*c2c66affSColin Finck * PURPOSE: IDirectDrawSurface Creation
6*c2c66affSColin Finck * PROGRAMMER: Magnus Olsen
7*c2c66affSColin Finck *
8*c2c66affSColin Finck */
9*c2c66affSColin Finck #include "rosdraw.h"
10*c2c66affSColin Finck
11*c2c66affSColin Finck /*
12*c2c66affSColin Finck * All parameters must have been checked if they are valid before they are passed to Internal_CreateSurface.
13*c2c66affSColin Finck * If not please fix the code in the functions which call Internal_CreateSurface.
14*c2c66affSColin Finck * ppSurf,pDDSD,pDDraw are being validated in Internal_CreateSurface.
15*c2c66affSColin Finck */
16*c2c66affSColin Finck
17*c2c66affSColin Finck HRESULT
Internal_CreateSurface(LPDDRAWI_DIRECTDRAW_INT pDDraw,LPDDSURFACEDESC2 pDDSD,LPDDRAWI_DDRAWSURFACE_INT * ppSurf,IUnknown * pUnkOuter)18*c2c66affSColin Finck Internal_CreateSurface( LPDDRAWI_DIRECTDRAW_INT pDDraw, LPDDSURFACEDESC2 pDDSD,
19*c2c66affSColin Finck LPDDRAWI_DDRAWSURFACE_INT *ppSurf, IUnknown *pUnkOuter)
20*c2c66affSColin Finck {
21*c2c66affSColin Finck DDHAL_CANCREATESURFACEDATA mDdCanCreateSurface = { 0 };
22*c2c66affSColin Finck DDHAL_CREATESURFACEDATA mDdCreateSurface = { 0 };
23*c2c66affSColin Finck
24*c2c66affSColin Finck LPDDRAWI_DDRAWSURFACE_INT ThisSurfInt;
25*c2c66affSColin Finck LPDDRAWI_DDRAWSURFACE_LCL ThisSurfLcl;
26*c2c66affSColin Finck LPDDRAWI_DDRAWSURFACE_GBL ThisSurfGbl;
27*c2c66affSColin Finck LPDDRAWI_DDRAWSURFACE_MORE ThisSurfMore;
28*c2c66affSColin Finck
29*c2c66affSColin Finck LPDDRAWI_DDRAWSURFACE_INT * slist_int = NULL;
30*c2c66affSColin Finck LPDDRAWI_DDRAWSURFACE_LCL * slist_lcl = NULL;
31*c2c66affSColin Finck LPDDRAWI_DDRAWSURFACE_GBL * slist_gbl = NULL;
32*c2c66affSColin Finck LPDDRAWI_DDRAWSURFACE_MORE * slist_more = NULL;
33*c2c66affSColin Finck DWORD num_of_surf=1;
34*c2c66affSColin Finck DWORD count;
35*c2c66affSColin Finck HRESULT ret;
36*c2c66affSColin Finck
37*c2c66affSColin Finck if((pDDraw->lpLcl->dwLocalFlags & DDRAWILCL_SETCOOPCALLED) != DDRAWILCL_SETCOOPCALLED)
38*c2c66affSColin Finck {
39*c2c66affSColin Finck return DDERR_NOCOOPERATIVELEVELSET;
40*c2c66affSColin Finck }
41*c2c66affSColin Finck
42*c2c66affSColin Finck if(pUnkOuter)
43*c2c66affSColin Finck {
44*c2c66affSColin Finck return CLASS_E_NOAGGREGATION;
45*c2c66affSColin Finck }
46*c2c66affSColin Finck
47*c2c66affSColin Finck if(!(pDDSD->dwFlags & DDSD_CAPS))
48*c2c66affSColin Finck {
49*c2c66affSColin Finck return DDERR_INVALIDPARAMS;
50*c2c66affSColin Finck }
51*c2c66affSColin Finck if (pDDraw->lpLcl->dwProcessId != GetCurrentProcessId() )
52*c2c66affSColin Finck {
53*c2c66affSColin Finck return DDERR_INVALIDOBJECT;
54*c2c66affSColin Finck }
55*c2c66affSColin Finck
56*c2c66affSColin Finck if ( ((pDDSD->ddsCaps.dwCaps & DDSCAPS_SYSTEMMEMORY) == DDSCAPS_SYSTEMMEMORY) &&
57*c2c66affSColin Finck ((pDDSD->ddsCaps.dwCaps & DDSCAPS_VIDEOMEMORY) == DDSCAPS_VIDEOMEMORY) )
58*c2c66affSColin Finck {
59*c2c66affSColin Finck return DDERR_INVALIDCAPS;
60*c2c66affSColin Finck }
61*c2c66affSColin Finck
62*c2c66affSColin Finck if((!(pDDSD->dwFlags & DDSD_HEIGHT) || !(pDDSD->dwFlags & DDSD_WIDTH))
63*c2c66affSColin Finck && !(pDDSD->ddsCaps.dwCaps & DDSCAPS_PRIMARYSURFACE))
64*c2c66affSColin Finck {
65*c2c66affSColin Finck return DDERR_INVALIDPARAMS;
66*c2c66affSColin Finck }
67*c2c66affSColin Finck
68*c2c66affSColin Finck else if(((pDDSD->dwFlags & DDSD_HEIGHT) || (pDDSD->dwFlags & DDSD_WIDTH))
69*c2c66affSColin Finck && (pDDSD->ddsCaps.dwCaps & DDSCAPS_PRIMARYSURFACE))
70*c2c66affSColin Finck {
71*c2c66affSColin Finck return DDERR_INVALIDPARAMS;
72*c2c66affSColin Finck }
73*c2c66affSColin Finck
74*c2c66affSColin Finck /*
75*c2c66affSColin Finck * program does not need set the DDSD_LPSURFACE,
76*c2c66affSColin Finck * if they forget set it, the ddraw will automatic
77*c2c66affSColin Finck * set it for system memory.
78*c2c66affSColin Finck */
79*c2c66affSColin Finck if ( ((pDDSD->ddsCaps.dwCaps & DDSCAPS_SYSTEMMEMORY) == DDSCAPS_SYSTEMMEMORY) &&
80*c2c66affSColin Finck ((pDDSD->dwFlags & DDSD_LPSURFACE) != DDSD_LPSURFACE) )
81*c2c66affSColin Finck {
82*c2c66affSColin Finck pDDSD->dwFlags = pDDSD->dwFlags | DDSD_LPSURFACE;
83*c2c66affSColin Finck }
84*c2c66affSColin Finck
85*c2c66affSColin Finck /* FIXME count how many surfaces we need */
86*c2c66affSColin Finck
87*c2c66affSColin Finck DxHeapMemAlloc(slist_int, num_of_surf * sizeof( LPDDRAWI_DDRAWSURFACE_INT ) );
88*c2c66affSColin Finck if( slist_int == NULL)
89*c2c66affSColin Finck {
90*c2c66affSColin Finck ret = DDERR_OUTOFMEMORY;
91*c2c66affSColin Finck goto cleanup;
92*c2c66affSColin Finck }
93*c2c66affSColin Finck
94*c2c66affSColin Finck DxHeapMemAlloc(slist_lcl, num_of_surf * sizeof( LPDDRAWI_DDRAWSURFACE_LCL ) );
95*c2c66affSColin Finck if( slist_lcl == NULL )
96*c2c66affSColin Finck {
97*c2c66affSColin Finck ret = DDERR_OUTOFMEMORY;
98*c2c66affSColin Finck goto cleanup;
99*c2c66affSColin Finck }
100*c2c66affSColin Finck
101*c2c66affSColin Finck /* keep pointers to all gbl surfs to be able to free them on error */
102*c2c66affSColin Finck DxHeapMemAlloc(slist_gbl, num_of_surf * sizeof( LPDDRAWI_DDRAWSURFACE_GBL ) );
103*c2c66affSColin Finck if( slist_gbl == NULL )
104*c2c66affSColin Finck {
105*c2c66affSColin Finck DxHeapMemFree(slist_int);
106*c2c66affSColin Finck return DDERR_OUTOFMEMORY;
107*c2c66affSColin Finck }
108*c2c66affSColin Finck
109*c2c66affSColin Finck /* keep pointers to all more surfs to be able to free them on error */
110*c2c66affSColin Finck DxHeapMemAlloc(slist_more, num_of_surf * sizeof( LPDDRAWI_DDRAWSURFACE_MORE ) );
111*c2c66affSColin Finck if( slist_more == NULL )
112*c2c66affSColin Finck {
113*c2c66affSColin Finck DxHeapMemFree(slist_int);
114*c2c66affSColin Finck return DDERR_OUTOFMEMORY;
115*c2c66affSColin Finck }
116*c2c66affSColin Finck
117*c2c66affSColin Finck for( count=0; count < num_of_surf; count++ )
118*c2c66affSColin Finck {
119*c2c66affSColin Finck /* Allocate the surface interface and needed members */
120*c2c66affSColin Finck DxHeapMemAlloc(ThisSurfInt, sizeof( DDRAWI_DDRAWSURFACE_INT ) );
121*c2c66affSColin Finck if( ThisSurfInt == NULL )
122*c2c66affSColin Finck {
123*c2c66affSColin Finck ret = DDERR_OUTOFMEMORY;
124*c2c66affSColin Finck goto cleanup;
125*c2c66affSColin Finck }
126*c2c66affSColin Finck
127*c2c66affSColin Finck DxHeapMemAlloc(ThisSurfLcl, sizeof( DDRAWI_DDRAWSURFACE_LCL ) );
128*c2c66affSColin Finck if( ThisSurfLcl == NULL )
129*c2c66affSColin Finck {
130*c2c66affSColin Finck ret = DDERR_OUTOFMEMORY;
131*c2c66affSColin Finck goto cleanup;
132*c2c66affSColin Finck }
133*c2c66affSColin Finck
134*c2c66affSColin Finck DxHeapMemAlloc(ThisSurfGbl, sizeof( DDRAWI_DDRAWSURFACE_GBL ) );
135*c2c66affSColin Finck if( ThisSurfGbl == NULL )
136*c2c66affSColin Finck {
137*c2c66affSColin Finck ret = DDERR_OUTOFMEMORY;
138*c2c66affSColin Finck goto cleanup;
139*c2c66affSColin Finck }
140*c2c66affSColin Finck
141*c2c66affSColin Finck DxHeapMemAlloc(ThisSurfMore, sizeof( DDRAWI_DDRAWSURFACE_MORE ) );
142*c2c66affSColin Finck if( ThisSurfMore == NULL )
143*c2c66affSColin Finck {
144*c2c66affSColin Finck ret = DDERR_OUTOFMEMORY;
145*c2c66affSColin Finck goto cleanup;
146*c2c66affSColin Finck }
147*c2c66affSColin Finck
148*c2c66affSColin Finck /* setup lists, really needed are slist_lcl, slist_int
149*c2c66affSColin Finck other slists should be released on return */
150*c2c66affSColin Finck
151*c2c66affSColin Finck slist_int[count] = ThisSurfInt;
152*c2c66affSColin Finck slist_lcl[count] = ThisSurfLcl;
153*c2c66affSColin Finck slist_gbl[count] = ThisSurfGbl;
154*c2c66affSColin Finck slist_more[count] = ThisSurfMore;
155*c2c66affSColin Finck
156*c2c66affSColin Finck /* Start now fill in the member as they shall look like before call to createsurface */
157*c2c66affSColin Finck
158*c2c66affSColin Finck ThisSurfInt->lpLcl = ThisSurfLcl;
159*c2c66affSColin Finck ThisSurfLcl->lpGbl = ThisSurfGbl;
160*c2c66affSColin Finck
161*c2c66affSColin Finck ThisSurfLcl->ddsCaps.dwCaps = pDDSD->ddsCaps.dwCaps;
162*c2c66affSColin Finck
163*c2c66affSColin Finck ThisSurfGbl->lpDD = pDDraw->lpLcl->lpGbl;
164*c2c66affSColin Finck ThisSurfGbl->lpDDHandle = pDDraw->lpLcl->lpGbl;
165*c2c66affSColin Finck
166*c2c66affSColin Finck /* FIXME ? */
167*c2c66affSColin Finck ThisSurfGbl->dwGlobalFlags = DDRAWISURFGBL_ISGDISURFACE;
168*c2c66affSColin Finck
169*c2c66affSColin Finck if (pDDSD->ddsCaps.dwCaps & DDSCAPS_PRIMARYSURFACE)
170*c2c66affSColin Finck {
171*c2c66affSColin Finck ThisSurfGbl->wWidth = pDDraw->lpLcl->lpGbl->vmiData.dwDisplayWidth;
172*c2c66affSColin Finck ThisSurfGbl->wHeight = pDDraw->lpLcl->lpGbl->vmiData.dwDisplayHeight;
173*c2c66affSColin Finck ThisSurfGbl->lPitch = pDDraw->lpLcl->lpGbl->vmiData.lDisplayPitch;
174*c2c66affSColin Finck ThisSurfGbl->dwLinearSize = pDDraw->lpLcl->lpGbl->vmiData.lDisplayPitch;
175*c2c66affSColin Finck
176*c2c66affSColin Finck
177*c2c66affSColin Finck ThisSurfMore->dmiDDrawReserved7.wWidth = pDDraw->lpLcl->lpGbl->vmiData.dwDisplayWidth;
178*c2c66affSColin Finck ThisSurfMore->dmiDDrawReserved7.wHeight = pDDraw->lpLcl->lpGbl->vmiData.dwDisplayHeight;
179*c2c66affSColin Finck ThisSurfMore->dmiDDrawReserved7.wBPP = pDDraw->lpLcl->lpGbl->dwMonitorFrequency;
180*c2c66affSColin Finck
181*c2c66affSColin Finck /* FIXME ThisSurfaceMore->dmiDDrawReserved7.wMonitorsAttachedToDesktop */
182*c2c66affSColin Finck ThisSurfMore->dmiDDrawReserved7.wMonitorsAttachedToDesktop = 1;
183*c2c66affSColin Finck pDDraw->lpLcl->lpPrimary = ThisSurfInt;
184*c2c66affSColin Finck }
185*c2c66affSColin Finck else
186*c2c66affSColin Finck {
187*c2c66affSColin Finck ThisSurfGbl->wWidth = (WORD)pDDSD->dwWidth;
188*c2c66affSColin Finck ThisSurfGbl->wHeight = (WORD)pDDSD->dwHeight;
189*c2c66affSColin Finck ThisSurfGbl->lPitch = pDDSD->lPitch;
190*c2c66affSColin Finck ThisSurfGbl->dwLinearSize = pDDSD->lPitch;
191*c2c66affSColin Finck }
192*c2c66affSColin Finck
193*c2c66affSColin Finck if(pDDraw->lpVtbl == &DirectDraw7_Vtable)
194*c2c66affSColin Finck {
195*c2c66affSColin Finck ThisSurfInt->lpVtbl = &DirectDrawSurface7_Vtable;
196*c2c66affSColin Finck }
197*c2c66affSColin Finck else if(pDDraw->lpVtbl == &DirectDraw4_Vtable)
198*c2c66affSColin Finck {
199*c2c66affSColin Finck ThisSurfInt->lpVtbl = &DirectDrawSurface4_Vtable;
200*c2c66affSColin Finck }
201*c2c66affSColin Finck else if(pDDraw->lpVtbl == &DirectDraw2_Vtable)
202*c2c66affSColin Finck {
203*c2c66affSColin Finck ThisSurfInt->lpVtbl = &DirectDrawSurface2_Vtable;
204*c2c66affSColin Finck }
205*c2c66affSColin Finck else if(pDDraw->lpVtbl == &DirectDraw_Vtable)
206*c2c66affSColin Finck {
207*c2c66affSColin Finck ThisSurfInt->lpVtbl = &DirectDrawSurface_Vtable;
208*c2c66affSColin Finck }
209*c2c66affSColin Finck else
210*c2c66affSColin Finck {
211*c2c66affSColin Finck ret = DDERR_NOTINITIALIZED;
212*c2c66affSColin Finck goto cleanup;
213*c2c66affSColin Finck }
214*c2c66affSColin Finck
215*c2c66affSColin Finck ThisSurfLcl->lpSurfMore = ThisSurfMore;
216*c2c66affSColin Finck ThisSurfMore->dwSize = sizeof(DDRAWI_DDRAWSURFACE_MORE);
217*c2c66affSColin Finck ThisSurfMore->lpDD_int = pDDraw;
218*c2c66affSColin Finck ThisSurfMore->lpDD_lcl = pDDraw->lpLcl;
219*c2c66affSColin Finck ThisSurfMore->slist = slist_lcl;
220*c2c66affSColin Finck
221*c2c66affSColin Finck ThisSurfLcl->dwProcessId = GetCurrentProcessId();
222*c2c66affSColin Finck
223*c2c66affSColin Finck /* FIXME the lpLnk */
224*c2c66affSColin Finck
225*c2c66affSColin Finck Main_DDrawSurface_AddRef(ThisSurfInt);
226*c2c66affSColin Finck }
227*c2c66affSColin Finck
228*c2c66affSColin Finck pDDraw->lpLcl->lpGbl->dsList = (LPDDRAWI_DDRAWSURFACE_INT) slist_int;
229*c2c66affSColin Finck
230*c2c66affSColin Finck /* Fixme call on DdCanCreate then on DdCreateSurface createsurface data here */
231*c2c66affSColin Finck
232*c2c66affSColin Finck /* FIXME bIsDifferentPixelFormat being set to true or false with automatic detections */
233*c2c66affSColin Finck mDdCanCreateSurface.bIsDifferentPixelFormat = FALSE;
234*c2c66affSColin Finck
235*c2c66affSColin Finck mDdCanCreateSurface.lpDD = pDDraw->lpLcl->lpGbl;
236*c2c66affSColin Finck mDdCanCreateSurface.CanCreateSurface = pDDraw->lpLcl->lpDDCB->HALDD.CanCreateSurface;
237*c2c66affSColin Finck mDdCanCreateSurface.lpDDSurfaceDesc = (LPDDSURFACEDESC) pDDSD;
238*c2c66affSColin Finck mDdCanCreateSurface.ddRVal = DDERR_GENERIC;
239*c2c66affSColin Finck
240*c2c66affSColin Finck if (mDdCanCreateSurface.CanCreateSurface(&mDdCanCreateSurface) == DDHAL_DRIVER_NOTHANDLED)
241*c2c66affSColin Finck {
242*c2c66affSColin Finck DX_STUB_str("mDdCanCreateSurface failed with DDHAL_DRIVER_NOTHANDLED.");
243*c2c66affSColin Finck ret = DDERR_NOTINITIALIZED;
244*c2c66affSColin Finck goto cleanup;
245*c2c66affSColin Finck }
246*c2c66affSColin Finck
247*c2c66affSColin Finck if (mDdCanCreateSurface.ddRVal != DD_OK)
248*c2c66affSColin Finck {
249*c2c66affSColin Finck DX_STUB_str("mDdCanCreateSurface failed.");
250*c2c66affSColin Finck ret = mDdCanCreateSurface.ddRVal;
251*c2c66affSColin Finck goto cleanup;
252*c2c66affSColin Finck }
253*c2c66affSColin Finck
254*c2c66affSColin Finck mDdCreateSurface.lpDD = pDDraw->lpLcl->lpGbl;
255*c2c66affSColin Finck mDdCreateSurface.CreateSurface = pDDraw->lpLcl->lpGbl->lpDDCBtmp->HALDD.CreateSurface;
256*c2c66affSColin Finck mDdCreateSurface.ddRVal = DDERR_GENERIC;
257*c2c66affSColin Finck mDdCreateSurface.dwSCnt = num_of_surf;
258*c2c66affSColin Finck mDdCreateSurface.lpDDSurfaceDesc = (LPDDSURFACEDESC) pDDSD;
259*c2c66affSColin Finck mDdCreateSurface.lplpSList = slist_lcl;
260*c2c66affSColin Finck
261*c2c66affSColin Finck if (mDdCreateSurface.CreateSurface(&mDdCreateSurface) == DDHAL_DRIVER_NOTHANDLED)
262*c2c66affSColin Finck {
263*c2c66affSColin Finck DX_STUB_str("mDdCreateSurface failed with DDHAL_DRIVER_NOTHANDLED.");
264*c2c66affSColin Finck ret = DDERR_NOTINITIALIZED;
265*c2c66affSColin Finck goto cleanup;
266*c2c66affSColin Finck }
267*c2c66affSColin Finck
268*c2c66affSColin Finck if (mDdCreateSurface.ddRVal != DD_OK)
269*c2c66affSColin Finck {
270*c2c66affSColin Finck DX_STUB_str("mDdCreateSurface failed.");
271*c2c66affSColin Finck ret = mDdCreateSurface.ddRVal;
272*c2c66affSColin Finck goto cleanup;
273*c2c66affSColin Finck }
274*c2c66affSColin Finck
275*c2c66affSColin Finck /* free unneeded slists */
276*c2c66affSColin Finck if (slist_more != NULL)
277*c2c66affSColin Finck DxHeapMemFree(slist_more);
278*c2c66affSColin Finck if (slist_gbl != NULL)
279*c2c66affSColin Finck DxHeapMemFree(slist_gbl);
280*c2c66affSColin Finck
281*c2c66affSColin Finck *ppSurf = (LPDDRAWI_DDRAWSURFACE_INT) &slist_int[0]->lpVtbl;
282*c2c66affSColin Finck
283*c2c66affSColin Finck return DD_OK;
284*c2c66affSColin Finck
285*c2c66affSColin Finck cleanup:
286*c2c66affSColin Finck for(count = 0; count < num_of_surf; count++)
287*c2c66affSColin Finck {
288*c2c66affSColin Finck if (slist_more[count] != NULL)
289*c2c66affSColin Finck DxHeapMemFree(slist_more[count]);
290*c2c66affSColin Finck if (slist_gbl[count] != NULL)
291*c2c66affSColin Finck DxHeapMemFree(slist_gbl[count]);
292*c2c66affSColin Finck if (slist_lcl[count] != NULL)
293*c2c66affSColin Finck DxHeapMemFree(slist_lcl[count]);
294*c2c66affSColin Finck if (slist_int[count] != NULL)
295*c2c66affSColin Finck DxHeapMemFree(slist_int[count]);
296*c2c66affSColin Finck }
297*c2c66affSColin Finck if (slist_more != NULL)
298*c2c66affSColin Finck DxHeapMemFree(slist_more);
299*c2c66affSColin Finck if (slist_gbl != NULL)
300*c2c66affSColin Finck DxHeapMemFree(slist_gbl);
301*c2c66affSColin Finck if (slist_lcl != NULL)
302*c2c66affSColin Finck DxHeapMemFree(slist_lcl);
303*c2c66affSColin Finck if (slist_int != NULL)
304*c2c66affSColin Finck DxHeapMemFree(slist_int);
305*c2c66affSColin Finck
306*c2c66affSColin Finck return ret;
307*c2c66affSColin Finck }
308*c2c66affSColin Finck
309*c2c66affSColin Finck
310*c2c66affSColin Finck
CopyDDSurfDescToDDSurfDesc2(LPDDSURFACEDESC2 dst_pDesc,LPDDSURFACEDESC src_pDesc)311*c2c66affSColin Finck void CopyDDSurfDescToDDSurfDesc2(LPDDSURFACEDESC2 dst_pDesc, LPDDSURFACEDESC src_pDesc)
312*c2c66affSColin Finck {
313*c2c66affSColin Finck RtlZeroMemory(dst_pDesc,sizeof(DDSURFACEDESC2));
314*c2c66affSColin Finck RtlCopyMemory(dst_pDesc,src_pDesc,sizeof(DDSURFACEDESC));
315*c2c66affSColin Finck dst_pDesc->dwSize = sizeof(DDSURFACEDESC2);
316*c2c66affSColin Finck }
317*c2c66affSColin Finck
318*c2c66affSColin Finck
319*c2c66affSColin Finck
320*c2c66affSColin Finck
321*c2c66affSColin Finck
322