- added thread-safety protection to XListPixmapFormats
[wine] / dlls / ddraw / ddraw / main.c
1 /*              DirectDraw IDirectDraw interface (generic)
2  *
3  * Copyright 1997-2000 Marcus Meissner
4  * Copyright 1998-2000 Lionel Ulmer (most of Direct3D stuff)
5  */
6
7 /*
8  * This file contains all the interface functions that are shared between
9  * all interfaces. Or better, it is a "common stub" library for the IDirectDraw*
10  * objects
11  */
12
13 #include "config.h"
14
15 #include <assert.h>
16 #include <unistd.h>
17 #include <fcntl.h>
18 #include <string.h>
19 #include <stdio.h>
20
21 #include "winerror.h"
22 #include "ddraw.h"
23 #include "d3d.h"
24 #include "debugtools.h"
25 #include "message.h"
26 #include "options.h"
27 #include "monitor.h"
28
29 DEFAULT_DEBUG_CHANNEL(ddraw);
30
31 #include "ddraw_private.h"
32
33 HRESULT WINAPI IDirectDraw2Impl_DuplicateSurface(
34     LPDIRECTDRAW2 iface,LPDIRECTDRAWSURFACE src,LPDIRECTDRAWSURFACE *dst
35 ) {
36     ICOM_THIS(IDirectDraw2Impl,iface);
37     FIXME("(%p)->(%p,%p) simply copies\n",This,src,dst);
38     *dst = src; /* FIXME */
39     return DD_OK;
40 }
41
42 HRESULT WINAPI IDirectDraw2Impl_SetCooperativeLevel(
43     LPDIRECTDRAW2 iface,HWND hwnd,DWORD cooplevel
44 ) {
45     ICOM_THIS(IDirectDraw2Impl,iface);
46
47     FIXME("(%p)->(%08lx,%08lx)\n",This,(DWORD)hwnd,cooplevel);
48     _dump_cooperativelevel(cooplevel);
49     This->d.mainWindow = hwnd;
50     return DD_OK;
51 }
52
53 /*
54  * Small helper to either use the cooperative window or create a new 
55  * one (for mouse and keyboard input) and drawing in the Xlib implementation.
56  * 
57  * Note this just uses USER calls, so it is safe in here.
58  */
59 void _common_IDirectDrawImpl_SetDisplayMode(IDirectDrawImpl* This) {
60     RECT        rect;
61
62     /* Do destroy only our window */
63     if (This->d.window && GetPropA(This->d.window,ddProp)) {
64         DestroyWindow(This->d.window);
65         This->d.window = 0;
66     }
67     /* Sanity check cooperative window before assigning it to drawing. */
68     if (IsWindow(This->d.mainWindow) &&
69         IsWindowVisible(This->d.mainWindow)
70     ) {
71         GetWindowRect(This->d.mainWindow,&rect);
72         if ((((rect.right-rect.left) >= This->d.width)  &&
73              ((rect.bottom-rect.top) >= This->d.height))
74         ) {
75             This->d.window = This->d.mainWindow;
76             /* FIXME: resizing is not windows compatible behaviour, need test */
77             /* SetWindowPos(This->d.mainWindow,HWND_TOPMOST,0,0,This->d.width,This->d.height,SWP_NOMOVE|SWP_NOACTIVATE|SWP_NOOWNERZORDER); */
78             This->d.paintable = 1; /* don't wait for WM_PAINT */
79         }
80     }
81     /* ... failed, create new one. */
82     if (!This->d.window) {
83         This->d.window = CreateWindowExA(
84             0,
85             "WINE_DirectDraw",
86             "WINE_DirectDraw",
87             WS_VISIBLE|WS_SYSMENU|WS_THICKFRAME|WS_BORDER,
88             0,0,
89             This->d.width,
90             This->d.height,
91             0,
92             0,
93             0,
94             NULL
95         );
96         /*Store THIS with the window. We'll use it in the window procedure*/
97         SetPropA(This->d.window,ddProp,(LONG)This);
98         ShowWindow(This->d.window,TRUE);
99         UpdateWindow(This->d.window);
100     }
101     SetFocus(This->d.window);
102 }
103
104 HRESULT WINAPI IDirectDrawImpl_SetDisplayMode(
105         LPDIRECTDRAW iface,DWORD width,DWORD height,DWORD depth
106 ) {
107         ICOM_THIS(IDirectDrawImpl,iface);
108
109         FIXME("(%p)->SetDisplayMode(%ld,%ld,%ld), needs to be implemented for your display adapter!\n",This,width,height,depth);
110         This->d.width   = width;
111         This->d.height  = height;
112         _common_IDirectDrawImpl_SetDisplayMode(This);
113         return DD_OK;
114 }
115
116 static void fill_caps(LPDDCAPS caps) {
117     /* This function tries to fill the capabilities of Wines DDraw
118      * implementation. Needs to be fixed, though.. */
119     if (caps == NULL)
120         return;
121
122     caps->dwSize = sizeof(*caps);
123     caps->dwCaps = DDCAPS_ALPHA | DDCAPS_BLT | DDCAPS_BLTSTRETCH | DDCAPS_BLTCOLORFILL | DDCAPS_BLTDEPTHFILL | DDCAPS_CANBLTSYSMEM |  DDCAPS_COLORKEY | DDCAPS_PALETTE /*| DDCAPS_NOHARDWARE*/;
124     caps->dwCaps2 = DDCAPS2_CERTIFIED | DDCAPS2_NOPAGELOCKREQUIRED | DDCAPS2_WIDESURFACES;
125     caps->dwCKeyCaps = 0xFFFFFFFF; /* Should put real caps here one day... */
126     caps->dwFXCaps = 0;
127     caps->dwFXAlphaCaps = 0;
128     caps->dwPalCaps = DDPCAPS_8BIT | DDPCAPS_ALLOW256;
129     caps->dwSVCaps = 0;
130     caps->dwZBufferBitDepths = DDBD_16;
131     /* I put here 8 Mo so that D3D applications will believe they have enough
132      * memory to put textures in video memory. BTW, is this only frame buffer
133      * memory or also texture memory (for Voodoo boards for example) ?
134      */
135     caps->dwVidMemTotal = 8192 * 1024;
136     caps->dwVidMemFree = 8192 * 1024;
137     /* These are all the supported capabilities of the surfaces */
138     caps->ddsCaps.dwCaps = DDSCAPS_ALPHA | DDSCAPS_BACKBUFFER | DDSCAPS_COMPLEX | DDSCAPS_FLIP |
139     DDSCAPS_FRONTBUFFER | DDSCAPS_LOCALVIDMEM | DDSCAPS_NONLOCALVIDMEM | DDSCAPS_OFFSCREENPLAIN |
140       /*DDSCAPS_OVERLAY |*/ DDSCAPS_PALETTE | DDSCAPS_PRIMARYSURFACE | DDSCAPS_SYSTEMMEMORY |
141         DDSCAPS_VIDEOMEMORY | DDSCAPS_VISIBLE;
142 }
143
144 HRESULT WINAPI IDirectDraw2Impl_GetCaps(
145     LPDIRECTDRAW2 iface,LPDDCAPS caps1,LPDDCAPS caps2
146 )  {
147     ICOM_THIS(IDirectDraw2Impl,iface);
148     TRACE("(%p)->GetCaps(%p,%p)\n",This,caps1,caps2);
149
150     /* Put the same caps for the two capabilities */
151     fill_caps(caps1);
152     fill_caps(caps2);
153
154     return DD_OK;
155 }
156
157 HRESULT WINAPI IDirectDraw2Impl_CreateClipper(
158     LPDIRECTDRAW2 iface,DWORD x,LPDIRECTDRAWCLIPPER *lpddclip,LPUNKNOWN lpunk
159 ) {
160     ICOM_THIS(IDirectDraw2Impl,iface);
161     IDirectDrawClipperImpl** ilpddclip=(IDirectDrawClipperImpl**)lpddclip;
162     FIXME("(%p)->(%08lx,%p,%p),stub!\n", This,x,ilpddclip,lpunk);
163     *ilpddclip = (IDirectDrawClipperImpl*)HeapAlloc(GetProcessHeap(),HEAP_ZERO_MEMORY,sizeof(IDirectDrawClipperImpl));
164     (*ilpddclip)->ref = 1;
165     ICOM_VTBL(*ilpddclip) = &ddclipvt;
166     return DD_OK;
167 }
168
169 HRESULT WINAPI common_IDirectDraw2Impl_CreatePalette(
170     IDirectDraw2Impl* This,DWORD dwFlags,LPPALETTEENTRY palent,
171     IDirectDrawPaletteImpl **lpddpal,LPUNKNOWN lpunk,int *psize
172 ) {
173     int size = 0;
174           
175     if (TRACE_ON(ddraw))
176         _dump_paletteformat(dwFlags);
177         
178     *lpddpal = (IDirectDrawPaletteImpl*)HeapAlloc(GetProcessHeap(),HEAP_ZERO_MEMORY,sizeof(IDirectDrawPaletteImpl));
179     if (*lpddpal == NULL) return E_OUTOFMEMORY;
180     (*lpddpal)->ref = 1;
181     (*lpddpal)->ddraw = (IDirectDrawImpl*)This;
182
183     if (dwFlags & DDPCAPS_1BIT)
184         size = 2;
185     else if (dwFlags & DDPCAPS_2BIT)
186         size = 4;
187     else if (dwFlags & DDPCAPS_4BIT)
188         size = 16;
189     else if (dwFlags & DDPCAPS_8BIT)
190         size = 256;
191     else
192         ERR("unhandled palette format\n");
193
194     *psize = size;
195     if (palent) {
196         /* Now, if we are in depth conversion mode, create the screen palette */
197         if (This->d.palette_convert != NULL)        
198             This->d.palette_convert(palent,(*lpddpal)->screen_palents,0,size);
199
200         memcpy((*lpddpal)->palents, palent, size * sizeof(PALETTEENTRY));
201     } else if (This->d.palette_convert != NULL) {
202         /* In that case, put all 0xFF */
203         memset((*lpddpal)->screen_palents, 0xFF, 256 * sizeof(int));
204     }
205     return DD_OK;
206 }
207
208 HRESULT WINAPI IDirectDraw2Impl_CreatePalette(
209     LPDIRECTDRAW2 iface,DWORD dwFlags,LPPALETTEENTRY palent,LPDIRECTDRAWPALETTE *lpddpal,LPUNKNOWN lpunk
210 ) {
211     ICOM_THIS(IDirectDraw2Impl,iface);
212     IDirectDrawPaletteImpl** ilpddpal=(IDirectDrawPaletteImpl**)lpddpal;
213     int xsize;
214     HRESULT res;
215
216     TRACE("(%p)->(%08lx,%p,%p,%p)\n",This,dwFlags,palent,ilpddpal,lpunk);
217     res = common_IDirectDraw2Impl_CreatePalette(This,dwFlags,palent,ilpddpal,lpunk,&xsize);
218     if (res != 0) return res;
219     ICOM_VTBL(*ilpddpal) = &ddraw_ddpalvt;
220     return DD_OK;
221 }
222
223 HRESULT WINAPI IDirectDraw2Impl_RestoreDisplayMode(LPDIRECTDRAW2 iface) {
224     ICOM_THIS(IDirectDraw2Impl,iface);
225     TRACE("(%p)->RestoreDisplayMode()\n", This);
226     Sleep(1000);
227     return DD_OK;
228 }
229
230 HRESULT WINAPI IDirectDraw2Impl_WaitForVerticalBlank(
231     LPDIRECTDRAW2 iface,DWORD x,HANDLE h
232 ) {
233     ICOM_THIS(IDirectDraw2Impl,iface);
234     FIXME("(%p)->(flags=0x%08lx,handle=0x%08x)\n",This,x,h);
235     return DD_OK;
236 }
237
238 ULONG WINAPI IDirectDraw2Impl_AddRef(LPDIRECTDRAW2 iface) {
239     ICOM_THIS(IDirectDraw2Impl,iface);
240     TRACE("(%p)->() incrementing from %lu.\n", This, This->ref );
241
242     return ++(This->ref);
243 }
244
245 ULONG WINAPI IDirectDraw2Impl_Release(LPDIRECTDRAW2 iface) {
246     ICOM_THIS(IDirectDraw2Impl,iface);
247     TRACE("(%p)->() decrementing from %lu.\n", This, This->ref );
248
249     if (!--(This->ref)) {
250         if (This->d.window && GetPropA(This->d.window,ddProp))
251             DestroyWindow(This->d.window);
252         HeapFree(GetProcessHeap(),0,This);
253         return S_OK;
254     }
255     return This->ref;
256 }
257
258 HRESULT WINAPI IDirectDraw2Impl_QueryInterface(
259     LPDIRECTDRAW2 iface,REFIID refiid,LPVOID *obj
260 ) {
261     ICOM_THIS(IDirectDraw2Impl,iface);
262
263     if ( IsEqualGUID( &IID_IUnknown, refiid ) ) {
264         *obj = This;
265         IDirectDraw2_AddRef(iface);
266         TRACE("  Creating IUnknown interface (%p)\n", *obj);
267         return S_OK;
268     }
269     ERR("(%p)->(%s,%p), must be implemented by display interface!\n",This,debugstr_guid(refiid),obj);
270     return OLE_E_ENUM_NOMORE;
271 }
272
273 HRESULT WINAPI IDirectDraw2Impl_GetVerticalBlankStatus(
274     LPDIRECTDRAW2 iface,BOOL *status
275 ) {
276     ICOM_THIS(IDirectDraw2Impl,iface);
277     TRACE("(%p)->(%p)\n",This,status);
278     *status = TRUE;
279     return DD_OK;
280 }
281
282 HRESULT WINAPI IDirectDraw2Impl_EnumDisplayModes(
283     LPDIRECTDRAW2 iface,DWORD dwFlags,LPDDSURFACEDESC lpddsfd,LPVOID context,
284     LPDDENUMMODESCALLBACK modescb
285 ) {
286     ICOM_THIS(IDirectDraw2Impl,iface);
287     DDSURFACEDESC       ddsfd;
288     static struct {
289         int w,h;
290     } modes[5] = { /* some of the usual modes */
291         {512,384},
292         {640,400},
293         {640,480},
294         {800,600},
295         {1024,768},
296     };
297     static int depths[4] = {8,16,24,32};
298     int i,j;
299
300     TRACE("(%p)->(0x%08lx,%p,%p,%p)\n",This,dwFlags,lpddsfd,context,modescb);
301     ddsfd.dwSize = sizeof(ddsfd);
302     ddsfd.dwFlags = DDSD_HEIGHT|DDSD_WIDTH|DDSD_BACKBUFFERCOUNT|DDSD_PIXELFORMAT|DDSD_CAPS;
303     if (dwFlags & DDEDM_REFRESHRATES) {
304         ddsfd.dwFlags |= DDSD_REFRESHRATE;
305         ddsfd.u.dwRefreshRate = 60;
306     }
307     ddsfd.ddsCaps.dwCaps = 0;
308     ddsfd.dwBackBufferCount = 1;
309
310     for (i=0;i<sizeof(depths)/sizeof(depths[0]);i++) {
311         ddsfd.dwBackBufferCount = 1;
312         ddsfd.ddpfPixelFormat.dwFourCC  = 0;
313         ddsfd.ddpfPixelFormat.dwFlags   = DDPF_RGB;
314         ddsfd.ddpfPixelFormat.u.dwRGBBitCount   = depths[i];
315         /* FIXME: those masks would have to be set in depth > 8 */
316         if (depths[i]==8) {
317           ddsfd.ddpfPixelFormat.u1.dwRBitMask   = 0;
318           ddsfd.ddpfPixelFormat.u2.dwGBitMask   = 0;
319           ddsfd.ddpfPixelFormat.u3.dwBBitMask   = 0;
320           ddsfd.ddpfPixelFormat.u4.dwRGBAlphaBitMask= 0;
321           ddsfd.ddsCaps.dwCaps=DDSCAPS_PALETTE;
322           ddsfd.ddpfPixelFormat.dwFlags|=DDPF_PALETTEINDEXED8;
323         } else {
324           ddsfd.ddpfPixelFormat.u4.dwRGBAlphaBitMask= 0;
325           
326           /* FIXME: We should query those from X itself */
327           switch (depths[i]) {
328           case 16:
329             ddsfd.ddpfPixelFormat.u1.dwRBitMask = 0xF800;
330             ddsfd.ddpfPixelFormat.u2.dwGBitMask = 0x07E0;
331             ddsfd.ddpfPixelFormat.u3.dwBBitMask= 0x001F;
332             break;
333           case 24:
334             ddsfd.ddpfPixelFormat.u1.dwRBitMask = 0x00FF0000;
335             ddsfd.ddpfPixelFormat.u2.dwGBitMask = 0x0000FF00;
336             ddsfd.ddpfPixelFormat.u3.dwBBitMask= 0x000000FF;
337             break;
338           case 32:
339             ddsfd.ddpfPixelFormat.u1.dwRBitMask = 0x00FF0000;
340             ddsfd.ddpfPixelFormat.u2.dwGBitMask = 0x0000FF00;
341             ddsfd.ddpfPixelFormat.u3.dwBBitMask= 0x000000FF;
342             break;
343           }
344         }
345
346         ddsfd.dwWidth = MONITOR_GetWidth(&MONITOR_PrimaryMonitor);
347         ddsfd.dwHeight = MONITOR_GetHeight(&MONITOR_PrimaryMonitor);
348         TRACE(" enumerating (%ldx%ldx%d)\n",ddsfd.dwWidth,ddsfd.dwHeight,depths[i]);
349         if (!modescb(&ddsfd,context)) return DD_OK;
350
351         for (j=0;j<sizeof(modes)/sizeof(modes[0]);j++) {
352             ddsfd.dwWidth       = modes[j].w;
353             ddsfd.dwHeight      = modes[j].h;
354             TRACE(" enumerating (%ldx%ldx%d)\n",ddsfd.dwWidth,ddsfd.dwHeight,depths[i]);
355             if (!modescb(&ddsfd,context)) return DD_OK;
356         }
357
358         if (!(dwFlags & DDEDM_STANDARDVGAMODES)) {
359             /* modeX is not standard VGA */
360
361             ddsfd.dwHeight = 200;
362             ddsfd.dwWidth = 320;
363             TRACE(" enumerating (320x200x%d)\n",depths[i]);
364             if (!modescb(&ddsfd,context)) return DD_OK;
365         }
366     }
367     return DD_OK;
368 }
369
370 HRESULT WINAPI IDirectDraw2Impl_GetDisplayMode(
371     LPDIRECTDRAW2 iface,LPDDSURFACEDESC lpddsfd
372 ) {
373     ICOM_THIS(IDirectDraw2Impl,iface);
374     TRACE("(%p)->GetDisplayMode(%p)\n",This,lpddsfd);
375     lpddsfd->dwFlags = DDSD_HEIGHT|DDSD_WIDTH|DDSD_PITCH|DDSD_BACKBUFFERCOUNT|DDSD_PIXELFORMAT|DDSD_CAPS;
376     lpddsfd->dwHeight = This->d.height;
377     lpddsfd->dwWidth = This->d.width;
378     lpddsfd->lPitch =lpddsfd->dwWidth*PFGET_BPP(This->d.directdraw_pixelformat);
379     lpddsfd->dwBackBufferCount = 2;
380     lpddsfd->u.dwRefreshRate = 60;
381     lpddsfd->ddsCaps.dwCaps = DDSCAPS_PALETTE;
382     lpddsfd->ddpfPixelFormat = This->d.directdraw_pixelformat;
383     if (TRACE_ON(ddraw))
384         _dump_surface_desc(lpddsfd);
385     return DD_OK;
386 }
387
388 HRESULT WINAPI IDirectDraw2Impl_FlipToGDISurface(LPDIRECTDRAW2 iface) {
389     ICOM_THIS(IDirectDraw2Impl,iface);
390     FIXME("(%p)->()\n",This);
391     return DD_OK;
392 }
393
394 HRESULT WINAPI IDirectDraw2Impl_GetMonitorFrequency(
395     LPDIRECTDRAW2 iface,LPDWORD freq
396 ) {
397     ICOM_THIS(IDirectDraw2Impl,iface);
398     FIXME("(%p)->(%p) returns 60 Hz always\n",This,freq);
399     *freq = 60*100; /* 60 Hz */
400     return DD_OK;
401 }
402
403 HRESULT WINAPI IDirectDraw2Impl_GetFourCCCodes(
404     LPDIRECTDRAW2 iface,LPDWORD x,LPDWORD y
405 ) {
406     ICOM_THIS(IDirectDraw2Impl,iface);
407     FIXME("(%p,%p,%p), stub\n",This,x,y);
408     return DD_OK;
409 }
410
411 HRESULT WINAPI IDirectDraw2Impl_EnumSurfaces(
412     LPDIRECTDRAW2 iface,DWORD x,LPDDSURFACEDESC ddsfd,LPVOID context,
413     LPDDENUMSURFACESCALLBACK ddsfcb
414 ) {
415     ICOM_THIS(IDirectDraw2Impl,iface);
416     FIXME("(%p)->(0x%08lx,%p,%p,%p),stub!\n",This,x,ddsfd,context,ddsfcb);
417     return DD_OK;
418 }
419
420 HRESULT WINAPI IDirectDraw2Impl_Compact( LPDIRECTDRAW2 iface ) {
421     ICOM_THIS(IDirectDraw2Impl,iface);
422     FIXME("(%p)->()\n", This );
423     return DD_OK;
424 }
425
426 HRESULT WINAPI IDirectDraw2Impl_GetGDISurface(
427     LPDIRECTDRAW2 iface, LPDIRECTDRAWSURFACE *lplpGDIDDSSurface
428 ) {
429     ICOM_THIS(IDirectDraw2Impl,iface);
430     FIXME("(%p)->(%p)\n", This, lplpGDIDDSSurface);
431     return DD_OK;
432 }
433
434 HRESULT WINAPI IDirectDraw2Impl_GetScanLine(
435     LPDIRECTDRAW2 iface, LPDWORD lpdwScanLine
436 ) {
437     ICOM_THIS(IDirectDraw2Impl,iface);
438     FIXME("(%p)->(%p)\n", This, lpdwScanLine);
439
440     if (lpdwScanLine)
441         *lpdwScanLine = 0;
442     return DD_OK;
443 }
444
445 HRESULT WINAPI IDirectDraw2Impl_Initialize(LPDIRECTDRAW2 iface, GUID *lpGUID) {
446     ICOM_THIS(IDirectDraw2Impl,iface);
447     FIXME("(%p)->(%p)\n", This, lpGUID);
448     return DD_OK;
449 }
450
451 /*****************************************************************************
452  *      IDirectDraw2
453  *
454  * We only need to list the changed/new functions.
455  */
456 HRESULT WINAPI IDirectDraw2Impl_SetDisplayMode(
457     LPDIRECTDRAW2 iface,DWORD width,DWORD height,DWORD depth,
458     DWORD dwRefreshRate, DWORD dwFlags
459 ) {
460     FIXME("Ignoring parameters (0x%08lx,0x%08lx)\n", dwRefreshRate, dwFlags ); 
461     return IDirectDrawImpl_SetDisplayMode((LPDIRECTDRAW)iface,width,height,depth);
462 }
463
464 HRESULT WINAPI IDirectDraw2Impl_GetAvailableVidMem(
465     LPDIRECTDRAW2 iface,LPDDSCAPS ddscaps,LPDWORD total,LPDWORD free
466 ) {
467     ICOM_THIS(IDirectDraw2Impl,iface);
468     TRACE("(%p)->(%p,%p,%p)\n", This,ddscaps,total,free);
469
470     /* We have 16 MB videomemory */
471     if (total)  *total= 16*1024*1024;
472     if (free)   *free = 16*1024*1024;
473     return DD_OK;
474 }
475
476 /*****************************************************************************
477  *      IDirectDraw4
478  *
479  */
480
481 HRESULT WINAPI IDirectDraw4Impl_GetSurfaceFromDC(
482     LPDIRECTDRAW4 iface, HDC hdc, LPDIRECTDRAWSURFACE *lpDDS
483 ) {
484     ICOM_THIS(IDirectDraw4Impl,iface);
485     FIXME("(%p)->(%08ld,%p)\n", This, (DWORD) hdc, lpDDS);
486
487     return DD_OK;
488 }
489
490 HRESULT WINAPI IDirectDraw4Impl_RestoreAllSurfaces(LPDIRECTDRAW4 iface) {
491     ICOM_THIS(IDirectDraw4Impl,iface);
492     FIXME("(%p)->()\n", This);
493
494     return DD_OK;
495 }
496
497 HRESULT WINAPI IDirectDraw4Impl_TestCooperativeLevel(LPDIRECTDRAW4 iface) {
498     ICOM_THIS(IDirectDraw4Impl,iface);
499     FIXME("(%p)->()\n", This);
500
501     return DD_OK;
502 }
503
504 HRESULT WINAPI IDirectDraw4Impl_GetDeviceIdentifier(
505     LPDIRECTDRAW4 iface,LPDDDEVICEIDENTIFIER lpdddi,DWORD dwFlags
506 ) {
507     ICOM_THIS(IDirectDraw4Impl,iface);
508     FIXME("(%p)->(%p,%08lx)\n", This, lpdddi, dwFlags);
509
510     /* just guessing values */
511     strcpy(lpdddi->szDriver,"directdraw");
512     strcpy(lpdddi->szDescription,"WINE DirectDraw");
513     lpdddi->liDriverVersion.s.HighPart = 7;
514     lpdddi->liDriverVersion.s.LowPart = 0;
515     /* Do I smell PCI ids here ? -MM */
516     lpdddi->dwVendorId                  = 0;
517     lpdddi->dwDeviceId                  = 0;
518     lpdddi->dwSubSysId                  = 0;
519     lpdddi->dwRevision                  = 1;
520     memset(&(lpdddi->guidDeviceIdentifier),0,sizeof(lpdddi->guidDeviceIdentifier));
521     return DD_OK;
522 }
523
524 HRESULT common_off_screen_CreateSurface(
525     IDirectDraw2Impl* This,IDirectDrawSurfaceImpl* lpdsf
526 ) {
527     int bpp;
528
529     /* The surface was already allocated when entering in this function */
530     TRACE("using system memory for a surface (%p) \n", lpdsf);
531
532     if (lpdsf->s.surface_desc.dwFlags & DDSD_ZBUFFERBITDEPTH) {
533         /* This is a Z Buffer */
534         TRACE("Creating Z-Buffer of %ld bit depth\n", lpdsf->s.surface_desc.u.dwZBufferBitDepth);
535         bpp = lpdsf->s.surface_desc.u.dwZBufferBitDepth / 8;
536     } else {
537         /* This is a standard image */
538         if (!(lpdsf->s.surface_desc.dwFlags & DDSD_PIXELFORMAT)) {
539             /* No pixel format => use DirectDraw's format */
540             lpdsf->s.surface_desc.ddpfPixelFormat = This->d.directdraw_pixelformat;
541             lpdsf->s.surface_desc.dwFlags |= DDSD_PIXELFORMAT;
542         }
543         bpp = GET_BPP(lpdsf->s.surface_desc);
544     }
545
546     if (lpdsf->s.surface_desc.dwFlags & DDSD_LPSURFACE)
547         ERR("Creates a surface that is already allocated : assuming this is an application bug !\n");
548
549     lpdsf->s.surface_desc.dwFlags |= DDSD_PITCH|DDSD_LPSURFACE;
550     lpdsf->s.surface_desc.u1.lpSurface =(LPBYTE)HeapAlloc(
551         GetProcessHeap(),
552         0,
553         lpdsf->s.surface_desc.dwWidth * lpdsf->s.surface_desc.dwHeight * bpp
554     );
555     lpdsf->s.surface_desc.lPitch = lpdsf->s.surface_desc.dwWidth * bpp;
556     return DD_OK;
557 }