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