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 isurf = ICOM_INTERFACE(surf, IDirectDrawSurface7);
880 if (TRACE_ON(ddraw)) {
881 TRACE(" => enumerating surface %p (priv. %p) with description:\n", isurf, surf);
882 DDRAW_dump_surface_desc(&surf->surface_desc);
885 IDirectDrawSurface7_AddRef(isurf);
887 desc = surf->surface_desc;
888 if (callback(isurf, &desc, context) == DDENUMRET_CANCEL)
892 TRACE(" end of enumeration.\n");
897 /* I really don't understand how this is supposed to work.
898 * We only consider dwHeight, dwWidth and ddpfPixelFormat.dwFlags. */
900 Main_DirectDraw_EnumCreateableSurfaces(IDirectDrawImpl *This, DWORD dwFlags,
901 LPDDSURFACEDESC2 lpDDSD2,
903 LPDDENUMSURFACESCALLBACK7 callback)
905 FIXME("This isn't going to work.\n");
907 if ((dwFlags & DDENUMSURFACES_MATCHTYPE) != DDENUMSURFACES_MATCH)
908 return DDERR_INVALIDPARAMS;
910 /* TODO: implement this.
911 * Does this work before SCL is called?
912 * Does it only consider off-screen surfaces?
918 /* For unsigned x. 0 is not a power of 2. */
919 #define IS_POW_2(x) (((x) & ((x) - 1)) == 0)
922 Main_DirectDraw_EnumSurfaces(LPDIRECTDRAW7 iface, DWORD dwFlags,
923 LPDDSURFACEDESC2 lpDDSD2, LPVOID context,
924 LPDDENUMSURFACESCALLBACK7 callback)
926 IDirectDrawImpl *This = (IDirectDrawImpl *)iface;
927 TRACE("(%p)->(0x%lx, %p, %p, %p)\n", iface, dwFlags, lpDDSD2, context,
929 if (TRACE_ON(ddraw)) {
930 TRACE(" flags: "); DDRAW_dump_DDENUMSURFACES(dwFlags);
933 if (callback == NULL)
934 return DDERR_INVALIDPARAMS;
936 if (dwFlags & ~(DDENUMSURFACES_SEARCHTYPE|DDENUMSURFACES_MATCHTYPE))
937 return DDERR_INVALIDPARAMS;
939 if (!IS_POW_2(dwFlags & DDENUMSURFACES_SEARCHTYPE)
940 || !IS_POW_2(dwFlags & DDENUMSURFACES_MATCHTYPE))
941 return DDERR_INVALIDPARAMS;
943 if (dwFlags & DDENUMSURFACES_DOESEXIST)
945 return Main_DirectDraw_EnumExistingSurfaces(This, dwFlags, lpDDSD2,
950 return Main_DirectDraw_EnumCreateableSurfaces(This, dwFlags, lpDDSD2,
956 Main_DirectDraw_EvaluateMode(LPDIRECTDRAW7 iface,DWORD a,DWORD* b)
958 IDirectDrawImpl *This = (IDirectDrawImpl *)iface;
959 FIXME("(%p)->() stub\n", This);
965 Main_DirectDraw_FlipToGDISurface(LPDIRECTDRAW7 iface)
967 IDirectDrawImpl *This = (IDirectDrawImpl *)iface;
968 TRACE("(%p)->()\n",This);
973 Main_DirectDraw_GetCaps(LPDIRECTDRAW7 iface, LPDDCAPS pDriverCaps,
976 IDirectDrawImpl *This = (IDirectDrawImpl *)iface;
977 TRACE("(%p,%p,%p)\n",This,pDriverCaps,pHELCaps);
978 if (pDriverCaps != NULL) {
979 DD_STRUCT_COPY_BYSIZE(pDriverCaps,&This->caps);
980 if (TRACE_ON(ddraw)) {
981 TRACE("Driver Caps :\n");
982 DDRAW_dump_DDCAPS(pDriverCaps);
985 if (pHELCaps != NULL) {
986 DD_STRUCT_COPY_BYSIZE(pHELCaps,&This->caps);
987 if (TRACE_ON(ddraw)) {
988 TRACE("HEL Caps :\n");
989 DDRAW_dump_DDCAPS(pHELCaps);
996 /* GetDeviceIdentifier */
1000 Main_DirectDraw_GetFourCCCodes(LPDIRECTDRAW7 iface, LPDWORD pNumCodes,
1003 IDirectDrawImpl *This = (IDirectDrawImpl *)iface;
1007 FIXME("(%p,%p,%p), stub\n",This,pNumCodes,pCodes);
1012 Main_DirectDraw_GetGDISurface(LPDIRECTDRAW7 iface,
1013 LPDIRECTDRAWSURFACE7 *lplpGDIDDSSurface)
1015 IDirectDrawImpl *This = (IDirectDrawImpl *)iface;
1016 TRACE("(%p)->(%p)\n", This, lplpGDIDDSSurface);
1017 TRACE("returning primary (%p)\n", This->primary_surface);
1018 *lplpGDIDDSSurface = ICOM_INTERFACE(This->primary_surface, IDirectDrawSurface7);
1019 if (*lplpGDIDDSSurface)
1020 IDirectDrawSurface7_AddRef(*lplpGDIDDSSurface);
1025 Main_DirectDraw_GetMonitorFrequency(LPDIRECTDRAW7 iface,LPDWORD freq)
1027 IDirectDrawImpl *This = (IDirectDrawImpl *)iface;
1028 FIXME("(%p)->(%p) returns 60 Hz always\n",This,freq);
1029 *freq = 60*100; /* 60 Hz */
1034 Main_DirectDraw_GetScanLine(LPDIRECTDRAW7 iface, LPDWORD lpdwScanLine)
1036 IDirectDrawImpl *This = (IDirectDrawImpl *)iface;
1039 /* Since this method is called often, show the fixme only once */
1041 FIXME("(%p)->(%p) semi-stub\n", This, lpdwScanLine);
1045 /* Fake the line sweeping of the monitor */
1046 /* FIXME: We should synchronize with a source to keep the refresh rate */
1047 *lpdwScanLine = This->cur_scanline++;
1048 /* Assume 20 scan lines in the vertical blank */
1049 if (This->cur_scanline >= This->height + 20)
1050 This->cur_scanline = 0;
1056 Main_DirectDraw_GetSurfaceFromDC(LPDIRECTDRAW7 iface, HDC hdc,
1057 LPDIRECTDRAWSURFACE7 *lpDDS)
1059 IDirectDrawImpl *This = (IDirectDrawImpl *)iface;
1060 FIXME("(%p)->(%p,%p)\n", This, hdc, lpDDS);
1066 Main_DirectDraw_GetVerticalBlankStatus(LPDIRECTDRAW7 iface, LPBOOL status)
1068 IDirectDrawImpl *This = (IDirectDrawImpl *)iface;
1069 TRACE("(%p)->(%p)\n",This,status);
1070 *status = This->fake_vblank;
1071 This->fake_vblank = !This->fake_vblank;
1075 /* If we were not initialised then Uninit_Main_IDirectDraw7_Initialize would
1076 * have been called instead. */
1078 Main_DirectDraw_Initialize(LPDIRECTDRAW7 iface, LPGUID lpGuid)
1080 TRACE("(%p)->(%s)\n", iface, debugstr_guid(lpGuid));
1082 return DDERR_ALREADYINITIALIZED;
1086 Main_DirectDraw_RestoreAllSurfaces(LPDIRECTDRAW7 iface)
1088 IDirectDrawImpl *This = (IDirectDrawImpl *)iface;
1089 IDirectDrawSurfaceImpl* surf;
1091 TRACE("(%p)->()\n", This);
1093 for (surf = This->surfaces; surf != NULL; surf = surf->next_ddraw)
1094 IDirectDrawSurface7_Restore(ICOM_INTERFACE(surf, IDirectDrawSurface7));
1099 static void DDRAW_SubclassWindow(IDirectDrawImpl* This)
1101 /* Well we don't actually subclass the window yet. */
1102 SetPropA(This->window, ddProp, This);
1105 static void DDRAW_UnsubclassWindow(IDirectDrawImpl* This)
1107 RemovePropA(This->window, ddProp);
1111 Main_DirectDraw_SetCooperativeLevel(LPDIRECTDRAW7 iface, HWND hwnd,
1114 IDirectDrawImpl *This = (IDirectDrawImpl *)iface;
1116 FIXME("(%p)->(%p,%08lx)\n",This,hwnd,cooplevel);
1117 DDRAW_dump_cooperativelevel(cooplevel);
1119 /* Makes realMYST test happy. */
1120 if (This->cooperative_level == cooplevel
1121 && This->window == hwnd)
1124 /* XXX "It cannot be reset while the process has surfaces or palettes
1125 * created." Otherwise the window can be changed???
1127 * This appears to be wrong - comment it out for now.
1128 * This seems to be true at least for DDSCL_SETFOCUSWINDOW
1129 * It looks like Windows doesn't store the HWND in all cases,
1130 * probably if DDSCL_NORMAL is specified, but that's not sure
1132 return DDERR_HWNDALREADYSET;
1135 /* DDSCL_EXCLUSIVE or DDSCL_NORMAL or DDSCL_SETFOCUSWINDOW must be given */
1136 if (!(cooplevel & (DDSCL_EXCLUSIVE|DDSCL_NORMAL|DDSCL_SETFOCUSWINDOW)))
1138 ERR("(%p) : Call to SetCooperativeLevel failed: cooplevel != DDSCL_EXCLUSIVE|DDSCL_NORMAL|DDSCL_SETFOCUSWINDOW, returning DDERR_INVALIDPARAMS\n", This);
1139 return DDERR_INVALIDPARAMS;
1141 /* Device window and focus Window. They only really matter in a
1142 * Multi-Monitor application, but some games specify them and we
1143 * have to react correctly. */
1144 if(cooplevel & DDSCL_SETFOCUSWINDOW)
1146 /* This flag is a biest: It is only valid when DDSCL_NORMAL has been set
1147 * or no hwnd is set and no other flags are allowed, except DDSCL_NOWINDOWCHANGES
1150 if(!(This->cooperative_level & DDSCL_NORMAL))
1152 ERR("(%p) : Call to SetCooperativeLevel failed: DDSCL_SETFOCUSWINDOW may not be used in Cooplevel %08lx, returning DDERR_HWNDALREADYSET\n",
1153 This, This->cooperative_level);
1154 return DDERR_HWNDALREADYSET;
1156 if((cooplevel != DDSCL_SETFOCUSWINDOW))
1157 if(cooplevel != (DDSCL_SETFOCUSWINDOW | DDSCL_NOWINDOWCHANGES) )
1159 ERR("(%p) : Call to SetCooperativeLevel failed: Invalid use of DDSCL_SETFOCUSWINDOW, returning DDERR_INVALIDPARAMS\n", This);
1160 return DDERR_INVALIDPARAMS;
1163 /* Don't know what exactly to do, but it's perfectly valid
1164 * to pass DDSCL_SETFOCUSWINDOW only */
1165 FIXME("(%p) : Poorly handled flag DDSCL_SETFOCUSWINDOW\n", This);
1167 /* Store the flag in the cooperative level. I don't think that all other
1168 * flags should be overwritten, so just add it
1169 * (In the most cases this will be DDSCL_SETFOCUSWINDOW | DDSCL_NORMAL) */
1170 cooplevel |= DDSCL_SETFOCUSWINDOW;
1175 /* DDSCL_EXCLUSE mode requires DDSCL_FULLSCREEN and vice versa */
1176 if((cooplevel & DDSCL_EXCLUSIVE) && !(cooplevel & DDSCL_FULLSCREEN))
1177 return DDERR_INVALIDPARAMS;
1178 /* The other case is checked above */
1180 /* Unhandled flags. Give a warning */
1181 if(cooplevel & DDSCL_SETDEVICEWINDOW)
1182 FIXME("(%p) : Unhandled flag DDSCL_SETDEVICEWINDOW.\n", This);
1183 if(cooplevel & DDSCL_CREATEDEVICEWINDOW)
1184 FIXME("(%p) : Unhandled flag DDSCL_CREATEDEVICEWINDOW.\n", This);
1186 /* Perhaps the hwnd is only set in DDSCL_EXLUSIVE and DDSCL_FULLSCREEN mode. Not sure */
1187 This->window = hwnd;
1188 This->cooperative_level = cooplevel;
1190 This->local.hWnd = (ULONG_PTR)hwnd;
1191 This->local.dwLocalFlags |= DDRAWILCL_SETCOOPCALLED;
1192 /* not entirely sure about these */
1193 if (cooplevel & DDSCL_EXCLUSIVE) This->local.dwLocalFlags |= DDRAWILCL_HASEXCLUSIVEMODE;
1194 if (cooplevel & DDSCL_FULLSCREEN) This->local.dwLocalFlags |= DDRAWILCL_ISFULLSCREEN;
1195 if (cooplevel & DDSCL_ALLOWMODEX) This->local.dwLocalFlags |= DDRAWILCL_ALLOWMODEX;
1196 if (cooplevel & DDSCL_MULTITHREADED) This->local.dwLocalFlags |= DDRAWILCL_MULTITHREADED;
1197 if (cooplevel & DDSCL_FPUSETUP) This->local.dwLocalFlags |= DDRAWILCL_FPUSETUP;
1198 if (cooplevel & DDSCL_FPUPRESERVE) This->local.dwLocalFlags |= DDRAWILCL_FPUPRESERVE;
1200 if (This->local.lpGbl) {
1201 /* assume that this app is the active app (in wine, there's
1202 * probably only one app per global ddraw object anyway) */
1203 if (cooplevel & DDSCL_EXCLUSIVE) This->local.lpGbl->lpExclusiveOwner = &This->local;
1204 else if (This->local.lpGbl->lpExclusiveOwner == &This->local)
1205 This->local.lpGbl->lpExclusiveOwner = NULL;
1206 if (This->set_exclusive_mode)
1207 This->set_exclusive_mode(This, (cooplevel & DDSCL_EXCLUSIVE) != 0);
1210 ShowWindow(hwnd, SW_SHOW);
1212 DDRAW_SubclassWindow(This);
1214 /* TODO Does it also get resized to the current screen size? */
1220 Main_DirectDraw_SetDisplayMode(LPDIRECTDRAW7 iface, DWORD dwWidth,
1221 DWORD dwHeight, LONG lPitch,
1222 DWORD dwRefreshRate, DWORD dwFlags,
1223 const DDPIXELFORMAT* pixelformat)
1228 IDirectDrawImpl *This = (IDirectDrawImpl *)iface;
1230 TRACE("(%p)->SetDisplayMode(%ld,%ld)\n",This,dwWidth,dwHeight);
1232 if (!(This->cooperative_level & DDSCL_EXCLUSIVE))
1233 return DDERR_NOEXCLUSIVEMODE;
1235 if (!IsWindow(This->window))
1236 return DDERR_GENERIC; /* unchecked */
1238 LosePrimarySurface(This);
1240 screenX = GetSystemMetrics(SM_CXSCREEN);
1241 screenY = GetSystemMetrics(SM_CYSCREEN);
1243 This->width = dwWidth;
1244 This->height = dwHeight;
1245 This->pitch = lPitch;
1246 This->pixelformat = *pixelformat;
1248 /* Position the window in the center of the screen - don't center for now */
1249 /* MoveWindow(This->window, (screenX-dwWidth)/2, (screenY-dwHeight)/2,
1250 dwWidth, dwHeight, TRUE);*/
1251 MoveWindow(This->window, 0, 0, dwWidth, dwHeight, TRUE);
1253 SetFocus(This->window);
1259 Main_DirectDraw_RestoreDisplayMode(LPDIRECTDRAW7 iface)
1261 IDirectDrawImpl *This = (IDirectDrawImpl *)iface;
1263 TRACE("(%p)\n",This);
1264 if (!(This->cooperative_level & DDSCL_EXCLUSIVE))
1265 return DDERR_NOEXCLUSIVEMODE;
1267 /* Lose the primary surface if the resolution changes. */
1268 if (This->orig_width != This->width || This->orig_height != This->height
1269 || This->orig_pitch != This->pitch
1270 || This->orig_pixelformat.dwFlags != This->pixelformat.dwFlags
1271 || !Main_DirectDraw_DDPIXELFORMAT_Match(&This->pixelformat,
1272 &This->orig_pixelformat))
1274 LosePrimarySurface(This);
1277 /* TODO Move the window back where it belongs. */
1283 Main_DirectDraw_WaitForVerticalBlank(LPDIRECTDRAW7 iface, DWORD dwFlags,
1286 IDirectDrawImpl *This = (IDirectDrawImpl *)iface;
1287 FIXME("(%p)->(flags=0x%08lx,handle=%p)\n",This,dwFlags,h);
1292 Main_DirectDraw_GetDisplayMode(LPDIRECTDRAW7 iface, LPDDSURFACEDESC2 pDDSD)
1294 IDirectDrawImpl *This = (IDirectDrawImpl *)iface;
1295 TRACE("(%p)->GetDisplayMode(%p)\n",This,pDDSD);
1297 pDDSD->dwFlags = DDSD_HEIGHT|DDSD_WIDTH|DDSD_PITCH|DDSD_PIXELFORMAT|DDSD_REFRESHRATE;
1298 pDDSD->dwHeight = This->height;
1299 pDDSD->dwWidth = This->width;
1300 pDDSD->u1.lPitch = This->pitch;
1301 pDDSD->u2.dwRefreshRate = 60;
1302 pDDSD->u4.ddpfPixelFormat = This->pixelformat;
1303 pDDSD->ddsCaps.dwCaps = 0;
1308 static INT32 allocate_memory(IDirectDrawImpl *This, DWORD mem)
1310 if (mem > This->available_vidmem) return -1;
1311 This->available_vidmem -= mem;
1312 return This->available_vidmem;
1315 static void free_memory(IDirectDrawImpl *This, DWORD mem)
1317 This->available_vidmem += mem;
1321 Main_DirectDraw_GetAvailableVidMem(LPDIRECTDRAW7 iface, LPDDSCAPS2 ddscaps,
1322 LPDWORD total, LPDWORD free)
1324 IDirectDrawImpl *This = (IDirectDrawImpl *)iface;
1325 TRACE("(%p)->(%p,%p,%p)\n", This,ddscaps,total,free);
1327 if (TRACE_ON(ddraw)) {
1328 TRACE(" Asking for memory of type : ");
1329 DDRAW_dump_DDSCAPS2(ddscaps); TRACE("\n");
1332 /* We have 16 MB videomemory */
1333 if (total) *total= This->total_vidmem;
1334 if (free) *free = This->available_vidmem;
1336 TRACE(" returning (total) %ld / (free) %ld\n",
1337 total != NULL ? *total : 0,
1338 free != NULL ? *free : 0);
1343 HRESULT WINAPI Main_DirectDraw_TestCooperativeLevel(LPDIRECTDRAW7 iface) {
1344 IDirectDrawImpl *This = (IDirectDrawImpl *)iface;
1345 TRACE("(%p)->(): stub\n", This);
1351 Main_DirectDraw_StartModeTest(LPDIRECTDRAW7 iface, LPSIZE pModes,
1352 DWORD dwNumModes, DWORD dwFlags)
1354 IDirectDrawImpl *This = (IDirectDrawImpl *)iface;
1355 FIXME("(%p)->() stub\n", This);
1360 /*** Owned object management. */
1362 void Main_DirectDraw_AddSurface(IDirectDrawImpl* This,
1363 IDirectDrawSurfaceImpl* surface)
1365 assert(surface->ddraw_owner == NULL || surface->ddraw_owner == This);
1367 surface->ddraw_owner = This;
1369 /* where should it go? */
1370 surface->next_ddraw = This->surfaces;
1371 surface->prev_ddraw = NULL;
1373 This->surfaces->prev_ddraw = surface;
1374 This->surfaces = surface;
1377 void Main_DirectDraw_RemoveSurface(IDirectDrawImpl* This,
1378 IDirectDrawSurfaceImpl* surface)
1380 assert(surface->ddraw_owner == This);
1382 if (This->surfaces == surface)
1383 This->surfaces = surface->next_ddraw;
1385 if (This->primary_surface == surface)
1386 This->primary_surface = NULL;
1388 if (surface->next_ddraw)
1389 surface->next_ddraw->prev_ddraw = surface->prev_ddraw;
1390 if (surface->prev_ddraw)
1391 surface->prev_ddraw->next_ddraw = surface->next_ddraw;
1394 static void Main_DirectDraw_DeleteSurfaces(IDirectDrawImpl* This)
1396 while (This->surfaces != NULL)
1397 Main_DirectDrawSurface_ForceDestroy(This->surfaces);
1400 void Main_DirectDraw_AddClipper(IDirectDrawImpl* This,
1401 IDirectDrawClipperImpl* clipper)
1403 assert(clipper->ddraw_owner == NULL || clipper->ddraw_owner == This);
1405 clipper->ddraw_owner = This;
1407 clipper->next_ddraw = This->clippers;
1408 clipper->prev_ddraw = NULL;
1410 This->clippers->prev_ddraw = clipper;
1411 This->clippers = clipper;
1414 void Main_DirectDraw_RemoveClipper(IDirectDrawImpl* This,
1415 IDirectDrawClipperImpl* clipper)
1417 assert(clipper->ddraw_owner == This);
1419 if (This->clippers == clipper)
1420 This->clippers = clipper->next_ddraw;
1422 if (clipper->next_ddraw)
1423 clipper->next_ddraw->prev_ddraw = clipper->prev_ddraw;
1424 if (clipper->prev_ddraw)
1425 clipper->prev_ddraw->next_ddraw = clipper->next_ddraw;
1428 static void Main_DirectDraw_DeleteClippers(IDirectDrawImpl* This)
1430 while (This->clippers != NULL)
1431 Main_DirectDrawClipper_ForceDestroy(This->clippers);
1434 void Main_DirectDraw_AddPalette(IDirectDrawImpl* This,
1435 IDirectDrawPaletteImpl* palette)
1437 assert(palette->ddraw_owner == NULL || palette->ddraw_owner == This);
1439 palette->ddraw_owner = This;
1441 /* where should it go? */
1442 palette->next_ddraw = This->palettes;
1443 palette->prev_ddraw = NULL;
1445 This->palettes->prev_ddraw = palette;
1446 This->palettes = palette;
1449 void Main_DirectDraw_RemovePalette(IDirectDrawImpl* This,
1450 IDirectDrawPaletteImpl* palette)
1452 IDirectDrawSurfaceImpl *surf;
1454 assert(palette->ddraw_owner == This);
1456 if (This->palettes == palette)
1457 This->palettes = palette->next_ddraw;
1459 if (palette->next_ddraw)
1460 palette->next_ddraw->prev_ddraw = palette->prev_ddraw;
1461 if (palette->prev_ddraw)
1462 palette->prev_ddraw->next_ddraw = palette->next_ddraw;
1464 /* Here we need also to remove tha palette from any surface which has it as the
1465 * current palette (checked on Windows)
1467 for (surf = This->surfaces; surf != NULL; surf = surf->next_ddraw) {
1468 if (surf->palette == palette) {
1469 TRACE("Palette %p attached to surface %p.\n", palette, surf);
1470 surf->palette = NULL;
1471 surf->set_palette(surf, NULL);
1476 static void Main_DirectDraw_DeletePalettes(IDirectDrawImpl* This)
1478 while (This->palettes != NULL)
1479 Main_DirectDrawPalette_ForceDestroy(This->palettes);
1485 LoseSurface(IDirectDrawSurfaceImpl *surface)
1487 if (surface != NULL) surface->lose_surface(surface);
1491 LosePrimarySurface(IDirectDrawImpl *This)
1493 /* MSDN: "If another application changes the display mode, the primary
1494 * surface is lost, and the method returns DDERR_SURFACELOST until the
1495 * primary surface is recreated to match the new display mode."
1497 * We mark all the primary surfaces as lost as soon as the display
1498 * mode is changed (by any application). */
1500 LoseSurface(This->primary_surface);
1503 /******************************************************************************
1504 * Uninitialised DirectDraw functions
1506 * This vtable is used when a DirectDraw object is created with
1507 * CoCreateInstance. The only usable method is Initialize.
1510 void Uninit_DirectDraw_final_release(IDirectDrawImpl *This)
1512 Main_DirectDraw_final_release(This);
1515 static const IDirectDraw7Vtbl Uninit_DirectDraw_VTable;
1517 /* Not called from the vtable. */
1518 HRESULT Uninit_DirectDraw_Construct(IDirectDrawImpl *This, BOOL ex)
1522 hr = Main_DirectDraw_Construct(This, ex);
1523 if (FAILED(hr)) return hr;
1525 This->final_release = Uninit_DirectDraw_final_release;
1526 ICOM_INIT_INTERFACE(This, IDirectDraw7, Uninit_DirectDraw_VTable);
1531 HRESULT Uninit_DirectDraw_Create(const GUID* pGUID,
1532 LPDIRECTDRAW7* pIface,
1533 IUnknown* pUnkOuter, BOOL ex)
1536 IDirectDrawImpl* This;
1538 assert(pUnkOuter == NULL); /* XXX no: we must check this */
1540 This = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY,
1541 sizeof(IDirectDrawImpl));
1542 if (This == NULL) return E_OUTOFMEMORY;
1544 hr = Uninit_DirectDraw_Construct(This, ex);
1546 HeapFree(GetProcessHeap(), HEAP_ZERO_MEMORY, This);
1548 *pIface = ICOM_INTERFACE(This, IDirectDraw7);
1553 static HRESULT WINAPI
1554 Uninit_DirectDraw_Initialize(LPDIRECTDRAW7 iface, LPGUID pDeviceGuid)
1556 const ddraw_driver* driver;
1557 IDirectDrawImpl *This = (IDirectDrawImpl *)iface;
1559 TRACE("(%p)->(%p)\n", iface, pDeviceGuid);
1561 driver = DDRAW_FindDriver(pDeviceGuid);
1562 /* XXX This return value is not documented. (Not checked.) */
1563 if (driver == NULL) return DDERR_INVALIDDIRECTDRAWGUID;
1565 return driver->init(This, pDeviceGuid);
1568 static HRESULT WINAPI
1569 Uninit_DirectDraw_Compact(LPDIRECTDRAW7 iface)
1571 return DDERR_NOTINITIALIZED;
1574 static HRESULT WINAPI
1575 Uninit_DirectDraw_CreateClipper(LPDIRECTDRAW7 iface, DWORD dwFlags,
1576 LPDIRECTDRAWCLIPPER *lplpDDClipper,
1577 IUnknown *pUnkOuter)
1580 return DDERR_NOTINITIALIZED;
1583 static HRESULT WINAPI
1584 Uninit_DirectDraw_CreatePalette(LPDIRECTDRAW7 iface, DWORD dwFlags,
1585 LPPALETTEENTRY lpColorTable,
1586 LPDIRECTDRAWPALETTE *lplpDDPalette,
1587 IUnknown *pUnkOuter)
1589 return DDERR_NOTINITIALIZED;
1592 static HRESULT WINAPI
1593 Uninit_DirectDraw_CreateSurface(LPDIRECTDRAW7 iface,
1594 LPDDSURFACEDESC2 lpDDSurfaceDesc,
1595 LPDIRECTDRAWSURFACE7 *lplpDDSurface,
1596 IUnknown *pUnkOuter)
1598 return DDERR_NOTINITIALIZED;
1601 static HRESULT WINAPI
1602 Uninit_DirectDraw_DuplicateSurface(LPDIRECTDRAW7 iface,
1603 LPDIRECTDRAWSURFACE7 pSurf,
1604 LPDIRECTDRAWSURFACE7 *pDupSurf)
1607 return DDERR_NOTINITIALIZED;
1610 static HRESULT WINAPI
1611 Uninit_DirectDraw_EnumDisplayModes(LPDIRECTDRAW7 iface, DWORD dwFlags,
1612 LPDDSURFACEDESC2 lpDDSD,
1614 LPDDENUMMODESCALLBACK2 cb)
1616 return DDERR_NOTINITIALIZED;
1619 static HRESULT WINAPI
1620 Uninit_DirectDraw_EnumSurfaces(LPDIRECTDRAW7 iface, DWORD dwFlags,
1621 LPDDSURFACEDESC2 pDDSD, LPVOID context,
1622 LPDDENUMSURFACESCALLBACK7 cb)
1624 return DDERR_NOTINITIALIZED;
1627 static HRESULT WINAPI
1628 Uninit_DirectDraw_FlipToGDISurface(LPDIRECTDRAW7 iface)
1630 return DDERR_NOTINITIALIZED;
1633 static HRESULT WINAPI
1634 Uninit_DirectDraw_GetCaps(LPDIRECTDRAW7 iface, LPDDCAPS pDriverCaps,
1637 return DDERR_NOTINITIALIZED;
1640 static HRESULT WINAPI
1641 Uninit_DirectDraw_GetDisplayMode(LPDIRECTDRAW7 iface,
1642 LPDDSURFACEDESC2 pDDSD)
1644 return DDERR_NOTINITIALIZED;
1647 static HRESULT WINAPI
1648 Uninit_DirectDraw_GetFourCCCodes(LPDIRECTDRAW7 iface, LPDWORD pNumCodes,
1651 return DDERR_NOTINITIALIZED;
1654 static HRESULT WINAPI
1655 Uninit_DirectDraw_GetGDISurface(LPDIRECTDRAW7 iface,
1656 LPDIRECTDRAWSURFACE7 *pGDISurf)
1658 return DDERR_NOTINITIALIZED;
1661 static HRESULT WINAPI
1662 Uninit_DirectDraw_GetMonitorFrequency(LPDIRECTDRAW7 iface, LPDWORD pdwFreq)
1664 return DDERR_NOTINITIALIZED;
1667 static HRESULT WINAPI
1668 Uninit_DirectDraw_GetScanLine(LPDIRECTDRAW7 iface, LPDWORD pdwScanLine)
1670 return DDERR_NOTINITIALIZED;
1673 static HRESULT WINAPI
1674 Uninit_DirectDraw_GetVerticalBlankStatus(LPDIRECTDRAW7 iface, PBOOL pbIsInVB)
1676 return DDERR_NOTINITIALIZED;
1679 static HRESULT WINAPI
1680 Uninit_DirectDraw_RestoreDisplayMode(LPDIRECTDRAW7 iface)
1682 return DDERR_NOTINITIALIZED;
1685 static HRESULT WINAPI
1686 Uninit_DirectDraw_SetCooperativeLevel(LPDIRECTDRAW7 iface, HWND hWnd,
1689 return DDERR_NOTINITIALIZED;
1692 static HRESULT WINAPI
1693 Uninit_DirectDraw_SetDisplayMode(LPDIRECTDRAW7 iface, DWORD dwWidth,
1694 DWORD dwHeight, DWORD dwBPP,
1695 DWORD dwRefreshRate, DWORD dwFlags)
1697 return DDERR_NOTINITIALIZED;
1700 static HRESULT WINAPI
1701 Uninit_DirectDraw_WaitForVerticalBlank(LPDIRECTDRAW7 iface, DWORD dwFlags,
1704 return DDERR_NOTINITIALIZED;
1707 static HRESULT WINAPI
1708 Uninit_DirectDraw_GetAvailableVidMem(LPDIRECTDRAW7 iface, LPDDSCAPS2 pDDCaps,
1709 LPDWORD pdwTotal, LPDWORD pdwFree)
1711 return DDERR_NOTINITIALIZED;
1714 static HRESULT WINAPI
1715 Uninit_DirectDraw_GetSurfaceFromDC(LPDIRECTDRAW7 iface, HDC hDC,
1716 LPDIRECTDRAWSURFACE7 *pSurf)
1718 return DDERR_NOTINITIALIZED;
1721 static HRESULT WINAPI
1722 Uninit_DirectDraw_RestoreAllSurfaces(LPDIRECTDRAW7 iface)
1724 return DDERR_NOTINITIALIZED;
1727 static HRESULT WINAPI
1728 Uninit_DirectDraw_TestCooperativeLevel(LPDIRECTDRAW7 iface)
1730 return DDERR_NOTINITIALIZED;
1733 static HRESULT WINAPI
1734 Uninit_DirectDraw_GetDeviceIdentifier(LPDIRECTDRAW7 iface,
1735 LPDDDEVICEIDENTIFIER2 pDDDI,
1738 return DDERR_NOTINITIALIZED;
1741 static HRESULT WINAPI
1742 Uninit_DirectDraw_StartModeTest(LPDIRECTDRAW7 iface, LPSIZE pszModes,
1743 DWORD cModes, DWORD dwFlags)
1745 return DDERR_NOTINITIALIZED;
1748 static HRESULT WINAPI
1749 Uninit_DirectDraw_EvaluateMode(LPDIRECTDRAW7 iface, DWORD dwFlags,
1752 return DDERR_NOTINITIALIZED;
1755 static const IDirectDraw7Vtbl Uninit_DirectDraw_VTable =
1757 Main_DirectDraw_QueryInterface,
1758 Main_DirectDraw_AddRef,
1759 Main_DirectDraw_Release,
1760 Uninit_DirectDraw_Compact,
1761 Uninit_DirectDraw_CreateClipper,
1762 Uninit_DirectDraw_CreatePalette,
1763 Uninit_DirectDraw_CreateSurface,
1764 Uninit_DirectDraw_DuplicateSurface,
1765 Uninit_DirectDraw_EnumDisplayModes,
1766 Uninit_DirectDraw_EnumSurfaces,
1767 Uninit_DirectDraw_FlipToGDISurface,
1768 Uninit_DirectDraw_GetCaps,
1769 Uninit_DirectDraw_GetDisplayMode,
1770 Uninit_DirectDraw_GetFourCCCodes,
1771 Uninit_DirectDraw_GetGDISurface,
1772 Uninit_DirectDraw_GetMonitorFrequency,
1773 Uninit_DirectDraw_GetScanLine,
1774 Uninit_DirectDraw_GetVerticalBlankStatus,
1775 Uninit_DirectDraw_Initialize,
1776 Uninit_DirectDraw_RestoreDisplayMode,
1777 Uninit_DirectDraw_SetCooperativeLevel,
1778 Uninit_DirectDraw_SetDisplayMode,
1779 Uninit_DirectDraw_WaitForVerticalBlank,
1780 Uninit_DirectDraw_GetAvailableVidMem,
1781 Uninit_DirectDraw_GetSurfaceFromDC,
1782 Uninit_DirectDraw_RestoreAllSurfaces,
1783 Uninit_DirectDraw_TestCooperativeLevel,
1784 Uninit_DirectDraw_GetDeviceIdentifier,
1785 Uninit_DirectDraw_StartModeTest,
1786 Uninit_DirectDraw_EvaluateMode