| /* DirectDraw IDirectDraw interface (generic) |
| * |
| * Copyright 1997-2000 Marcus Meissner |
| * Copyright 1998-2000 Lionel Ulmer (most of Direct3D stuff) |
| * Copyright 2000-2001 TransGaming Technologies Inc. |
| * |
| * This library is free software; you can redistribute it and/or |
| * modify it under the terms of the GNU Lesser General Public |
| * License as published by the Free Software Foundation; either |
| * version 2.1 of the License, or (at your option) any later version. |
| * |
| * This library is distributed in the hope that it will be useful, |
| * but WITHOUT ANY WARRANTY; without even the implied warranty of |
| * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU |
| * Lesser General Public License for more details. |
| * |
| * You should have received a copy of the GNU Lesser General Public |
| * License along with this library; if not, write to the Free Software |
| * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA |
| * |
| * NOTES |
| * |
| * WINE currently implements a very basic set of the DirectDraw functionality |
| * in graphics/ddraw.c. This implementation uses either the XFree86-DGA extension |
| * to get very fast access to the graphics card framebuffer and doublebuffering |
| * features or Xlib, which is slower. |
| * The implementation using XFree86-DGA is as fast as the MS equivalent for the |
| * stuff that is implemented. |
| * |
| * Several applications already work, see below. |
| * Problems of the implementation using XFree86-DGA: |
| * |
| * - XFree86 cannot switch depth on the fly. |
| * This is a problem with X and unavoidable. |
| * Current solution is to pop up a MessageBox with an error for |
| * mismatched parameters and advice the user to restart the X server |
| * with the specified depth. |
| * - The rest of the functionality that has to be implemented will have |
| * to be done in software and will be very slow. |
| * - This requires WINE to be run as root user so XF86DGA can mmap the |
| * framebuffer into the addressspace of the process. |
| * - Blocks all other X windowed applications. |
| * |
| * This file contains all the interface functions that are shared between |
| * all interfaces. Or better, it is a "common stub" library for the |
| * IDirectDraw* objects |
| */ |
| |
| #include "config.h" |
| #include "wine/port.h" |
| |
| #include <assert.h> |
| #include <stdarg.h> |
| #include <string.h> |
| |
| #define NONAMELESSUNION |
| #define NONAMELESSSTRUCT |
| |
| #include "winerror.h" |
| #include "windef.h" |
| #include "winbase.h" |
| #include "wingdi.h" |
| #include "ddraw.h" |
| #include "d3d.h" |
| #include "wine/debug.h" |
| |
| #include "ddraw_private.h" |
| #include "opengl_private.h" /* To have the D3D creation function */ |
| |
| WINE_DEFAULT_DEBUG_CHANNEL(ddraw); |
| |
| extern const IDirectDrawVtbl DDRAW_IDirectDraw_VTable; |
| extern const IDirectDraw2Vtbl DDRAW_IDirectDraw2_VTable; |
| extern const IDirectDraw4Vtbl DDRAW_IDirectDraw4_VTable; |
| |
| static void DDRAW_UnsubclassWindow(IDirectDrawImpl* This); |
| |
| static void Main_DirectDraw_DeleteSurfaces(IDirectDrawImpl* This); |
| static void Main_DirectDraw_DeleteClippers(IDirectDrawImpl* This); |
| static void Main_DirectDraw_DeletePalettes(IDirectDrawImpl* This); |
| static void LosePrimarySurface(IDirectDrawImpl* This); |
| |
| static INT32 allocate_memory(IDirectDrawImpl *This, DWORD mem) ; |
| static void free_memory(IDirectDrawImpl *This, DWORD mem) ; |
| |
| |
| static const char ddProp[] = "WINE_DDRAW_Property"; |
| |
| /* Not called from the vtable. */ |
| HRESULT Main_DirectDraw_Construct(IDirectDrawImpl *This, BOOL ex) |
| { |
| /* NOTE: The creator must use HEAP_ZERO_MEMORY or equivalent. */ |
| This->ref = 1; |
| This->ex = ex; |
| |
| if (ex) This->local.dwLocalFlags |= DDRAWILCL_DIRECTDRAW7; |
| This->local.dwProcessId = GetCurrentProcessId(); |
| |
| This->final_release = Main_DirectDraw_final_release; |
| |
| This->create_palette = Main_DirectDrawPalette_Create; |
| |
| This->create_offscreen = Main_create_offscreen; |
| This->create_texture = Main_create_texture; |
| This->create_zbuffer = Main_create_zbuffer; |
| /* There are no generic versions of create_{primary,backbuffer}. */ |
| |
| ICOM_INIT_INTERFACE(This, IDirectDraw, DDRAW_IDirectDraw_VTable); |
| ICOM_INIT_INTERFACE(This, IDirectDraw2, DDRAW_IDirectDraw2_VTable); |
| ICOM_INIT_INTERFACE(This, IDirectDraw4, DDRAW_IDirectDraw4_VTable); |
| /* There is no generic implementation of IDD7 */ |
| |
| /* This is for the moment here... */ |
| This->free_memory = free_memory; |
| This->allocate_memory = allocate_memory; |
| This->total_vidmem = 64 * 1024 * 1024; |
| This->available_vidmem = This->total_vidmem; |
| |
| return DD_OK; |
| } |
| |
| void Main_DirectDraw_final_release(IDirectDrawImpl* This) |
| { |
| if (IsWindow(This->window)) |
| { |
| if (GetPropA(This->window, ddProp)) |
| DDRAW_UnsubclassWindow(This); |
| else |
| FIXME("this shouldn't happen, right?\n"); |
| } |
| |
| Main_DirectDraw_DeleteSurfaces(This); |
| Main_DirectDraw_DeleteClippers(This); |
| Main_DirectDraw_DeletePalettes(This); |
| if (This->local.lpGbl && This->local.lpGbl->lpExclusiveOwner == &This->local) |
| { |
| This->local.lpGbl->lpExclusiveOwner = NULL; |
| if (This->set_exclusive_mode) |
| This->set_exclusive_mode(This, FALSE); |
| } |
| } |
| |
| /* There is no Main_DirectDraw_Create. */ |
| |
| ULONG WINAPI Main_DirectDraw_AddRef(LPDIRECTDRAW7 iface) { |
| IDirectDrawImpl *This = (IDirectDrawImpl *)iface; |
| ULONG ref = InterlockedIncrement(&This->ref); |
| |
| TRACE("(%p)->() incrementing from %lu.\n", This, ref -1); |
| |
| return ref; |
| } |
| |
| ULONG WINAPI Main_DirectDraw_Release(LPDIRECTDRAW7 iface) { |
| IDirectDrawImpl *This = (IDirectDrawImpl *)iface; |
| ULONG ref = InterlockedDecrement(&This->ref); |
| |
| TRACE("(%p)->() decrementing from %lu.\n", This, ref +1); |
| |
| if (ref == 0) |
| { |
| if (This->final_release != NULL) |
| This->final_release(This); |
| |
| /* We free the private. This is an artifact of the fact that I don't |
| * have the destructors set up correctly. */ |
| if (This->private != (This+1)) |
| HeapFree(GetProcessHeap(), 0, This->private); |
| |
| HeapFree(GetProcessHeap(), 0, This); |
| } |
| |
| return ref; |
| } |
| |
| HRESULT WINAPI Main_DirectDraw_QueryInterface( |
| LPDIRECTDRAW7 iface,REFIID refiid,LPVOID *obj |
| ) { |
| IDirectDrawImpl *This = (IDirectDrawImpl *)iface; |
| TRACE("(%p)->(%s,%p)\n", This, debugstr_guid(refiid), obj); |
| |
| /* According to COM docs, if the QueryInterface fails, obj should be set to NULL */ |
| *obj = NULL; |
| |
| if ( IsEqualGUID( &IID_IUnknown, refiid ) |
| || IsEqualGUID( &IID_IDirectDraw7, refiid ) ) |
| { |
| *obj = ICOM_INTERFACE(This, IDirectDraw7); |
| } |
| else if ( IsEqualGUID( &IID_IDirectDraw, refiid ) ) |
| { |
| *obj = ICOM_INTERFACE(This, IDirectDraw); |
| } |
| else if ( IsEqualGUID( &IID_IDirectDraw2, refiid ) ) |
| { |
| *obj = ICOM_INTERFACE(This, IDirectDraw2); |
| } |
| else if ( IsEqualGUID( &IID_IDirectDraw4, refiid ) ) |
| { |
| *obj = ICOM_INTERFACE(This, IDirectDraw4); |
| } |
| #ifdef HAVE_OPENGL |
| else if ( IsEqualGUID( &IID_IDirect3D , refiid ) || |
| IsEqualGUID( &IID_IDirect3D2 , refiid ) || |
| IsEqualGUID( &IID_IDirect3D3 , refiid ) || |
| IsEqualGUID( &IID_IDirect3D7 , refiid ) ) |
| { |
| if (opengl_initialized) { |
| HRESULT ret_value; |
| |
| ret_value = direct3d_create(This); |
| if (FAILED(ret_value)) return ret_value; |
| |
| if ( IsEqualGUID( &IID_IDirect3D , refiid ) ) { |
| *obj = ICOM_INTERFACE(This, IDirect3D); |
| TRACE(" returning Direct3D interface at %p.\n", *obj); |
| } else if ( IsEqualGUID( &IID_IDirect3D2 , refiid ) ) { |
| *obj = ICOM_INTERFACE(This, IDirect3D2); |
| TRACE(" returning Direct3D2 interface at %p.\n", *obj); |
| } else if ( IsEqualGUID( &IID_IDirect3D3 , refiid ) ) { |
| *obj = ICOM_INTERFACE(This, IDirect3D3); |
| TRACE(" returning Direct3D3 interface at %p.\n", *obj); |
| } else { |
| *obj = ICOM_INTERFACE(This, IDirect3D7); |
| TRACE(" returning Direct3D7 interface at %p.\n", *obj); |
| } |
| } else { |
| ERR("Application requests a Direct3D interface but dynamic OpenGL support loading failed !\n"); |
| ERR("(%p)->(%s,%p): no interface\n",This,debugstr_guid(refiid),obj); |
| return E_NOINTERFACE; |
| } |
| } |
| #else |
| else if ( IsEqualGUID( &IID_IDirect3D , refiid ) || |
| IsEqualGUID( &IID_IDirect3D2 , refiid ) || |
| IsEqualGUID( &IID_IDirect3D3 , refiid ) || |
| IsEqualGUID( &IID_IDirect3D7 , refiid ) ) |
| { |
| ERR("Application requests a Direct3D interface but OpenGL support not built-in !\n"); |
| ERR("(%p)->(%s,%p): no interface\n",This,debugstr_guid(refiid),obj); |
| return E_NOINTERFACE; |
| } |
| #endif |
| else |
| { |
| FIXME("(%p)->(%s,%p): no interface\n",This,debugstr_guid(refiid),obj); |
| return E_NOINTERFACE; |
| } |
| |
| IDirectDraw7_AddRef(iface); |
| return S_OK; |
| } |
| |
| /* MSDN: "not currently implemented". */ |
| HRESULT WINAPI Main_DirectDraw_Compact(LPDIRECTDRAW7 iface) |
| { |
| TRACE("(%p)\n", iface); |
| |
| return DD_OK; |
| } |
| |
| HRESULT WINAPI Main_DirectDraw_CreateClipper(LPDIRECTDRAW7 iface, |
| DWORD dwFlags, |
| LPDIRECTDRAWCLIPPER *ppClipper, |
| IUnknown *pUnkOuter) |
| { |
| IDirectDrawImpl *This = (IDirectDrawImpl *)iface; |
| HRESULT hr; |
| |
| TRACE("(%p)->(0x%lx, %p, %p)\n", iface, dwFlags, ppClipper, pUnkOuter); |
| |
| hr = DirectDrawCreateClipper(dwFlags, ppClipper, pUnkOuter); |
| if (FAILED(hr)) return hr; |
| |
| /* dwFlags is passed twice, apparently an API wart. */ |
| hr = IDirectDrawClipper_Initialize(*ppClipper, |
| ICOM_INTERFACE(This, IDirectDraw), |
| dwFlags); |
| if (FAILED(hr)) |
| { |
| IDirectDrawClipper_Release(*ppClipper); |
| return hr; |
| } |
| |
| return DD_OK; |
| } |
| |
| HRESULT WINAPI |
| Main_DirectDraw_CreatePalette(LPDIRECTDRAW7 iface, DWORD dwFlags, |
| LPPALETTEENTRY palent, |
| LPDIRECTDRAWPALETTE* ppPalette, |
| LPUNKNOWN pUnknown) |
| { |
| IDirectDrawImpl *This = (IDirectDrawImpl *)iface; |
| LPDIRECTDRAWPALETTE pPalette; |
| HRESULT hr; |
| |
| TRACE("(%p)->(%08lx,%p,%p,%p)\n",This,dwFlags,palent,ppPalette,pUnknown); |
| |
| if (ppPalette == NULL) return E_POINTER; /* unchecked */ |
| if (pUnknown != NULL) return CLASS_E_NOAGGREGATION; /* unchecked */ |
| |
| hr = This->create_palette(This, dwFlags, &pPalette, pUnknown); |
| if (FAILED(hr)) return hr; |
| |
| hr = IDirectDrawPalette_SetEntries(pPalette, 0, 0, |
| Main_DirectDrawPalette_Size(dwFlags), |
| palent); |
| if (FAILED(hr)) |
| { |
| IDirectDrawPalette_Release(pPalette); |
| return hr; |
| } |
| else |
| { |
| *ppPalette = pPalette; |
| return DD_OK; |
| } |
| } |
| |
| HRESULT |
| Main_create_offscreen(IDirectDrawImpl* This, const DDSURFACEDESC2* pDDSD, |
| LPDIRECTDRAWSURFACE7* ppSurf, LPUNKNOWN pOuter) |
| { |
| assert(pOuter == NULL); |
| |
| return DIB_DirectDrawSurface_Create(This, pDDSD, ppSurf, pOuter); |
| } |
| |
| HRESULT |
| Main_create_texture(IDirectDrawImpl* This, const DDSURFACEDESC2* pDDSD, |
| LPDIRECTDRAWSURFACE7* ppSurf, LPUNKNOWN pOuter, |
| DWORD dwMipMapLevel) |
| { |
| assert(pOuter == NULL); |
| |
| return DIB_DirectDrawSurface_Create(This, pDDSD, ppSurf, pOuter); |
| } |
| |
| HRESULT |
| Main_create_zbuffer(IDirectDrawImpl* This, const DDSURFACEDESC2* pDDSD, |
| LPDIRECTDRAWSURFACE7* ppSurf, LPUNKNOWN pOuter) |
| { |
| assert(pOuter == NULL); |
| |
| return FakeZBuffer_DirectDrawSurface_Create(This, pDDSD, ppSurf, pOuter); |
| } |
| |
| /* Does the texture surface described in pDDSD have any smaller mipmaps? */ |
| static BOOL more_mipmaps(const DDSURFACEDESC2 *pDDSD) |
| { |
| return ((pDDSD->dwFlags & DDSD_MIPMAPCOUNT) && pDDSD->u2.dwMipMapCount > 1 |
| && (pDDSD->dwWidth > 1 || pDDSD->dwHeight > 1)); |
| } |
| |
| /* Create a texture surface along with any of its mipmaps. */ |
| static HRESULT |
| create_texture(IDirectDrawImpl* This, const DDSURFACEDESC2 *pDDSD, |
| LPDIRECTDRAWSURFACE7* ppSurf, LPUNKNOWN pUnkOuter) |
| { |
| DDSURFACEDESC2 ddsd; |
| DWORD mipmap_level = 0; |
| HRESULT hr; |
| |
| assert(pUnkOuter == NULL); |
| |
| /* is this check right? (pixelformat can be copied from primary) */ |
| if ((pDDSD->dwFlags&(DDSD_HEIGHT|DDSD_WIDTH)) != (DDSD_HEIGHT|DDSD_WIDTH)) |
| return DDERR_INVALIDPARAMS; |
| |
| ddsd.dwSize = sizeof(ddsd); |
| DD_STRUCT_COPY_BYSIZE((&ddsd),pDDSD); |
| |
| if (!(ddsd.dwFlags & DDSD_PIXELFORMAT)) |
| { |
| ddsd.u4.ddpfPixelFormat = This->pixelformat; |
| } |
| |
| #ifdef HAVE_OPENGL |
| /* We support for now only DXT1, DXT3 & DXT5 compressed texture formats... */ |
| if ((ddsd.u4.ddpfPixelFormat.dwFlags & DDPF_FOURCC) && |
| (ddsd.u4.ddpfPixelFormat.dwFourCC != MAKE_FOURCC('D','X','T','1')) && |
| (ddsd.u4.ddpfPixelFormat.dwFourCC != MAKE_FOURCC('D','X','T','3')) && |
| (ddsd.u4.ddpfPixelFormat.dwFourCC != MAKE_FOURCC('D','X','T','5')) ) |
| { |
| return DDERR_INVALIDPIXELFORMAT; |
| } |
| |
| /* Check if we can really support DXT1, DXT3 & DXT5 */ |
| if ((ddsd.u4.ddpfPixelFormat.dwFlags & DDPF_FOURCC) && |
| !GL_extensions.s3tc_compressed_texture && !s3tc_initialized) { |
| static BOOLEAN user_warned = 0; |
| if (user_warned == 0) { |
| ERR("Trying to create DXT1, DXT3 or DXT5 texture which is not supported by the video card!!!\n"); |
| ERR("However there is a library libtxc_dxtn.so that can be used to do the software decompression...\n"); |
| user_warned = 1; |
| } |
| return DDERR_INVALIDPIXELFORMAT; |
| } |
| #else |
| if (ddsd.u4.ddpfPixelFormat.dwFlags & DDPF_FOURCC) |
| { |
| return DDERR_INVALIDPIXELFORMAT; |
| } |
| #endif |
| |
| if ((ddsd.u4.ddpfPixelFormat.dwFlags & DDPF_FOURCC) && !(ddsd.dwFlags & DDSD_LINEARSIZE)) |
| { |
| int size = 0; |
| int width = ddsd.dwWidth; |
| int height = ddsd.dwHeight; |
| switch(ddsd.u4.ddpfPixelFormat.dwFourCC) { |
| case MAKE_FOURCC('D','X','T','1'): size = ((width+3)&~3) * ((height+3)&~3) / 16 * 8; break; |
| case MAKE_FOURCC('D','X','T','3'): size = ((width+3)&~3) * ((height+3)&~3) / 16 * 16; break; |
| case MAKE_FOURCC('D','X','T','5'): size = ((width+3)&~3) * ((height+3)&~3) / 16 * 16; break; |
| default: FIXME("FOURCC not supported\n"); break; |
| } |
| ddsd.u1.dwLinearSize = size; |
| ddsd.dwFlags |= DDSD_LINEARSIZE; |
| } else if (!(ddsd.u4.ddpfPixelFormat.dwFlags & DDPF_FOURCC) && !(ddsd.dwFlags & DDSD_PITCH)) { |
| ddsd.u1.lPitch = DDRAW_width_bpp_to_pitch(ddsd.dwWidth, GET_BPP(ddsd)*8); |
| ddsd.dwFlags |= DDSD_PITCH; |
| } |
| |
| if((ddsd.ddsCaps.dwCaps & DDSCAPS_MIPMAP) && |
| !(ddsd.dwFlags & DDSD_MIPMAPCOUNT)) |
| { |
| if(ddsd.ddsCaps.dwCaps & DDSCAPS_COMPLEX) |
| { |
| /* Undocumented feature: if DDSCAPS_MIPMAP and DDSCAPS_COMPLEX are |
| * both set, but mipmap count isn't given, as many mipmap levels |
| * as necessary are created to get down to a size where either |
| * the width or the height of the texture is 1. |
| * |
| * This is needed by Anarchy Online. */ |
| DWORD min = ddsd.dwWidth < ddsd.dwHeight ? |
| ddsd.dwWidth : ddsd.dwHeight; |
| ddsd.u2.dwMipMapCount = 0; |
| while( min ) |
| { |
| ddsd.u2.dwMipMapCount++; |
| min >>= 1; |
| } |
| } |
| else |
| /* Create a single mipmap. */ |
| ddsd.u2.dwMipMapCount = 1; |
| |
| ddsd.dwFlags |= DDSD_MIPMAPCOUNT; |
| } |
| |
| ddsd.dwFlags |= DDSD_PIXELFORMAT; |
| |
| hr = This->create_texture(This, &ddsd, ppSurf, pUnkOuter, mipmap_level); |
| if (FAILED(hr)) return hr; |
| |
| if (This->d3d_private) This->d3d_create_texture(This, ICOM_OBJECT(IDirectDrawSurfaceImpl, IDirectDrawSurface7, *ppSurf), TRUE, |
| ICOM_OBJECT(IDirectDrawSurfaceImpl, IDirectDrawSurface7, *ppSurf)); |
| |
| /* Create attached mipmaps if required. */ |
| if (more_mipmaps(&ddsd)) |
| { |
| LPDIRECTDRAWSURFACE7 mipmap; |
| LPDIRECTDRAWSURFACE7 prev_mipmap; |
| DDSURFACEDESC2 mipmap_surface_desc; |
| |
| prev_mipmap = *ppSurf; |
| IDirectDrawSurface7_AddRef(prev_mipmap); |
| mipmap_surface_desc = ddsd; |
| mipmap_surface_desc.ddsCaps.dwCaps2 |= DDSCAPS2_MIPMAPSUBLEVEL; |
| |
| while (more_mipmaps(&mipmap_surface_desc)) |
| { |
| IDirectDrawSurfaceImpl *mipmap_impl; |
| |
| mipmap_level++; |
| mipmap_surface_desc.u2.dwMipMapCount--; |
| |
| if (mipmap_surface_desc.dwWidth > 1) |
| mipmap_surface_desc.dwWidth /= 2; |
| |
| if (mipmap_surface_desc.dwHeight > 1) |
| mipmap_surface_desc.dwHeight /= 2; |
| |
| if (mipmap_surface_desc.u4.ddpfPixelFormat.dwFlags & DDPF_FOURCC) { |
| int size = 0; |
| int width = mipmap_surface_desc.dwWidth; |
| int height = mipmap_surface_desc.dwHeight; |
| switch(mipmap_surface_desc.u4.ddpfPixelFormat.dwFourCC) { |
| case MAKE_FOURCC('D','X','T','1'): size = ((width+3)&~3) * ((height+3)&~3) / 16 * 8; break; |
| case MAKE_FOURCC('D','X','T','3'): size = ((width+3)&~3) * ((height+3)&~3) / 16 * 16; break; |
| case MAKE_FOURCC('D','X','T','5'): size = ((width+3)&~3) * ((height+3)&~3) / 16 * 16; break; |
| default: FIXME("FOURCC not supported\n"); break; |
| } |
| mipmap_surface_desc.u1.dwLinearSize = size; |
| } else { |
| ddsd.u1.lPitch = DDRAW_width_bpp_to_pitch(ddsd.dwWidth, GET_BPP(ddsd)*8); |
| mipmap_surface_desc.u1.lPitch |
| = DDRAW_width_bpp_to_pitch(mipmap_surface_desc.dwWidth, |
| GET_BPP(ddsd)*8); |
| } |
| |
| hr = This->create_texture(This, &mipmap_surface_desc, &mipmap, |
| pUnkOuter, mipmap_level); |
| if (FAILED(hr)) |
| { |
| IDirectDrawSurface7_Release(prev_mipmap); |
| IDirectDrawSurface7_Release(*ppSurf); |
| return hr; |
| } |
| |
| /* This is needed for delayed mipmap creation */ |
| mipmap_impl = ICOM_OBJECT(IDirectDrawSurfaceImpl, IDirectDrawSurface7, mipmap); |
| mipmap_impl->mip_main = ICOM_OBJECT(IDirectDrawSurfaceImpl, IDirectDrawSurface7, *ppSurf); |
| mipmap_impl->mipmap_level = mipmap_level; |
| |
| if (This->d3d_private) This->d3d_create_texture(This, ICOM_OBJECT(IDirectDrawSurfaceImpl, IDirectDrawSurface7, mipmap), TRUE, |
| ICOM_OBJECT(IDirectDrawSurfaceImpl, IDirectDrawSurface7, *ppSurf)); |
| |
| IDirectDrawSurface7_AddAttachedSurface(prev_mipmap, mipmap); |
| IDirectDrawSurface7_Release(prev_mipmap); |
| prev_mipmap = mipmap; |
| } |
| |
| IDirectDrawSurface7_Release(prev_mipmap); |
| } |
| |
| return DD_OK; |
| } |
| |
| /* Creates a primary surface and any indicated backbuffers. */ |
| static HRESULT |
| create_primary(IDirectDrawImpl* This, LPDDSURFACEDESC2 pDDSD, |
| LPDIRECTDRAWSURFACE7* ppSurf, LPUNKNOWN pUnkOuter) |
| { |
| DDSURFACEDESC2 ddsd; |
| HRESULT hr; |
| |
| assert(pUnkOuter == NULL); |
| |
| if (This->primary_surface != NULL) |
| return DDERR_PRIMARYSURFACEALREADYEXISTS; |
| |
| /* as documented (what about pitch?) */ |
| if (pDDSD->dwFlags & (DDSD_HEIGHT|DDSD_WIDTH|DDSD_PIXELFORMAT)) |
| return DDERR_INVALIDPARAMS; |
| |
| ddsd.dwSize = sizeof(ddsd); |
| DD_STRUCT_COPY_BYSIZE((&ddsd),pDDSD); |
| ddsd.dwFlags |= DDSD_HEIGHT | DDSD_WIDTH | DDSD_PITCH | DDSD_PIXELFORMAT; |
| ddsd.dwHeight = This->height; |
| ddsd.dwWidth = This->width; |
| ddsd.u1.lPitch = This->pitch; |
| ddsd.u4.ddpfPixelFormat = This->pixelformat; |
| ddsd.ddsCaps.dwCaps |= DDSCAPS_LOCALVIDMEM | DDSCAPS_VIDEOMEMORY |
| | DDSCAPS_VISIBLE | DDSCAPS_FRONTBUFFER; |
| |
| if ((ddsd.dwFlags & DDSD_BACKBUFFERCOUNT) && ddsd.dwBackBufferCount > 0) |
| ddsd.ddsCaps.dwCaps |= DDSCAPS_FLIP; |
| |
| hr = This->create_primary(This, &ddsd, ppSurf, pUnkOuter); |
| if (FAILED(hr)) return hr; |
| |
| if (ddsd.dwFlags & DDSD_BACKBUFFERCOUNT) |
| { |
| IDirectDrawSurfaceImpl* primary; |
| LPDIRECTDRAWSURFACE7 pPrev; |
| DWORD i; |
| |
| ddsd.dwFlags &= ~DDSD_BACKBUFFERCOUNT; |
| ddsd.ddsCaps.dwCaps &= ~(DDSCAPS_VISIBLE | DDSCAPS_PRIMARYSURFACE |
| | DDSCAPS_BACKBUFFER | DDSCAPS_FRONTBUFFER); |
| |
| primary = ICOM_OBJECT(IDirectDrawSurfaceImpl,IDirectDrawSurface7, |
| *ppSurf); |
| pPrev = *ppSurf; |
| IDirectDrawSurface7_AddRef(pPrev); |
| |
| for (i=0; i < ddsd.dwBackBufferCount; i++) |
| { |
| LPDIRECTDRAWSURFACE7 pBack; |
| |
| if (i == 0) |
| ddsd.ddsCaps.dwCaps |= DDSCAPS_BACKBUFFER; |
| else |
| ddsd.ddsCaps.dwCaps &= ~DDSCAPS_BACKBUFFER; |
| |
| hr = This->create_backbuffer(This, &ddsd, &pBack, pUnkOuter, |
| primary); |
| |
| if (FAILED(hr)) |
| { |
| IDirectDraw7_Release(pPrev); |
| IDirectDraw7_Release(*ppSurf); |
| return hr; |
| } |
| |
| IDirectDrawSurface7_AddAttachedSurface(pPrev, pBack); |
| IDirectDrawSurface7_Release(pPrev); |
| pPrev = pBack; |
| } |
| |
| IDirectDrawSurface7_Release(pPrev); |
| } |
| |
| This->primary_surface = (IDirectDrawSurfaceImpl *)*ppSurf; |
| |
| return DD_OK; |
| } |
| |
| static HRESULT |
| create_offscreen(IDirectDrawImpl* This, LPDDSURFACEDESC2 pDDSD, |
| LPDIRECTDRAWSURFACE7* ppSurf, LPUNKNOWN pUnkOuter) |
| { |
| DDSURFACEDESC2 ddsd; |
| HRESULT hr; |
| |
| /* is this check right? (pixelformat can be copied from primary) */ |
| if ((pDDSD->dwFlags&(DDSD_HEIGHT|DDSD_WIDTH)) != (DDSD_HEIGHT|DDSD_WIDTH)) |
| return DDERR_INVALIDPARAMS; |
| |
| ddsd.dwSize = sizeof(ddsd); |
| DD_STRUCT_COPY_BYSIZE((&ddsd),pDDSD); |
| |
| if (!(ddsd.dwFlags & DDSD_PIXELFORMAT)) |
| { |
| ddsd.u4.ddpfPixelFormat = This->pixelformat; |
| } |
| |
| if (!(ddsd.dwFlags & DDSD_PITCH)) |
| { |
| ddsd.u1.lPitch = DDRAW_width_bpp_to_pitch(ddsd.dwWidth, |
| GET_BPP(ddsd)*8); |
| } |
| |
| ddsd.dwFlags |= DDSD_PITCH | DDSD_PIXELFORMAT; |
| |
| hr = This->create_offscreen(This, &ddsd, ppSurf, pUnkOuter); |
| if (FAILED(hr)) return hr; |
| |
| return hr; |
| } |
| |
| HRESULT WINAPI |
| Main_DirectDraw_CreateSurface(LPDIRECTDRAW7 iface, LPDDSURFACEDESC2 pDDSD, |
| LPDIRECTDRAWSURFACE7 *ppSurf, |
| IUnknown *pUnkOuter) |
| { |
| HRESULT hr; |
| IDirectDrawImpl *This = (IDirectDrawImpl *)iface; |
| |
| TRACE("(%p)->(%p,%p,%p)\n",This,pDDSD,ppSurf,pUnkOuter); |
| if (TRACE_ON(ddraw)) { |
| TRACE("Requesting surface desc :\n"); |
| DDRAW_dump_surface_desc(pDDSD); |
| } |
| |
| if (pUnkOuter != NULL) { |
| FIXME("outer != NULL?\n"); |
| return CLASS_E_NOAGGREGATION; /* unchecked */ |
| } |
| |
| if (!(pDDSD->dwFlags & DDSD_CAPS)) { |
| /* DVIDEO.DLL does forget the DDSD_CAPS flag ... *sigh* */ |
| pDDSD->dwFlags |= DDSD_CAPS; |
| } |
| if (pDDSD->ddsCaps.dwCaps == 0) { |
| /* This has been checked on real Windows */ |
| pDDSD->ddsCaps.dwCaps = DDSCAPS_LOCALVIDMEM | DDSCAPS_VIDEOMEMORY; |
| } |
| |
| if (pDDSD->ddsCaps.dwCaps & DDSCAPS_ALLOCONLOAD) { |
| /* If the surface is of the 'alloconload' type, ignore the LPSURFACE field */ |
| pDDSD->dwFlags &= ~DDSD_LPSURFACE; |
| } |
| |
| if ((pDDSD->dwFlags & DDSD_LPSURFACE) && (pDDSD->lpSurface == NULL)) { |
| /* Frank Herbert's Dune specifies a null pointer for the surface, ignore the LPSURFACE field */ |
| WARN("Null surface pointer specified, ignore it!\n"); |
| pDDSD->dwFlags &= ~DDSD_LPSURFACE; |
| } |
| |
| if (ppSurf == NULL) { |
| FIXME("You want to get back a surface? Don't give NULL ptrs!\n"); |
| return E_POINTER; /* unchecked */ |
| } |
| |
| if (pDDSD->ddsCaps.dwCaps & DDSCAPS_PRIMARYSURFACE) |
| { |
| /* create primary surface & backbuffers */ |
| hr = create_primary(This, pDDSD, ppSurf, pUnkOuter); |
| } |
| else if (pDDSD->ddsCaps.dwCaps & DDSCAPS_BACKBUFFER) |
| { |
| /* create backbuffer surface */ |
| hr = This->create_backbuffer(This, pDDSD, ppSurf, pUnkOuter, NULL); |
| } |
| else if (pDDSD->ddsCaps.dwCaps & DDSCAPS_TEXTURE) |
| { |
| /* create texture */ |
| hr = create_texture(This, pDDSD, ppSurf, pUnkOuter); |
| } |
| else if ( (pDDSD->ddsCaps.dwCaps & DDSCAPS_ZBUFFER) && |
| !(pDDSD->ddsCaps.dwCaps & DDSCAPS_OFFSCREENPLAIN)) /* Support DDSCAPS_SYSTEMMEMORY */ |
| { |
| /* create z-buffer */ |
| hr = This->create_zbuffer(This, pDDSD, ppSurf, pUnkOuter); |
| } |
| else if ((pDDSD->ddsCaps.dwCaps & DDSCAPS_OFFSCREENPLAIN) || |
| (pDDSD->ddsCaps.dwCaps & DDSCAPS_SYSTEMMEMORY)) /* No difference in Wine right now */ |
| { |
| /* create offscreenplain surface */ |
| hr = create_offscreen(This, pDDSD, ppSurf, pUnkOuter); |
| } |
| else |
| { |
| /* Otherwise, assume offscreenplain surface */ |
| TRACE("App didn't request a valid surface type - assuming offscreenplain\n"); |
| hr = create_offscreen(This, pDDSD, ppSurf, pUnkOuter); |
| } |
| |
| if (FAILED(hr)) { |
| FIXME("failed surface creation with code 0x%08lx\n",hr); |
| return hr; |
| } |
| |
| return DD_OK; |
| } |
| |
| HRESULT WINAPI |
| Main_DirectDraw_DuplicateSurface(LPDIRECTDRAW7 iface, LPDIRECTDRAWSURFACE7 src, |
| LPDIRECTDRAWSURFACE7* dst) |
| { |
| IDirectDrawImpl *This = (IDirectDrawImpl *)iface; |
| |
| IDirectDrawSurfaceImpl *pSrc = ICOM_OBJECT(IDirectDrawSurfaceImpl, |
| IDirectDrawSurface7, src); |
| |
| TRACE("(%p)->(%p,%p)\n",This,src,dst); |
| |
| return pSrc->duplicate_surface(pSrc, dst); |
| } |
| |
| /* EnumDisplayModes */ |
| |
| BOOL Main_DirectDraw_DDPIXELFORMAT_Match(const DDPIXELFORMAT *requested, |
| const DDPIXELFORMAT *provided) |
| { |
| /* Some flags must be present in both or neither for a match. */ |
| static const DWORD must_match = DDPF_PALETTEINDEXED1 | DDPF_PALETTEINDEXED2 |
| | DDPF_PALETTEINDEXED4 | DDPF_PALETTEINDEXED8 | DDPF_FOURCC |
| | DDPF_ZBUFFER | DDPF_STENCILBUFFER; |
| |
| if ((requested->dwFlags & provided->dwFlags) != requested->dwFlags) |
| return FALSE; |
| |
| if ((requested->dwFlags & must_match) != (provided->dwFlags & must_match)) |
| return FALSE; |
| |
| if (requested->dwFlags & DDPF_FOURCC) |
| if (requested->dwFourCC != provided->dwFourCC) |
| return FALSE; |
| |
| if (requested->dwFlags & (DDPF_RGB|DDPF_YUV|DDPF_ZBUFFER|DDPF_ALPHA |
| |DDPF_LUMINANCE|DDPF_BUMPDUDV)) |
| if (requested->u1.dwRGBBitCount != provided->u1.dwRGBBitCount) |
| return FALSE; |
| |
| if (requested->dwFlags & (DDPF_RGB|DDPF_YUV|DDPF_STENCILBUFFER |
| |DDPF_LUMINANCE|DDPF_BUMPDUDV)) |
| if (requested->u2.dwRBitMask != provided->u2.dwRBitMask) |
| return FALSE; |
| |
| if (requested->dwFlags & (DDPF_RGB|DDPF_YUV|DDPF_ZBUFFER|DDPF_BUMPDUDV)) |
| if (requested->u3.dwGBitMask != provided->u3.dwGBitMask) |
| return FALSE; |
| |
| /* I could be wrong about the bumpmapping. MSDN docs are vague. */ |
| if (requested->dwFlags & (DDPF_RGB|DDPF_YUV|DDPF_STENCILBUFFER |
| |DDPF_BUMPDUDV)) |
| if (requested->u4.dwBBitMask != provided->u4.dwBBitMask) |
| return FALSE; |
| |
| if (requested->dwFlags & (DDPF_ALPHAPIXELS|DDPF_ZPIXELS)) |
| if (requested->u5.dwRGBAlphaBitMask != provided->u5.dwRGBAlphaBitMask) |
| return FALSE; |
| |
| return TRUE; |
| } |
| |
| BOOL Main_DirectDraw_DDSD_Match(const DDSURFACEDESC2* requested, |
| const DDSURFACEDESC2* provided) |
| { |
| struct compare_info |
| { |
| DWORD flag; |
| ptrdiff_t offset; |
| size_t size; |
| }; |
| |
| #define CMP(FLAG, FIELD) \ |
| { DDSD_##FLAG, offsetof(DDSURFACEDESC2, FIELD), \ |
| sizeof(((DDSURFACEDESC2 *)(NULL))->FIELD) } |
| |
| static const struct compare_info compare[] = { |
| CMP(ALPHABITDEPTH, dwAlphaBitDepth), |
| CMP(BACKBUFFERCOUNT, dwBackBufferCount), |
| CMP(CAPS, ddsCaps), |
| CMP(CKDESTBLT, ddckCKDestBlt), |
| CMP(CKDESTOVERLAY, u3.ddckCKDestOverlay), |
| CMP(CKSRCBLT, ddckCKSrcBlt), |
| CMP(CKSRCOVERLAY, ddckCKSrcOverlay), |
| CMP(HEIGHT, dwHeight), |
| CMP(LINEARSIZE, u1.dwLinearSize), |
| CMP(LPSURFACE, lpSurface), |
| CMP(MIPMAPCOUNT, u2.dwMipMapCount), |
| CMP(PITCH, u1.lPitch), |
| /* PIXELFORMAT: manual */ |
| CMP(REFRESHRATE, u2.dwRefreshRate), |
| CMP(TEXTURESTAGE, dwTextureStage), |
| CMP(WIDTH, dwWidth), |
| /* ZBUFFERBITDEPTH: "obsolete" */ |
| }; |
| |
| #undef CMP |
| |
| unsigned int i; |
| |
| if ((requested->dwFlags & provided->dwFlags) != requested->dwFlags) |
| return FALSE; |
| |
| for (i=0; i < sizeof(compare)/sizeof(compare[0]); i++) |
| { |
| if (requested->dwFlags & compare[i].flag |
| && memcmp((const char *)provided + compare[i].offset, |
| (const char *)requested + compare[i].offset, |
| compare[i].size) != 0) |
| return FALSE; |
| } |
| |
| if (requested->dwFlags & DDSD_PIXELFORMAT) |
| { |
| if (!Main_DirectDraw_DDPIXELFORMAT_Match(&requested->u4.ddpfPixelFormat, |
| &provided->u4.ddpfPixelFormat)) |
| return FALSE; |
| } |
| |
| return TRUE; |
| } |
| |
| #define DDENUMSURFACES_SEARCHTYPE (DDENUMSURFACES_CANBECREATED|DDENUMSURFACES_DOESEXIST) |
| #define DDENUMSURFACES_MATCHTYPE (DDENUMSURFACES_ALL|DDENUMSURFACES_MATCH|DDENUMSURFACES_NOMATCH) |
| |
| /* This should be extended so that it can be used by |
| * IDirectDrawSurface7::EnumAttachedSurfaces. */ |
| HRESULT |
| Main_DirectDraw_EnumExistingSurfaces(IDirectDrawImpl *This, DWORD dwFlags, |
| LPDDSURFACEDESC2 lpDDSD2, LPVOID context, |
| LPDDENUMSURFACESCALLBACK7 callback) |
| { |
| IDirectDrawSurfaceImpl *surf; |
| BOOL all, nomatch; |
| |
| /* A NULL lpDDSD2 is permitted if we are enumerating all surfaces anyway */ |
| if (lpDDSD2 == NULL && !(dwFlags & DDENUMSURFACES_ALL)) |
| return DDERR_INVALIDPARAMS; |
| |
| all = dwFlags & DDENUMSURFACES_ALL; |
| nomatch = dwFlags & DDENUMSURFACES_NOMATCH; |
| |
| for (surf = This->surfaces; surf != NULL; surf = surf->next_ddraw) |
| { |
| if (all |
| || (nomatch != Main_DirectDraw_DDSD_Match(lpDDSD2, |
| &surf->surface_desc))) |
| { |
| LPDIRECTDRAWSURFACE7 isurf = ICOM_INTERFACE(surf, IDirectDrawSurface7); |
| DDSURFACEDESC2 desc; |
| |
| if (TRACE_ON(ddraw)) { |
| TRACE(" => enumerating surface %p (priv. %p) with description:\n", isurf, surf); |
| DDRAW_dump_surface_desc(&surf->surface_desc); |
| } |
| |
| IDirectDrawSurface7_AddRef(isurf); |
| |
| desc = surf->surface_desc; |
| if (callback(isurf, &desc, context) == DDENUMRET_CANCEL) |
| break; |
| } |
| } |
| TRACE(" end of enumeration.\n"); |
| |
| return DD_OK; |
| } |
| |
| /* I really don't understand how this is supposed to work. |
| * We only consider dwHeight, dwWidth and ddpfPixelFormat.dwFlags. */ |
| HRESULT |
| Main_DirectDraw_EnumCreateableSurfaces(IDirectDrawImpl *This, DWORD dwFlags, |
| LPDDSURFACEDESC2 lpDDSD2, |
| LPVOID context, |
| LPDDENUMSURFACESCALLBACK7 callback) |
| { |
| FIXME("This isn't going to work.\n"); |
| |
| if ((dwFlags & DDENUMSURFACES_MATCHTYPE) != DDENUMSURFACES_MATCH) |
| return DDERR_INVALIDPARAMS; |
| |
| /* TODO: implement this. |
| * Does this work before SCL is called? |
| * Does it only consider off-screen surfaces? |
| */ |
| |
| return E_FAIL; |
| } |
| |
| /* For unsigned x. 0 is not a power of 2. */ |
| #define IS_POW_2(x) (((x) & ((x) - 1)) == 0) |
| |
| HRESULT WINAPI |
| Main_DirectDraw_EnumSurfaces(LPDIRECTDRAW7 iface, DWORD dwFlags, |
| LPDDSURFACEDESC2 lpDDSD2, LPVOID context, |
| LPDDENUMSURFACESCALLBACK7 callback) |
| { |
| IDirectDrawImpl *This = (IDirectDrawImpl *)iface; |
| TRACE("(%p)->(0x%lx, %p, %p, %p)\n", iface, dwFlags, lpDDSD2, context, |
| callback); |
| if (TRACE_ON(ddraw)) { |
| TRACE(" flags: "); DDRAW_dump_DDENUMSURFACES(dwFlags); |
| } |
| |
| if (callback == NULL) |
| return DDERR_INVALIDPARAMS; |
| |
| if (dwFlags & ~(DDENUMSURFACES_SEARCHTYPE|DDENUMSURFACES_MATCHTYPE)) |
| return DDERR_INVALIDPARAMS; |
| |
| if (!IS_POW_2(dwFlags & DDENUMSURFACES_SEARCHTYPE) |
| || !IS_POW_2(dwFlags & DDENUMSURFACES_MATCHTYPE)) |
| return DDERR_INVALIDPARAMS; |
| |
| if (dwFlags & DDENUMSURFACES_DOESEXIST) |
| { |
| return Main_DirectDraw_EnumExistingSurfaces(This, dwFlags, lpDDSD2, |
| context, callback); |
| } |
| else |
| { |
| return Main_DirectDraw_EnumCreateableSurfaces(This, dwFlags, lpDDSD2, |
| context, callback); |
| } |
| } |
| |
| HRESULT WINAPI |
| Main_DirectDraw_EvaluateMode(LPDIRECTDRAW7 iface,DWORD a,DWORD* b) |
| { |
| IDirectDrawImpl *This = (IDirectDrawImpl *)iface; |
| FIXME("(%p)->() stub\n", This); |
| |
| return DD_OK; |
| } |
| |
| HRESULT WINAPI |
| Main_DirectDraw_FlipToGDISurface(LPDIRECTDRAW7 iface) |
| { |
| IDirectDrawImpl *This = (IDirectDrawImpl *)iface; |
| TRACE("(%p)->()\n",This); |
| return DD_OK; |
| } |
| |
| HRESULT WINAPI |
| Main_DirectDraw_GetCaps(LPDIRECTDRAW7 iface, LPDDCAPS pDriverCaps, |
| LPDDCAPS pHELCaps) |
| { |
| IDirectDrawImpl *This = (IDirectDrawImpl *)iface; |
| TRACE("(%p,%p,%p)\n",This,pDriverCaps,pHELCaps); |
| if (pDriverCaps != NULL) { |
| DD_STRUCT_COPY_BYSIZE(pDriverCaps,&This->caps); |
| if (TRACE_ON(ddraw)) { |
| TRACE("Driver Caps :\n"); |
| DDRAW_dump_DDCAPS(pDriverCaps); |
| } |
| } |
| if (pHELCaps != NULL) { |
| DD_STRUCT_COPY_BYSIZE(pHELCaps,&This->caps); |
| if (TRACE_ON(ddraw)) { |
| TRACE("HEL Caps :\n"); |
| DDRAW_dump_DDCAPS(pHELCaps); |
| } |
| } |
| return DD_OK; |
| } |
| |
| /* GetCaps */ |
| /* GetDeviceIdentifier */ |
| /* GetDIsplayMode */ |
| |
| HRESULT WINAPI |
| Main_DirectDraw_GetFourCCCodes(LPDIRECTDRAW7 iface, LPDWORD pNumCodes, |
| LPDWORD pCodes) |
| { |
| IDirectDrawImpl *This = (IDirectDrawImpl *)iface; |
| if (*pNumCodes) { |
| *pNumCodes=0; |
| } |
| FIXME("(%p,%p,%p), stub\n",This,pNumCodes,pCodes); |
| return DD_OK; |
| } |
| |
| HRESULT WINAPI |
| Main_DirectDraw_GetGDISurface(LPDIRECTDRAW7 iface, |
| LPDIRECTDRAWSURFACE7 *lplpGDIDDSSurface) |
| { |
| IDirectDrawImpl *This = (IDirectDrawImpl *)iface; |
| TRACE("(%p)->(%p)\n", This, lplpGDIDDSSurface); |
| TRACE("returning primary (%p)\n", This->primary_surface); |
| *lplpGDIDDSSurface = ICOM_INTERFACE(This->primary_surface, IDirectDrawSurface7); |
| if (*lplpGDIDDSSurface) |
| IDirectDrawSurface7_AddRef(*lplpGDIDDSSurface); |
| return DD_OK; |
| } |
| |
| HRESULT WINAPI |
| Main_DirectDraw_GetMonitorFrequency(LPDIRECTDRAW7 iface,LPDWORD freq) |
| { |
| IDirectDrawImpl *This = (IDirectDrawImpl *)iface; |
| FIXME("(%p)->(%p) returns 60 Hz always\n",This,freq); |
| *freq = 60*100; /* 60 Hz */ |
| return DD_OK; |
| } |
| |
| HRESULT WINAPI |
| Main_DirectDraw_GetScanLine(LPDIRECTDRAW7 iface, LPDWORD lpdwScanLine) |
| { |
| IDirectDrawImpl *This = (IDirectDrawImpl *)iface; |
| static BOOL hide; |
| |
| /* Since this method is called often, show the fixme only once */ |
| if (!hide) { |
| FIXME("(%p)->(%p) semi-stub\n", This, lpdwScanLine); |
| hide = TRUE; |
| } |
| |
| /* Fake the line sweeping of the monitor */ |
| /* FIXME: We should synchronize with a source to keep the refresh rate */ |
| *lpdwScanLine = This->cur_scanline++; |
| /* Assume 20 scan lines in the vertical blank */ |
| if (This->cur_scanline >= This->height + 20) |
| This->cur_scanline = 0; |
| |
| return DD_OK; |
| } |
| |
| HRESULT WINAPI |
| Main_DirectDraw_GetSurfaceFromDC(LPDIRECTDRAW7 iface, HDC hdc, |
| LPDIRECTDRAWSURFACE7 *lpDDS) |
| { |
| IDirectDrawImpl *This = (IDirectDrawImpl *)iface; |
| FIXME("(%p)->(%p,%p)\n", This, hdc, lpDDS); |
| |
| return DD_OK; |
| } |
| |
| HRESULT WINAPI |
| Main_DirectDraw_GetVerticalBlankStatus(LPDIRECTDRAW7 iface, LPBOOL status) |
| { |
| IDirectDrawImpl *This = (IDirectDrawImpl *)iface; |
| TRACE("(%p)->(%p)\n",This,status); |
| *status = TRUE; |
| return DD_OK; |
| } |
| |
| /* If we were not initialised then Uninit_Main_IDirectDraw7_Initialize would |
| * have been called instead. */ |
| HRESULT WINAPI |
| Main_DirectDraw_Initialize(LPDIRECTDRAW7 iface, LPGUID lpGuid) |
| { |
| TRACE("(%p)->(%s)\n", iface, debugstr_guid(lpGuid)); |
| |
| return DDERR_ALREADYINITIALIZED; |
| } |
| |
| HRESULT WINAPI |
| Main_DirectDraw_RestoreAllSurfaces(LPDIRECTDRAW7 iface) |
| { |
| IDirectDrawImpl *This = (IDirectDrawImpl *)iface; |
| IDirectDrawSurfaceImpl* surf; |
| |
| TRACE("(%p)->()\n", This); |
| |
| for (surf = This->surfaces; surf != NULL; surf = surf->next_ddraw) |
| IDirectDrawSurface7_Restore(ICOM_INTERFACE(surf, IDirectDrawSurface7)); |
| |
| return DD_OK; |
| } |
| |
| static void DDRAW_SubclassWindow(IDirectDrawImpl* This) |
| { |
| /* Well we don't actually subclass the window yet. */ |
| SetPropA(This->window, ddProp, This); |
| } |
| |
| static void DDRAW_UnsubclassWindow(IDirectDrawImpl* This) |
| { |
| RemovePropA(This->window, ddProp); |
| } |
| |
| HRESULT WINAPI |
| Main_DirectDraw_SetCooperativeLevel(LPDIRECTDRAW7 iface, HWND hwnd, |
| DWORD cooplevel) |
| { |
| IDirectDrawImpl *This = (IDirectDrawImpl *)iface; |
| |
| FIXME("(%p)->(%p,%08lx)\n",This,hwnd,cooplevel); |
| DDRAW_dump_cooperativelevel(cooplevel); |
| |
| /* Makes realMYST test happy. */ |
| if (This->cooperative_level == cooplevel |
| && This->window == hwnd) |
| return DD_OK; |
| |
| /* XXX "It cannot be reset while the process has surfaces or palettes |
| * created." Otherwise the window can be changed??? |
| * |
| * This appears to be wrong - comment it out for now. |
| * This seems to be true at least for DDSCL_SETFOCUSWINDOW |
| * It looks like Windows doesn't store the HWND in all cases, |
| * probably if DDSCL_NORMAL is specified, but that's not sure |
| if (This->window) |
| return DDERR_HWNDALREADYSET; |
| */ |
| |
| /* DDSCL_EXCLUSIVE or DDSCL_NORMAL or DDSCL_SETFOCUSWINDOW must be given */ |
| if (!(cooplevel & (DDSCL_EXCLUSIVE|DDSCL_NORMAL|DDSCL_SETFOCUSWINDOW))) |
| { |
| ERR("(%p) : Call to SetCooperativeLevel failed: cooplevel != DDSCL_EXCLUSIVE|DDSCL_NORMAL|DDSCL_SETFOCUSWINDOW, returning DDERR_INVALIDPARAMS\n", This); |
| return DDERR_INVALIDPARAMS; |
| } |
| /* Device window and focus Window. They only really matter in a |
| * Multi-Monitor application, but some games specify them and we |
| * have to react correctly. */ |
| if(cooplevel & DDSCL_SETFOCUSWINDOW) |
| { |
| /* This flag is a biest: It is only valid when DDSCL_NORMAL has been set |
| * or no hwnd is set and no other flags are allowed, except DDSCL_NOWINDOWCHANGES |
| */ |
| if(This->window) |
| if(!(This->cooperative_level & DDSCL_NORMAL)) |
| { |
| ERR("(%p) : Call to SetCooperativeLevel failed: DDSCL_SETFOCUSWINDOW may not be used in Cooplevel %08lx, returning DDERR_HWNDALREADYSET\n", |
| This, This->cooperative_level); |
| return DDERR_HWNDALREADYSET; |
| } |
| if((cooplevel != DDSCL_SETFOCUSWINDOW)) |
| if(cooplevel != (DDSCL_SETFOCUSWINDOW | DDSCL_NOWINDOWCHANGES) ) |
| { |
| ERR("(%p) : Call to SetCooperativeLevel failed: Invalid use of DDSCL_SETFOCUSWINDOW, returning DDERR_INVALIDPARAMS\n", This); |
| return DDERR_INVALIDPARAMS; |
| } |
| |
| /* Don't know what exactly to do, but it's perfectly valid |
| * to pass DDSCL_SETFOCUSWINDOW only */ |
| FIXME("(%p) : Poorly handled flag DDSCL_SETFOCUSWINDOW\n", This); |
| |
| /* Store the flag in the cooperative level. I don't think that all other |
| * flags should be overwritten, so just add it |
| * (In the most cases this will be DDSCL_SETFOCUSWINDOW | DDSCL_NORMAL) */ |
| cooplevel |= DDSCL_SETFOCUSWINDOW; |
| |
| return DD_OK; |
| } |
| |
| /* DDSCL_EXCLUSE mode requires DDSCL_FULLSCREEN and vice versa */ |
| if((cooplevel & DDSCL_EXCLUSIVE) && !(cooplevel & DDSCL_FULLSCREEN)) |
| return DDERR_INVALIDPARAMS; |
| /* The other case is checked above */ |
| |
| /* Unhandled flags. Give a warning */ |
| if(cooplevel & DDSCL_SETDEVICEWINDOW) |
| FIXME("(%p) : Unhandled flag DDSCL_SETDEVICEWINDOW.\n", This); |
| if(cooplevel & DDSCL_CREATEDEVICEWINDOW) |
| FIXME("(%p) : Unhandled flag DDSCL_CREATEDEVICEWINDOW.\n", This); |
| |
| /* Perhaps the hwnd is only set in DDSCL_EXLUSIVE and DDSCL_FULLSCREEN mode. Not sure */ |
| This->window = hwnd; |
| This->cooperative_level = cooplevel; |
| |
| This->local.hWnd = (ULONG_PTR)hwnd; |
| This->local.dwLocalFlags |= DDRAWILCL_SETCOOPCALLED; |
| /* not entirely sure about these */ |
| if (cooplevel & DDSCL_EXCLUSIVE) This->local.dwLocalFlags |= DDRAWILCL_HASEXCLUSIVEMODE; |
| if (cooplevel & DDSCL_FULLSCREEN) This->local.dwLocalFlags |= DDRAWILCL_ISFULLSCREEN; |
| if (cooplevel & DDSCL_ALLOWMODEX) This->local.dwLocalFlags |= DDRAWILCL_ALLOWMODEX; |
| if (cooplevel & DDSCL_MULTITHREADED) This->local.dwLocalFlags |= DDRAWILCL_MULTITHREADED; |
| if (cooplevel & DDSCL_FPUSETUP) This->local.dwLocalFlags |= DDRAWILCL_FPUSETUP; |
| if (cooplevel & DDSCL_FPUPRESERVE) This->local.dwLocalFlags |= DDRAWILCL_FPUPRESERVE; |
| |
| if (This->local.lpGbl) { |
| /* assume that this app is the active app (in wine, there's |
| * probably only one app per global ddraw object anyway) */ |
| if (cooplevel & DDSCL_EXCLUSIVE) This->local.lpGbl->lpExclusiveOwner = &This->local; |
| else if (This->local.lpGbl->lpExclusiveOwner == &This->local) |
| This->local.lpGbl->lpExclusiveOwner = NULL; |
| if (This->set_exclusive_mode) |
| This->set_exclusive_mode(This, (cooplevel & DDSCL_EXCLUSIVE) != 0); |
| } |
| |
| ShowWindow(hwnd, SW_SHOW); |
| |
| DDRAW_SubclassWindow(This); |
| |
| /* TODO Does it also get resized to the current screen size? */ |
| |
| return DD_OK; |
| } |
| |
| HRESULT WINAPI |
| Main_DirectDraw_SetDisplayMode(LPDIRECTDRAW7 iface, DWORD dwWidth, |
| DWORD dwHeight, LONG lPitch, |
| DWORD dwRefreshRate, DWORD dwFlags, |
| const DDPIXELFORMAT* pixelformat) |
| { |
| short screenX; |
| short screenY; |
| |
| IDirectDrawImpl *This = (IDirectDrawImpl *)iface; |
| |
| TRACE("(%p)->SetDisplayMode(%ld,%ld)\n",This,dwWidth,dwHeight); |
| |
| if (!(This->cooperative_level & DDSCL_EXCLUSIVE)) |
| return DDERR_NOEXCLUSIVEMODE; |
| |
| if (!IsWindow(This->window)) |
| return DDERR_GENERIC; /* unchecked */ |
| |
| LosePrimarySurface(This); |
| |
| screenX = GetSystemMetrics(SM_CXSCREEN); |
| screenY = GetSystemMetrics(SM_CYSCREEN); |
| |
| This->width = dwWidth; |
| This->height = dwHeight; |
| This->pitch = lPitch; |
| This->pixelformat = *pixelformat; |
| |
| /* Position the window in the center of the screen - don't center for now */ |
| /* MoveWindow(This->window, (screenX-dwWidth)/2, (screenY-dwHeight)/2, |
| dwWidth, dwHeight, TRUE);*/ |
| MoveWindow(This->window, 0, 0, dwWidth, dwHeight, TRUE); |
| |
| SetFocus(This->window); |
| |
| return DD_OK; |
| } |
| |
| HRESULT WINAPI |
| Main_DirectDraw_RestoreDisplayMode(LPDIRECTDRAW7 iface) |
| { |
| IDirectDrawImpl *This = (IDirectDrawImpl *)iface; |
| |
| TRACE("(%p)\n",This); |
| if (!(This->cooperative_level & DDSCL_EXCLUSIVE)) |
| return DDERR_NOEXCLUSIVEMODE; |
| |
| /* Lose the primary surface if the resolution changes. */ |
| if (This->orig_width != This->width || This->orig_height != This->height |
| || This->orig_pitch != This->pitch |
| || This->orig_pixelformat.dwFlags != This->pixelformat.dwFlags |
| || !Main_DirectDraw_DDPIXELFORMAT_Match(&This->pixelformat, |
| &This->orig_pixelformat)) |
| { |
| LosePrimarySurface(This); |
| } |
| |
| /* TODO Move the window back where it belongs. */ |
| |
| return DD_OK; |
| } |
| |
| HRESULT WINAPI |
| Main_DirectDraw_WaitForVerticalBlank(LPDIRECTDRAW7 iface, DWORD dwFlags, |
| HANDLE h) |
| { |
| IDirectDrawImpl *This = (IDirectDrawImpl *)iface; |
| FIXME("(%p)->(flags=0x%08lx,handle=%p)\n",This,dwFlags,h); |
| return DD_OK; |
| } |
| |
| HRESULT WINAPI |
| Main_DirectDraw_GetDisplayMode(LPDIRECTDRAW7 iface, LPDDSURFACEDESC2 pDDSD) |
| { |
| IDirectDrawImpl *This = (IDirectDrawImpl *)iface; |
| TRACE("(%p)->GetDisplayMode(%p)\n",This,pDDSD); |
| |
| pDDSD->dwFlags = DDSD_HEIGHT|DDSD_WIDTH|DDSD_PITCH|DDSD_PIXELFORMAT|DDSD_REFRESHRATE; |
| pDDSD->dwHeight = This->height; |
| pDDSD->dwWidth = This->width; |
| pDDSD->u1.lPitch = This->pitch; |
| pDDSD->u2.dwRefreshRate = 60; |
| pDDSD->u4.ddpfPixelFormat = This->pixelformat; |
| pDDSD->ddsCaps.dwCaps = 0; |
| |
| return DD_OK; |
| } |
| |
| static INT32 allocate_memory(IDirectDrawImpl *This, DWORD mem) |
| { |
| if (mem > This->available_vidmem) return -1; |
| This->available_vidmem -= mem; |
| return This->available_vidmem; |
| } |
| |
| static void free_memory(IDirectDrawImpl *This, DWORD mem) |
| { |
| This->available_vidmem += mem; |
| } |
| |
| HRESULT WINAPI |
| Main_DirectDraw_GetAvailableVidMem(LPDIRECTDRAW7 iface, LPDDSCAPS2 ddscaps, |
| LPDWORD total, LPDWORD free) |
| { |
| IDirectDrawImpl *This = (IDirectDrawImpl *)iface; |
| TRACE("(%p)->(%p,%p,%p)\n", This,ddscaps,total,free); |
| |
| if (TRACE_ON(ddraw)) { |
| TRACE(" Asking for memory of type : "); |
| DDRAW_dump_DDSCAPS2(ddscaps); TRACE("\n"); |
| } |
| |
| /* We have 16 MB videomemory */ |
| if (total) *total= This->total_vidmem; |
| if (free) *free = This->available_vidmem; |
| |
| TRACE(" returning (total) %ld / (free) %ld\n", |
| total != NULL ? *total : 0, |
| free != NULL ? *free : 0); |
| |
| return DD_OK; |
| } |
| |
| HRESULT WINAPI Main_DirectDraw_TestCooperativeLevel(LPDIRECTDRAW7 iface) { |
| IDirectDrawImpl *This = (IDirectDrawImpl *)iface; |
| TRACE("(%p)->(): stub\n", This); |
| |
| return DD_OK; |
| } |
| |
| HRESULT WINAPI |
| Main_DirectDraw_StartModeTest(LPDIRECTDRAW7 iface, LPSIZE pModes, |
| DWORD dwNumModes, DWORD dwFlags) |
| { |
| IDirectDrawImpl *This = (IDirectDrawImpl *)iface; |
| FIXME("(%p)->() stub\n", This); |
| |
| return DD_OK; |
| } |
| |
| /*** Owned object management. */ |
| |
| void Main_DirectDraw_AddSurface(IDirectDrawImpl* This, |
| IDirectDrawSurfaceImpl* surface) |
| { |
| assert(surface->ddraw_owner == NULL || surface->ddraw_owner == This); |
| |
| surface->ddraw_owner = This; |
| |
| /* where should it go? */ |
| surface->next_ddraw = This->surfaces; |
| surface->prev_ddraw = NULL; |
| if (This->surfaces) |
| This->surfaces->prev_ddraw = surface; |
| This->surfaces = surface; |
| } |
| |
| void Main_DirectDraw_RemoveSurface(IDirectDrawImpl* This, |
| IDirectDrawSurfaceImpl* surface) |
| { |
| assert(surface->ddraw_owner == This); |
| |
| if (This->surfaces == surface) |
| This->surfaces = surface->next_ddraw; |
| |
| if (This->primary_surface == surface) |
| This->primary_surface = NULL; |
| |
| if (surface->next_ddraw) |
| surface->next_ddraw->prev_ddraw = surface->prev_ddraw; |
| if (surface->prev_ddraw) |
| surface->prev_ddraw->next_ddraw = surface->next_ddraw; |
| } |
| |
| static void Main_DirectDraw_DeleteSurfaces(IDirectDrawImpl* This) |
| { |
| while (This->surfaces != NULL) |
| Main_DirectDrawSurface_ForceDestroy(This->surfaces); |
| } |
| |
| void Main_DirectDraw_AddClipper(IDirectDrawImpl* This, |
| IDirectDrawClipperImpl* clipper) |
| { |
| assert(clipper->ddraw_owner == NULL || clipper->ddraw_owner == This); |
| |
| clipper->ddraw_owner = This; |
| |
| clipper->next_ddraw = This->clippers; |
| clipper->prev_ddraw = NULL; |
| if (This->clippers) |
| This->clippers->prev_ddraw = clipper; |
| This->clippers = clipper; |
| } |
| |
| void Main_DirectDraw_RemoveClipper(IDirectDrawImpl* This, |
| IDirectDrawClipperImpl* clipper) |
| { |
| assert(clipper->ddraw_owner == This); |
| |
| if (This->clippers == clipper) |
| This->clippers = clipper->next_ddraw; |
| |
| if (clipper->next_ddraw) |
| clipper->next_ddraw->prev_ddraw = clipper->prev_ddraw; |
| if (clipper->prev_ddraw) |
| clipper->prev_ddraw->next_ddraw = clipper->next_ddraw; |
| } |
| |
| static void Main_DirectDraw_DeleteClippers(IDirectDrawImpl* This) |
| { |
| while (This->clippers != NULL) |
| Main_DirectDrawClipper_ForceDestroy(This->clippers); |
| } |
| |
| void Main_DirectDraw_AddPalette(IDirectDrawImpl* This, |
| IDirectDrawPaletteImpl* palette) |
| { |
| assert(palette->ddraw_owner == NULL || palette->ddraw_owner == This); |
| |
| palette->ddraw_owner = This; |
| |
| /* where should it go? */ |
| palette->next_ddraw = This->palettes; |
| palette->prev_ddraw = NULL; |
| if (This->palettes) |
| This->palettes->prev_ddraw = palette; |
| This->palettes = palette; |
| } |
| |
| void Main_DirectDraw_RemovePalette(IDirectDrawImpl* This, |
| IDirectDrawPaletteImpl* palette) |
| { |
| IDirectDrawSurfaceImpl *surf; |
| |
| assert(palette->ddraw_owner == This); |
| |
| if (This->palettes == palette) |
| This->palettes = palette->next_ddraw; |
| |
| if (palette->next_ddraw) |
| palette->next_ddraw->prev_ddraw = palette->prev_ddraw; |
| if (palette->prev_ddraw) |
| palette->prev_ddraw->next_ddraw = palette->next_ddraw; |
| |
| /* Here we need also to remove tha palette from any surface which has it as the |
| * current palette (checked on Windows) |
| */ |
| for (surf = This->surfaces; surf != NULL; surf = surf->next_ddraw) { |
| if (surf->palette == palette) { |
| TRACE("Palette %p attached to surface %p.\n", palette, surf); |
| surf->palette = NULL; |
| surf->set_palette(surf, NULL); |
| } |
| } |
| } |
| |
| static void Main_DirectDraw_DeletePalettes(IDirectDrawImpl* This) |
| { |
| while (This->palettes != NULL) |
| Main_DirectDrawPalette_ForceDestroy(This->palettes); |
| } |
| |
| /*** ??? */ |
| |
| static void |
| LoseSurface(IDirectDrawSurfaceImpl *surface) |
| { |
| if (surface != NULL) surface->lose_surface(surface); |
| } |
| |
| static void |
| LosePrimarySurface(IDirectDrawImpl *This) |
| { |
| /* MSDN: "If another application changes the display mode, the primary |
| * surface is lost, and the method returns DDERR_SURFACELOST until the |
| * primary surface is recreated to match the new display mode." |
| * |
| * We mark all the primary surfaces as lost as soon as the display |
| * mode is changed (by any application). */ |
| |
| LoseSurface(This->primary_surface); |
| } |
| |
| /****************************************************************************** |
| * Uninitialised DirectDraw functions |
| * |
| * This vtable is used when a DirectDraw object is created with |
| * CoCreateInstance. The only usable method is Initialize. |
| */ |
| |
| void Uninit_DirectDraw_final_release(IDirectDrawImpl *This) |
| { |
| Main_DirectDraw_final_release(This); |
| } |
| |
| static const IDirectDraw7Vtbl Uninit_DirectDraw_VTable; |
| |
| /* Not called from the vtable. */ |
| HRESULT Uninit_DirectDraw_Construct(IDirectDrawImpl *This, BOOL ex) |
| { |
| HRESULT hr; |
| |
| hr = Main_DirectDraw_Construct(This, ex); |
| if (FAILED(hr)) return hr; |
| |
| This->final_release = Uninit_DirectDraw_final_release; |
| ICOM_INIT_INTERFACE(This, IDirectDraw7, Uninit_DirectDraw_VTable); |
| |
| return S_OK; |
| } |
| |
| HRESULT Uninit_DirectDraw_Create(const GUID* pGUID, |
| LPDIRECTDRAW7* pIface, |
| IUnknown* pUnkOuter, BOOL ex) |
| { |
| HRESULT hr; |
| IDirectDrawImpl* This; |
| |
| assert(pUnkOuter == NULL); /* XXX no: we must check this */ |
| |
| This = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, |
| sizeof(IDirectDrawImpl)); |
| if (This == NULL) return E_OUTOFMEMORY; |
| |
| hr = Uninit_DirectDraw_Construct(This, ex); |
| if (FAILED(hr)) |
| HeapFree(GetProcessHeap(), HEAP_ZERO_MEMORY, This); |
| else |
| *pIface = ICOM_INTERFACE(This, IDirectDraw7); |
| |
| return hr; |
| } |
| |
| static HRESULT WINAPI |
| Uninit_DirectDraw_Initialize(LPDIRECTDRAW7 iface, LPGUID pDeviceGuid) |
| { |
| const ddraw_driver* driver; |
| IDirectDrawImpl *This = (IDirectDrawImpl *)iface; |
| |
| TRACE("(%p)->(%p)\n", iface, pDeviceGuid); |
| |
| driver = DDRAW_FindDriver(pDeviceGuid); |
| /* XXX This return value is not documented. (Not checked.) */ |
| if (driver == NULL) return DDERR_INVALIDDIRECTDRAWGUID; |
| |
| return driver->init(This, pDeviceGuid); |
| } |
| |
| static HRESULT WINAPI |
| Uninit_DirectDraw_Compact(LPDIRECTDRAW7 iface) |
| { |
| return DDERR_NOTINITIALIZED; |
| } |
| |
| static HRESULT WINAPI |
| Uninit_DirectDraw_CreateClipper(LPDIRECTDRAW7 iface, DWORD dwFlags, |
| LPDIRECTDRAWCLIPPER *lplpDDClipper, |
| IUnknown *pUnkOuter) |
| |
| { |
| return DDERR_NOTINITIALIZED; |
| } |
| |
| static HRESULT WINAPI |
| Uninit_DirectDraw_CreatePalette(LPDIRECTDRAW7 iface, DWORD dwFlags, |
| LPPALETTEENTRY lpColorTable, |
| LPDIRECTDRAWPALETTE *lplpDDPalette, |
| IUnknown *pUnkOuter) |
| { |
| return DDERR_NOTINITIALIZED; |
| } |
| |
| static HRESULT WINAPI |
| Uninit_DirectDraw_CreateSurface(LPDIRECTDRAW7 iface, |
| LPDDSURFACEDESC2 lpDDSurfaceDesc, |
| LPDIRECTDRAWSURFACE7 *lplpDDSurface, |
| IUnknown *pUnkOuter) |
| { |
| return DDERR_NOTINITIALIZED; |
| } |
| |
| static HRESULT WINAPI |
| Uninit_DirectDraw_DuplicateSurface(LPDIRECTDRAW7 iface, |
| LPDIRECTDRAWSURFACE7 pSurf, |
| LPDIRECTDRAWSURFACE7 *pDupSurf) |
| |
| { |
| return DDERR_NOTINITIALIZED; |
| } |
| |
| static HRESULT WINAPI |
| Uninit_DirectDraw_EnumDisplayModes(LPDIRECTDRAW7 iface, DWORD dwFlags, |
| LPDDSURFACEDESC2 lpDDSD, |
| LPVOID context, |
| LPDDENUMMODESCALLBACK2 cb) |
| { |
| return DDERR_NOTINITIALIZED; |
| } |
| |
| static HRESULT WINAPI |
| Uninit_DirectDraw_EnumSurfaces(LPDIRECTDRAW7 iface, DWORD dwFlags, |
| LPDDSURFACEDESC2 pDDSD, LPVOID context, |
| LPDDENUMSURFACESCALLBACK7 cb) |
| { |
| return DDERR_NOTINITIALIZED; |
| } |
| |
| static HRESULT WINAPI |
| Uninit_DirectDraw_FlipToGDISurface(LPDIRECTDRAW7 iface) |
| { |
| return DDERR_NOTINITIALIZED; |
| } |
| |
| static HRESULT WINAPI |
| Uninit_DirectDraw_GetCaps(LPDIRECTDRAW7 iface, LPDDCAPS pDriverCaps, |
| LPDDCAPS pHELCaps) |
| { |
| return DDERR_NOTINITIALIZED; |
| } |
| |
| static HRESULT WINAPI |
| Uninit_DirectDraw_GetDisplayMode(LPDIRECTDRAW7 iface, |
| LPDDSURFACEDESC2 pDDSD) |
| { |
| return DDERR_NOTINITIALIZED; |
| } |
| |
| static HRESULT WINAPI |
| Uninit_DirectDraw_GetFourCCCodes(LPDIRECTDRAW7 iface, LPDWORD pNumCodes, |
| LPDWORD pCodes) |
| { |
| return DDERR_NOTINITIALIZED; |
| } |
| |
| static HRESULT WINAPI |
| Uninit_DirectDraw_GetGDISurface(LPDIRECTDRAW7 iface, |
| LPDIRECTDRAWSURFACE7 *pGDISurf) |
| { |
| return DDERR_NOTINITIALIZED; |
| } |
| |
| static HRESULT WINAPI |
| Uninit_DirectDraw_GetMonitorFrequency(LPDIRECTDRAW7 iface, LPDWORD pdwFreq) |
| { |
| return DDERR_NOTINITIALIZED; |
| } |
| |
| static HRESULT WINAPI |
| Uninit_DirectDraw_GetScanLine(LPDIRECTDRAW7 iface, LPDWORD pdwScanLine) |
| { |
| return DDERR_NOTINITIALIZED; |
| } |
| |
| static HRESULT WINAPI |
| Uninit_DirectDraw_GetVerticalBlankStatus(LPDIRECTDRAW7 iface, PBOOL pbIsInVB) |
| { |
| return DDERR_NOTINITIALIZED; |
| } |
| |
| static HRESULT WINAPI |
| Uninit_DirectDraw_RestoreDisplayMode(LPDIRECTDRAW7 iface) |
| { |
| return DDERR_NOTINITIALIZED; |
| } |
| |
| static HRESULT WINAPI |
| Uninit_DirectDraw_SetCooperativeLevel(LPDIRECTDRAW7 iface, HWND hWnd, |
| DWORD dwFlags) |
| { |
| return DDERR_NOTINITIALIZED; |
| } |
| |
| static HRESULT WINAPI |
| Uninit_DirectDraw_SetDisplayMode(LPDIRECTDRAW7 iface, DWORD dwWidth, |
| DWORD dwHeight, DWORD dwBPP, |
| DWORD dwRefreshRate, DWORD dwFlags) |
| { |
| return DDERR_NOTINITIALIZED; |
| } |
| |
| static HRESULT WINAPI |
| Uninit_DirectDraw_WaitForVerticalBlank(LPDIRECTDRAW7 iface, DWORD dwFlags, |
| HANDLE hEvent) |
| { |
| return DDERR_NOTINITIALIZED; |
| } |
| |
| static HRESULT WINAPI |
| Uninit_DirectDraw_GetAvailableVidMem(LPDIRECTDRAW7 iface, LPDDSCAPS2 pDDCaps, |
| LPDWORD pdwTotal, LPDWORD pdwFree) |
| { |
| return DDERR_NOTINITIALIZED; |
| } |
| |
| static HRESULT WINAPI |
| Uninit_DirectDraw_GetSurfaceFromDC(LPDIRECTDRAW7 iface, HDC hDC, |
| LPDIRECTDRAWSURFACE7 *pSurf) |
| { |
| return DDERR_NOTINITIALIZED; |
| } |
| |
| static HRESULT WINAPI |
| Uninit_DirectDraw_RestoreAllSurfaces(LPDIRECTDRAW7 iface) |
| { |
| return DDERR_NOTINITIALIZED; |
| } |
| |
| static HRESULT WINAPI |
| Uninit_DirectDraw_TestCooperativeLevel(LPDIRECTDRAW7 iface) |
| { |
| return DDERR_NOTINITIALIZED; |
| } |
| |
| static HRESULT WINAPI |
| Uninit_DirectDraw_GetDeviceIdentifier(LPDIRECTDRAW7 iface, |
| LPDDDEVICEIDENTIFIER2 pDDDI, |
| DWORD dwFlags) |
| { |
| return DDERR_NOTINITIALIZED; |
| } |
| |
| static HRESULT WINAPI |
| Uninit_DirectDraw_StartModeTest(LPDIRECTDRAW7 iface, LPSIZE pszModes, |
| DWORD cModes, DWORD dwFlags) |
| { |
| return DDERR_NOTINITIALIZED; |
| } |
| |
| static HRESULT WINAPI |
| Uninit_DirectDraw_EvaluateMode(LPDIRECTDRAW7 iface, DWORD dwFlags, |
| LPDWORD pTimeout) |
| { |
| return DDERR_NOTINITIALIZED; |
| } |
| |
| static const IDirectDraw7Vtbl Uninit_DirectDraw_VTable = |
| { |
| Main_DirectDraw_QueryInterface, |
| Main_DirectDraw_AddRef, |
| Main_DirectDraw_Release, |
| Uninit_DirectDraw_Compact, |
| Uninit_DirectDraw_CreateClipper, |
| Uninit_DirectDraw_CreatePalette, |
| Uninit_DirectDraw_CreateSurface, |
| Uninit_DirectDraw_DuplicateSurface, |
| Uninit_DirectDraw_EnumDisplayModes, |
| Uninit_DirectDraw_EnumSurfaces, |
| Uninit_DirectDraw_FlipToGDISurface, |
| Uninit_DirectDraw_GetCaps, |
| Uninit_DirectDraw_GetDisplayMode, |
| Uninit_DirectDraw_GetFourCCCodes, |
| Uninit_DirectDraw_GetGDISurface, |
| Uninit_DirectDraw_GetMonitorFrequency, |
| Uninit_DirectDraw_GetScanLine, |
| Uninit_DirectDraw_GetVerticalBlankStatus, |
| Uninit_DirectDraw_Initialize, |
| Uninit_DirectDraw_RestoreDisplayMode, |
| Uninit_DirectDraw_SetCooperativeLevel, |
| Uninit_DirectDraw_SetDisplayMode, |
| Uninit_DirectDraw_WaitForVerticalBlank, |
| Uninit_DirectDraw_GetAvailableVidMem, |
| Uninit_DirectDraw_GetSurfaceFromDC, |
| Uninit_DirectDraw_RestoreAllSurfaces, |
| Uninit_DirectDraw_TestCooperativeLevel, |
| Uninit_DirectDraw_GetDeviceIdentifier, |
| Uninit_DirectDraw_StartModeTest, |
| Uninit_DirectDraw_EvaluateMode |
| }; |