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