📄 main.c
字号:
/* 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 "mesa_private.h" /* To have the D3D creation function */#include "ddraw/main.h"#include "dclipper/main.h"#include "dpalette/main.h"#include "dsurface/main.h"#include "dsurface/dib.h"#include "dsurface/fakezbuffer.h"WINE_DEFAULT_DEBUG_CHANNEL(ddraw);extern ICOM_VTABLE(IDirectDraw) DDRAW_IDirectDraw_VTable;extern ICOM_VTABLE(IDirectDraw2) DDRAW_IDirectDraw2_VTable;extern ICOM_VTABLE(IDirectDraw4) 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 = 16 * 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) { ICOM_THIS(IDirectDrawImpl,iface); TRACE("(%p)->() incrementing from %lu.\n", This, This->ref ); return ++This->ref;}ULONG WINAPI Main_DirectDraw_Release(LPDIRECTDRAW7 iface) { ULONG ref; ICOM_THIS(IDirectDrawImpl,iface); TRACE("(%p)->() decrementing from %lu.\n", This, This->ref ); ref = --This->ref; 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) { ICOM_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){ ICOM_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 WINAPIMain_DirectDraw_CreatePalette(LPDIRECTDRAW7 iface, DWORD dwFlags, LPPALETTEENTRY palent, LPDIRECTDRAWPALETTE* ppPalette, LPUNKNOWN pUnknown){ ICOM_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; }}HRESULTMain_create_offscreen(IDirectDrawImpl* This, const DDSURFACEDESC2* pDDSD, LPDIRECTDRAWSURFACE7* ppSurf, LPUNKNOWN pOuter){ assert(pOuter == NULL); return DIB_DirectDrawSurface_Create(This, pDDSD, ppSurf, pOuter);}HRESULTMain_create_texture(IDirectDrawImpl* This, const DDSURFACEDESC2* pDDSD, LPDIRECTDRAWSURFACE7* ppSurf, LPUNKNOWN pOuter, DWORD dwMipMapLevel){ assert(pOuter == NULL); return DIB_DirectDrawSurface_Create(This, pDDSD, ppSurf, pOuter);}HRESULTMain_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 HRESULTcreate_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; } /* We do not support for now compressed texture formats... */ if (ddsd.u4.ddpfPixelFormat.dwFlags & DDPF_FOURCC) { return DDERR_INVALIDPIXELFORMAT; } if (!(ddsd.dwFlags & DDSD_PITCH)) { ddsd.u1.lPitch = DDRAW_width_bpp_to_pitch(ddsd.dwWidth, GET_BPP(ddsd)*8); } /* Check also for the MIPMAP / MIPMAPCOUNT flags. As checked on Windows, this is the right behaviour. No mipmaps seem to be generated. */ if (((ddsd.dwFlags & DDSD_MIPMAPCOUNT) == 0) && ((ddsd.ddsCaps.dwCaps & DDSCAPS_MIPMAP) != 0)) { ddsd.dwFlags |= DDSD_MIPMAPCOUNT; ddsd.u2.dwMipMapCount = 1; } ddsd.dwFlags |= DDSD_PITCH | 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));
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -