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
65 #include "wine/debug.h"
67 #include "ddraw_private.h"
68 #include "opengl_private.h" /* To have the D3D creation function */
70 WINE_DEFAULT_DEBUG_CHANNEL(ddraw
);
72 extern const IDirectDrawVtbl DDRAW_IDirectDraw_VTable
;
73 extern const IDirectDraw2Vtbl DDRAW_IDirectDraw2_VTable
;
74 extern const IDirectDraw4Vtbl DDRAW_IDirectDraw4_VTable
;
76 static void DDRAW_UnsubclassWindow(IDirectDrawImpl
* This
);
78 static void Main_DirectDraw_DeleteSurfaces(IDirectDrawImpl
* This
);
79 static void Main_DirectDraw_DeleteClippers(IDirectDrawImpl
* This
);
80 static void Main_DirectDraw_DeletePalettes(IDirectDrawImpl
* This
);
81 static void LosePrimarySurface(IDirectDrawImpl
* This
);
83 static INT32
allocate_memory(IDirectDrawImpl
*This
, DWORD mem
) ;
84 static void free_memory(IDirectDrawImpl
*This
, DWORD mem
) ;
87 static const char ddProp
[] = "WINE_DDRAW_Property";
89 /* Not called from the vtable. */
90 HRESULT
Main_DirectDraw_Construct(IDirectDrawImpl
*This
, BOOL ex
)
92 /* NOTE: The creator must use HEAP_ZERO_MEMORY or equivalent. */
96 if (ex
) This
->local
.dwLocalFlags
|= DDRAWILCL_DIRECTDRAW7
;
97 This
->local
.dwProcessId
= GetCurrentProcessId();
99 This
->final_release
= Main_DirectDraw_final_release
;
101 This
->create_palette
= Main_DirectDrawPalette_Create
;
103 This
->create_offscreen
= Main_create_offscreen
;
104 This
->create_texture
= Main_create_texture
;
105 This
->create_zbuffer
= Main_create_zbuffer
;
106 /* There are no generic versions of create_{primary,backbuffer}. */
108 ICOM_INIT_INTERFACE(This
, IDirectDraw
, DDRAW_IDirectDraw_VTable
);
109 ICOM_INIT_INTERFACE(This
, IDirectDraw2
, DDRAW_IDirectDraw2_VTable
);
110 ICOM_INIT_INTERFACE(This
, IDirectDraw4
, DDRAW_IDirectDraw4_VTable
);
111 /* There is no generic implementation of IDD7 */
113 /* This is for the moment here... */
114 This
->free_memory
= free_memory
;
115 This
->allocate_memory
= allocate_memory
;
116 This
->total_vidmem
= 64 * 1024 * 1024;
117 This
->available_vidmem
= This
->total_vidmem
;
122 void Main_DirectDraw_final_release(IDirectDrawImpl
* This
)
124 if (IsWindow(This
->window
))
126 if (GetPropA(This
->window
, ddProp
))
127 DDRAW_UnsubclassWindow(This
);
129 FIXME("this shouldn't happen, right?\n");
132 Main_DirectDraw_DeleteSurfaces(This
);
133 Main_DirectDraw_DeleteClippers(This
);
134 Main_DirectDraw_DeletePalettes(This
);
135 if (This
->local
.lpGbl
&& This
->local
.lpGbl
->lpExclusiveOwner
== &This
->local
)
137 This
->local
.lpGbl
->lpExclusiveOwner
= NULL
;
138 if (This
->set_exclusive_mode
)
139 This
->set_exclusive_mode(This
, FALSE
);
143 /* There is no Main_DirectDraw_Create. */
145 ULONG WINAPI
Main_DirectDraw_AddRef(LPDIRECTDRAW7 iface
) {
146 IDirectDrawImpl
*This
= (IDirectDrawImpl
*)iface
;
147 ULONG ref
= InterlockedIncrement(&This
->ref
);
149 TRACE("(%p)->() incrementing from %lu.\n", This
, ref
-1);
154 ULONG WINAPI
Main_DirectDraw_Release(LPDIRECTDRAW7 iface
) {
155 IDirectDrawImpl
*This
= (IDirectDrawImpl
*)iface
;
156 ULONG ref
= InterlockedDecrement(&This
->ref
);
158 TRACE("(%p)->() decrementing from %lu.\n", This
, ref
+1);
162 if (This
->final_release
!= NULL
)
163 This
->final_release(This
);
165 /* We free the private. This is an artifact of the fact that I don't
166 * have the destructors set up correctly. */
167 if (This
->private != (This
+1))
168 HeapFree(GetProcessHeap(), 0, This
->private);
170 HeapFree(GetProcessHeap(), 0, This
);
176 HRESULT WINAPI
Main_DirectDraw_QueryInterface(
177 LPDIRECTDRAW7 iface
,REFIID refiid
,LPVOID
*obj
179 IDirectDrawImpl
*This
= (IDirectDrawImpl
*)iface
;
180 TRACE("(%p)->(%s,%p)\n", This
, debugstr_guid(refiid
), obj
);
182 /* According to COM docs, if the QueryInterface fails, obj should be set to NULL */
185 if ( IsEqualGUID( &IID_IUnknown
, refiid
)
186 || IsEqualGUID( &IID_IDirectDraw7
, refiid
) )
188 *obj
= ICOM_INTERFACE(This
, IDirectDraw7
);
190 else if ( IsEqualGUID( &IID_IDirectDraw
, refiid
) )
192 *obj
= ICOM_INTERFACE(This
, IDirectDraw
);
194 else if ( IsEqualGUID( &IID_IDirectDraw2
, refiid
) )
196 *obj
= ICOM_INTERFACE(This
, IDirectDraw2
);
198 else if ( IsEqualGUID( &IID_IDirectDraw4
, refiid
) )
200 *obj
= ICOM_INTERFACE(This
, IDirectDraw4
);
203 else if ( IsEqualGUID( &IID_IDirect3D
, refiid
) ||
204 IsEqualGUID( &IID_IDirect3D2
, refiid
) ||
205 IsEqualGUID( &IID_IDirect3D3
, refiid
) ||
206 IsEqualGUID( &IID_IDirect3D7
, refiid
) )
208 if (opengl_initialized
) {
211 ret_value
= direct3d_create(This
);
212 if (FAILED(ret_value
)) return ret_value
;
214 if ( IsEqualGUID( &IID_IDirect3D
, refiid
) ) {
215 *obj
= ICOM_INTERFACE(This
, IDirect3D
);
216 TRACE(" returning Direct3D interface at %p.\n", *obj
);
217 } else if ( IsEqualGUID( &IID_IDirect3D2
, refiid
) ) {
218 *obj
= ICOM_INTERFACE(This
, IDirect3D2
);
219 TRACE(" returning Direct3D2 interface at %p.\n", *obj
);
220 } else if ( IsEqualGUID( &IID_IDirect3D3
, refiid
) ) {
221 *obj
= ICOM_INTERFACE(This
, IDirect3D3
);
222 TRACE(" returning Direct3D3 interface at %p.\n", *obj
);
224 *obj
= ICOM_INTERFACE(This
, IDirect3D7
);
225 TRACE(" returning Direct3D7 interface at %p.\n", *obj
);
228 ERR("Application requests a Direct3D interface but dynamic OpenGL support loading failed !\n");
229 ERR("(%p)->(%s,%p): no interface\n",This
,debugstr_guid(refiid
),obj
);
230 return E_NOINTERFACE
;
234 else if ( IsEqualGUID( &IID_IDirect3D
, refiid
) ||
235 IsEqualGUID( &IID_IDirect3D2
, refiid
) ||
236 IsEqualGUID( &IID_IDirect3D3
, refiid
) ||
237 IsEqualGUID( &IID_IDirect3D7
, refiid
) )
239 ERR("Application requests a Direct3D interface but OpenGL support not built-in !\n");
240 ERR("(%p)->(%s,%p): no interface\n",This
,debugstr_guid(refiid
),obj
);
241 return E_NOINTERFACE
;
246 FIXME("(%p)->(%s,%p): no interface\n",This
,debugstr_guid(refiid
),obj
);
247 return E_NOINTERFACE
;
250 IDirectDraw7_AddRef(iface
);
254 /* MSDN: "not currently implemented". */
255 HRESULT WINAPI
Main_DirectDraw_Compact(LPDIRECTDRAW7 iface
)
257 TRACE("(%p)\n", iface
);
262 HRESULT WINAPI
Main_DirectDraw_CreateClipper(LPDIRECTDRAW7 iface
,
264 LPDIRECTDRAWCLIPPER
*ppClipper
,
267 IDirectDrawImpl
*This
= (IDirectDrawImpl
*)iface
;
270 TRACE("(%p)->(0x%lx, %p, %p)\n", iface
, dwFlags
, ppClipper
, pUnkOuter
);
272 hr
= DirectDrawCreateClipper(dwFlags
, ppClipper
, pUnkOuter
);
273 if (FAILED(hr
)) return hr
;
275 /* dwFlags is passed twice, apparently an API wart. */
276 hr
= IDirectDrawClipper_Initialize(*ppClipper
,
277 ICOM_INTERFACE(This
, IDirectDraw
),
281 IDirectDrawClipper_Release(*ppClipper
);
289 Main_DirectDraw_CreatePalette(LPDIRECTDRAW7 iface
, DWORD dwFlags
,
290 LPPALETTEENTRY palent
,
291 LPDIRECTDRAWPALETTE
* ppPalette
,
294 IDirectDrawImpl
*This
= (IDirectDrawImpl
*)iface
;
295 LPDIRECTDRAWPALETTE pPalette
;
298 TRACE("(%p)->(%08lx,%p,%p,%p)\n",This
,dwFlags
,palent
,ppPalette
,pUnknown
);
300 if (ppPalette
== NULL
) return E_POINTER
; /* unchecked */
301 if (pUnknown
!= NULL
) return CLASS_E_NOAGGREGATION
; /* unchecked */
303 hr
= This
->create_palette(This
, dwFlags
, &pPalette
, pUnknown
);
304 if (FAILED(hr
)) return hr
;
306 hr
= IDirectDrawPalette_SetEntries(pPalette
, 0, 0,
307 Main_DirectDrawPalette_Size(dwFlags
),
311 IDirectDrawPalette_Release(pPalette
);
316 *ppPalette
= pPalette
;
322 Main_create_offscreen(IDirectDrawImpl
* This
, const DDSURFACEDESC2
* pDDSD
,
323 LPDIRECTDRAWSURFACE7
* ppSurf
, LPUNKNOWN pOuter
)
325 assert(pOuter
== NULL
);
327 return DIB_DirectDrawSurface_Create(This
, pDDSD
, ppSurf
, pOuter
);
331 Main_create_texture(IDirectDrawImpl
* This
, const DDSURFACEDESC2
* pDDSD
,
332 LPDIRECTDRAWSURFACE7
* ppSurf
, LPUNKNOWN pOuter
,
335 assert(pOuter
== NULL
);
337 return DIB_DirectDrawSurface_Create(This
, pDDSD
, ppSurf
, pOuter
);
341 Main_create_zbuffer(IDirectDrawImpl
* This
, const DDSURFACEDESC2
* pDDSD
,
342 LPDIRECTDRAWSURFACE7
* ppSurf
, LPUNKNOWN pOuter
)
344 assert(pOuter
== NULL
);
346 return FakeZBuffer_DirectDrawSurface_Create(This
, pDDSD
, ppSurf
, pOuter
);
349 /* Does the texture surface described in pDDSD have any smaller mipmaps? */
350 static BOOL
more_mipmaps(const DDSURFACEDESC2
*pDDSD
)
352 return ((pDDSD
->dwFlags
& DDSD_MIPMAPCOUNT
) && pDDSD
->u2
.dwMipMapCount
> 1
353 && (pDDSD
->dwWidth
> 1 || pDDSD
->dwHeight
> 1));
356 /* Create a texture surface along with any of its mipmaps. */
358 create_texture(IDirectDrawImpl
* This
, const DDSURFACEDESC2
*pDDSD
,
359 LPDIRECTDRAWSURFACE7
* ppSurf
, LPUNKNOWN pUnkOuter
)
362 DWORD mipmap_level
= 0;
365 assert(pUnkOuter
== NULL
);
367 /* is this check right? (pixelformat can be copied from primary) */
368 if ((pDDSD
->dwFlags
&(DDSD_HEIGHT
|DDSD_WIDTH
)) != (DDSD_HEIGHT
|DDSD_WIDTH
))
369 return DDERR_INVALIDPARAMS
;
371 ddsd
.dwSize
= sizeof(ddsd
);
372 DD_STRUCT_COPY_BYSIZE((&ddsd
),pDDSD
);
374 if (!(ddsd
.dwFlags
& DDSD_PIXELFORMAT
))
376 ddsd
.u4
.ddpfPixelFormat
= This
->pixelformat
;
380 /* We support for now only DXT1, DXT3 & DXT5 compressed texture formats... */
381 if ((ddsd
.u4
.ddpfPixelFormat
.dwFlags
& DDPF_FOURCC
) &&
382 (ddsd
.u4
.ddpfPixelFormat
.dwFourCC
!= MAKE_FOURCC('D','X','T','1')) &&
383 (ddsd
.u4
.ddpfPixelFormat
.dwFourCC
!= MAKE_FOURCC('D','X','T','3')) &&
384 (ddsd
.u4
.ddpfPixelFormat
.dwFourCC
!= MAKE_FOURCC('D','X','T','5')) )
386 return DDERR_INVALIDPIXELFORMAT
;
389 /* Check if we can really support DXT1, DXT3 & DXT5 */
390 if ((ddsd
.u4
.ddpfPixelFormat
.dwFlags
& DDPF_FOURCC
) &&
391 !GL_extensions
.s3tc_compressed_texture
&& !s3tc_initialized
) {
392 static BOOLEAN user_warned
= 0;
393 if (user_warned
== 0) {
394 ERR("Trying to create DXT1, DXT3 or DXT5 texture which is not supported by the video card!!!\n");
395 ERR("However there is a library libtxc_dxtn.so that can be used to do the software decompression...\n");
398 return DDERR_INVALIDPIXELFORMAT
;
401 if (ddsd
.u4
.ddpfPixelFormat
.dwFlags
& DDPF_FOURCC
)
403 return DDERR_INVALIDPIXELFORMAT
;
407 if ((ddsd
.u4
.ddpfPixelFormat
.dwFlags
& DDPF_FOURCC
) && !(ddsd
.dwFlags
& DDSD_LINEARSIZE
))
410 int width
= ddsd
.dwWidth
;
411 int height
= ddsd
.dwHeight
;
412 switch(ddsd
.u4
.ddpfPixelFormat
.dwFourCC
) {
413 case MAKE_FOURCC('D','X','T','1'): size
= ((width
+3)&~3) * ((height
+3)&~3) / 16 * 8; break;
414 case MAKE_FOURCC('D','X','T','3'): size
= ((width
+3)&~3) * ((height
+3)&~3) / 16 * 16; break;
415 case MAKE_FOURCC('D','X','T','5'): size
= ((width
+3)&~3) * ((height
+3)&~3) / 16 * 16; break;
416 default: FIXME("FOURCC not supported\n"); break;
418 ddsd
.u1
.dwLinearSize
= size
;
419 ddsd
.dwFlags
|= DDSD_LINEARSIZE
;
420 } else if (!(ddsd
.u4
.ddpfPixelFormat
.dwFlags
& DDPF_FOURCC
) && !(ddsd
.dwFlags
& DDSD_PITCH
)) {
421 ddsd
.u1
.lPitch
= DDRAW_width_bpp_to_pitch(ddsd
.dwWidth
, GET_BPP(ddsd
)*8);
422 ddsd
.dwFlags
|= DDSD_PITCH
;
425 if((ddsd
.ddsCaps
.dwCaps
& DDSCAPS_MIPMAP
) &&
426 !(ddsd
.dwFlags
& DDSD_MIPMAPCOUNT
))
428 if(ddsd
.ddsCaps
.dwCaps
& DDSCAPS_COMPLEX
)
430 /* Undocumented feature: if DDSCAPS_MIPMAP and DDSCAPS_COMPLEX are
431 * both set, but mipmap count isn't given, as many mipmap levels
432 * as necessary are created to get down to a size where either
433 * the width or the height of the texture is 1.
435 * This is needed by Anarchy Online. */
436 DWORD min
= ddsd
.dwWidth
< ddsd
.dwHeight
?
437 ddsd
.dwWidth
: ddsd
.dwHeight
;
438 ddsd
.u2
.dwMipMapCount
= 0;
441 ddsd
.u2
.dwMipMapCount
++;
446 /* Create a single mipmap. */
447 ddsd
.u2
.dwMipMapCount
= 1;
449 ddsd
.dwFlags
|= DDSD_MIPMAPCOUNT
;
452 ddsd
.dwFlags
|= DDSD_PIXELFORMAT
;
454 hr
= This
->create_texture(This
, &ddsd
, ppSurf
, pUnkOuter
, mipmap_level
);
455 if (FAILED(hr
)) return hr
;
457 if (This
->d3d_private
) This
->d3d_create_texture(This
, ICOM_OBJECT(IDirectDrawSurfaceImpl
, IDirectDrawSurface7
, *ppSurf
), TRUE
,
458 ICOM_OBJECT(IDirectDrawSurfaceImpl
, IDirectDrawSurface7
, *ppSurf
));
460 /* Create attached mipmaps if required. */
461 if (more_mipmaps(&ddsd
))
463 LPDIRECTDRAWSURFACE7 mipmap
;
464 LPDIRECTDRAWSURFACE7 prev_mipmap
;
465 DDSURFACEDESC2 mipmap_surface_desc
;
467 prev_mipmap
= *ppSurf
;
468 IDirectDrawSurface7_AddRef(prev_mipmap
);
469 mipmap_surface_desc
= ddsd
;
470 mipmap_surface_desc
.ddsCaps
.dwCaps2
|= DDSCAPS2_MIPMAPSUBLEVEL
;
472 while (more_mipmaps(&mipmap_surface_desc
))
474 IDirectDrawSurfaceImpl
*mipmap_impl
;
477 mipmap_surface_desc
.u2
.dwMipMapCount
--;
479 if (mipmap_surface_desc
.dwWidth
> 1)
480 mipmap_surface_desc
.dwWidth
/= 2;
482 if (mipmap_surface_desc
.dwHeight
> 1)
483 mipmap_surface_desc
.dwHeight
/= 2;
485 if (mipmap_surface_desc
.u4
.ddpfPixelFormat
.dwFlags
& DDPF_FOURCC
) {
487 int width
= mipmap_surface_desc
.dwWidth
;
488 int height
= mipmap_surface_desc
.dwHeight
;
489 switch(mipmap_surface_desc
.u4
.ddpfPixelFormat
.dwFourCC
) {
490 case MAKE_FOURCC('D','X','T','1'): size
= ((width
+3)&~3) * ((height
+3)&~3) / 16 * 8; break;
491 case MAKE_FOURCC('D','X','T','3'): size
= ((width
+3)&~3) * ((height
+3)&~3) / 16 * 16; break;
492 case MAKE_FOURCC('D','X','T','5'): size
= ((width
+3)&~3) * ((height
+3)&~3) / 16 * 16; break;
493 default: FIXME("FOURCC not supported\n"); break;
495 mipmap_surface_desc
.u1
.dwLinearSize
= size
;
497 ddsd
.u1
.lPitch
= DDRAW_width_bpp_to_pitch(ddsd
.dwWidth
, GET_BPP(ddsd
)*8);
498 mipmap_surface_desc
.u1
.lPitch
499 = DDRAW_width_bpp_to_pitch(mipmap_surface_desc
.dwWidth
,
503 hr
= This
->create_texture(This
, &mipmap_surface_desc
, &mipmap
,
504 pUnkOuter
, mipmap_level
);
507 IDirectDrawSurface7_Release(prev_mipmap
);
508 IDirectDrawSurface7_Release(*ppSurf
);
512 /* This is needed for delayed mipmap creation */
513 mipmap_impl
= ICOM_OBJECT(IDirectDrawSurfaceImpl
, IDirectDrawSurface7
, mipmap
);
514 mipmap_impl
->mip_main
= ICOM_OBJECT(IDirectDrawSurfaceImpl
, IDirectDrawSurface7
, *ppSurf
);
515 mipmap_impl
->mipmap_level
= mipmap_level
;
517 if (This
->d3d_private
) This
->d3d_create_texture(This
, ICOM_OBJECT(IDirectDrawSurfaceImpl
, IDirectDrawSurface7
, mipmap
), TRUE
,
518 ICOM_OBJECT(IDirectDrawSurfaceImpl
, IDirectDrawSurface7
, *ppSurf
));
520 IDirectDrawSurface7_AddAttachedSurface(prev_mipmap
, mipmap
);
521 IDirectDrawSurface7_Release(prev_mipmap
);
522 prev_mipmap
= mipmap
;
525 IDirectDrawSurface7_Release(prev_mipmap
);
531 /* Creates a primary surface and any indicated backbuffers. */
533 create_primary(IDirectDrawImpl
* This
, LPDDSURFACEDESC2 pDDSD
,
534 LPDIRECTDRAWSURFACE7
* ppSurf
, LPUNKNOWN pUnkOuter
)
539 assert(pUnkOuter
== NULL
);
541 if (This
->primary_surface
!= NULL
)
542 return DDERR_PRIMARYSURFACEALREADYEXISTS
;
544 /* as documented (what about pitch?) */
545 if (pDDSD
->dwFlags
& (DDSD_HEIGHT
|DDSD_WIDTH
|DDSD_PIXELFORMAT
))
546 return DDERR_INVALIDPARAMS
;
548 ddsd
.dwSize
= sizeof(ddsd
);
549 DD_STRUCT_COPY_BYSIZE((&ddsd
),pDDSD
);
550 ddsd
.dwFlags
|= DDSD_HEIGHT
| DDSD_WIDTH
| DDSD_PITCH
| DDSD_PIXELFORMAT
;
551 ddsd
.dwHeight
= This
->height
;
552 ddsd
.dwWidth
= This
->width
;
553 ddsd
.u1
.lPitch
= This
->pitch
;
554 ddsd
.u4
.ddpfPixelFormat
= This
->pixelformat
;
555 ddsd
.ddsCaps
.dwCaps
|= DDSCAPS_LOCALVIDMEM
| DDSCAPS_VIDEOMEMORY
556 | DDSCAPS_VISIBLE
| DDSCAPS_FRONTBUFFER
;
558 if ((ddsd
.dwFlags
& DDSD_BACKBUFFERCOUNT
) && ddsd
.dwBackBufferCount
> 0)
559 ddsd
.ddsCaps
.dwCaps
|= DDSCAPS_FLIP
;
561 hr
= This
->create_primary(This
, &ddsd
, ppSurf
, pUnkOuter
);
562 if (FAILED(hr
)) return hr
;
564 if (ddsd
.dwFlags
& DDSD_BACKBUFFERCOUNT
)
566 IDirectDrawSurfaceImpl
* primary
;
567 LPDIRECTDRAWSURFACE7 pPrev
;
570 ddsd
.dwFlags
&= ~DDSD_BACKBUFFERCOUNT
;
571 ddsd
.ddsCaps
.dwCaps
&= ~(DDSCAPS_VISIBLE
| DDSCAPS_PRIMARYSURFACE
572 | DDSCAPS_BACKBUFFER
| DDSCAPS_FRONTBUFFER
);
574 primary
= ICOM_OBJECT(IDirectDrawSurfaceImpl
,IDirectDrawSurface7
,
577 IDirectDrawSurface7_AddRef(pPrev
);
579 for (i
=0; i
< ddsd
.dwBackBufferCount
; i
++)
581 LPDIRECTDRAWSURFACE7 pBack
;
584 ddsd
.ddsCaps
.dwCaps
|= DDSCAPS_BACKBUFFER
;
586 ddsd
.ddsCaps
.dwCaps
&= ~DDSCAPS_BACKBUFFER
;
588 hr
= This
->create_backbuffer(This
, &ddsd
, &pBack
, pUnkOuter
,
593 IDirectDraw7_Release(pPrev
);
594 IDirectDraw7_Release(*ppSurf
);
598 IDirectDrawSurface7_AddAttachedSurface(pPrev
, pBack
);
599 IDirectDrawSurface7_Release(pPrev
);
603 IDirectDrawSurface7_Release(pPrev
);
606 This
->primary_surface
= (IDirectDrawSurfaceImpl
*)*ppSurf
;
612 create_offscreen(IDirectDrawImpl
* This
, LPDDSURFACEDESC2 pDDSD
,
613 LPDIRECTDRAWSURFACE7
* ppSurf
, LPUNKNOWN pUnkOuter
)
618 /* is this check right? (pixelformat can be copied from primary) */
619 if ((pDDSD
->dwFlags
&(DDSD_HEIGHT
|DDSD_WIDTH
)) != (DDSD_HEIGHT
|DDSD_WIDTH
))
620 return DDERR_INVALIDPARAMS
;
622 ddsd
.dwSize
= sizeof(ddsd
);
623 DD_STRUCT_COPY_BYSIZE((&ddsd
),pDDSD
);
625 if (!(ddsd
.dwFlags
& DDSD_PIXELFORMAT
))
627 ddsd
.u4
.ddpfPixelFormat
= This
->pixelformat
;
630 if (!(ddsd
.dwFlags
& DDSD_PITCH
))
632 ddsd
.u1
.lPitch
= DDRAW_width_bpp_to_pitch(ddsd
.dwWidth
,
636 ddsd
.dwFlags
|= DDSD_PITCH
| DDSD_PIXELFORMAT
;
638 hr
= This
->create_offscreen(This
, &ddsd
, ppSurf
, pUnkOuter
);
639 if (FAILED(hr
)) return hr
;
645 Main_DirectDraw_CreateSurface(LPDIRECTDRAW7 iface
, LPDDSURFACEDESC2 pDDSD
,
646 LPDIRECTDRAWSURFACE7
*ppSurf
,
650 IDirectDrawImpl
*This
= (IDirectDrawImpl
*)iface
;
652 TRACE("(%p)->(%p,%p,%p)\n",This
,pDDSD
,ppSurf
,pUnkOuter
);
653 if (TRACE_ON(ddraw
)) {
654 TRACE("Requesting surface desc :\n");
655 DDRAW_dump_surface_desc(pDDSD
);
658 if (pUnkOuter
!= NULL
) {
659 FIXME("outer != NULL?\n");
660 return CLASS_E_NOAGGREGATION
; /* unchecked */
663 if (!(pDDSD
->dwFlags
& DDSD_CAPS
)) {
664 /* DVIDEO.DLL does forget the DDSD_CAPS flag ... *sigh* */
665 pDDSD
->dwFlags
|= DDSD_CAPS
;
667 if (pDDSD
->ddsCaps
.dwCaps
== 0) {
668 /* This has been checked on real Windows */
669 pDDSD
->ddsCaps
.dwCaps
= DDSCAPS_LOCALVIDMEM
| DDSCAPS_VIDEOMEMORY
;
672 if (pDDSD
->ddsCaps
.dwCaps
& DDSCAPS_ALLOCONLOAD
) {
673 /* If the surface is of the 'alloconload' type, ignore the LPSURFACE field */
674 pDDSD
->dwFlags
&= ~DDSD_LPSURFACE
;
677 if ((pDDSD
->dwFlags
& DDSD_LPSURFACE
) && (pDDSD
->lpSurface
== NULL
)) {
678 /* Frank Herbert's Dune specifies a null pointer for the surface, ignore the LPSURFACE field */
679 WARN("Null surface pointer specified, ignore it!\n");
680 pDDSD
->dwFlags
&= ~DDSD_LPSURFACE
;
683 if (ppSurf
== NULL
) {
684 FIXME("You want to get back a surface? Don't give NULL ptrs!\n");
685 return E_POINTER
; /* unchecked */
688 if (pDDSD
->ddsCaps
.dwCaps
& DDSCAPS_PRIMARYSURFACE
)
690 /* create primary surface & backbuffers */
691 hr
= create_primary(This
, pDDSD
, ppSurf
, pUnkOuter
);
693 else if (pDDSD
->ddsCaps
.dwCaps
& DDSCAPS_BACKBUFFER
)
695 /* create backbuffer surface */
696 hr
= This
->create_backbuffer(This
, pDDSD
, ppSurf
, pUnkOuter
, NULL
);
698 else if (pDDSD
->ddsCaps
.dwCaps
& DDSCAPS_TEXTURE
)
701 hr
= create_texture(This
, pDDSD
, ppSurf
, pUnkOuter
);
703 else if ( (pDDSD
->ddsCaps
.dwCaps
& DDSCAPS_ZBUFFER
) &&
704 !(pDDSD
->ddsCaps
.dwCaps
& DDSCAPS_OFFSCREENPLAIN
)) /* Support DDSCAPS_SYSTEMMEMORY */
706 /* create z-buffer */
707 hr
= This
->create_zbuffer(This
, pDDSD
, ppSurf
, pUnkOuter
);
709 else if ((pDDSD
->ddsCaps
.dwCaps
& DDSCAPS_OFFSCREENPLAIN
) ||
710 (pDDSD
->ddsCaps
.dwCaps
& DDSCAPS_SYSTEMMEMORY
)) /* No difference in Wine right now */
712 /* create offscreenplain surface */
713 hr
= create_offscreen(This
, pDDSD
, ppSurf
, pUnkOuter
);
717 /* Otherwise, assume offscreenplain surface */
718 TRACE("App didn't request a valid surface type - assuming offscreenplain\n");
719 hr
= create_offscreen(This
, pDDSD
, ppSurf
, pUnkOuter
);
723 FIXME("failed surface creation with code 0x%08lx\n",hr
);
731 Main_DirectDraw_DuplicateSurface(LPDIRECTDRAW7 iface
, LPDIRECTDRAWSURFACE7 src
,
732 LPDIRECTDRAWSURFACE7
* dst
)
734 IDirectDrawImpl
*This
= (IDirectDrawImpl
*)iface
;
736 IDirectDrawSurfaceImpl
*pSrc
= ICOM_OBJECT(IDirectDrawSurfaceImpl
,
737 IDirectDrawSurface7
, src
);
739 TRACE("(%p)->(%p,%p)\n",This
,src
,dst
);
741 return pSrc
->duplicate_surface(pSrc
, dst
);
744 /* EnumDisplayModes */
746 BOOL
Main_DirectDraw_DDPIXELFORMAT_Match(const DDPIXELFORMAT
*requested
,
747 const DDPIXELFORMAT
*provided
)
749 /* Some flags must be present in both or neither for a match. */
750 static const DWORD must_match
= DDPF_PALETTEINDEXED1
| DDPF_PALETTEINDEXED2
751 | DDPF_PALETTEINDEXED4
| DDPF_PALETTEINDEXED8
| DDPF_FOURCC
752 | DDPF_ZBUFFER
| DDPF_STENCILBUFFER
;
754 if ((requested
->dwFlags
& provided
->dwFlags
) != requested
->dwFlags
)
757 if ((requested
->dwFlags
& must_match
) != (provided
->dwFlags
& must_match
))
760 if (requested
->dwFlags
& DDPF_FOURCC
)
761 if (requested
->dwFourCC
!= provided
->dwFourCC
)
764 if (requested
->dwFlags
& (DDPF_RGB
|DDPF_YUV
|DDPF_ZBUFFER
|DDPF_ALPHA
765 |DDPF_LUMINANCE
|DDPF_BUMPDUDV
))
766 if (requested
->u1
.dwRGBBitCount
!= provided
->u1
.dwRGBBitCount
)
769 if (requested
->dwFlags
& (DDPF_RGB
|DDPF_YUV
|DDPF_STENCILBUFFER
770 |DDPF_LUMINANCE
|DDPF_BUMPDUDV
))
771 if (requested
->u2
.dwRBitMask
!= provided
->u2
.dwRBitMask
)
774 if (requested
->dwFlags
& (DDPF_RGB
|DDPF_YUV
|DDPF_ZBUFFER
|DDPF_BUMPDUDV
))
775 if (requested
->u3
.dwGBitMask
!= provided
->u3
.dwGBitMask
)
778 /* I could be wrong about the bumpmapping. MSDN docs are vague. */
779 if (requested
->dwFlags
& (DDPF_RGB
|DDPF_YUV
|DDPF_STENCILBUFFER
781 if (requested
->u4
.dwBBitMask
!= provided
->u4
.dwBBitMask
)
784 if (requested
->dwFlags
& (DDPF_ALPHAPIXELS
|DDPF_ZPIXELS
))
785 if (requested
->u5
.dwRGBAlphaBitMask
!= provided
->u5
.dwRGBAlphaBitMask
)
791 BOOL
Main_DirectDraw_DDSD_Match(const DDSURFACEDESC2
* requested
,
792 const DDSURFACEDESC2
* provided
)
801 #define CMP(FLAG, FIELD) \
802 { DDSD_##FLAG, offsetof(DDSURFACEDESC2, FIELD), \
803 sizeof(((DDSURFACEDESC2 *)(NULL))->FIELD) }
805 static const struct compare_info compare
[] = {
806 CMP(ALPHABITDEPTH
, dwAlphaBitDepth
),
807 CMP(BACKBUFFERCOUNT
, dwBackBufferCount
),
809 CMP(CKDESTBLT
, ddckCKDestBlt
),
810 CMP(CKDESTOVERLAY
, u3
.ddckCKDestOverlay
),
811 CMP(CKSRCBLT
, ddckCKSrcBlt
),
812 CMP(CKSRCOVERLAY
, ddckCKSrcOverlay
),
813 CMP(HEIGHT
, dwHeight
),
814 CMP(LINEARSIZE
, u1
.dwLinearSize
),
815 CMP(LPSURFACE
, lpSurface
),
816 CMP(MIPMAPCOUNT
, u2
.dwMipMapCount
),
817 CMP(PITCH
, u1
.lPitch
),
818 /* PIXELFORMAT: manual */
819 CMP(REFRESHRATE
, u2
.dwRefreshRate
),
820 CMP(TEXTURESTAGE
, dwTextureStage
),
822 /* ZBUFFERBITDEPTH: "obsolete" */
829 if ((requested
->dwFlags
& provided
->dwFlags
) != requested
->dwFlags
)
832 for (i
=0; i
< sizeof(compare
)/sizeof(compare
[0]); i
++)
834 if (requested
->dwFlags
& compare
[i
].flag
835 && memcmp((const char *)provided
+ compare
[i
].offset
,
836 (const char *)requested
+ compare
[i
].offset
,
837 compare
[i
].size
) != 0)
841 if (requested
->dwFlags
& DDSD_PIXELFORMAT
)
843 if (!Main_DirectDraw_DDPIXELFORMAT_Match(&requested
->u4
.ddpfPixelFormat
,
844 &provided
->u4
.ddpfPixelFormat
))
851 #define DDENUMSURFACES_SEARCHTYPE (DDENUMSURFACES_CANBECREATED|DDENUMSURFACES_DOESEXIST)
852 #define DDENUMSURFACES_MATCHTYPE (DDENUMSURFACES_ALL|DDENUMSURFACES_MATCH|DDENUMSURFACES_NOMATCH)
854 /* This should be extended so that it can be used by
855 * IDirectDrawSurface7::EnumAttachedSurfaces. */
857 Main_DirectDraw_EnumExistingSurfaces(IDirectDrawImpl
*This
, DWORD dwFlags
,
858 LPDDSURFACEDESC2 lpDDSD2
, LPVOID context
,
859 LPDDENUMSURFACESCALLBACK7 callback
)
861 IDirectDrawSurfaceImpl
*surf
;
864 /* A NULL lpDDSD2 is permitted if we are enumerating all surfaces anyway */
865 if (lpDDSD2
== NULL
&& !(dwFlags
& DDENUMSURFACES_ALL
))
866 return DDERR_INVALIDPARAMS
;
868 all
= dwFlags
& DDENUMSURFACES_ALL
;
869 nomatch
= dwFlags
& DDENUMSURFACES_NOMATCH
;
871 for (surf
= This
->surfaces
; surf
!= NULL
; surf
= surf
->next_ddraw
)
874 || (nomatch
!= Main_DirectDraw_DDSD_Match(lpDDSD2
,
875 &surf
->surface_desc
)))
877 LPDIRECTDRAWSURFACE7 surface
= ICOM_INTERFACE(surf
,
878 IDirectDrawSurface7
);
880 /* BOGUS! Violates COM rules, but MSDN says so. */
881 IDirectDrawSurface7_AddRef(surface
);
883 if (callback(surface
, &surf
->surface_desc
, context
)
892 /* I really don't understand how this is supposed to work.
893 * We only consider dwHeight, dwWidth and ddpfPixelFormat.dwFlags. */
895 Main_DirectDraw_EnumCreateableSurfaces(IDirectDrawImpl
*This
, DWORD dwFlags
,
896 LPDDSURFACEDESC2 lpDDSD2
,
898 LPDDENUMSURFACESCALLBACK7 callback
)
900 FIXME("This isn't going to work.\n");
902 if ((dwFlags
& DDENUMSURFACES_MATCHTYPE
) != DDENUMSURFACES_MATCH
)
903 return DDERR_INVALIDPARAMS
;
905 /* TODO: implement this.
906 * Does this work before SCL is called?
907 * Does it only consider off-screen surfaces?
913 /* For unsigned x. 0 is not a power of 2. */
914 #define IS_POW_2(x) (((x) & ((x) - 1)) == 0)
917 Main_DirectDraw_EnumSurfaces(LPDIRECTDRAW7 iface
, DWORD dwFlags
,
918 LPDDSURFACEDESC2 lpDDSD2
, LPVOID context
,
919 LPDDENUMSURFACESCALLBACK7 callback
)
921 IDirectDrawImpl
*This
= (IDirectDrawImpl
*)iface
;
922 TRACE("(%p)->(0x%lx, %p, %p, %p)\n", iface
, dwFlags
, lpDDSD2
, context
,
925 if (callback
== NULL
)
926 return DDERR_INVALIDPARAMS
;
928 if (dwFlags
& ~(DDENUMSURFACES_SEARCHTYPE
|DDENUMSURFACES_MATCHTYPE
))
929 return DDERR_INVALIDPARAMS
;
931 if (!IS_POW_2(dwFlags
& DDENUMSURFACES_SEARCHTYPE
)
932 || !IS_POW_2(dwFlags
& DDENUMSURFACES_MATCHTYPE
))
933 return DDERR_INVALIDPARAMS
;
935 if (dwFlags
& DDENUMSURFACES_DOESEXIST
)
937 return Main_DirectDraw_EnumExistingSurfaces(This
, dwFlags
, lpDDSD2
,
942 return Main_DirectDraw_EnumCreateableSurfaces(This
, dwFlags
, lpDDSD2
,
948 Main_DirectDraw_EvaluateMode(LPDIRECTDRAW7 iface
,DWORD a
,DWORD
* b
)
950 IDirectDrawImpl
*This
= (IDirectDrawImpl
*)iface
;
951 FIXME("(%p)->() stub\n", This
);
957 Main_DirectDraw_FlipToGDISurface(LPDIRECTDRAW7 iface
)
959 IDirectDrawImpl
*This
= (IDirectDrawImpl
*)iface
;
960 TRACE("(%p)->()\n",This
);
965 Main_DirectDraw_GetCaps(LPDIRECTDRAW7 iface
, LPDDCAPS pDriverCaps
,
968 IDirectDrawImpl
*This
= (IDirectDrawImpl
*)iface
;
969 TRACE("(%p,%p,%p)\n",This
,pDriverCaps
,pHELCaps
);
970 if (pDriverCaps
!= NULL
) {
971 DD_STRUCT_COPY_BYSIZE(pDriverCaps
,&This
->caps
);
972 if (TRACE_ON(ddraw
)) {
973 TRACE("Driver Caps : \n");
974 DDRAW_dump_DDCAPS(pDriverCaps
);
977 if (pHELCaps
!= NULL
) {
978 DD_STRUCT_COPY_BYSIZE(pHELCaps
,&This
->caps
);
979 if (TRACE_ON(ddraw
)) {
980 TRACE("HEL Caps : \n");
981 DDRAW_dump_DDCAPS(pHELCaps
);
988 /* GetDeviceIdentifier */
992 Main_DirectDraw_GetFourCCCodes(LPDIRECTDRAW7 iface
, LPDWORD pNumCodes
,
995 IDirectDrawImpl
*This
= (IDirectDrawImpl
*)iface
;
999 FIXME("(%p,%p,%p), stub\n",This
,pNumCodes
,pCodes
);
1004 Main_DirectDraw_GetGDISurface(LPDIRECTDRAW7 iface
,
1005 LPDIRECTDRAWSURFACE7
*lplpGDIDDSSurface
)
1007 IDirectDrawImpl
*This
= (IDirectDrawImpl
*)iface
;
1008 TRACE("(%p)->(%p)\n", This
, lplpGDIDDSSurface
);
1009 TRACE("returning primary (%p)\n", This
->primary_surface
);
1010 *lplpGDIDDSSurface
= ICOM_INTERFACE(This
->primary_surface
, IDirectDrawSurface7
);
1011 if (*lplpGDIDDSSurface
)
1012 IDirectDrawSurface7_AddRef(*lplpGDIDDSSurface
);
1017 Main_DirectDraw_GetMonitorFrequency(LPDIRECTDRAW7 iface
,LPDWORD freq
)
1019 IDirectDrawImpl
*This
= (IDirectDrawImpl
*)iface
;
1020 FIXME("(%p)->(%p) returns 60 Hz always\n",This
,freq
);
1021 *freq
= 60*100; /* 60 Hz */
1026 Main_DirectDraw_GetScanLine(LPDIRECTDRAW7 iface
, LPDWORD lpdwScanLine
)
1028 IDirectDrawImpl
*This
= (IDirectDrawImpl
*)iface
;
1031 /* Since this method is called often, show the fixme only once */
1033 FIXME("(%p)->(%p) semi-stub\n", This
, lpdwScanLine
);
1037 /* Fake the line sweeping of the monitor */
1038 /* FIXME: We should synchronize with a source to keep the refresh rate */
1039 *lpdwScanLine
= This
->cur_scanline
++;
1040 /* Assume 20 scan lines in the vertical blank */
1041 if (This
->cur_scanline
>= This
->height
+ 20)
1042 This
->cur_scanline
= 0;
1048 Main_DirectDraw_GetSurfaceFromDC(LPDIRECTDRAW7 iface
, HDC hdc
,
1049 LPDIRECTDRAWSURFACE7
*lpDDS
)
1051 IDirectDrawImpl
*This
= (IDirectDrawImpl
*)iface
;
1052 FIXME("(%p)->(%p,%p)\n", This
, hdc
, lpDDS
);
1058 Main_DirectDraw_GetVerticalBlankStatus(LPDIRECTDRAW7 iface
, LPBOOL status
)
1060 IDirectDrawImpl
*This
= (IDirectDrawImpl
*)iface
;
1061 TRACE("(%p)->(%p)\n",This
,status
);
1066 /* If we were not initialised then Uninit_Main_IDirectDraw7_Initialize would
1067 * have been called instead. */
1069 Main_DirectDraw_Initialize(LPDIRECTDRAW7 iface
, LPGUID lpGuid
)
1071 TRACE("(%p)->(%s)\n", iface
, debugstr_guid(lpGuid
));
1073 return DDERR_ALREADYINITIALIZED
;
1077 Main_DirectDraw_RestoreAllSurfaces(LPDIRECTDRAW7 iface
)
1079 IDirectDrawImpl
*This
= (IDirectDrawImpl
*)iface
;
1080 IDirectDrawSurfaceImpl
* surf
;
1082 TRACE("(%p)->()\n", This
);
1084 for (surf
= This
->surfaces
; surf
!= NULL
; surf
= surf
->next_ddraw
)
1085 IDirectDrawSurface7_Restore(ICOM_INTERFACE(surf
, IDirectDrawSurface7
));
1090 static void DDRAW_SubclassWindow(IDirectDrawImpl
* This
)
1092 /* Well we don't actually subclass the window yet. */
1093 SetPropA(This
->window
, ddProp
, This
);
1096 static void DDRAW_UnsubclassWindow(IDirectDrawImpl
* This
)
1098 RemovePropA(This
->window
, ddProp
);
1102 Main_DirectDraw_SetCooperativeLevel(LPDIRECTDRAW7 iface
, HWND hwnd
,
1105 IDirectDrawImpl
*This
= (IDirectDrawImpl
*)iface
;
1107 FIXME("(%p)->(%p,%08lx)\n",This
,hwnd
,cooplevel
);
1108 DDRAW_dump_cooperativelevel(cooplevel
);
1110 /* Makes realMYST test happy. */
1111 if (This
->cooperative_level
== cooplevel
1112 && This
->window
== hwnd
)
1115 /* XXX "It cannot be reset while the process has surfaces or palettes
1116 * created." Otherwise the window can be changed???
1118 * This appears to be wrong - comment it out for now.
1120 return DDERR_HWNDALREADYSET;
1123 if (!(cooplevel
& (DDSCL_EXCLUSIVE
|DDSCL_NORMAL
)))
1124 return DDERR_INVALIDPARAMS
;
1126 This
->window
= hwnd
;
1127 This
->cooperative_level
= cooplevel
;
1129 This
->local
.hWnd
= (ULONG_PTR
)hwnd
;
1130 This
->local
.dwLocalFlags
|= DDRAWILCL_SETCOOPCALLED
;
1131 /* not entirely sure about these */
1132 if (cooplevel
& DDSCL_EXCLUSIVE
) This
->local
.dwLocalFlags
|= DDRAWILCL_HASEXCLUSIVEMODE
;
1133 if (cooplevel
& DDSCL_FULLSCREEN
) This
->local
.dwLocalFlags
|= DDRAWILCL_ISFULLSCREEN
;
1134 if (cooplevel
& DDSCL_ALLOWMODEX
) This
->local
.dwLocalFlags
|= DDRAWILCL_ALLOWMODEX
;
1135 if (cooplevel
& DDSCL_MULTITHREADED
) This
->local
.dwLocalFlags
|= DDRAWILCL_MULTITHREADED
;
1136 if (cooplevel
& DDSCL_FPUSETUP
) This
->local
.dwLocalFlags
|= DDRAWILCL_FPUSETUP
;
1137 if (cooplevel
& DDSCL_FPUPRESERVE
) This
->local
.dwLocalFlags
|= DDRAWILCL_FPUPRESERVE
;
1139 if (This
->local
.lpGbl
) {
1140 /* assume that this app is the active app (in wine, there's
1141 * probably only one app per global ddraw object anyway) */
1142 if (cooplevel
& DDSCL_EXCLUSIVE
) This
->local
.lpGbl
->lpExclusiveOwner
= &This
->local
;
1143 else if (This
->local
.lpGbl
->lpExclusiveOwner
== &This
->local
)
1144 This
->local
.lpGbl
->lpExclusiveOwner
= NULL
;
1145 if (This
->set_exclusive_mode
)
1146 This
->set_exclusive_mode(This
, (cooplevel
& DDSCL_EXCLUSIVE
) != 0);
1149 ShowWindow(hwnd
, SW_SHOW
);
1151 DDRAW_SubclassWindow(This
);
1153 /* TODO Does it also get resized to the current screen size? */
1159 Main_DirectDraw_SetDisplayMode(LPDIRECTDRAW7 iface
, DWORD dwWidth
,
1160 DWORD dwHeight
, LONG lPitch
,
1161 DWORD dwRefreshRate
, DWORD dwFlags
,
1162 const DDPIXELFORMAT
* pixelformat
)
1167 IDirectDrawImpl
*This
= (IDirectDrawImpl
*)iface
;
1169 TRACE("(%p)->SetDisplayMode(%ld,%ld)\n",This
,dwWidth
,dwHeight
);
1171 if (!(This
->cooperative_level
& DDSCL_EXCLUSIVE
))
1172 return DDERR_NOEXCLUSIVEMODE
;
1174 if (!IsWindow(This
->window
))
1175 return DDERR_GENERIC
; /* unchecked */
1177 LosePrimarySurface(This
);
1179 screenX
= GetSystemMetrics(SM_CXSCREEN
);
1180 screenY
= GetSystemMetrics(SM_CYSCREEN
);
1182 This
->width
= dwWidth
;
1183 This
->height
= dwHeight
;
1184 This
->pitch
= lPitch
;
1185 This
->pixelformat
= *pixelformat
;
1187 /* Position the window in the center of the screen - don't center for now */
1188 /* MoveWindow(This->window, (screenX-dwWidth)/2, (screenY-dwHeight)/2,
1189 dwWidth, dwHeight, TRUE);*/
1190 MoveWindow(This
->window
, 0, 0, dwWidth
, dwHeight
, TRUE
);
1192 SetFocus(This
->window
);
1198 Main_DirectDraw_RestoreDisplayMode(LPDIRECTDRAW7 iface
)
1200 IDirectDrawImpl
*This
= (IDirectDrawImpl
*)iface
;
1202 TRACE("(%p)\n",This
);
1203 if (!(This
->cooperative_level
& DDSCL_EXCLUSIVE
))
1204 return DDERR_NOEXCLUSIVEMODE
;
1206 /* Lose the primary surface if the resolution changes. */
1207 if (This
->orig_width
!= This
->width
|| This
->orig_height
!= This
->height
1208 || This
->orig_pitch
!= This
->pitch
1209 || This
->orig_pixelformat
.dwFlags
!= This
->pixelformat
.dwFlags
1210 || !Main_DirectDraw_DDPIXELFORMAT_Match(&This
->pixelformat
,
1211 &This
->orig_pixelformat
))
1213 LosePrimarySurface(This
);
1216 /* TODO Move the window back where it belongs. */
1222 Main_DirectDraw_WaitForVerticalBlank(LPDIRECTDRAW7 iface
, DWORD dwFlags
,
1225 IDirectDrawImpl
*This
= (IDirectDrawImpl
*)iface
;
1226 FIXME("(%p)->(flags=0x%08lx,handle=%p)\n",This
,dwFlags
,h
);
1231 Main_DirectDraw_GetDisplayMode(LPDIRECTDRAW7 iface
, LPDDSURFACEDESC2 pDDSD
)
1233 IDirectDrawImpl
*This
= (IDirectDrawImpl
*)iface
;
1234 TRACE("(%p)->GetDisplayMode(%p)\n",This
,pDDSD
);
1236 pDDSD
->dwFlags
= DDSD_HEIGHT
|DDSD_WIDTH
|DDSD_PITCH
|DDSD_PIXELFORMAT
|DDSD_REFRESHRATE
;
1237 pDDSD
->dwHeight
= This
->height
;
1238 pDDSD
->dwWidth
= This
->width
;
1239 pDDSD
->u1
.lPitch
= This
->pitch
;
1240 pDDSD
->u2
.dwRefreshRate
= 60;
1241 pDDSD
->u4
.ddpfPixelFormat
= This
->pixelformat
;
1242 pDDSD
->ddsCaps
.dwCaps
= 0;
1247 static INT32
allocate_memory(IDirectDrawImpl
*This
, DWORD mem
)
1249 if (mem
> This
->available_vidmem
) return -1;
1250 This
->available_vidmem
-= mem
;
1251 return This
->available_vidmem
;
1254 static void free_memory(IDirectDrawImpl
*This
, DWORD mem
)
1256 This
->available_vidmem
+= mem
;
1260 Main_DirectDraw_GetAvailableVidMem(LPDIRECTDRAW7 iface
, LPDDSCAPS2 ddscaps
,
1261 LPDWORD total
, LPDWORD free
)
1263 IDirectDrawImpl
*This
= (IDirectDrawImpl
*)iface
;
1264 TRACE("(%p)->(%p,%p,%p)\n", This
,ddscaps
,total
,free
);
1266 if (TRACE_ON(ddraw
)) {
1267 TRACE(" Asking for memory of type : ");
1268 DDRAW_dump_DDSCAPS2(ddscaps
); TRACE("\n");
1271 /* We have 16 MB videomemory */
1272 if (total
) *total
= This
->total_vidmem
;
1273 if (free
) *free
= This
->available_vidmem
;
1275 TRACE(" returning (total) %ld / (free) %ld\n",
1276 total
!= NULL
? *total
: 0,
1277 free
!= NULL
? *free
: 0);
1282 HRESULT WINAPI
Main_DirectDraw_TestCooperativeLevel(LPDIRECTDRAW7 iface
) {
1283 IDirectDrawImpl
*This
= (IDirectDrawImpl
*)iface
;
1284 TRACE("(%p)->(): stub\n", This
);
1290 Main_DirectDraw_StartModeTest(LPDIRECTDRAW7 iface
, LPSIZE pModes
,
1291 DWORD dwNumModes
, DWORD dwFlags
)
1293 IDirectDrawImpl
*This
= (IDirectDrawImpl
*)iface
;
1294 FIXME("(%p)->() stub\n", This
);
1299 /*** Owned object management. */
1301 void Main_DirectDraw_AddSurface(IDirectDrawImpl
* This
,
1302 IDirectDrawSurfaceImpl
* surface
)
1304 assert(surface
->ddraw_owner
== NULL
|| surface
->ddraw_owner
== This
);
1306 surface
->ddraw_owner
= This
;
1308 /* where should it go? */
1309 surface
->next_ddraw
= This
->surfaces
;
1310 surface
->prev_ddraw
= NULL
;
1312 This
->surfaces
->prev_ddraw
= surface
;
1313 This
->surfaces
= surface
;
1316 void Main_DirectDraw_RemoveSurface(IDirectDrawImpl
* This
,
1317 IDirectDrawSurfaceImpl
* surface
)
1319 assert(surface
->ddraw_owner
== This
);
1321 if (This
->surfaces
== surface
)
1322 This
->surfaces
= surface
->next_ddraw
;
1324 if (This
->primary_surface
== surface
)
1325 This
->primary_surface
= NULL
;
1327 if (surface
->next_ddraw
)
1328 surface
->next_ddraw
->prev_ddraw
= surface
->prev_ddraw
;
1329 if (surface
->prev_ddraw
)
1330 surface
->prev_ddraw
->next_ddraw
= surface
->next_ddraw
;
1333 static void Main_DirectDraw_DeleteSurfaces(IDirectDrawImpl
* This
)
1335 while (This
->surfaces
!= NULL
)
1336 Main_DirectDrawSurface_ForceDestroy(This
->surfaces
);
1339 void Main_DirectDraw_AddClipper(IDirectDrawImpl
* This
,
1340 IDirectDrawClipperImpl
* clipper
)
1342 assert(clipper
->ddraw_owner
== NULL
|| clipper
->ddraw_owner
== This
);
1344 clipper
->ddraw_owner
= This
;
1346 clipper
->next_ddraw
= This
->clippers
;
1347 clipper
->prev_ddraw
= NULL
;
1349 This
->clippers
->prev_ddraw
= clipper
;
1350 This
->clippers
= clipper
;
1353 void Main_DirectDraw_RemoveClipper(IDirectDrawImpl
* This
,
1354 IDirectDrawClipperImpl
* clipper
)
1356 assert(clipper
->ddraw_owner
== This
);
1358 if (This
->clippers
== clipper
)
1359 This
->clippers
= clipper
->next_ddraw
;
1361 if (clipper
->next_ddraw
)
1362 clipper
->next_ddraw
->prev_ddraw
= clipper
->prev_ddraw
;
1363 if (clipper
->prev_ddraw
)
1364 clipper
->prev_ddraw
->next_ddraw
= clipper
->next_ddraw
;
1367 static void Main_DirectDraw_DeleteClippers(IDirectDrawImpl
* This
)
1369 while (This
->clippers
!= NULL
)
1370 Main_DirectDrawClipper_ForceDestroy(This
->clippers
);
1373 void Main_DirectDraw_AddPalette(IDirectDrawImpl
* This
,
1374 IDirectDrawPaletteImpl
* palette
)
1376 assert(palette
->ddraw_owner
== NULL
|| palette
->ddraw_owner
== This
);
1378 palette
->ddraw_owner
= This
;
1380 /* where should it go? */
1381 palette
->next_ddraw
= This
->palettes
;
1382 palette
->prev_ddraw
= NULL
;
1384 This
->palettes
->prev_ddraw
= palette
;
1385 This
->palettes
= palette
;
1388 void Main_DirectDraw_RemovePalette(IDirectDrawImpl
* This
,
1389 IDirectDrawPaletteImpl
* palette
)
1391 IDirectDrawSurfaceImpl
*surf
;
1393 assert(palette
->ddraw_owner
== This
);
1395 if (This
->palettes
== palette
)
1396 This
->palettes
= palette
->next_ddraw
;
1398 if (palette
->next_ddraw
)
1399 palette
->next_ddraw
->prev_ddraw
= palette
->prev_ddraw
;
1400 if (palette
->prev_ddraw
)
1401 palette
->prev_ddraw
->next_ddraw
= palette
->next_ddraw
;
1403 /* Here we need also to remove tha palette from any surface which has it as the
1404 * current palette (checked on Windows)
1406 for (surf
= This
->surfaces
; surf
!= NULL
; surf
= surf
->next_ddraw
) {
1407 if (surf
->palette
== palette
) {
1408 TRACE("Palette %p attached to surface %p.\n", palette
, surf
);
1409 surf
->palette
= NULL
;
1410 surf
->set_palette(surf
, NULL
);
1415 static void Main_DirectDraw_DeletePalettes(IDirectDrawImpl
* This
)
1417 while (This
->palettes
!= NULL
)
1418 Main_DirectDrawPalette_ForceDestroy(This
->palettes
);
1424 LoseSurface(IDirectDrawSurfaceImpl
*surface
)
1426 if (surface
!= NULL
) surface
->lose_surface(surface
);
1430 LosePrimarySurface(IDirectDrawImpl
*This
)
1432 /* MSDN: "If another application changes the display mode, the primary
1433 * surface is lost, and the method returns DDERR_SURFACELOST until the
1434 * primary surface is recreated to match the new display mode."
1436 * We mark all the primary surfaces as lost as soon as the display
1437 * mode is changed (by any application). */
1439 LoseSurface(This
->primary_surface
);
1442 /******************************************************************************
1443 * Uninitialised DirectDraw functions
1445 * This vtable is used when a DirectDraw object is created with
1446 * CoCreateInstance. The only usable method is Initialize.
1449 void Uninit_DirectDraw_final_release(IDirectDrawImpl
*This
)
1451 Main_DirectDraw_final_release(This
);
1454 static const IDirectDraw7Vtbl Uninit_DirectDraw_VTable
;
1456 /* Not called from the vtable. */
1457 HRESULT
Uninit_DirectDraw_Construct(IDirectDrawImpl
*This
, BOOL ex
)
1461 hr
= Main_DirectDraw_Construct(This
, ex
);
1462 if (FAILED(hr
)) return hr
;
1464 This
->final_release
= Uninit_DirectDraw_final_release
;
1465 ICOM_INIT_INTERFACE(This
, IDirectDraw7
, Uninit_DirectDraw_VTable
);
1470 HRESULT
Uninit_DirectDraw_Create(const GUID
* pGUID
,
1471 LPDIRECTDRAW7
* pIface
,
1472 IUnknown
* pUnkOuter
, BOOL ex
)
1475 IDirectDrawImpl
* This
;
1477 assert(pUnkOuter
== NULL
); /* XXX no: we must check this */
1479 This
= HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY
,
1480 sizeof(IDirectDrawImpl
));
1481 if (This
== NULL
) return E_OUTOFMEMORY
;
1483 hr
= Uninit_DirectDraw_Construct(This
, ex
);
1485 HeapFree(GetProcessHeap(), HEAP_ZERO_MEMORY
, This
);
1487 *pIface
= ICOM_INTERFACE(This
, IDirectDraw7
);
1492 static HRESULT WINAPI
1493 Uninit_DirectDraw_Initialize(LPDIRECTDRAW7 iface
, LPGUID pDeviceGuid
)
1495 const ddraw_driver
* driver
;
1496 IDirectDrawImpl
*This
= (IDirectDrawImpl
*)iface
;
1498 TRACE("(%p)->(%p)\n", iface
, pDeviceGuid
);
1500 driver
= DDRAW_FindDriver(pDeviceGuid
);
1501 /* XXX This return value is not documented. (Not checked.) */
1502 if (driver
== NULL
) return DDERR_INVALIDDIRECTDRAWGUID
;
1504 return driver
->init(This
, pDeviceGuid
);
1507 static HRESULT WINAPI
1508 Uninit_DirectDraw_Compact(LPDIRECTDRAW7 iface
)
1510 return DDERR_NOTINITIALIZED
;
1513 static HRESULT WINAPI
1514 Uninit_DirectDraw_CreateClipper(LPDIRECTDRAW7 iface
, DWORD dwFlags
,
1515 LPDIRECTDRAWCLIPPER
*lplpDDClipper
,
1516 IUnknown
*pUnkOuter
)
1519 return DDERR_NOTINITIALIZED
;
1522 static HRESULT WINAPI
1523 Uninit_DirectDraw_CreatePalette(LPDIRECTDRAW7 iface
, DWORD dwFlags
,
1524 LPPALETTEENTRY lpColorTable
,
1525 LPDIRECTDRAWPALETTE
*lplpDDPalette
,
1526 IUnknown
*pUnkOuter
)
1528 return DDERR_NOTINITIALIZED
;
1531 static HRESULT WINAPI
1532 Uninit_DirectDraw_CreateSurface(LPDIRECTDRAW7 iface
,
1533 LPDDSURFACEDESC2 lpDDSurfaceDesc
,
1534 LPDIRECTDRAWSURFACE7
*lplpDDSurface
,
1535 IUnknown
*pUnkOuter
)
1537 return DDERR_NOTINITIALIZED
;
1540 static HRESULT WINAPI
1541 Uninit_DirectDraw_DuplicateSurface(LPDIRECTDRAW7 iface
,
1542 LPDIRECTDRAWSURFACE7 pSurf
,
1543 LPDIRECTDRAWSURFACE7
*pDupSurf
)
1546 return DDERR_NOTINITIALIZED
;
1549 static HRESULT WINAPI
1550 Uninit_DirectDraw_EnumDisplayModes(LPDIRECTDRAW7 iface
, DWORD dwFlags
,
1551 LPDDSURFACEDESC2 lpDDSD
,
1553 LPDDENUMMODESCALLBACK2 cb
)
1555 return DDERR_NOTINITIALIZED
;
1558 static HRESULT WINAPI
1559 Uninit_DirectDraw_EnumSurfaces(LPDIRECTDRAW7 iface
, DWORD dwFlags
,
1560 LPDDSURFACEDESC2 pDDSD
, LPVOID context
,
1561 LPDDENUMSURFACESCALLBACK7 cb
)
1563 return DDERR_NOTINITIALIZED
;
1566 static HRESULT WINAPI
1567 Uninit_DirectDraw_FlipToGDISurface(LPDIRECTDRAW7 iface
)
1569 return DDERR_NOTINITIALIZED
;
1572 static HRESULT WINAPI
1573 Uninit_DirectDraw_GetCaps(LPDIRECTDRAW7 iface
, LPDDCAPS pDriverCaps
,
1576 return DDERR_NOTINITIALIZED
;
1579 static HRESULT WINAPI
1580 Uninit_DirectDraw_GetDisplayMode(LPDIRECTDRAW7 iface
,
1581 LPDDSURFACEDESC2 pDDSD
)
1583 return DDERR_NOTINITIALIZED
;
1586 static HRESULT WINAPI
1587 Uninit_DirectDraw_GetFourCCCodes(LPDIRECTDRAW7 iface
, LPDWORD pNumCodes
,
1590 return DDERR_NOTINITIALIZED
;
1593 static HRESULT WINAPI
1594 Uninit_DirectDraw_GetGDISurface(LPDIRECTDRAW7 iface
,
1595 LPDIRECTDRAWSURFACE7
*pGDISurf
)
1597 return DDERR_NOTINITIALIZED
;
1600 static HRESULT WINAPI
1601 Uninit_DirectDraw_GetMonitorFrequency(LPDIRECTDRAW7 iface
, LPDWORD pdwFreq
)
1603 return DDERR_NOTINITIALIZED
;
1606 static HRESULT WINAPI
1607 Uninit_DirectDraw_GetScanLine(LPDIRECTDRAW7 iface
, LPDWORD pdwScanLine
)
1609 return DDERR_NOTINITIALIZED
;
1612 static HRESULT WINAPI
1613 Uninit_DirectDraw_GetVerticalBlankStatus(LPDIRECTDRAW7 iface
, PBOOL pbIsInVB
)
1615 return DDERR_NOTINITIALIZED
;
1618 static HRESULT WINAPI
1619 Uninit_DirectDraw_RestoreDisplayMode(LPDIRECTDRAW7 iface
)
1621 return DDERR_NOTINITIALIZED
;
1624 static HRESULT WINAPI
1625 Uninit_DirectDraw_SetCooperativeLevel(LPDIRECTDRAW7 iface
, HWND hWnd
,
1628 return DDERR_NOTINITIALIZED
;
1631 static HRESULT WINAPI
1632 Uninit_DirectDraw_SetDisplayMode(LPDIRECTDRAW7 iface
, DWORD dwWidth
,
1633 DWORD dwHeight
, DWORD dwBPP
,
1634 DWORD dwRefreshRate
, DWORD dwFlags
)
1636 return DDERR_NOTINITIALIZED
;
1639 static HRESULT WINAPI
1640 Uninit_DirectDraw_WaitForVerticalBlank(LPDIRECTDRAW7 iface
, DWORD dwFlags
,
1643 return DDERR_NOTINITIALIZED
;
1646 static HRESULT WINAPI
1647 Uninit_DirectDraw_GetAvailableVidMem(LPDIRECTDRAW7 iface
, LPDDSCAPS2 pDDCaps
,
1648 LPDWORD pdwTotal
, LPDWORD pdwFree
)
1650 return DDERR_NOTINITIALIZED
;
1653 static HRESULT WINAPI
1654 Uninit_DirectDraw_GetSurfaceFromDC(LPDIRECTDRAW7 iface
, HDC hDC
,
1655 LPDIRECTDRAWSURFACE7
*pSurf
)
1657 return DDERR_NOTINITIALIZED
;
1660 static HRESULT WINAPI
1661 Uninit_DirectDraw_RestoreAllSurfaces(LPDIRECTDRAW7 iface
)
1663 return DDERR_NOTINITIALIZED
;
1666 static HRESULT WINAPI
1667 Uninit_DirectDraw_TestCooperativeLevel(LPDIRECTDRAW7 iface
)
1669 return DDERR_NOTINITIALIZED
;
1672 static HRESULT WINAPI
1673 Uninit_DirectDraw_GetDeviceIdentifier(LPDIRECTDRAW7 iface
,
1674 LPDDDEVICEIDENTIFIER2 pDDDI
,
1677 return DDERR_NOTINITIALIZED
;
1680 static HRESULT WINAPI
1681 Uninit_DirectDraw_StartModeTest(LPDIRECTDRAW7 iface
, LPSIZE pszModes
,
1682 DWORD cModes
, DWORD dwFlags
)
1684 return DDERR_NOTINITIALIZED
;
1687 static HRESULT WINAPI
1688 Uninit_DirectDraw_EvaluateMode(LPDIRECTDRAW7 iface
, DWORD dwFlags
,
1691 return DDERR_NOTINITIALIZED
;
1694 static const IDirectDraw7Vtbl Uninit_DirectDraw_VTable
=
1696 Main_DirectDraw_QueryInterface
,
1697 Main_DirectDraw_AddRef
,
1698 Main_DirectDraw_Release
,
1699 Uninit_DirectDraw_Compact
,
1700 Uninit_DirectDraw_CreateClipper
,
1701 Uninit_DirectDraw_CreatePalette
,
1702 Uninit_DirectDraw_CreateSurface
,
1703 Uninit_DirectDraw_DuplicateSurface
,
1704 Uninit_DirectDraw_EnumDisplayModes
,
1705 Uninit_DirectDraw_EnumSurfaces
,
1706 Uninit_DirectDraw_FlipToGDISurface
,
1707 Uninit_DirectDraw_GetCaps
,
1708 Uninit_DirectDraw_GetDisplayMode
,
1709 Uninit_DirectDraw_GetFourCCCodes
,
1710 Uninit_DirectDraw_GetGDISurface
,
1711 Uninit_DirectDraw_GetMonitorFrequency
,
1712 Uninit_DirectDraw_GetScanLine
,
1713 Uninit_DirectDraw_GetVerticalBlankStatus
,
1714 Uninit_DirectDraw_Initialize
,
1715 Uninit_DirectDraw_RestoreDisplayMode
,
1716 Uninit_DirectDraw_SetCooperativeLevel
,
1717 Uninit_DirectDraw_SetDisplayMode
,
1718 Uninit_DirectDraw_WaitForVerticalBlank
,
1719 Uninit_DirectDraw_GetAvailableVidMem
,
1720 Uninit_DirectDraw_GetSurfaceFromDC
,
1721 Uninit_DirectDraw_RestoreAllSurfaces
,
1722 Uninit_DirectDraw_TestCooperativeLevel
,
1723 Uninit_DirectDraw_GetDeviceIdentifier
,
1724 Uninit_DirectDraw_StartModeTest
,
1725 Uninit_DirectDraw_EvaluateMode