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