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);
1074 /* If we were not initialised then Uninit_Main_IDirectDraw7_Initialize would
1075 * have been called instead. */
1077 Main_DirectDraw_Initialize(LPDIRECTDRAW7 iface, LPGUID lpGuid)
1079 TRACE("(%p)->(%s)\n", iface, debugstr_guid(lpGuid));
1081 return DDERR_ALREADYINITIALIZED;
1085 Main_DirectDraw_RestoreAllSurfaces(LPDIRECTDRAW7 iface)
1087 IDirectDrawImpl *This = (IDirectDrawImpl *)iface;
1088 IDirectDrawSurfaceImpl* surf;
1090 TRACE("(%p)->()\n", This);
1092 for (surf = This->surfaces; surf != NULL; surf = surf->next_ddraw)
1093 IDirectDrawSurface7_Restore(ICOM_INTERFACE(surf, IDirectDrawSurface7));
1098 static void DDRAW_SubclassWindow(IDirectDrawImpl* This)
1100 /* Well we don't actually subclass the window yet. */
1101 SetPropA(This->window, ddProp, This);
1104 static void DDRAW_UnsubclassWindow(IDirectDrawImpl* This)
1106 RemovePropA(This->window, ddProp);
1110 Main_DirectDraw_SetCooperativeLevel(LPDIRECTDRAW7 iface, HWND hwnd,
1113 IDirectDrawImpl *This = (IDirectDrawImpl *)iface;
1115 FIXME("(%p)->(%p,%08lx)\n",This,hwnd,cooplevel);
1116 DDRAW_dump_cooperativelevel(cooplevel);
1118 /* Makes realMYST test happy. */
1119 if (This->cooperative_level == cooplevel
1120 && This->window == hwnd)
1123 /* XXX "It cannot be reset while the process has surfaces or palettes
1124 * created." Otherwise the window can be changed???
1126 * This appears to be wrong - comment it out for now.
1127 * This seems to be true at least for DDSCL_SETFOCUSWINDOW
1128 * It looks like Windows doesn't store the HWND in all cases,
1129 * probably if DDSCL_NORMAL is specified, but that's not sure
1131 return DDERR_HWNDALREADYSET;
1134 /* DDSCL_EXCLUSIVE or DDSCL_NORMAL or DDSCL_SETFOCUSWINDOW must be given */
1135 if (!(cooplevel & (DDSCL_EXCLUSIVE|DDSCL_NORMAL|DDSCL_SETFOCUSWINDOW)))
1137 ERR("(%p) : Call to SetCooperativeLevel failed: cooplevel != DDSCL_EXCLUSIVE|DDSCL_NORMAL|DDSCL_SETFOCUSWINDOW, returning DDERR_INVALIDPARAMS\n", This);
1138 return DDERR_INVALIDPARAMS;
1140 /* Device window and focus Window. They only really matter in a
1141 * Multi-Monitor application, but some games specify them and we
1142 * have to react correctly. */
1143 if(cooplevel & DDSCL_SETFOCUSWINDOW)
1145 /* This flag is a biest: It is only valid when DDSCL_NORMAL has been set
1146 * or no hwnd is set and no other flags are allowed, except DDSCL_NOWINDOWCHANGES
1149 if(!(This->cooperative_level & DDSCL_NORMAL))
1151 ERR("(%p) : Call to SetCooperativeLevel failed: DDSCL_SETFOCUSWINDOW may not be used in Cooplevel %08lx, returning DDERR_HWNDALREADYSET\n",
1152 This, This->cooperative_level);
1153 return DDERR_HWNDALREADYSET;
1155 if((cooplevel != DDSCL_SETFOCUSWINDOW))
1156 if(cooplevel != (DDSCL_SETFOCUSWINDOW | DDSCL_NOWINDOWCHANGES) )
1158 ERR("(%p) : Call to SetCooperativeLevel failed: Invalid use of DDSCL_SETFOCUSWINDOW, returning DDERR_INVALIDPARAMS\n", This);
1159 return DDERR_INVALIDPARAMS;
1162 /* Don't know what exactly to do, but it's perfectly valid
1163 * to pass DDSCL_SETFOCUSWINDOW only */
1164 FIXME("(%p) : Poorly handled flag DDSCL_SETFOCUSWINDOW\n", This);
1166 /* Store the flag in the cooperative level. I don't think that all other
1167 * flags should be overwritten, so just add it
1168 * (In the most cases this will be DDSCL_SETFOCUSWINDOW | DDSCL_NORMAL) */
1169 cooplevel |= DDSCL_SETFOCUSWINDOW;
1174 /* DDSCL_EXCLUSE mode requires DDSCL_FULLSCREEN and vice versa */
1175 if((cooplevel & DDSCL_EXCLUSIVE) && !(cooplevel & DDSCL_FULLSCREEN))
1176 return DDERR_INVALIDPARAMS;
1177 /* The other case is checked above */
1179 /* Unhandled flags. Give a warning */
1180 if(cooplevel & DDSCL_SETDEVICEWINDOW)
1181 FIXME("(%p) : Unhandled flag DDSCL_SETDEVICEWINDOW.\n", This);
1182 if(cooplevel & DDSCL_CREATEDEVICEWINDOW)
1183 FIXME("(%p) : Unhandled flag DDSCL_CREATEDEVICEWINDOW.\n", This);
1185 /* Perhaps the hwnd is only set in DDSCL_EXLUSIVE and DDSCL_FULLSCREEN mode. Not sure */
1186 This->window = hwnd;
1187 This->cooperative_level = cooplevel;
1189 This->local.hWnd = (ULONG_PTR)hwnd;
1190 This->local.dwLocalFlags |= DDRAWILCL_SETCOOPCALLED;
1191 /* not entirely sure about these */
1192 if (cooplevel & DDSCL_EXCLUSIVE) This->local.dwLocalFlags |= DDRAWILCL_HASEXCLUSIVEMODE;
1193 if (cooplevel & DDSCL_FULLSCREEN) This->local.dwLocalFlags |= DDRAWILCL_ISFULLSCREEN;
1194 if (cooplevel & DDSCL_ALLOWMODEX) This->local.dwLocalFlags |= DDRAWILCL_ALLOWMODEX;
1195 if (cooplevel & DDSCL_MULTITHREADED) This->local.dwLocalFlags |= DDRAWILCL_MULTITHREADED;
1196 if (cooplevel & DDSCL_FPUSETUP) This->local.dwLocalFlags |= DDRAWILCL_FPUSETUP;
1197 if (cooplevel & DDSCL_FPUPRESERVE) This->local.dwLocalFlags |= DDRAWILCL_FPUPRESERVE;
1199 if (This->local.lpGbl) {
1200 /* assume that this app is the active app (in wine, there's
1201 * probably only one app per global ddraw object anyway) */
1202 if (cooplevel & DDSCL_EXCLUSIVE) This->local.lpGbl->lpExclusiveOwner = &This->local;
1203 else if (This->local.lpGbl->lpExclusiveOwner == &This->local)
1204 This->local.lpGbl->lpExclusiveOwner = NULL;
1205 if (This->set_exclusive_mode)
1206 This->set_exclusive_mode(This, (cooplevel & DDSCL_EXCLUSIVE) != 0);
1209 ShowWindow(hwnd, SW_SHOW);
1211 DDRAW_SubclassWindow(This);
1213 /* TODO Does it also get resized to the current screen size? */
1219 Main_DirectDraw_SetDisplayMode(LPDIRECTDRAW7 iface, DWORD dwWidth,
1220 DWORD dwHeight, LONG lPitch,
1221 DWORD dwRefreshRate, DWORD dwFlags,
1222 const DDPIXELFORMAT* pixelformat)
1227 IDirectDrawImpl *This = (IDirectDrawImpl *)iface;
1229 TRACE("(%p)->SetDisplayMode(%ld,%ld)\n",This,dwWidth,dwHeight);
1231 if (!(This->cooperative_level & DDSCL_EXCLUSIVE))
1232 return DDERR_NOEXCLUSIVEMODE;
1234 if (!IsWindow(This->window))
1235 return DDERR_GENERIC; /* unchecked */
1237 LosePrimarySurface(This);
1239 screenX = GetSystemMetrics(SM_CXSCREEN);
1240 screenY = GetSystemMetrics(SM_CYSCREEN);
1242 This->width = dwWidth;
1243 This->height = dwHeight;
1244 This->pitch = lPitch;
1245 This->pixelformat = *pixelformat;
1247 /* Position the window in the center of the screen - don't center for now */
1248 /* MoveWindow(This->window, (screenX-dwWidth)/2, (screenY-dwHeight)/2,
1249 dwWidth, dwHeight, TRUE);*/
1250 MoveWindow(This->window, 0, 0, dwWidth, dwHeight, TRUE);
1252 SetFocus(This->window);
1258 Main_DirectDraw_RestoreDisplayMode(LPDIRECTDRAW7 iface)
1260 IDirectDrawImpl *This = (IDirectDrawImpl *)iface;
1262 TRACE("(%p)\n",This);
1263 if (!(This->cooperative_level & DDSCL_EXCLUSIVE))
1264 return DDERR_NOEXCLUSIVEMODE;
1266 /* Lose the primary surface if the resolution changes. */
1267 if (This->orig_width != This->width || This->orig_height != This->height
1268 || This->orig_pitch != This->pitch
1269 || This->orig_pixelformat.dwFlags != This->pixelformat.dwFlags
1270 || !Main_DirectDraw_DDPIXELFORMAT_Match(&This->pixelformat,
1271 &This->orig_pixelformat))
1273 LosePrimarySurface(This);
1276 /* TODO Move the window back where it belongs. */
1282 Main_DirectDraw_WaitForVerticalBlank(LPDIRECTDRAW7 iface, DWORD dwFlags,
1285 IDirectDrawImpl *This = (IDirectDrawImpl *)iface;
1286 FIXME("(%p)->(flags=0x%08lx,handle=%p)\n",This,dwFlags,h);
1291 Main_DirectDraw_GetDisplayMode(LPDIRECTDRAW7 iface, LPDDSURFACEDESC2 pDDSD)
1293 IDirectDrawImpl *This = (IDirectDrawImpl *)iface;
1294 TRACE("(%p)->GetDisplayMode(%p)\n",This,pDDSD);
1296 pDDSD->dwFlags = DDSD_HEIGHT|DDSD_WIDTH|DDSD_PITCH|DDSD_PIXELFORMAT|DDSD_REFRESHRATE;
1297 pDDSD->dwHeight = This->height;
1298 pDDSD->dwWidth = This->width;
1299 pDDSD->u1.lPitch = This->pitch;
1300 pDDSD->u2.dwRefreshRate = 60;
1301 pDDSD->u4.ddpfPixelFormat = This->pixelformat;
1302 pDDSD->ddsCaps.dwCaps = 0;
1307 static INT32 allocate_memory(IDirectDrawImpl *This, DWORD mem)
1309 if (mem > This->available_vidmem) return -1;
1310 This->available_vidmem -= mem;
1311 return This->available_vidmem;
1314 static void free_memory(IDirectDrawImpl *This, DWORD mem)
1316 This->available_vidmem += mem;
1320 Main_DirectDraw_GetAvailableVidMem(LPDIRECTDRAW7 iface, LPDDSCAPS2 ddscaps,
1321 LPDWORD total, LPDWORD free)
1323 IDirectDrawImpl *This = (IDirectDrawImpl *)iface;
1324 TRACE("(%p)->(%p,%p,%p)\n", This,ddscaps,total,free);
1326 if (TRACE_ON(ddraw)) {
1327 TRACE(" Asking for memory of type : ");
1328 DDRAW_dump_DDSCAPS2(ddscaps); TRACE("\n");
1331 /* We have 16 MB videomemory */
1332 if (total) *total= This->total_vidmem;
1333 if (free) *free = This->available_vidmem;
1335 TRACE(" returning (total) %ld / (free) %ld\n",
1336 total != NULL ? *total : 0,
1337 free != NULL ? *free : 0);
1342 HRESULT WINAPI Main_DirectDraw_TestCooperativeLevel(LPDIRECTDRAW7 iface) {
1343 IDirectDrawImpl *This = (IDirectDrawImpl *)iface;
1344 TRACE("(%p)->(): stub\n", This);
1350 Main_DirectDraw_StartModeTest(LPDIRECTDRAW7 iface, LPSIZE pModes,
1351 DWORD dwNumModes, DWORD dwFlags)
1353 IDirectDrawImpl *This = (IDirectDrawImpl *)iface;
1354 FIXME("(%p)->() stub\n", This);
1359 /*** Owned object management. */
1361 void Main_DirectDraw_AddSurface(IDirectDrawImpl* This,
1362 IDirectDrawSurfaceImpl* surface)
1364 assert(surface->ddraw_owner == NULL || surface->ddraw_owner == This);
1366 surface->ddraw_owner = This;
1368 /* where should it go? */
1369 surface->next_ddraw = This->surfaces;
1370 surface->prev_ddraw = NULL;
1372 This->surfaces->prev_ddraw = surface;
1373 This->surfaces = surface;
1376 void Main_DirectDraw_RemoveSurface(IDirectDrawImpl* This,
1377 IDirectDrawSurfaceImpl* surface)
1379 assert(surface->ddraw_owner == This);
1381 if (This->surfaces == surface)
1382 This->surfaces = surface->next_ddraw;
1384 if (This->primary_surface == surface)
1385 This->primary_surface = NULL;
1387 if (surface->next_ddraw)
1388 surface->next_ddraw->prev_ddraw = surface->prev_ddraw;
1389 if (surface->prev_ddraw)
1390 surface->prev_ddraw->next_ddraw = surface->next_ddraw;
1393 static void Main_DirectDraw_DeleteSurfaces(IDirectDrawImpl* This)
1395 while (This->surfaces != NULL)
1396 Main_DirectDrawSurface_ForceDestroy(This->surfaces);
1399 void Main_DirectDraw_AddClipper(IDirectDrawImpl* This,
1400 IDirectDrawClipperImpl* clipper)
1402 assert(clipper->ddraw_owner == NULL || clipper->ddraw_owner == This);
1404 clipper->ddraw_owner = This;
1406 clipper->next_ddraw = This->clippers;
1407 clipper->prev_ddraw = NULL;
1409 This->clippers->prev_ddraw = clipper;
1410 This->clippers = clipper;
1413 void Main_DirectDraw_RemoveClipper(IDirectDrawImpl* This,
1414 IDirectDrawClipperImpl* clipper)
1416 assert(clipper->ddraw_owner == This);
1418 if (This->clippers == clipper)
1419 This->clippers = clipper->next_ddraw;
1421 if (clipper->next_ddraw)
1422 clipper->next_ddraw->prev_ddraw = clipper->prev_ddraw;
1423 if (clipper->prev_ddraw)
1424 clipper->prev_ddraw->next_ddraw = clipper->next_ddraw;
1427 static void Main_DirectDraw_DeleteClippers(IDirectDrawImpl* This)
1429 while (This->clippers != NULL)
1430 Main_DirectDrawClipper_ForceDestroy(This->clippers);
1433 void Main_DirectDraw_AddPalette(IDirectDrawImpl* This,
1434 IDirectDrawPaletteImpl* palette)
1436 assert(palette->ddraw_owner == NULL || palette->ddraw_owner == This);
1438 palette->ddraw_owner = This;
1440 /* where should it go? */
1441 palette->next_ddraw = This->palettes;
1442 palette->prev_ddraw = NULL;
1444 This->palettes->prev_ddraw = palette;
1445 This->palettes = palette;
1448 void Main_DirectDraw_RemovePalette(IDirectDrawImpl* This,
1449 IDirectDrawPaletteImpl* palette)
1451 IDirectDrawSurfaceImpl *surf;
1453 assert(palette->ddraw_owner == This);
1455 if (This->palettes == palette)
1456 This->palettes = palette->next_ddraw;
1458 if (palette->next_ddraw)
1459 palette->next_ddraw->prev_ddraw = palette->prev_ddraw;
1460 if (palette->prev_ddraw)
1461 palette->prev_ddraw->next_ddraw = palette->next_ddraw;
1463 /* Here we need also to remove tha palette from any surface which has it as the
1464 * current palette (checked on Windows)
1466 for (surf = This->surfaces; surf != NULL; surf = surf->next_ddraw) {
1467 if (surf->palette == palette) {
1468 TRACE("Palette %p attached to surface %p.\n", palette, surf);
1469 surf->palette = NULL;
1470 surf->set_palette(surf, NULL);
1475 static void Main_DirectDraw_DeletePalettes(IDirectDrawImpl* This)
1477 while (This->palettes != NULL)
1478 Main_DirectDrawPalette_ForceDestroy(This->palettes);
1484 LoseSurface(IDirectDrawSurfaceImpl *surface)
1486 if (surface != NULL) surface->lose_surface(surface);
1490 LosePrimarySurface(IDirectDrawImpl *This)
1492 /* MSDN: "If another application changes the display mode, the primary
1493 * surface is lost, and the method returns DDERR_SURFACELOST until the
1494 * primary surface is recreated to match the new display mode."
1496 * We mark all the primary surfaces as lost as soon as the display
1497 * mode is changed (by any application). */
1499 LoseSurface(This->primary_surface);
1502 /******************************************************************************
1503 * Uninitialised DirectDraw functions
1505 * This vtable is used when a DirectDraw object is created with
1506 * CoCreateInstance. The only usable method is Initialize.
1509 void Uninit_DirectDraw_final_release(IDirectDrawImpl *This)
1511 Main_DirectDraw_final_release(This);
1514 static const IDirectDraw7Vtbl Uninit_DirectDraw_VTable;
1516 /* Not called from the vtable. */
1517 HRESULT Uninit_DirectDraw_Construct(IDirectDrawImpl *This, BOOL ex)
1521 hr = Main_DirectDraw_Construct(This, ex);
1522 if (FAILED(hr)) return hr;
1524 This->final_release = Uninit_DirectDraw_final_release;
1525 ICOM_INIT_INTERFACE(This, IDirectDraw7, Uninit_DirectDraw_VTable);
1530 HRESULT Uninit_DirectDraw_Create(const GUID* pGUID,
1531 LPDIRECTDRAW7* pIface,
1532 IUnknown* pUnkOuter, BOOL ex)
1535 IDirectDrawImpl* This;
1537 assert(pUnkOuter == NULL); /* XXX no: we must check this */
1539 This = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY,
1540 sizeof(IDirectDrawImpl));
1541 if (This == NULL) return E_OUTOFMEMORY;
1543 hr = Uninit_DirectDraw_Construct(This, ex);
1545 HeapFree(GetProcessHeap(), HEAP_ZERO_MEMORY, This);
1547 *pIface = ICOM_INTERFACE(This, IDirectDraw7);
1552 static HRESULT WINAPI
1553 Uninit_DirectDraw_Initialize(LPDIRECTDRAW7 iface, LPGUID pDeviceGuid)
1555 const ddraw_driver* driver;
1556 IDirectDrawImpl *This = (IDirectDrawImpl *)iface;
1558 TRACE("(%p)->(%p)\n", iface, pDeviceGuid);
1560 driver = DDRAW_FindDriver(pDeviceGuid);
1561 /* XXX This return value is not documented. (Not checked.) */
1562 if (driver == NULL) return DDERR_INVALIDDIRECTDRAWGUID;
1564 return driver->init(This, pDeviceGuid);
1567 static HRESULT WINAPI
1568 Uninit_DirectDraw_Compact(LPDIRECTDRAW7 iface)
1570 return DDERR_NOTINITIALIZED;
1573 static HRESULT WINAPI
1574 Uninit_DirectDraw_CreateClipper(LPDIRECTDRAW7 iface, DWORD dwFlags,
1575 LPDIRECTDRAWCLIPPER *lplpDDClipper,
1576 IUnknown *pUnkOuter)
1579 return DDERR_NOTINITIALIZED;
1582 static HRESULT WINAPI
1583 Uninit_DirectDraw_CreatePalette(LPDIRECTDRAW7 iface, DWORD dwFlags,
1584 LPPALETTEENTRY lpColorTable,
1585 LPDIRECTDRAWPALETTE *lplpDDPalette,
1586 IUnknown *pUnkOuter)
1588 return DDERR_NOTINITIALIZED;
1591 static HRESULT WINAPI
1592 Uninit_DirectDraw_CreateSurface(LPDIRECTDRAW7 iface,
1593 LPDDSURFACEDESC2 lpDDSurfaceDesc,
1594 LPDIRECTDRAWSURFACE7 *lplpDDSurface,
1595 IUnknown *pUnkOuter)
1597 return DDERR_NOTINITIALIZED;
1600 static HRESULT WINAPI
1601 Uninit_DirectDraw_DuplicateSurface(LPDIRECTDRAW7 iface,
1602 LPDIRECTDRAWSURFACE7 pSurf,
1603 LPDIRECTDRAWSURFACE7 *pDupSurf)
1606 return DDERR_NOTINITIALIZED;
1609 static HRESULT WINAPI
1610 Uninit_DirectDraw_EnumDisplayModes(LPDIRECTDRAW7 iface, DWORD dwFlags,
1611 LPDDSURFACEDESC2 lpDDSD,
1613 LPDDENUMMODESCALLBACK2 cb)
1615 return DDERR_NOTINITIALIZED;
1618 static HRESULT WINAPI
1619 Uninit_DirectDraw_EnumSurfaces(LPDIRECTDRAW7 iface, DWORD dwFlags,
1620 LPDDSURFACEDESC2 pDDSD, LPVOID context,
1621 LPDDENUMSURFACESCALLBACK7 cb)
1623 return DDERR_NOTINITIALIZED;
1626 static HRESULT WINAPI
1627 Uninit_DirectDraw_FlipToGDISurface(LPDIRECTDRAW7 iface)
1629 return DDERR_NOTINITIALIZED;
1632 static HRESULT WINAPI
1633 Uninit_DirectDraw_GetCaps(LPDIRECTDRAW7 iface, LPDDCAPS pDriverCaps,
1636 return DDERR_NOTINITIALIZED;
1639 static HRESULT WINAPI
1640 Uninit_DirectDraw_GetDisplayMode(LPDIRECTDRAW7 iface,
1641 LPDDSURFACEDESC2 pDDSD)
1643 return DDERR_NOTINITIALIZED;
1646 static HRESULT WINAPI
1647 Uninit_DirectDraw_GetFourCCCodes(LPDIRECTDRAW7 iface, LPDWORD pNumCodes,
1650 return DDERR_NOTINITIALIZED;
1653 static HRESULT WINAPI
1654 Uninit_DirectDraw_GetGDISurface(LPDIRECTDRAW7 iface,
1655 LPDIRECTDRAWSURFACE7 *pGDISurf)
1657 return DDERR_NOTINITIALIZED;
1660 static HRESULT WINAPI
1661 Uninit_DirectDraw_GetMonitorFrequency(LPDIRECTDRAW7 iface, LPDWORD pdwFreq)
1663 return DDERR_NOTINITIALIZED;
1666 static HRESULT WINAPI
1667 Uninit_DirectDraw_GetScanLine(LPDIRECTDRAW7 iface, LPDWORD pdwScanLine)
1669 return DDERR_NOTINITIALIZED;
1672 static HRESULT WINAPI
1673 Uninit_DirectDraw_GetVerticalBlankStatus(LPDIRECTDRAW7 iface, PBOOL pbIsInVB)
1675 return DDERR_NOTINITIALIZED;
1678 static HRESULT WINAPI
1679 Uninit_DirectDraw_RestoreDisplayMode(LPDIRECTDRAW7 iface)
1681 return DDERR_NOTINITIALIZED;
1684 static HRESULT WINAPI
1685 Uninit_DirectDraw_SetCooperativeLevel(LPDIRECTDRAW7 iface, HWND hWnd,
1688 return DDERR_NOTINITIALIZED;
1691 static HRESULT WINAPI
1692 Uninit_DirectDraw_SetDisplayMode(LPDIRECTDRAW7 iface, DWORD dwWidth,
1693 DWORD dwHeight, DWORD dwBPP,
1694 DWORD dwRefreshRate, DWORD dwFlags)
1696 return DDERR_NOTINITIALIZED;
1699 static HRESULT WINAPI
1700 Uninit_DirectDraw_WaitForVerticalBlank(LPDIRECTDRAW7 iface, DWORD dwFlags,
1703 return DDERR_NOTINITIALIZED;
1706 static HRESULT WINAPI
1707 Uninit_DirectDraw_GetAvailableVidMem(LPDIRECTDRAW7 iface, LPDDSCAPS2 pDDCaps,
1708 LPDWORD pdwTotal, LPDWORD pdwFree)
1710 return DDERR_NOTINITIALIZED;
1713 static HRESULT WINAPI
1714 Uninit_DirectDraw_GetSurfaceFromDC(LPDIRECTDRAW7 iface, HDC hDC,
1715 LPDIRECTDRAWSURFACE7 *pSurf)
1717 return DDERR_NOTINITIALIZED;
1720 static HRESULT WINAPI
1721 Uninit_DirectDraw_RestoreAllSurfaces(LPDIRECTDRAW7 iface)
1723 return DDERR_NOTINITIALIZED;
1726 static HRESULT WINAPI
1727 Uninit_DirectDraw_TestCooperativeLevel(LPDIRECTDRAW7 iface)
1729 return DDERR_NOTINITIALIZED;
1732 static HRESULT WINAPI
1733 Uninit_DirectDraw_GetDeviceIdentifier(LPDIRECTDRAW7 iface,
1734 LPDDDEVICEIDENTIFIER2 pDDDI,
1737 return DDERR_NOTINITIALIZED;
1740 static HRESULT WINAPI
1741 Uninit_DirectDraw_StartModeTest(LPDIRECTDRAW7 iface, LPSIZE pszModes,
1742 DWORD cModes, DWORD dwFlags)
1744 return DDERR_NOTINITIALIZED;
1747 static HRESULT WINAPI
1748 Uninit_DirectDraw_EvaluateMode(LPDIRECTDRAW7 iface, DWORD dwFlags,
1751 return DDERR_NOTINITIALIZED;
1754 static const IDirectDraw7Vtbl Uninit_DirectDraw_VTable =
1756 Main_DirectDraw_QueryInterface,
1757 Main_DirectDraw_AddRef,
1758 Main_DirectDraw_Release,
1759 Uninit_DirectDraw_Compact,
1760 Uninit_DirectDraw_CreateClipper,
1761 Uninit_DirectDraw_CreatePalette,
1762 Uninit_DirectDraw_CreateSurface,
1763 Uninit_DirectDraw_DuplicateSurface,
1764 Uninit_DirectDraw_EnumDisplayModes,
1765 Uninit_DirectDraw_EnumSurfaces,
1766 Uninit_DirectDraw_FlipToGDISurface,
1767 Uninit_DirectDraw_GetCaps,
1768 Uninit_DirectDraw_GetDisplayMode,
1769 Uninit_DirectDraw_GetFourCCCodes,
1770 Uninit_DirectDraw_GetGDISurface,
1771 Uninit_DirectDraw_GetMonitorFrequency,
1772 Uninit_DirectDraw_GetScanLine,
1773 Uninit_DirectDraw_GetVerticalBlankStatus,
1774 Uninit_DirectDraw_Initialize,
1775 Uninit_DirectDraw_RestoreDisplayMode,
1776 Uninit_DirectDraw_SetCooperativeLevel,
1777 Uninit_DirectDraw_SetDisplayMode,
1778 Uninit_DirectDraw_WaitForVerticalBlank,
1779 Uninit_DirectDraw_GetAvailableVidMem,
1780 Uninit_DirectDraw_GetSurfaceFromDC,
1781 Uninit_DirectDraw_RestoreAllSurfaces,
1782 Uninit_DirectDraw_TestCooperativeLevel,
1783 Uninit_DirectDraw_GetDeviceIdentifier,
1784 Uninit_DirectDraw_StartModeTest,
1785 Uninit_DirectDraw_EvaluateMode