1 /* DirectDraw IDirectDraw interface (generic)
3 * Copyright 1997-2000 Marcus Meissner
4 * Copyright 1998-2000 Lionel Ulmer (most of Direct3D stuff)
5 * Copyright 2000-2001 TransGaming Technologies Inc.
7 * This library is free software; you can redistribute it and/or
8 * modify it under the terms of the GNU Lesser General Public
9 * License as published by the Free Software Foundation; either
10 * version 2.1 of the License, or (at your option) any later version.
12 * This library is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15 * Lesser General Public License for more details.
17 * You should have received a copy of the GNU Lesser General Public
18 * License along with this library; if not, write to the Free Software
19 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
23 * WINE currently implements a very basic set of the DirectDraw functionality
24 * in graphics/ddraw.c. This implementation uses either the XFree86-DGA extension
25 * to get very fast access to the graphics card framebuffer and doublebuffering
26 * features or Xlib, which is slower.
27 * The implementation using XFree86-DGA is as fast as the MS equivalent for the
28 * stuff that is implemented.
30 * Several applications already work, see below.
31 * Problems of the implementation using XFree86-DGA:
33 * - XFree86 cannot switch depth on the fly.
34 * This is a problem with X and unavoidable.
35 * Current solution is to pop up a MessageBox with an error for
36 * mismatched parameters and advice the user to restart the X server
37 * with the specified depth.
38 * - The rest of the functionality that has to be implemented will have
39 * to be done in software and will be very slow.
40 * - This requires WINE to be run as root user so XF86DGA can mmap the
41 * framebuffer into the addressspace of the process.
42 * - Blocks all other X windowed applications.
44 * This file contains all the interface functions that are shared between
45 * all interfaces. Or better, it is a "common stub" library for the
46 * IDirectDraw* objects
50 #include "wine/port.h"
56 #define NONAMELESSUNION
57 #define NONAMELESSSTRUCT
67 #include "wine/debug.h"
69 #include "ddraw_private.h"
70 #include "opengl_private.h" /* To have the D3D creation function */
72 WINE_DEFAULT_DEBUG_CHANNEL(ddraw
);
74 extern const IDirectDrawVtbl DDRAW_IDirectDraw_VTable
;
75 extern const IDirectDraw2Vtbl DDRAW_IDirectDraw2_VTable
;
76 extern const IDirectDraw4Vtbl DDRAW_IDirectDraw4_VTable
;
78 static void DDRAW_UnsubclassWindow(IDirectDrawImpl
* This
);
80 static void Main_DirectDraw_DeleteSurfaces(IDirectDrawImpl
* This
);
81 static void Main_DirectDraw_DeleteClippers(IDirectDrawImpl
* This
);
82 static void Main_DirectDraw_DeletePalettes(IDirectDrawImpl
* This
);
83 static void LosePrimarySurface(IDirectDrawImpl
* This
);
85 static INT32
allocate_memory(IDirectDrawImpl
*This
, DWORD mem
) ;
86 static void free_memory(IDirectDrawImpl
*This
, DWORD mem
) ;
89 static const char ddProp
[] = "WINE_DDRAW_Property";
91 /* Not called from the vtable. */
92 HRESULT
Main_DirectDraw_Construct(IDirectDrawImpl
*This
, BOOL ex
)
94 /* NOTE: The creator must use HEAP_ZERO_MEMORY or equivalent. */
98 if (ex
) This
->local
.dwLocalFlags
|= DDRAWILCL_DIRECTDRAW7
;
99 This
->local
.dwProcessId
= GetCurrentProcessId();
101 This
->final_release
= Main_DirectDraw_final_release
;
103 This
->create_palette
= Main_DirectDrawPalette_Create
;
105 This
->create_offscreen
= Main_create_offscreen
;
106 This
->create_texture
= Main_create_texture
;
107 This
->create_zbuffer
= Main_create_zbuffer
;
108 /* There are no generic versions of create_{primary,backbuffer}. */
110 ICOM_INIT_INTERFACE(This
, IDirectDraw
, DDRAW_IDirectDraw_VTable
);
111 ICOM_INIT_INTERFACE(This
, IDirectDraw2
, DDRAW_IDirectDraw2_VTable
);
112 ICOM_INIT_INTERFACE(This
, IDirectDraw4
, DDRAW_IDirectDraw4_VTable
);
113 /* There is no generic implementation of IDD7 */
115 /* This is for the moment here... */
116 This
->free_memory
= free_memory
;
117 This
->allocate_memory
= allocate_memory
;
118 This
->total_vidmem
= 64 * 1024 * 1024;
119 This
->available_vidmem
= This
->total_vidmem
;
124 void Main_DirectDraw_final_release(IDirectDrawImpl
* This
)
126 if (IsWindow(This
->window
))
128 if (GetPropA(This
->window
, ddProp
))
129 DDRAW_UnsubclassWindow(This
);
131 FIXME("this shouldn't happen, right?\n");
134 Main_DirectDraw_DeleteSurfaces(This
);
135 Main_DirectDraw_DeleteClippers(This
);
136 Main_DirectDraw_DeletePalettes(This
);
137 if (This
->local
.lpGbl
&& This
->local
.lpGbl
->lpExclusiveOwner
== &This
->local
)
139 This
->local
.lpGbl
->lpExclusiveOwner
= NULL
;
140 if (This
->set_exclusive_mode
)
141 This
->set_exclusive_mode(This
, FALSE
);
145 /* There is no Main_DirectDraw_Create. */
147 ULONG WINAPI
Main_DirectDraw_AddRef(LPDIRECTDRAW7 iface
) {
148 IDirectDrawImpl
*This
= (IDirectDrawImpl
*)iface
;
149 ULONG ref
= InterlockedIncrement(&This
->ref
);
151 TRACE("(%p)->() incrementing from %lu.\n", This
, ref
-1);
156 ULONG WINAPI
Main_DirectDraw_Release(LPDIRECTDRAW7 iface
) {
157 IDirectDrawImpl
*This
= (IDirectDrawImpl
*)iface
;
158 ULONG ref
= InterlockedDecrement(&This
->ref
);
160 TRACE("(%p)->() decrementing from %lu.\n", This
, ref
+1);
164 if (This
->final_release
!= NULL
)
165 This
->final_release(This
);
167 /* We free the private. This is an artifact of the fact that I don't
168 * have the destructors set up correctly. */
169 if (This
->private != (This
+1))
170 HeapFree(GetProcessHeap(), 0, This
->private);
172 HeapFree(GetProcessHeap(), 0, This
);
178 HRESULT WINAPI
Main_DirectDraw_QueryInterface(
179 LPDIRECTDRAW7 iface
,REFIID refiid
,LPVOID
*obj
181 IDirectDrawImpl
*This
= (IDirectDrawImpl
*)iface
;
182 TRACE("(%p)->(%s,%p)\n", This
, debugstr_guid(refiid
), obj
);
184 /* According to COM docs, if the QueryInterface fails, obj should be set to NULL */
187 if ( IsEqualGUID( &IID_IUnknown
, refiid
)
188 || IsEqualGUID( &IID_IDirectDraw7
, refiid
) )
190 *obj
= ICOM_INTERFACE(This
, IDirectDraw7
);
192 else if ( IsEqualGUID( &IID_IDirectDraw
, refiid
) )
194 *obj
= ICOM_INTERFACE(This
, IDirectDraw
);
196 else if ( IsEqualGUID( &IID_IDirectDraw2
, refiid
) )
198 *obj
= ICOM_INTERFACE(This
, IDirectDraw2
);
200 else if ( IsEqualGUID( &IID_IDirectDraw4
, refiid
) )
202 *obj
= ICOM_INTERFACE(This
, IDirectDraw4
);
205 else if ( IsEqualGUID( &IID_IDirect3D
, refiid
) ||
206 IsEqualGUID( &IID_IDirect3D2
, refiid
) ||
207 IsEqualGUID( &IID_IDirect3D3
, refiid
) ||
208 IsEqualGUID( &IID_IDirect3D7
, refiid
) )
210 if (opengl_initialized
) {
213 ret_value
= direct3d_create(This
);
214 if (FAILED(ret_value
)) return ret_value
;
216 if ( IsEqualGUID( &IID_IDirect3D
, refiid
) ) {
217 *obj
= ICOM_INTERFACE(This
, IDirect3D
);
218 TRACE(" returning Direct3D interface at %p.\n", *obj
);
219 } else if ( IsEqualGUID( &IID_IDirect3D2
, refiid
) ) {
220 *obj
= ICOM_INTERFACE(This
, IDirect3D2
);
221 TRACE(" returning Direct3D2 interface at %p.\n", *obj
);
222 } else if ( IsEqualGUID( &IID_IDirect3D3
, refiid
) ) {
223 *obj
= ICOM_INTERFACE(This
, IDirect3D3
);
224 TRACE(" returning Direct3D3 interface at %p.\n", *obj
);
226 *obj
= ICOM_INTERFACE(This
, IDirect3D7
);
227 TRACE(" returning Direct3D7 interface at %p.\n", *obj
);
230 ERR("Application requests a Direct3D interface but dynamic OpenGL support loading failed !\n");
231 ERR("(%p)->(%s,%p): no interface\n",This
,debugstr_guid(refiid
),obj
);
232 return E_NOINTERFACE
;
236 else if ( IsEqualGUID( &IID_IDirect3D
, refiid
) ||
237 IsEqualGUID( &IID_IDirect3D2
, refiid
) ||
238 IsEqualGUID( &IID_IDirect3D3
, refiid
) ||
239 IsEqualGUID( &IID_IDirect3D7
, refiid
) )
241 ERR("Application requests a Direct3D interface but OpenGL support not built-in !\n");
242 ERR("(%p)->(%s,%p): no interface\n",This
,debugstr_guid(refiid
),obj
);
243 return E_NOINTERFACE
;
248 FIXME("(%p)->(%s,%p): no interface\n",This
,debugstr_guid(refiid
),obj
);
249 return E_NOINTERFACE
;
252 IDirectDraw7_AddRef(iface
);
256 /* MSDN: "not currently implemented". */
257 HRESULT WINAPI
Main_DirectDraw_Compact(LPDIRECTDRAW7 iface
)
259 TRACE("(%p)\n", iface
);
264 HRESULT WINAPI
Main_DirectDraw_CreateClipper(LPDIRECTDRAW7 iface
,
266 LPDIRECTDRAWCLIPPER
*ppClipper
,
269 IDirectDrawImpl
*This
= (IDirectDrawImpl
*)iface
;
272 TRACE("(%p)->(0x%lx, %p, %p)\n", iface
, dwFlags
, ppClipper
, pUnkOuter
);
274 hr
= DirectDrawCreateClipper(dwFlags
, ppClipper
, pUnkOuter
);
275 if (FAILED(hr
)) return hr
;
277 /* dwFlags is passed twice, apparently an API wart. */
278 hr
= IDirectDrawClipper_Initialize(*ppClipper
,
279 ICOM_INTERFACE(This
, IDirectDraw
),
283 IDirectDrawClipper_Release(*ppClipper
);
291 Main_DirectDraw_CreatePalette(LPDIRECTDRAW7 iface
, DWORD dwFlags
,
292 LPPALETTEENTRY palent
,
293 LPDIRECTDRAWPALETTE
* ppPalette
,
296 IDirectDrawImpl
*This
= (IDirectDrawImpl
*)iface
;
297 LPDIRECTDRAWPALETTE pPalette
;
300 TRACE("(%p)->(%08lx,%p,%p,%p)\n",This
,dwFlags
,palent
,ppPalette
,pUnknown
);
302 if (ppPalette
== NULL
) return E_POINTER
; /* unchecked */
303 if (pUnknown
!= NULL
) return CLASS_E_NOAGGREGATION
; /* unchecked */
305 hr
= This
->create_palette(This
, dwFlags
, &pPalette
, pUnknown
);
306 if (FAILED(hr
)) return hr
;
308 hr
= IDirectDrawPalette_SetEntries(pPalette
, 0, 0,
309 Main_DirectDrawPalette_Size(dwFlags
),
313 IDirectDrawPalette_Release(pPalette
);
318 *ppPalette
= pPalette
;
324 Main_create_offscreen(IDirectDrawImpl
* This
, const DDSURFACEDESC2
* pDDSD
,
325 LPDIRECTDRAWSURFACE7
* ppSurf
, LPUNKNOWN pOuter
)
327 assert(pOuter
== NULL
);
329 return DIB_DirectDrawSurface_Create(This
, pDDSD
, ppSurf
, pOuter
);
333 Main_create_texture(IDirectDrawImpl
* This
, const DDSURFACEDESC2
* pDDSD
,
334 LPDIRECTDRAWSURFACE7
* ppSurf
, LPUNKNOWN pOuter
,
337 assert(pOuter
== NULL
);
339 return DIB_DirectDrawSurface_Create(This
, pDDSD
, ppSurf
, pOuter
);
343 Main_create_zbuffer(IDirectDrawImpl
* This
, const DDSURFACEDESC2
* pDDSD
,
344 LPDIRECTDRAWSURFACE7
* ppSurf
, LPUNKNOWN pOuter
)
346 assert(pOuter
== NULL
);
348 return FakeZBuffer_DirectDrawSurface_Create(This
, pDDSD
, ppSurf
, pOuter
);
351 /* Does the texture surface described in pDDSD have any smaller mipmaps? */
352 static BOOL
more_mipmaps(const DDSURFACEDESC2
*pDDSD
)
354 return ((pDDSD
->dwFlags
& DDSD_MIPMAPCOUNT
) && pDDSD
->u2
.dwMipMapCount
> 1
355 && (pDDSD
->dwWidth
> 1 || pDDSD
->dwHeight
> 1));
358 /* Create a texture surface along with any of its mipmaps. */
360 create_texture(IDirectDrawImpl
* This
, const DDSURFACEDESC2
*pDDSD
,
361 LPDIRECTDRAWSURFACE7
* ppSurf
, LPUNKNOWN pUnkOuter
)
364 DWORD mipmap_level
= 0;
367 assert(pUnkOuter
== NULL
);
369 /* is this check right? (pixelformat can be copied from primary) */
370 if ((pDDSD
->dwFlags
&(DDSD_HEIGHT
|DDSD_WIDTH
)) != (DDSD_HEIGHT
|DDSD_WIDTH
))
371 return DDERR_INVALIDPARAMS
;
373 ddsd
.dwSize
= sizeof(ddsd
);
374 DD_STRUCT_COPY_BYSIZE((&ddsd
),pDDSD
);
376 if (!(ddsd
.dwFlags
& DDSD_PIXELFORMAT
))
378 ddsd
.u4
.ddpfPixelFormat
= This
->pixelformat
;
382 /* We support for now only DXT1, DXT3 & DXT5 compressed texture formats... */
383 if ((ddsd
.u4
.ddpfPixelFormat
.dwFlags
& DDPF_FOURCC
) &&
384 (ddsd
.u4
.ddpfPixelFormat
.dwFourCC
!= MAKE_FOURCC('D','X','T','1')) &&
385 (ddsd
.u4
.ddpfPixelFormat
.dwFourCC
!= MAKE_FOURCC('D','X','T','3')) &&
386 (ddsd
.u4
.ddpfPixelFormat
.dwFourCC
!= MAKE_FOURCC('D','X','T','5')) )
388 return DDERR_INVALIDPIXELFORMAT
;
391 /* Check if we can really support DXT1, DXT3 & DXT5 */
392 if ((ddsd
.u4
.ddpfPixelFormat
.dwFlags
& DDPF_FOURCC
) &&
393 !GL_extensions
.s3tc_compressed_texture
&& !s3tc_initialized
) {
394 static BOOLEAN user_warned
= 0;
395 if (user_warned
== 0) {
396 ERR("Trying to create DXT1, DXT3 or DXT5 texture which is not supported by the video card!!!\n");
397 ERR("However there is a library libtxc_dxtn.so that can be used to do the software decompression...\n");
400 return DDERR_INVALIDPIXELFORMAT
;
403 if (ddsd
.u4
.ddpfPixelFormat
.dwFlags
& DDPF_FOURCC
)
405 return DDERR_INVALIDPIXELFORMAT
;
409 if ((ddsd
.u4
.ddpfPixelFormat
.dwFlags
& DDPF_FOURCC
) && !(ddsd
.dwFlags
& DDSD_LINEARSIZE
))
412 int width
= ddsd
.dwWidth
;
413 int height
= ddsd
.dwHeight
;
414 switch(ddsd
.u4
.ddpfPixelFormat
.dwFourCC
) {
415 case MAKE_FOURCC('D','X','T','1'): size
= ((width
+3)&~3) * ((height
+3)&~3) / 16 * 8; break;
416 case MAKE_FOURCC('D','X','T','3'): size
= ((width
+3)&~3) * ((height
+3)&~3) / 16 * 16; break;
417 case MAKE_FOURCC('D','X','T','5'): size
= ((width
+3)&~3) * ((height
+3)&~3) / 16 * 16; break;
418 default: FIXME("FOURCC not supported\n"); break;
420 ddsd
.u1
.dwLinearSize
= size
;
421 ddsd
.dwFlags
|= DDSD_LINEARSIZE
;
422 } else if (!(ddsd
.u4
.ddpfPixelFormat
.dwFlags
& DDPF_FOURCC
) && !(ddsd
.dwFlags
& DDSD_PITCH
)) {
423 ddsd
.u1
.lPitch
= DDRAW_width_bpp_to_pitch(ddsd
.dwWidth
, GET_BPP(ddsd
)*8);
424 ddsd
.dwFlags
|= DDSD_PITCH
;
427 if((ddsd
.ddsCaps
.dwCaps
& DDSCAPS_MIPMAP
) &&
428 !(ddsd
.dwFlags
& DDSD_MIPMAPCOUNT
))
430 if(ddsd
.ddsCaps
.dwCaps
& DDSCAPS_COMPLEX
)
432 /* Undocumented feature: if DDSCAPS_MIPMAP and DDSCAPS_COMPLEX are
433 * both set, but mipmap count isn't given, as many mipmap levels
434 * as necessary are created to get down to a size where either
435 * the width or the height of the texture is 1.
437 * This is needed by Anarchy Online. */
438 DWORD min
= ddsd
.dwWidth
< ddsd
.dwHeight
?
439 ddsd
.dwWidth
: ddsd
.dwHeight
;
440 ddsd
.u2
.dwMipMapCount
= 0;
443 ddsd
.u2
.dwMipMapCount
++;
448 /* Create a single mipmap. */
449 ddsd
.u2
.dwMipMapCount
= 1;
451 ddsd
.dwFlags
|= DDSD_MIPMAPCOUNT
;
454 ddsd
.dwFlags
|= DDSD_PIXELFORMAT
;
456 hr
= This
->create_texture(This
, &ddsd
, ppSurf
, pUnkOuter
, mipmap_level
);
457 if (FAILED(hr
)) return hr
;
459 if (This
->d3d_private
) This
->d3d_create_texture(This
, ICOM_OBJECT(IDirectDrawSurfaceImpl
, IDirectDrawSurface7
, *ppSurf
), TRUE
,
460 ICOM_OBJECT(IDirectDrawSurfaceImpl
, IDirectDrawSurface7
, *ppSurf
));
462 /* Create attached mipmaps if required. */
463 if (more_mipmaps(&ddsd
))
465 LPDIRECTDRAWSURFACE7 mipmap
;
466 LPDIRECTDRAWSURFACE7 prev_mipmap
;
467 DDSURFACEDESC2 mipmap_surface_desc
;
469 prev_mipmap
= *ppSurf
;
470 IDirectDrawSurface7_AddRef(prev_mipmap
);
471 mipmap_surface_desc
= ddsd
;
472 mipmap_surface_desc
.ddsCaps
.dwCaps2
|= DDSCAPS2_MIPMAPSUBLEVEL
;
474 while (more_mipmaps(&mipmap_surface_desc
))
476 IDirectDrawSurfaceImpl
*mipmap_impl
;
479 mipmap_surface_desc
.u2
.dwMipMapCount
--;
481 if (mipmap_surface_desc
.dwWidth
> 1)
482 mipmap_surface_desc
.dwWidth
/= 2;
484 if (mipmap_surface_desc
.dwHeight
> 1)
485 mipmap_surface_desc
.dwHeight
/= 2;
487 if (mipmap_surface_desc
.u4
.ddpfPixelFormat
.dwFlags
& DDPF_FOURCC
) {
489 int width
= mipmap_surface_desc
.dwWidth
;
490 int height
= mipmap_surface_desc
.dwHeight
;
491 switch(mipmap_surface_desc
.u4
.ddpfPixelFormat
.dwFourCC
) {
492 case MAKE_FOURCC('D','X','T','1'): size
= ((width
+3)&~3) * ((height
+3)&~3) / 16 * 8; break;
493 case MAKE_FOURCC('D','X','T','3'): size
= ((width
+3)&~3) * ((height
+3)&~3) / 16 * 16; break;
494 case MAKE_FOURCC('D','X','T','5'): size
= ((width
+3)&~3) * ((height
+3)&~3) / 16 * 16; break;
495 default: FIXME("FOURCC not supported\n"); break;
497 mipmap_surface_desc
.u1
.dwLinearSize
= size
;
499 ddsd
.u1
.lPitch
= DDRAW_width_bpp_to_pitch(ddsd
.dwWidth
, GET_BPP(ddsd
)*8);
500 mipmap_surface_desc
.u1
.lPitch
501 = DDRAW_width_bpp_to_pitch(mipmap_surface_desc
.dwWidth
,
505 hr
= This
->create_texture(This
, &mipmap_surface_desc
, &mipmap
,
506 pUnkOuter
, mipmap_level
);
509 IDirectDrawSurface7_Release(prev_mipmap
);
510 IDirectDrawSurface7_Release(*ppSurf
);
514 /* This is needed for delayed mipmap creation */
515 mipmap_impl
= ICOM_OBJECT(IDirectDrawSurfaceImpl
, IDirectDrawSurface7
, mipmap
);
516 mipmap_impl
->mip_main
= ICOM_OBJECT(IDirectDrawSurfaceImpl
, IDirectDrawSurface7
, *ppSurf
);
517 mipmap_impl
->mipmap_level
= mipmap_level
;
519 if (This
->d3d_private
) This
->d3d_create_texture(This
, ICOM_OBJECT(IDirectDrawSurfaceImpl
, IDirectDrawSurface7
, mipmap
), TRUE
,
520 ICOM_OBJECT(IDirectDrawSurfaceImpl
, IDirectDrawSurface7
, *ppSurf
));
522 IDirectDrawSurface7_AddAttachedSurface(prev_mipmap
, mipmap
);
523 IDirectDrawSurface7_Release(prev_mipmap
);
524 prev_mipmap
= mipmap
;
527 IDirectDrawSurface7_Release(prev_mipmap
);
533 /* Creates a primary surface and any indicated backbuffers. */
535 create_primary(IDirectDrawImpl
* This
, LPDDSURFACEDESC2 pDDSD
,
536 LPDIRECTDRAWSURFACE7
* ppSurf
, LPUNKNOWN pUnkOuter
)
541 assert(pUnkOuter
== NULL
);
543 if (This
->primary_surface
!= NULL
)
544 return DDERR_PRIMARYSURFACEALREADYEXISTS
;
546 /* as documented (what about pitch?) */
547 if (pDDSD
->dwFlags
& (DDSD_HEIGHT
|DDSD_WIDTH
|DDSD_PIXELFORMAT
))
548 return DDERR_INVALIDPARAMS
;
550 ddsd
.dwSize
= sizeof(ddsd
);
551 DD_STRUCT_COPY_BYSIZE((&ddsd
),pDDSD
);
552 ddsd
.dwFlags
|= DDSD_HEIGHT
| DDSD_WIDTH
| DDSD_PITCH
| DDSD_PIXELFORMAT
;
553 ddsd
.dwHeight
= This
->height
;
554 ddsd
.dwWidth
= This
->width
;
555 ddsd
.u1
.lPitch
= This
->pitch
;
556 ddsd
.u4
.ddpfPixelFormat
= This
->pixelformat
;
557 ddsd
.ddsCaps
.dwCaps
|= DDSCAPS_LOCALVIDMEM
| DDSCAPS_VIDEOMEMORY
558 | DDSCAPS_VISIBLE
| DDSCAPS_FRONTBUFFER
;
560 if ((ddsd
.dwFlags
& DDSD_BACKBUFFERCOUNT
) && ddsd
.dwBackBufferCount
> 0)
561 ddsd
.ddsCaps
.dwCaps
|= DDSCAPS_FLIP
;
563 hr
= This
->create_primary(This
, &ddsd
, ppSurf
, pUnkOuter
);
564 if (FAILED(hr
)) return hr
;
566 if (ddsd
.dwFlags
& DDSD_BACKBUFFERCOUNT
)
568 IDirectDrawSurfaceImpl
* primary
;
569 LPDIRECTDRAWSURFACE7 pPrev
;
572 ddsd
.dwFlags
&= ~DDSD_BACKBUFFERCOUNT
;
573 ddsd
.ddsCaps
.dwCaps
&= ~(DDSCAPS_VISIBLE
| DDSCAPS_PRIMARYSURFACE
574 | DDSCAPS_BACKBUFFER
| DDSCAPS_FRONTBUFFER
);
576 primary
= ICOM_OBJECT(IDirectDrawSurfaceImpl
,IDirectDrawSurface7
,
579 IDirectDrawSurface7_AddRef(pPrev
);
581 for (i
=0; i
< ddsd
.dwBackBufferCount
; i
++)
583 LPDIRECTDRAWSURFACE7 pBack
;
586 ddsd
.ddsCaps
.dwCaps
|= DDSCAPS_BACKBUFFER
;
588 ddsd
.ddsCaps
.dwCaps
&= ~DDSCAPS_BACKBUFFER
;
590 hr
= This
->create_backbuffer(This
, &ddsd
, &pBack
, pUnkOuter
,
595 IDirectDraw7_Release(pPrev
);
596 IDirectDraw7_Release(*ppSurf
);
600 IDirectDrawSurface7_AddAttachedSurface(pPrev
, pBack
);
601 IDirectDrawSurface7_Release(pPrev
);
605 IDirectDrawSurface7_Release(pPrev
);
608 This
->primary_surface
= (IDirectDrawSurfaceImpl
*)*ppSurf
;
614 create_offscreen(IDirectDrawImpl
* This
, LPDDSURFACEDESC2 pDDSD
,
615 LPDIRECTDRAWSURFACE7
* ppSurf
, LPUNKNOWN pUnkOuter
)
620 /* is this check right? (pixelformat can be copied from primary) */
621 if ((pDDSD
->dwFlags
&(DDSD_HEIGHT
|DDSD_WIDTH
)) != (DDSD_HEIGHT
|DDSD_WIDTH
))
622 return DDERR_INVALIDPARAMS
;
624 ddsd
.dwSize
= sizeof(ddsd
);
625 DD_STRUCT_COPY_BYSIZE((&ddsd
),pDDSD
);
627 if (!(ddsd
.dwFlags
& DDSD_PIXELFORMAT
))
629 ddsd
.u4
.ddpfPixelFormat
= This
->pixelformat
;
632 if (!(ddsd
.dwFlags
& DDSD_PITCH
))
634 ddsd
.u1
.lPitch
= DDRAW_width_bpp_to_pitch(ddsd
.dwWidth
,
638 ddsd
.dwFlags
|= DDSD_PITCH
| DDSD_PIXELFORMAT
;
640 hr
= This
->create_offscreen(This
, &ddsd
, ppSurf
, pUnkOuter
);
641 if (FAILED(hr
)) return hr
;
647 Main_DirectDraw_CreateSurface(LPDIRECTDRAW7 iface
, LPDDSURFACEDESC2 pDDSD
,
648 LPDIRECTDRAWSURFACE7
*ppSurf
,
652 IDirectDrawImpl
*This
= (IDirectDrawImpl
*)iface
;
654 TRACE("(%p)->(%p,%p,%p)\n",This
,pDDSD
,ppSurf
,pUnkOuter
);
655 if (TRACE_ON(ddraw
)) {
656 TRACE("Requesting surface desc :\n");
657 DDRAW_dump_surface_desc(pDDSD
);
660 if (pUnkOuter
!= NULL
) {
661 FIXME("outer != NULL?\n");
662 return CLASS_E_NOAGGREGATION
; /* unchecked */
665 if (!(pDDSD
->dwFlags
& DDSD_CAPS
)) {
666 /* DVIDEO.DLL does forget the DDSD_CAPS flag ... *sigh* */
667 pDDSD
->dwFlags
|= DDSD_CAPS
;
669 if (pDDSD
->ddsCaps
.dwCaps
== 0) {
670 /* This has been checked on real Windows */
671 pDDSD
->ddsCaps
.dwCaps
= DDSCAPS_LOCALVIDMEM
| DDSCAPS_VIDEOMEMORY
;
674 if (pDDSD
->ddsCaps
.dwCaps
& DDSCAPS_ALLOCONLOAD
) {
675 /* If the surface is of the 'alloconload' type, ignore the LPSURFACE field */
676 pDDSD
->dwFlags
&= ~DDSD_LPSURFACE
;
679 if ((pDDSD
->dwFlags
& DDSD_LPSURFACE
) && (pDDSD
->lpSurface
== NULL
)) {
680 /* Frank Herbert's Dune specifies a null pointer for the surface, ignore the LPSURFACE field */
681 WARN("Null surface pointer specified, ignore it!\n");
682 pDDSD
->dwFlags
&= ~DDSD_LPSURFACE
;
685 if (ppSurf
== NULL
) {
686 FIXME("You want to get back a surface? Don't give NULL ptrs!\n");
687 return E_POINTER
; /* unchecked */
690 if (pDDSD
->ddsCaps
.dwCaps
& DDSCAPS_PRIMARYSURFACE
)
692 /* create primary surface & backbuffers */
693 hr
= create_primary(This
, pDDSD
, ppSurf
, pUnkOuter
);
695 else if (pDDSD
->ddsCaps
.dwCaps
& DDSCAPS_BACKBUFFER
)
697 /* create backbuffer surface */
698 hr
= This
->create_backbuffer(This
, pDDSD
, ppSurf
, pUnkOuter
, NULL
);
700 else if (pDDSD
->ddsCaps
.dwCaps
& DDSCAPS_TEXTURE
)
703 hr
= create_texture(This
, pDDSD
, ppSurf
, pUnkOuter
);
705 else if ( (pDDSD
->ddsCaps
.dwCaps
& DDSCAPS_ZBUFFER
) &&
706 !(pDDSD
->ddsCaps
.dwCaps
& DDSCAPS_OFFSCREENPLAIN
)) /* Support DDSCAPS_SYSTEMMEMORY */
708 /* create z-buffer */
709 hr
= This
->create_zbuffer(This
, pDDSD
, ppSurf
, pUnkOuter
);
711 else if ((pDDSD
->ddsCaps
.dwCaps
& DDSCAPS_OFFSCREENPLAIN
) ||
712 (pDDSD
->ddsCaps
.dwCaps
& DDSCAPS_SYSTEMMEMORY
)) /* No difference in Wine right now */
714 /* create offscreenplain surface */
715 hr
= create_offscreen(This
, pDDSD
, ppSurf
, pUnkOuter
);
719 /* Otherwise, assume offscreenplain surface */
720 TRACE("App didn't request a valid surface type - assuming offscreenplain\n");
721 hr
= create_offscreen(This
, pDDSD
, ppSurf
, pUnkOuter
);
725 FIXME("failed surface creation with code 0x%08lx\n",hr
);
733 Main_DirectDraw_DuplicateSurface(LPDIRECTDRAW7 iface
, LPDIRECTDRAWSURFACE7 src
,
734 LPDIRECTDRAWSURFACE7
* dst
)
736 IDirectDrawImpl
*This
= (IDirectDrawImpl
*)iface
;
738 IDirectDrawSurfaceImpl
*pSrc
= ICOM_OBJECT(IDirectDrawSurfaceImpl
,
739 IDirectDrawSurface7
, src
);
741 TRACE("(%p)->(%p,%p)\n",This
,src
,dst
);
743 return pSrc
->duplicate_surface(pSrc
, dst
);
746 /* EnumDisplayModes */
748 BOOL
Main_DirectDraw_DDPIXELFORMAT_Match(const DDPIXELFORMAT
*requested
,
749 const DDPIXELFORMAT
*provided
)
751 /* Some flags must be present in both or neither for a match. */
752 static const DWORD must_match
= DDPF_PALETTEINDEXED1
| DDPF_PALETTEINDEXED2
753 | DDPF_PALETTEINDEXED4
| DDPF_PALETTEINDEXED8
| DDPF_FOURCC
754 | DDPF_ZBUFFER
| DDPF_STENCILBUFFER
;
756 if ((requested
->dwFlags
& provided
->dwFlags
) != requested
->dwFlags
)
759 if ((requested
->dwFlags
& must_match
) != (provided
->dwFlags
& must_match
))
762 if (requested
->dwFlags
& DDPF_FOURCC
)
763 if (requested
->dwFourCC
!= provided
->dwFourCC
)
766 if (requested
->dwFlags
& (DDPF_RGB
|DDPF_YUV
|DDPF_ZBUFFER
|DDPF_ALPHA
767 |DDPF_LUMINANCE
|DDPF_BUMPDUDV
))
768 if (requested
->u1
.dwRGBBitCount
!= provided
->u1
.dwRGBBitCount
)
771 if (requested
->dwFlags
& (DDPF_RGB
|DDPF_YUV
|DDPF_STENCILBUFFER
772 |DDPF_LUMINANCE
|DDPF_BUMPDUDV
))
773 if (requested
->u2
.dwRBitMask
!= provided
->u2
.dwRBitMask
)
776 if (requested
->dwFlags
& (DDPF_RGB
|DDPF_YUV
|DDPF_ZBUFFER
|DDPF_BUMPDUDV
))
777 if (requested
->u3
.dwGBitMask
!= provided
->u3
.dwGBitMask
)
780 /* I could be wrong about the bumpmapping. MSDN docs are vague. */
781 if (requested
->dwFlags
& (DDPF_RGB
|DDPF_YUV
|DDPF_STENCILBUFFER
783 if (requested
->u4
.dwBBitMask
!= provided
->u4
.dwBBitMask
)
786 if (requested
->dwFlags
& (DDPF_ALPHAPIXELS
|DDPF_ZPIXELS
))
787 if (requested
->u5
.dwRGBAlphaBitMask
!= provided
->u5
.dwRGBAlphaBitMask
)
793 BOOL
Main_DirectDraw_DDSD_Match(const DDSURFACEDESC2
* requested
,
794 const DDSURFACEDESC2
* provided
)
803 #define CMP(FLAG, FIELD) \
804 { DDSD_##FLAG, offsetof(DDSURFACEDESC2, FIELD), \
805 sizeof(((DDSURFACEDESC2 *)(NULL))->FIELD) }
807 static const struct compare_info compare
[] = {
808 CMP(ALPHABITDEPTH
, dwAlphaBitDepth
),
809 CMP(BACKBUFFERCOUNT
, dwBackBufferCount
),
811 CMP(CKDESTBLT
, ddckCKDestBlt
),
812 CMP(CKDESTOVERLAY
, u3
.ddckCKDestOverlay
),
813 CMP(CKSRCBLT
, ddckCKSrcBlt
),
814 CMP(CKSRCOVERLAY
, ddckCKSrcOverlay
),
815 CMP(HEIGHT
, dwHeight
),
816 CMP(LINEARSIZE
, u1
.dwLinearSize
),
817 CMP(LPSURFACE
, lpSurface
),
818 CMP(MIPMAPCOUNT
, u2
.dwMipMapCount
),
819 CMP(PITCH
, u1
.lPitch
),
820 /* PIXELFORMAT: manual */
821 CMP(REFRESHRATE
, u2
.dwRefreshRate
),
822 CMP(TEXTURESTAGE
, dwTextureStage
),
824 /* ZBUFFERBITDEPTH: "obsolete" */
831 if ((requested
->dwFlags
& provided
->dwFlags
) != requested
->dwFlags
)
834 for (i
=0; i
< sizeof(compare
)/sizeof(compare
[0]); i
++)
836 if (requested
->dwFlags
& compare
[i
].flag
837 && memcmp((const char *)provided
+ compare
[i
].offset
,
838 (const char *)requested
+ compare
[i
].offset
,
839 compare
[i
].size
) != 0)
843 if (requested
->dwFlags
& DDSD_PIXELFORMAT
)
845 if (!Main_DirectDraw_DDPIXELFORMAT_Match(&requested
->u4
.ddpfPixelFormat
,
846 &provided
->u4
.ddpfPixelFormat
))
853 #define DDENUMSURFACES_SEARCHTYPE (DDENUMSURFACES_CANBECREATED|DDENUMSURFACES_DOESEXIST)
854 #define DDENUMSURFACES_MATCHTYPE (DDENUMSURFACES_ALL|DDENUMSURFACES_MATCH|DDENUMSURFACES_NOMATCH)
856 /* This should be extended so that it can be used by
857 * IDirectDrawSurface7::EnumAttachedSurfaces. */
859 Main_DirectDraw_EnumExistingSurfaces(IDirectDrawImpl
*This
, DWORD dwFlags
,
860 LPDDSURFACEDESC2 lpDDSD2
, LPVOID context
,
861 LPDDENUMSURFACESCALLBACK7 callback
)
863 IDirectDrawSurfaceImpl
*surf
;
866 /* A NULL lpDDSD2 is permitted if we are enumerating all surfaces anyway */
867 if (lpDDSD2
== NULL
&& !(dwFlags
& DDENUMSURFACES_ALL
))
868 return DDERR_INVALIDPARAMS
;
870 all
= dwFlags
& DDENUMSURFACES_ALL
;
871 nomatch
= dwFlags
& DDENUMSURFACES_NOMATCH
;
873 for (surf
= This
->surfaces
; surf
!= NULL
; surf
= surf
->next_ddraw
)
876 || (nomatch
!= Main_DirectDraw_DDSD_Match(lpDDSD2
,
877 &surf
->surface_desc
)))
879 LPDIRECTDRAWSURFACE7 surface
= ICOM_INTERFACE(surf
,
880 IDirectDrawSurface7
);
882 /* BOGUS! Violates COM rules, but MSDN says so. */
883 IDirectDrawSurface7_AddRef(surface
);
885 if (callback(surface
, &surf
->surface_desc
, context
)
894 /* I really don't understand how this is supposed to work.
895 * We only consider dwHeight, dwWidth and ddpfPixelFormat.dwFlags. */
897 Main_DirectDraw_EnumCreateableSurfaces(IDirectDrawImpl
*This
, DWORD dwFlags
,
898 LPDDSURFACEDESC2 lpDDSD2
,
900 LPDDENUMSURFACESCALLBACK7 callback
)
902 FIXME("This isn't going to work.\n");
904 if ((dwFlags
& DDENUMSURFACES_MATCHTYPE
) != DDENUMSURFACES_MATCH
)
905 return DDERR_INVALIDPARAMS
;
907 /* TODO: implement this.
908 * Does this work before SCL is called?
909 * Does it only consider off-screen surfaces?
915 /* For unsigned x. 0 is not a power of 2. */
916 #define IS_POW_2(x) (((x) & ((x) - 1)) == 0)
919 Main_DirectDraw_EnumSurfaces(LPDIRECTDRAW7 iface
, DWORD dwFlags
,
920 LPDDSURFACEDESC2 lpDDSD2
, LPVOID context
,
921 LPDDENUMSURFACESCALLBACK7 callback
)
923 IDirectDrawImpl
*This
= (IDirectDrawImpl
*)iface
;
924 TRACE("(%p)->(0x%lx, %p, %p, %p)\n", iface
, dwFlags
, lpDDSD2
, context
,
927 if (callback
== NULL
)
928 return DDERR_INVALIDPARAMS
;
930 if (dwFlags
& ~(DDENUMSURFACES_SEARCHTYPE
|DDENUMSURFACES_MATCHTYPE
))
931 return DDERR_INVALIDPARAMS
;
933 if (!IS_POW_2(dwFlags
& DDENUMSURFACES_SEARCHTYPE
)
934 || !IS_POW_2(dwFlags
& DDENUMSURFACES_MATCHTYPE
))
935 return DDERR_INVALIDPARAMS
;
937 if (dwFlags
& DDENUMSURFACES_DOESEXIST
)
939 return Main_DirectDraw_EnumExistingSurfaces(This
, dwFlags
, lpDDSD2
,
944 return Main_DirectDraw_EnumCreateableSurfaces(This
, dwFlags
, lpDDSD2
,
950 Main_DirectDraw_EvaluateMode(LPDIRECTDRAW7 iface
,DWORD a
,DWORD
* b
)
952 IDirectDrawImpl
*This
= (IDirectDrawImpl
*)iface
;
953 FIXME("(%p)->() stub\n", This
);
959 Main_DirectDraw_FlipToGDISurface(LPDIRECTDRAW7 iface
)
961 IDirectDrawImpl
*This
= (IDirectDrawImpl
*)iface
;
962 TRACE("(%p)->()\n",This
);
967 Main_DirectDraw_GetCaps(LPDIRECTDRAW7 iface
, LPDDCAPS pDriverCaps
,
970 IDirectDrawImpl
*This
= (IDirectDrawImpl
*)iface
;
971 TRACE("(%p,%p,%p)\n",This
,pDriverCaps
,pHELCaps
);
972 if (pDriverCaps
!= NULL
) {
973 DD_STRUCT_COPY_BYSIZE(pDriverCaps
,&This
->caps
);
974 if (TRACE_ON(ddraw
)) {
975 TRACE("Driver Caps : \n");
976 DDRAW_dump_DDCAPS(pDriverCaps
);
979 if (pHELCaps
!= NULL
) {
980 DD_STRUCT_COPY_BYSIZE(pHELCaps
,&This
->caps
);
981 if (TRACE_ON(ddraw
)) {
982 TRACE("HEL Caps : \n");
983 DDRAW_dump_DDCAPS(pHELCaps
);
990 /* GetDeviceIdentifier */
994 Main_DirectDraw_GetFourCCCodes(LPDIRECTDRAW7 iface
, LPDWORD pNumCodes
,
997 IDirectDrawImpl
*This
= (IDirectDrawImpl
*)iface
;
1001 FIXME("(%p,%p,%p), stub\n",This
,pNumCodes
,pCodes
);
1006 Main_DirectDraw_GetGDISurface(LPDIRECTDRAW7 iface
,
1007 LPDIRECTDRAWSURFACE7
*lplpGDIDDSSurface
)
1009 IDirectDrawImpl
*This
= (IDirectDrawImpl
*)iface
;
1010 TRACE("(%p)->(%p)\n", This
, lplpGDIDDSSurface
);
1011 TRACE("returning primary (%p)\n", This
->primary_surface
);
1012 *lplpGDIDDSSurface
= ICOM_INTERFACE(This
->primary_surface
, IDirectDrawSurface7
);
1013 if (*lplpGDIDDSSurface
)
1014 IDirectDrawSurface7_AddRef(*lplpGDIDDSSurface
);
1019 Main_DirectDraw_GetMonitorFrequency(LPDIRECTDRAW7 iface
,LPDWORD freq
)
1021 IDirectDrawImpl
*This
= (IDirectDrawImpl
*)iface
;
1022 FIXME("(%p)->(%p) returns 60 Hz always\n",This
,freq
);
1023 *freq
= 60*100; /* 60 Hz */
1028 Main_DirectDraw_GetScanLine(LPDIRECTDRAW7 iface
, LPDWORD lpdwScanLine
)
1030 IDirectDrawImpl
*This
= (IDirectDrawImpl
*)iface
;
1033 /* Since this method is called often, show the fixme only once */
1035 FIXME("(%p)->(%p) semi-stub\n", This
, lpdwScanLine
);
1039 /* Fake the line sweeping of the monitor */
1040 /* FIXME: We should synchronize with a source to keep the refresh rate */
1041 *lpdwScanLine
= This
->cur_scanline
++;
1042 /* Assume 20 scan lines in the vertical blank */
1043 if (This
->cur_scanline
>= This
->height
+ 20)
1044 This
->cur_scanline
= 0;
1050 Main_DirectDraw_GetSurfaceFromDC(LPDIRECTDRAW7 iface
, HDC hdc
,
1051 LPDIRECTDRAWSURFACE7
*lpDDS
)
1053 IDirectDrawImpl
*This
= (IDirectDrawImpl
*)iface
;
1054 FIXME("(%p)->(%08ld,%p)\n", This
, (DWORD
) hdc
, lpDDS
);
1060 Main_DirectDraw_GetVerticalBlankStatus(LPDIRECTDRAW7 iface
, LPBOOL status
)
1062 IDirectDrawImpl
*This
= (IDirectDrawImpl
*)iface
;
1063 TRACE("(%p)->(%p)\n",This
,status
);
1068 /* If we were not initialised then Uninit_Main_IDirectDraw7_Initialize would
1069 * have been called instead. */
1071 Main_DirectDraw_Initialize(LPDIRECTDRAW7 iface
, LPGUID lpGuid
)
1073 TRACE("(%p)->(%s)\n", iface
, debugstr_guid(lpGuid
));
1075 return DDERR_ALREADYINITIALIZED
;
1079 Main_DirectDraw_RestoreAllSurfaces(LPDIRECTDRAW7 iface
)
1081 IDirectDrawImpl
*This
= (IDirectDrawImpl
*)iface
;
1082 IDirectDrawSurfaceImpl
* surf
;
1084 TRACE("(%p)->()\n", This
);
1086 for (surf
= This
->surfaces
; surf
!= NULL
; surf
= surf
->next_ddraw
)
1087 IDirectDrawSurface7_Restore(ICOM_INTERFACE(surf
, IDirectDrawSurface7
));
1092 static void DDRAW_SubclassWindow(IDirectDrawImpl
* This
)
1094 /* Well we don't actually subclass the window yet. */
1095 SetPropA(This
->window
, ddProp
, This
);
1098 static void DDRAW_UnsubclassWindow(IDirectDrawImpl
* This
)
1100 RemovePropA(This
->window
, ddProp
);
1104 Main_DirectDraw_SetCooperativeLevel(LPDIRECTDRAW7 iface
, HWND hwnd
,
1107 IDirectDrawImpl
*This
= (IDirectDrawImpl
*)iface
;
1109 FIXME("(%p)->(%08lx,%08lx)\n",This
,(DWORD
)hwnd
,cooplevel
);
1110 DDRAW_dump_cooperativelevel(cooplevel
);
1112 /* Makes realMYST test happy. */
1113 if (This
->cooperative_level
== cooplevel
1114 && This
->window
== hwnd
)
1117 /* XXX "It cannot be reset while the process has surfaces or palettes
1118 * created." Otherwise the window can be changed???
1120 * This appears to be wrong - comment it out for now.
1122 return DDERR_HWNDALREADYSET;
1125 if (!(cooplevel
& (DDSCL_EXCLUSIVE
|DDSCL_NORMAL
)))
1126 return DDERR_INVALIDPARAMS
;
1128 This
->window
= hwnd
;
1129 This
->cooperative_level
= cooplevel
;
1131 This
->local
.hWnd
= (ULONG_PTR
)hwnd
;
1132 This
->local
.dwLocalFlags
|= DDRAWILCL_SETCOOPCALLED
;
1133 /* not entirely sure about these */
1134 if (cooplevel
& DDSCL_EXCLUSIVE
) This
->local
.dwLocalFlags
|= DDRAWILCL_HASEXCLUSIVEMODE
;
1135 if (cooplevel
& DDSCL_FULLSCREEN
) This
->local
.dwLocalFlags
|= DDRAWILCL_ISFULLSCREEN
;
1136 if (cooplevel
& DDSCL_ALLOWMODEX
) This
->local
.dwLocalFlags
|= DDRAWILCL_ALLOWMODEX
;
1137 if (cooplevel
& DDSCL_MULTITHREADED
) This
->local
.dwLocalFlags
|= DDRAWILCL_MULTITHREADED
;
1138 if (cooplevel
& DDSCL_FPUSETUP
) This
->local
.dwLocalFlags
|= DDRAWILCL_FPUSETUP
;
1139 if (cooplevel
& DDSCL_FPUPRESERVE
) This
->local
.dwLocalFlags
|= DDRAWILCL_FPUPRESERVE
;
1141 if (This
->local
.lpGbl
) {
1142 /* assume that this app is the active app (in wine, there's
1143 * probably only one app per global ddraw object anyway) */
1144 if (cooplevel
& DDSCL_EXCLUSIVE
) This
->local
.lpGbl
->lpExclusiveOwner
= &This
->local
;
1145 else if (This
->local
.lpGbl
->lpExclusiveOwner
== &This
->local
)
1146 This
->local
.lpGbl
->lpExclusiveOwner
= NULL
;
1147 if (This
->set_exclusive_mode
)
1148 This
->set_exclusive_mode(This
, (cooplevel
& DDSCL_EXCLUSIVE
) != 0);
1151 ShowWindow(hwnd
, SW_SHOW
);
1153 DDRAW_SubclassWindow(This
);
1155 /* TODO Does it also get resized to the current screen size? */
1161 Main_DirectDraw_SetDisplayMode(LPDIRECTDRAW7 iface
, DWORD dwWidth
,
1162 DWORD dwHeight
, LONG lPitch
,
1163 DWORD dwRefreshRate
, DWORD dwFlags
,
1164 const DDPIXELFORMAT
* pixelformat
)
1169 IDirectDrawImpl
*This
= (IDirectDrawImpl
*)iface
;
1171 TRACE("(%p)->SetDisplayMode(%ld,%ld)\n",This
,dwWidth
,dwHeight
);
1173 if (!(This
->cooperative_level
& DDSCL_EXCLUSIVE
))
1174 return DDERR_NOEXCLUSIVEMODE
;
1176 if (!IsWindow(This
->window
))
1177 return DDERR_GENERIC
; /* unchecked */
1179 LosePrimarySurface(This
);
1181 screenX
= GetSystemMetrics(SM_CXSCREEN
);
1182 screenY
= GetSystemMetrics(SM_CYSCREEN
);
1184 This
->width
= dwWidth
;
1185 This
->height
= dwHeight
;
1186 This
->pitch
= lPitch
;
1187 This
->pixelformat
= *pixelformat
;
1189 /* Position the window in the center of the screen - don't center for now */
1190 /* MoveWindow(This->window, (screenX-dwWidth)/2, (screenY-dwHeight)/2,
1191 dwWidth, dwHeight, TRUE);*/
1192 MoveWindow(This
->window
, 0, 0, dwWidth
, dwHeight
, TRUE
);
1194 SetFocus(This
->window
);
1200 Main_DirectDraw_RestoreDisplayMode(LPDIRECTDRAW7 iface
)
1202 IDirectDrawImpl
*This
= (IDirectDrawImpl
*)iface
;
1204 TRACE("(%p)\n",This
);
1205 if (!(This
->cooperative_level
& DDSCL_EXCLUSIVE
))
1206 return DDERR_NOEXCLUSIVEMODE
;
1208 /* Lose the primary surface if the resolution changes. */
1209 if (This
->orig_width
!= This
->width
|| This
->orig_height
!= This
->height
1210 || This
->orig_pitch
!= This
->pitch
1211 || This
->orig_pixelformat
.dwFlags
!= This
->pixelformat
.dwFlags
1212 || !Main_DirectDraw_DDPIXELFORMAT_Match(&This
->pixelformat
,
1213 &This
->orig_pixelformat
))
1215 LosePrimarySurface(This
);
1218 /* TODO Move the window back where it belongs. */
1224 Main_DirectDraw_WaitForVerticalBlank(LPDIRECTDRAW7 iface
, DWORD dwFlags
,
1227 IDirectDrawImpl
*This
= (IDirectDrawImpl
*)iface
;
1228 FIXME("(%p)->(flags=0x%08lx,handle=%p)\n",This
,dwFlags
,h
);
1233 Main_DirectDraw_GetDisplayMode(LPDIRECTDRAW7 iface
, LPDDSURFACEDESC2 pDDSD
)
1235 IDirectDrawImpl
*This
= (IDirectDrawImpl
*)iface
;
1236 TRACE("(%p)->GetDisplayMode(%p)\n",This
,pDDSD
);
1238 pDDSD
->dwFlags
= DDSD_HEIGHT
|DDSD_WIDTH
|DDSD_PITCH
|DDSD_PIXELFORMAT
|DDSD_REFRESHRATE
;
1239 pDDSD
->dwHeight
= This
->height
;
1240 pDDSD
->dwWidth
= This
->width
;
1241 pDDSD
->u1
.lPitch
= This
->pitch
;
1242 pDDSD
->u2
.dwRefreshRate
= 60;
1243 pDDSD
->u4
.ddpfPixelFormat
= This
->pixelformat
;
1244 pDDSD
->ddsCaps
.dwCaps
= 0;
1249 static INT32
allocate_memory(IDirectDrawImpl
*This
, DWORD mem
)
1251 if (mem
> This
->available_vidmem
) return -1;
1252 This
->available_vidmem
-= mem
;
1253 return This
->available_vidmem
;
1256 static void free_memory(IDirectDrawImpl
*This
, DWORD mem
)
1258 This
->available_vidmem
+= mem
;
1262 Main_DirectDraw_GetAvailableVidMem(LPDIRECTDRAW7 iface
, LPDDSCAPS2 ddscaps
,
1263 LPDWORD total
, LPDWORD free
)
1265 IDirectDrawImpl
*This
= (IDirectDrawImpl
*)iface
;
1266 TRACE("(%p)->(%p,%p,%p)\n", This
,ddscaps
,total
,free
);
1268 if (TRACE_ON(ddraw
)) {
1269 TRACE(" Asking for memory of type : ");
1270 DDRAW_dump_DDSCAPS2(ddscaps
); TRACE("\n");
1273 /* We have 16 MB videomemory */
1274 if (total
) *total
= This
->total_vidmem
;
1275 if (free
) *free
= This
->available_vidmem
;
1277 TRACE(" returning (total) %ld / (free) %ld\n",
1278 total
!= NULL
? *total
: 0,
1279 free
!= NULL
? *free
: 0);
1284 HRESULT WINAPI
Main_DirectDraw_TestCooperativeLevel(LPDIRECTDRAW7 iface
) {
1285 IDirectDrawImpl
*This
= (IDirectDrawImpl
*)iface
;
1286 TRACE("(%p)->(): stub\n", This
);
1292 Main_DirectDraw_StartModeTest(LPDIRECTDRAW7 iface
, LPSIZE pModes
,
1293 DWORD dwNumModes
, DWORD dwFlags
)
1295 IDirectDrawImpl
*This
= (IDirectDrawImpl
*)iface
;
1296 FIXME("(%p)->() stub\n", This
);
1301 /*** Owned object management. */
1303 void Main_DirectDraw_AddSurface(IDirectDrawImpl
* This
,
1304 IDirectDrawSurfaceImpl
* surface
)
1306 assert(surface
->ddraw_owner
== NULL
|| surface
->ddraw_owner
== This
);
1308 surface
->ddraw_owner
= This
;
1310 /* where should it go? */
1311 surface
->next_ddraw
= This
->surfaces
;
1312 surface
->prev_ddraw
= NULL
;
1314 This
->surfaces
->prev_ddraw
= surface
;
1315 This
->surfaces
= surface
;
1318 void Main_DirectDraw_RemoveSurface(IDirectDrawImpl
* This
,
1319 IDirectDrawSurfaceImpl
* surface
)
1321 assert(surface
->ddraw_owner
== This
);
1323 if (This
->surfaces
== surface
)
1324 This
->surfaces
= surface
->next_ddraw
;
1326 if (This
->primary_surface
== surface
)
1327 This
->primary_surface
= NULL
;
1329 if (surface
->next_ddraw
)
1330 surface
->next_ddraw
->prev_ddraw
= surface
->prev_ddraw
;
1331 if (surface
->prev_ddraw
)
1332 surface
->prev_ddraw
->next_ddraw
= surface
->next_ddraw
;
1335 static void Main_DirectDraw_DeleteSurfaces(IDirectDrawImpl
* This
)
1337 while (This
->surfaces
!= NULL
)
1338 Main_DirectDrawSurface_ForceDestroy(This
->surfaces
);
1341 void Main_DirectDraw_AddClipper(IDirectDrawImpl
* This
,
1342 IDirectDrawClipperImpl
* clipper
)
1344 assert(clipper
->ddraw_owner
== NULL
|| clipper
->ddraw_owner
== This
);
1346 clipper
->ddraw_owner
= This
;
1348 clipper
->next_ddraw
= This
->clippers
;
1349 clipper
->prev_ddraw
= NULL
;
1351 This
->clippers
->prev_ddraw
= clipper
;
1352 This
->clippers
= clipper
;
1355 void Main_DirectDraw_RemoveClipper(IDirectDrawImpl
* This
,
1356 IDirectDrawClipperImpl
* clipper
)
1358 assert(clipper
->ddraw_owner
== This
);
1360 if (This
->clippers
== clipper
)
1361 This
->clippers
= clipper
->next_ddraw
;
1363 if (clipper
->next_ddraw
)
1364 clipper
->next_ddraw
->prev_ddraw
= clipper
->prev_ddraw
;
1365 if (clipper
->prev_ddraw
)
1366 clipper
->prev_ddraw
->next_ddraw
= clipper
->next_ddraw
;
1369 static void Main_DirectDraw_DeleteClippers(IDirectDrawImpl
* This
)
1371 while (This
->clippers
!= NULL
)
1372 Main_DirectDrawClipper_ForceDestroy(This
->clippers
);
1375 void Main_DirectDraw_AddPalette(IDirectDrawImpl
* This
,
1376 IDirectDrawPaletteImpl
* palette
)
1378 assert(palette
->ddraw_owner
== NULL
|| palette
->ddraw_owner
== This
);
1380 palette
->ddraw_owner
= This
;
1382 /* where should it go? */
1383 palette
->next_ddraw
= This
->palettes
;
1384 palette
->prev_ddraw
= NULL
;
1386 This
->palettes
->prev_ddraw
= palette
;
1387 This
->palettes
= palette
;
1390 void Main_DirectDraw_RemovePalette(IDirectDrawImpl
* This
,
1391 IDirectDrawPaletteImpl
* palette
)
1393 IDirectDrawSurfaceImpl
*surf
;
1395 assert(palette
->ddraw_owner
== This
);
1397 if (This
->palettes
== palette
)
1398 This
->palettes
= palette
->next_ddraw
;
1400 if (palette
->next_ddraw
)
1401 palette
->next_ddraw
->prev_ddraw
= palette
->prev_ddraw
;
1402 if (palette
->prev_ddraw
)
1403 palette
->prev_ddraw
->next_ddraw
= palette
->next_ddraw
;
1405 /* Here we need also to remove tha palette from any surface which has it as the
1406 * current palette (checked on Windows)
1408 for (surf
= This
->surfaces
; surf
!= NULL
; surf
= surf
->next_ddraw
) {
1409 if (surf
->palette
== palette
) {
1410 TRACE("Palette %p attached to surface %p.\n", palette
, surf
);
1411 surf
->palette
= NULL
;
1412 surf
->set_palette(surf
, NULL
);
1417 static void Main_DirectDraw_DeletePalettes(IDirectDrawImpl
* This
)
1419 while (This
->palettes
!= NULL
)
1420 Main_DirectDrawPalette_ForceDestroy(This
->palettes
);
1426 LoseSurface(IDirectDrawSurfaceImpl
*surface
)
1428 if (surface
!= NULL
) surface
->lose_surface(surface
);
1432 LosePrimarySurface(IDirectDrawImpl
*This
)
1434 /* MSDN: "If another application changes the display mode, the primary
1435 * surface is lost, and the method returns DDERR_SURFACELOST until the
1436 * primary surface is recreated to match the new display mode."
1438 * We mark all the primary surfaces as lost as soon as the display
1439 * mode is changed (by any application). */
1441 LoseSurface(This
->primary_surface
);
1444 /******************************************************************************
1445 * Uninitialised DirectDraw functions
1447 * This vtable is used when a DirectDraw object is created with
1448 * CoCreateInstance. The only usable method is Initialize.
1451 void Uninit_DirectDraw_final_release(IDirectDrawImpl
*This
)
1453 Main_DirectDraw_final_release(This
);
1456 static const IDirectDraw7Vtbl Uninit_DirectDraw_VTable
;
1458 /* Not called from the vtable. */
1459 HRESULT
Uninit_DirectDraw_Construct(IDirectDrawImpl
*This
, BOOL ex
)
1463 hr
= Main_DirectDraw_Construct(This
, ex
);
1464 if (FAILED(hr
)) return hr
;
1466 This
->final_release
= Uninit_DirectDraw_final_release
;
1467 ICOM_INIT_INTERFACE(This
, IDirectDraw7
, Uninit_DirectDraw_VTable
);
1472 HRESULT
Uninit_DirectDraw_Create(const GUID
* pGUID
,
1473 LPDIRECTDRAW7
* pIface
,
1474 IUnknown
* pUnkOuter
, BOOL ex
)
1477 IDirectDrawImpl
* This
;
1479 assert(pUnkOuter
== NULL
); /* XXX no: we must check this */
1481 This
= HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY
,
1482 sizeof(IDirectDrawImpl
));
1483 if (This
== NULL
) return E_OUTOFMEMORY
;
1485 hr
= Uninit_DirectDraw_Construct(This
, ex
);
1487 HeapFree(GetProcessHeap(), HEAP_ZERO_MEMORY
, This
);
1489 *pIface
= ICOM_INTERFACE(This
, IDirectDraw7
);
1494 static HRESULT WINAPI
1495 Uninit_DirectDraw_Initialize(LPDIRECTDRAW7 iface
, LPGUID pDeviceGuid
)
1497 const ddraw_driver
* driver
;
1498 IDirectDrawImpl
*This
= (IDirectDrawImpl
*)iface
;
1500 TRACE("(%p)->(%p)\n", iface
, pDeviceGuid
);
1502 driver
= DDRAW_FindDriver(pDeviceGuid
);
1503 /* XXX This return value is not documented. (Not checked.) */
1504 if (driver
== NULL
) return DDERR_INVALIDDIRECTDRAWGUID
;
1506 return driver
->init(This
, pDeviceGuid
);
1509 static HRESULT WINAPI
1510 Uninit_DirectDraw_Compact(LPDIRECTDRAW7 iface
)
1512 return DDERR_NOTINITIALIZED
;
1515 static HRESULT WINAPI
1516 Uninit_DirectDraw_CreateClipper(LPDIRECTDRAW7 iface
, DWORD dwFlags
,
1517 LPDIRECTDRAWCLIPPER
*lplpDDClipper
,
1518 IUnknown
*pUnkOuter
)
1521 return DDERR_NOTINITIALIZED
;
1524 static HRESULT WINAPI
1525 Uninit_DirectDraw_CreatePalette(LPDIRECTDRAW7 iface
, DWORD dwFlags
,
1526 LPPALETTEENTRY lpColorTable
,
1527 LPDIRECTDRAWPALETTE
*lplpDDPalette
,
1528 IUnknown
*pUnkOuter
)
1530 return DDERR_NOTINITIALIZED
;
1533 static HRESULT WINAPI
1534 Uninit_DirectDraw_CreateSurface(LPDIRECTDRAW7 iface
,
1535 LPDDSURFACEDESC2 lpDDSurfaceDesc
,
1536 LPDIRECTDRAWSURFACE7
*lplpDDSurface
,
1537 IUnknown
*pUnkOuter
)
1539 return DDERR_NOTINITIALIZED
;
1542 static HRESULT WINAPI
1543 Uninit_DirectDraw_DuplicateSurface(LPDIRECTDRAW7 iface
,
1544 LPDIRECTDRAWSURFACE7 pSurf
,
1545 LPDIRECTDRAWSURFACE7
*pDupSurf
)
1548 return DDERR_NOTINITIALIZED
;
1551 static HRESULT WINAPI
1552 Uninit_DirectDraw_EnumDisplayModes(LPDIRECTDRAW7 iface
, DWORD dwFlags
,
1553 LPDDSURFACEDESC2 lpDDSD
,
1555 LPDDENUMMODESCALLBACK2 cb
)
1557 return DDERR_NOTINITIALIZED
;
1560 static HRESULT WINAPI
1561 Uninit_DirectDraw_EnumSurfaces(LPDIRECTDRAW7 iface
, DWORD dwFlags
,
1562 LPDDSURFACEDESC2 pDDSD
, LPVOID context
,
1563 LPDDENUMSURFACESCALLBACK7 cb
)
1565 return DDERR_NOTINITIALIZED
;
1568 static HRESULT WINAPI
1569 Uninit_DirectDraw_FlipToGDISurface(LPDIRECTDRAW7 iface
)
1571 return DDERR_NOTINITIALIZED
;
1574 static HRESULT WINAPI
1575 Uninit_DirectDraw_GetCaps(LPDIRECTDRAW7 iface
, LPDDCAPS pDriverCaps
,
1578 return DDERR_NOTINITIALIZED
;
1581 static HRESULT WINAPI
1582 Uninit_DirectDraw_GetDisplayMode(LPDIRECTDRAW7 iface
,
1583 LPDDSURFACEDESC2 pDDSD
)
1585 return DDERR_NOTINITIALIZED
;
1588 static HRESULT WINAPI
1589 Uninit_DirectDraw_GetFourCCCodes(LPDIRECTDRAW7 iface
, LPDWORD pNumCodes
,
1592 return DDERR_NOTINITIALIZED
;
1595 static HRESULT WINAPI
1596 Uninit_DirectDraw_GetGDISurface(LPDIRECTDRAW7 iface
,
1597 LPDIRECTDRAWSURFACE7
*pGDISurf
)
1599 return DDERR_NOTINITIALIZED
;
1602 static HRESULT WINAPI
1603 Uninit_DirectDraw_GetMonitorFrequency(LPDIRECTDRAW7 iface
, LPDWORD pdwFreq
)
1605 return DDERR_NOTINITIALIZED
;
1608 static HRESULT WINAPI
1609 Uninit_DirectDraw_GetScanLine(LPDIRECTDRAW7 iface
, LPDWORD pdwScanLine
)
1611 return DDERR_NOTINITIALIZED
;
1614 static HRESULT WINAPI
1615 Uninit_DirectDraw_GetVerticalBlankStatus(LPDIRECTDRAW7 iface
, PBOOL pbIsInVB
)
1617 return DDERR_NOTINITIALIZED
;
1620 static HRESULT WINAPI
1621 Uninit_DirectDraw_RestoreDisplayMode(LPDIRECTDRAW7 iface
)
1623 return DDERR_NOTINITIALIZED
;
1626 static HRESULT WINAPI
1627 Uninit_DirectDraw_SetCooperativeLevel(LPDIRECTDRAW7 iface
, HWND hWnd
,
1630 return DDERR_NOTINITIALIZED
;
1633 static HRESULT WINAPI
1634 Uninit_DirectDraw_SetDisplayMode(LPDIRECTDRAW7 iface
, DWORD dwWidth
,
1635 DWORD dwHeight
, DWORD dwBPP
,
1636 DWORD dwRefreshRate
, DWORD dwFlags
)
1638 return DDERR_NOTINITIALIZED
;
1641 static HRESULT WINAPI
1642 Uninit_DirectDraw_WaitForVerticalBlank(LPDIRECTDRAW7 iface
, DWORD dwFlags
,
1645 return DDERR_NOTINITIALIZED
;
1648 static HRESULT WINAPI
1649 Uninit_DirectDraw_GetAvailableVidMem(LPDIRECTDRAW7 iface
, LPDDSCAPS2 pDDCaps
,
1650 LPDWORD pdwTotal
, LPDWORD pdwFree
)
1652 return DDERR_NOTINITIALIZED
;
1655 static HRESULT WINAPI
1656 Uninit_DirectDraw_GetSurfaceFromDC(LPDIRECTDRAW7 iface
, HDC hDC
,
1657 LPDIRECTDRAWSURFACE7
*pSurf
)
1659 return DDERR_NOTINITIALIZED
;
1662 static HRESULT WINAPI
1663 Uninit_DirectDraw_RestoreAllSurfaces(LPDIRECTDRAW7 iface
)
1665 return DDERR_NOTINITIALIZED
;
1668 static HRESULT WINAPI
1669 Uninit_DirectDraw_TestCooperativeLevel(LPDIRECTDRAW7 iface
)
1671 return DDERR_NOTINITIALIZED
;
1674 static HRESULT WINAPI
1675 Uninit_DirectDraw_GetDeviceIdentifier(LPDIRECTDRAW7 iface
,
1676 LPDDDEVICEIDENTIFIER2 pDDDI
,
1679 return DDERR_NOTINITIALIZED
;
1682 static HRESULT WINAPI
1683 Uninit_DirectDraw_StartModeTest(LPDIRECTDRAW7 iface
, LPSIZE pszModes
,
1684 DWORD cModes
, DWORD dwFlags
)
1686 return DDERR_NOTINITIALIZED
;
1689 static HRESULT WINAPI
1690 Uninit_DirectDraw_EvaluateMode(LPDIRECTDRAW7 iface
, DWORD dwFlags
,
1693 return DDERR_NOTINITIALIZED
;
1696 static const IDirectDraw7Vtbl Uninit_DirectDraw_VTable
=
1698 Main_DirectDraw_QueryInterface
,
1699 Main_DirectDraw_AddRef
,
1700 Main_DirectDraw_Release
,
1701 Uninit_DirectDraw_Compact
,
1702 Uninit_DirectDraw_CreateClipper
,
1703 Uninit_DirectDraw_CreatePalette
,
1704 Uninit_DirectDraw_CreateSurface
,
1705 Uninit_DirectDraw_DuplicateSurface
,
1706 Uninit_DirectDraw_EnumDisplayModes
,
1707 Uninit_DirectDraw_EnumSurfaces
,
1708 Uninit_DirectDraw_FlipToGDISurface
,
1709 Uninit_DirectDraw_GetCaps
,
1710 Uninit_DirectDraw_GetDisplayMode
,
1711 Uninit_DirectDraw_GetFourCCCodes
,
1712 Uninit_DirectDraw_GetGDISurface
,
1713 Uninit_DirectDraw_GetMonitorFrequency
,
1714 Uninit_DirectDraw_GetScanLine
,
1715 Uninit_DirectDraw_GetVerticalBlankStatus
,
1716 Uninit_DirectDraw_Initialize
,
1717 Uninit_DirectDraw_RestoreDisplayMode
,
1718 Uninit_DirectDraw_SetCooperativeLevel
,
1719 Uninit_DirectDraw_SetDisplayMode
,
1720 Uninit_DirectDraw_WaitForVerticalBlank
,
1721 Uninit_DirectDraw_GetAvailableVidMem
,
1722 Uninit_DirectDraw_GetSurfaceFromDC
,
1723 Uninit_DirectDraw_RestoreAllSurfaces
,
1724 Uninit_DirectDraw_TestCooperativeLevel
,
1725 Uninit_DirectDraw_GetDeviceIdentifier
,
1726 Uninit_DirectDraw_StartModeTest
,
1727 Uninit_DirectDraw_EvaluateMode