wined3d: Use a swapchain for GDI surfaces.

This is a long-needed cleanup aimed at removing the ddraw_primary,
ddraw_window, ddraw_width and ddraw_height members from
IWineD3DDeviceImpl, which just do not belong there.  Destination
window and screen handling is supposed to be done by swapchains.
This commit is contained in:
Stefan Dösinger 2008-08-05 14:23:00 -05:00 committed by Alexandre Julliard
parent 66738fbb87
commit e178ddd9e1
12 changed files with 517 additions and 261 deletions

View File

@ -307,7 +307,7 @@ static HRESULT WINAPI IDirect3DDevice8Impl_CreateAdditionalSwapChain(LPDIRECT3DD
localParameters.PresentationInterval = pPresentationParameters->FullScreen_PresentationInterval;
EnterCriticalSection(&d3d8_cs);
hrc = IWineD3DDevice_CreateAdditionalSwapChain(This->WineD3DDevice, &localParameters, &object->wineD3DSwapChain, (IUnknown*)object, D3D8CB_CreateRenderTarget, D3D8CB_CreateDepthStencilSurface);
hrc = IWineD3DDevice_CreateAdditionalSwapChain(This->WineD3DDevice, &localParameters, &object->wineD3DSwapChain, (IUnknown*)object, D3D8CB_CreateRenderTarget, D3D8CB_CreateDepthStencilSurface, SURFACE_OPENGL);
LeaveCriticalSection(&d3d8_cs);
pPresentationParameters->BackBufferWidth = localParameters.BackBufferWidth;

View File

@ -229,7 +229,7 @@ HRESULT WINAPI IDirect3DDevice9Impl_CreateAdditionalSwapChain(LPDIRECT3DDEVICE
localParameters.PresentationInterval = pPresentationParameters->PresentationInterval;
EnterCriticalSection(&d3d9_cs);
hrc = IWineD3DDevice_CreateAdditionalSwapChain(This->WineD3DDevice, &localParameters, &object->wineD3DSwapChain, (IUnknown*)object, D3D9CB_CreateRenderTarget, D3D9CB_CreateDepthStencilSurface);
hrc = IWineD3DDevice_CreateAdditionalSwapChain(This->WineD3DDevice, &localParameters, &object->wineD3DSwapChain, (IUnknown*)object, D3D9CB_CreateRenderTarget, D3D9CB_CreateDepthStencilSurface, SURFACE_OPENGL);
LeaveCriticalSection(&d3d9_cs);
pPresentationParameters->BackBufferWidth = localParameters.BackBufferWidth;

View File

@ -48,6 +48,7 @@ WINE_DEFAULT_DEBUG_CHANNEL(ddraw);
static BOOL IDirectDrawImpl_DDSD_Match(const DDSURFACEDESC2* requested, const DDSURFACEDESC2* provided);
static HRESULT WINAPI IDirectDrawImpl_AttachD3DDevice(IDirectDrawImpl *This, IDirectDrawSurfaceImpl *primary);
static HRESULT WINAPI IDirectDrawImpl_CreateNewSurface(IDirectDrawImpl *This, DDSURFACEDESC2 *pDDSD, IDirectDrawSurfaceImpl **ppSurf, UINT level);
static HRESULT WINAPI IDirectDrawImpl_CreateGDISwapChain(IDirectDrawImpl *This, IDirectDrawSurfaceImpl *primary);
/* Device identifier. Don't relay it to WineD3D */
static const DDDEVICEIDENTIFIER2 deviceidentifier =
@ -1626,6 +1627,7 @@ IDirectDrawImpl_RecreateSurfacesCallback(IDirectDrawSurface7 *surf,
IUnknown *Parent;
IParentImpl *parImpl = NULL;
IWineD3DSurface *wineD3DSurface;
IWineD3DSwapChain *swapchain;
HRESULT hr;
void *tmp;
IWineD3DClipper *clipper = NULL;
@ -1650,6 +1652,8 @@ IDirectDrawImpl_RecreateSurfacesCallback(IDirectDrawSurface7 *surf,
if(surfImpl->ImplType == This->ImplType) return DDENUMRET_OK; /* Continue */
/* Get the objects */
swapchain = surfImpl->wineD3DSwapChain;
surfImpl->wineD3DSwapChain = NULL;
wineD3DSurface = surfImpl->WineD3DSurface;
IWineD3DSurface_GetParent(wineD3DSurface, &Parent);
IUnknown_Release(Parent); /* For the getParent */
@ -1681,6 +1685,17 @@ IDirectDrawImpl_RecreateSurfacesCallback(IDirectDrawSurface7 *surf,
hr = IWineD3DSurface_GetDesc(wineD3DSurface, &Desc);
if(hr != D3D_OK) return hr;
if(swapchain) {
/* If there's a swapchain, it owns the IParent interface. Create a new one for the
* new surface
*/
parImpl = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(*parImpl));
ICOM_INIT_INTERFACE(parImpl, IParent, IParent_Vtbl);
parImpl->ref = 1;
Parent = (IUnknown *) parImpl;
}
/* Create the new surface */
hr = IWineD3DDevice_CreateSurface(This->wineD3DDevice,
Width, Height, Format,
@ -1711,10 +1726,23 @@ IDirectDrawImpl_RecreateSurfacesCallback(IDirectDrawSurface7 *surf,
}
/* TODO: Copy the surface content, except for render targets */
/* If there's a swapchain, it owns the wined3d surfaces. So Destroy
* the swapchain
*/
if(swapchain) {
/* The backbuffers have the swapchain set as well, but the primary
* owns it and destroys it
*/
if(surfImpl->surface_desc.ddsCaps.dwCaps & DDSCAPS_PRIMARYSURFACE) {
IWineD3DDevice_UninitGDI(This->wineD3DDevice, D3D7CB_DestroySwapChain);
}
surfImpl->isRenderTarget = FALSE;
} else {
if(IWineD3DSurface_Release(wineD3DSurface) == 0)
TRACE("Surface released successful, next surface\n");
else
ERR("Something's still holding the old WineD3DSurface\n");
}
surfImpl->ImplType = This->ImplType;
@ -2711,6 +2739,8 @@ IDirectDrawImpl_CreateSurface(IDirectDraw7 *iface,
LeaveCriticalSection(&ddraw_cs);
return hr;
}
} else if(!(This->d3d_initialized) && desc2.ddsCaps.dwCaps & DDSCAPS_PRIMARYSURFACE) {
IDirectDrawImpl_CreateGDISwapChain(This, object);
}
/* Addref the ddraw interface to keep an reference for each surface */
@ -3117,6 +3147,7 @@ D3D7CB_CreateAdditionalSwapChain(IUnknown *device,
IParentImpl *object = NULL;
HRESULT res = D3D_OK;
IWineD3DSwapChain *swapchain;
IDirectDrawSurfaceImpl *iterator;
TRACE("(%p) call back\n", device);
object = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(IParentImpl));
@ -3135,7 +3166,8 @@ D3D7CB_CreateAdditionalSwapChain(IUnknown *device,
&swapchain,
(IUnknown*) ICOM_INTERFACE(object, IParent),
D3D7CB_CreateRenderTarget,
D3D7CB_CreateDepthStencilSurface);
D3D7CB_CreateDepthStencilSurface,
This->ImplType);
if (res != D3D_OK)
{
FIXME("(%p) call to IWineD3DDevice_CreateAdditionalSwapChain failed\n", This);
@ -3146,11 +3178,63 @@ D3D7CB_CreateAdditionalSwapChain(IUnknown *device,
{
*ppSwapChain = swapchain;
object->child = (IUnknown *) swapchain;
This->d3d_target->wineD3DSwapChain = swapchain;
iterator = This->d3d_target->complex_array[0];
while(iterator) {
iterator->wineD3DSwapChain = swapchain;
iterator = iterator->complex_array[0];
}
}
return res;
}
static HRESULT WINAPI IDirectDrawImpl_CreateGDISwapChain(IDirectDrawImpl *This,
IDirectDrawSurfaceImpl *primary) {
HRESULT hr;
WINED3DPRESENT_PARAMETERS presentation_parameters;
HWND window;
hr = IWineD3DDevice_GetHWND(This->wineD3DDevice,
&window);
if(FAILED(hr)) {
return hr;
}
memset(&presentation_parameters, 0, sizeof(presentation_parameters));
/* Use the surface description for the device parameters, not the
* Device settings. The app might render to an offscreen surface
*/
presentation_parameters.BackBufferWidth = primary->surface_desc.dwWidth;
presentation_parameters.BackBufferHeight = primary->surface_desc.dwHeight;
presentation_parameters.BackBufferFormat = PixelFormat_DD2WineD3D(&primary->surface_desc.u4.ddpfPixelFormat);
presentation_parameters.BackBufferCount = (primary->surface_desc.dwFlags & DDSD_BACKBUFFERCOUNT) ? primary->surface_desc.dwBackBufferCount : 0;
presentation_parameters.MultiSampleType = WINED3DMULTISAMPLE_NONE;
presentation_parameters.MultiSampleQuality = 0;
presentation_parameters.SwapEffect = WINED3DSWAPEFFECT_FLIP;
presentation_parameters.hDeviceWindow = window;
presentation_parameters.Windowed = !(This->cooperative_level & DDSCL_FULLSCREEN);
presentation_parameters.EnableAutoDepthStencil = FALSE; /* Not on GDI swapchains */
presentation_parameters.AutoDepthStencilFormat = 0;
presentation_parameters.Flags = 0;
presentation_parameters.FullScreen_RefreshRateInHz = WINED3DPRESENT_RATE_DEFAULT; /* Default rate: It's already set */
presentation_parameters.PresentationInterval = WINED3DPRESENT_INTERVAL_DEFAULT;
This->d3d_target = primary;
hr = IWineD3DDevice_InitGDI(This->wineD3DDevice,
&presentation_parameters,
D3D7CB_CreateAdditionalSwapChain);
This->d3d_target = NULL;
if (hr != D3D_OK)
{
FIXME("(%p) call to IWineD3DDevice_CreateAdditionalSwapChain failed\n", This);
primary->wineD3DSwapChain = NULL;
}
return hr;
}
/*****************************************************************************
* IDirectDrawImpl_AttachD3DDevice
*

View File

@ -228,6 +228,7 @@ struct IDirectDrawSurfaceImpl
IDirectDrawImpl *ddraw;
IWineD3DSurface *WineD3DSurface;
IWineD3DBaseTexture *wineD3DTexture;
IWineD3DSwapChain *wineD3DSwapChain;
/* This implementation handles attaching surfaces to other surfaces */
IDirectDrawSurfaceImpl *next_attached;

View File

@ -307,8 +307,9 @@ IDirectDrawSurfaceImpl_Release(IDirectDrawSurface7 *iface)
IWineD3DBaseTexture_Release(This->wineD3DTexture);
}
/* If it's the RenderTarget, destroy the d3ddevice */
else if( (ddraw->d3d_initialized) && (This == ddraw->d3d_target))
else if(This->wineD3DSwapChain)
{
if((ddraw->d3d_initialized) && (This == ddraw->d3d_target)) {
TRACE("(%p) Destroying the render target, uninitializing D3D\n", This);
/* Unset any index buffer, just to be sure */
@ -339,8 +340,13 @@ IDirectDrawSurfaceImpl_Release(IDirectDrawSurface7 *iface)
/* Unset the pointers */
}
This->wineD3DSwapChain = NULL; /* Uninit3D releases the swapchain */
ddraw->d3d_initialized = FALSE;
ddraw->d3d_target = NULL;
} else {
IWineD3DDevice_UninitGDI(ddraw->wineD3DDevice, D3D7CB_DestroySwapChain);
This->wineD3DSwapChain = NULL;
}
/* Reset to the default surface implementation type. This is needed if apps use
* non render target surfaces and expect blits to work after destroying the render

View File

@ -30,6 +30,7 @@ C_SRCS = \
surface.c \
surface_gdi.c \
swapchain.c \
swapchain_gdi.c \
swapchain_base.c \
texture.c \
utils.c \

View File

@ -718,10 +718,6 @@ static HRESULT WINAPI IWineD3DDeviceImpl_CreateSurface(IWineD3DDevice *iface, U
This, Width, Height, Format, debug_d3dformat(Format),
(WINED3DFMT_D16_LOCKABLE == Format), *ppSurface, object->resource.allocatedMemory, object->resource.size);
/* Store the DirectDraw primary surface. This is the first rendertarget surface created */
if( (Usage & WINED3DUSAGE_RENDERTARGET) && (!This->ddraw_primary) )
This->ddraw_primary = (IWineD3DSurface *) object;
/* Look at the implementation and set the correct Vtable */
switch(Impl) {
case SURFACE_OPENGL:
@ -1387,7 +1383,8 @@ static void WINAPI IWineD3DDeviceImpl_RestoreWindow(IWineD3DDevice *iface, HWND
static HRESULT WINAPI IWineD3DDeviceImpl_CreateAdditionalSwapChain(IWineD3DDevice* iface, WINED3DPRESENT_PARAMETERS* pPresentationParameters, IWineD3DSwapChain** ppSwapChain,
IUnknown* parent,
D3DCB_CREATERENDERTARGETFN D3DCB_CreateRenderTarget,
D3DCB_CREATEDEPTHSTENCILSURFACEFN D3DCB_CreateDepthStencil) {
D3DCB_CREATEDEPTHSTENCILSURFACEFN D3DCB_CreateDepthStencil,
WINED3DSURFTYPE surface_type) {
IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
HDC hDc;
@ -1414,6 +1411,17 @@ static HRESULT WINAPI IWineD3DDeviceImpl_CreateAdditionalSwapChain(IWineD3DDevic
}
D3DCREATEOBJECTINSTANCE(object, SwapChain)
switch(surface_type) {
case SURFACE_GDI:
object->lpVtbl = &IWineGDISwapChain_Vtbl;
break;
case SURFACE_OPENGL:
object->lpVtbl = &IWineD3DSwapChain_Vtbl;
break;
case SURFACE_UNKNOWN:
FIXME("Caller tried to create a SURFACE_UNKNOWN swapchain\n");
return WINED3DERR_INVALIDCALL;
}
/*********************
* Lookup the window Handle and the relating X window handle
@ -1485,7 +1493,9 @@ static HRESULT WINAPI IWineD3DDeviceImpl_CreateAdditionalSwapChain(IWineD3DDevic
NULL /* pShared (always null)*/);
if (object->frontBuffer != NULL) {
IWineD3DSurface_SetContainer(object->frontBuffer, (IWineD3DBase *)object);
if(surface_type == SURFACE_OPENGL) {
IWineD3DSurface_ModifyLocation(object->frontBuffer, SFLAG_INDRAWABLE, TRUE);
}
} else {
ERR("Failed to create the front buffer\n");
goto error;
@ -1530,6 +1540,7 @@ static HRESULT WINAPI IWineD3DDeviceImpl_CreateAdditionalSwapChain(IWineD3DDevic
return E_OUTOFMEMORY;
object->num_contexts = 1;
if(surface_type == SURFACE_OPENGL) {
object->context[0] = CreateContext(This, (IWineD3DSurfaceImpl *) object->frontBuffer, object->win_handle, FALSE /* pbuffer */, pPresentationParameters);
if (!object->context[0]) {
ERR("Failed to create a new context\n");
@ -1539,6 +1550,7 @@ static HRESULT WINAPI IWineD3DDeviceImpl_CreateAdditionalSwapChain(IWineD3DDevic
TRACE("Context created (HWND=%p, glContext=%p)\n",
object->win_handle, object->context[0]->glCtx);
}
}
/*********************
* Create the back, front and stencil buffers
@ -1571,23 +1583,27 @@ static HRESULT WINAPI IWineD3DDeviceImpl_CreateAdditionalSwapChain(IWineD3DDevic
ERR("Cannot create new back buffer\n");
goto error;
}
if(surface_type == SURFACE_OPENGL) {
ENTER_GL();
glDrawBuffer(GL_BACK);
checkGLcall("glDrawBuffer(GL_BACK)");
LEAVE_GL();
}
}
} else {
object->backBuffer = NULL;
/* Single buffering - draw to front buffer */
if(surface_type == SURFACE_OPENGL) {
ENTER_GL();
glDrawBuffer(GL_FRONT);
checkGLcall("glDrawBuffer(GL_FRONT)");
LEAVE_GL();
}
}
/* Under directX swapchains share the depth stencil, so only create one depth-stencil */
if (pPresentationParameters->EnableAutoDepthStencil && hr == WINED3D_OK) {
if (pPresentationParameters->EnableAutoDepthStencil && hr == WINED3D_OK && surface_type == SURFACE_OPENGL) {
TRACE("Creating depth stencil buffer\n");
if (This->auto_depth_stencil_buffer == NULL ) {
hr = D3DCB_CreateDepthStencil(This->parent,
@ -2240,6 +2256,33 @@ err_out:
return hr;
}
static HRESULT WINAPI IWineD3DDeviceImpl_InitGDI(IWineD3DDevice *iface, WINED3DPRESENT_PARAMETERS* pPresentationParameters, D3DCB_CREATEADDITIONALSWAPCHAIN D3DCB_CreateAdditionalSwapChain) {
IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *) iface;
IWineD3DSwapChainImpl *swapchain = NULL;
HRESULT hr;
/* Setup the implicit swapchain */
TRACE("Creating implicit swapchain\n");
hr=D3DCB_CreateAdditionalSwapChain(This->parent, pPresentationParameters, (IWineD3DSwapChain **)&swapchain);
if (FAILED(hr) || !swapchain) {
WARN("Failed to create implicit swapchain\n");
goto err_out;
}
This->NumberOfSwapChains = 1;
This->swapchains = HeapAlloc(GetProcessHeap(), 0, This->NumberOfSwapChains * sizeof(IWineD3DSwapChain *));
if(!This->swapchains) {
ERR("Out of memory!\n");
goto err_out;
}
This->swapchains[0] = (IWineD3DSwapChain *) swapchain;
return WINED3D_OK;
err_out:
IWineD3DSwapChain_Release((IWineD3DSwapChain *) swapchain);
return hr;
}
static HRESULT WINAPI IWineD3DDeviceImpl_Uninit3D(IWineD3DDevice *iface, D3DCB_DESTROYSURFACEFN D3DCB_DestroyDepthStencilSurface, D3DCB_DESTROYSWAPCHAINFN D3DCB_DestroySwapChain) {
IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *) iface;
int sampler;
@ -2377,6 +2420,23 @@ static HRESULT WINAPI IWineD3DDeviceImpl_Uninit3D(IWineD3DDevice *iface, D3DCB_D
return WINED3D_OK;
}
static HRESULT WINAPI IWineD3DDeviceImpl_UninitGDI(IWineD3DDevice *iface, D3DCB_DESTROYSWAPCHAINFN D3DCB_DestroySwapChain) {
IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *) iface;
unsigned int i;
for(i=0; i < This->NumberOfSwapChains; i++) {
TRACE("Releasing the implicit swapchain %d\n", i);
if (D3DCB_DestroySwapChain(This->swapchains[i]) > 0) {
FIXME("(%p) Something's still holding the implicit swapchain\n", This);
}
}
HeapFree(GetProcessHeap(), 0, This->swapchains);
This->swapchains = NULL;
This->NumberOfSwapChains = 0;
return WINED3D_OK;
}
static void WINAPI IWineD3DDeviceImpl_SetFullscreen(IWineD3DDevice *iface, BOOL fullscreen) {
IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *) iface;
TRACE("(%p) Setting DDraw fullscreen mode to %s\n", This, fullscreen ? "true" : "false");
@ -7644,7 +7704,9 @@ const IWineD3DDeviceVtbl IWineD3DDevice_Vtbl =
IWineD3DDeviceImpl_CreatePalette,
/*** Odd functions **/
IWineD3DDeviceImpl_Init3D,
IWineD3DDeviceImpl_InitGDI,
IWineD3DDeviceImpl_Uninit3D,
IWineD3DDeviceImpl_UninitGDI,
IWineD3DDeviceImpl_SetFullscreen,
IWineD3DDeviceImpl_SetMultithreaded,
IWineD3DDeviceImpl_EvictManagedResources,
@ -7790,7 +7852,9 @@ const IWineD3DDeviceVtbl IWineD3DDevice_DirtyConst_Vtbl =
IWineD3DDeviceImpl_CreatePalette,
/*** Odd functions **/
IWineD3DDeviceImpl_Init3D,
IWineD3DDeviceImpl_InitGDI,
IWineD3DDeviceImpl_Uninit3D,
IWineD3DDeviceImpl_UninitGDI,
IWineD3DDeviceImpl_SetFullscreen,
IWineD3DDeviceImpl_SetMultithreaded,
IWineD3DDeviceImpl_EvictManagedResources,

View File

@ -471,8 +471,6 @@ ULONG WINAPI IWineD3DSurfaceImpl_Release(IWineD3DSurface *iface) {
HeapFree(GetProcessHeap(), 0, This->palette9);
IWineD3DResourceImpl_CleanUp((IWineD3DResource *)iface);
if(iface == device->ddraw_primary)
device->ddraw_primary = NULL;
if(This->overlay_dest) {
list_remove(&This->overlay_entry);
@ -1460,7 +1458,10 @@ HRESULT WINAPI IWineD3DSurfaceImpl_GetDC(IWineD3DSurface *iface, HDC *pHDC) {
if(This->palette) {
pal = This->palette->palents;
} else {
IWineD3DSurfaceImpl *dds_primary = (IWineD3DSurfaceImpl *)This->resource.wineD3DDevice->ddraw_primary;
IWineD3DSurfaceImpl *dds_primary;
IWineD3DSwapChainImpl *swapchain;
swapchain = (IWineD3DSwapChainImpl *)This->resource.wineD3DDevice->swapchains[0];
dds_primary = (IWineD3DSurfaceImpl *)swapchain->frontBuffer;
if (dds_primary && dds_primary->palette)
pal = dds_primary->palette->palents;
}

View File

@ -34,99 +34,6 @@
/* Use the d3d_surface debug channel to have one channel for all surfaces */
WINE_DEFAULT_DEBUG_CHANNEL(d3d_surface);
WINE_DECLARE_DEBUG_CHANNEL(fps);
/*****************************************************************************
* x11_copy_to_screen
*
* Helper function that blts the front buffer contents to the target window
*
* Params:
* This: Surface to copy from
* rc: Rectangle to copy
*
*****************************************************************************/
static void
x11_copy_to_screen(IWineD3DSurfaceImpl *This,
LPRECT rc)
{
if(This->resource.usage & WINED3DUSAGE_RENDERTARGET)
{
POINT offset = {0,0};
HWND hDisplayWnd;
HDC hDisplayDC;
HDC hSurfaceDC = 0;
RECT drawrect;
TRACE("(%p)->(%p): Copying to screen\n", This, rc);
hSurfaceDC = This->hDC;
hDisplayWnd = This->resource.wineD3DDevice->ddraw_window;
hDisplayDC = GetDCEx(hDisplayWnd, 0, DCX_CLIPSIBLINGS|DCX_CACHE);
if(rc)
{
TRACE(" copying rect (%d,%d)->(%d,%d), offset (%d,%d)\n",
rc->left, rc->top, rc->right, rc->bottom, offset.x, offset.y);
}
/* Front buffer coordinates are screen coordinates. Map them to the destination
* window if not fullscreened
*/
if(!This->resource.wineD3DDevice->ddraw_fullscreen) {
ClientToScreen(hDisplayWnd, &offset);
}
#if 0
/* FIXME: this doesn't work... if users really want to run
* X in 8bpp, then we need to call directly into display.drv
* (or Wine's equivalent), and force a private colormap
* without default entries. */
if (This->palette) {
SelectPalette(hDisplayDC, This->palette->hpal, FALSE);
RealizePalette(hDisplayDC); /* sends messages => deadlocks */
}
#endif
drawrect.left = 0;
drawrect.right = This->currentDesc.Width;
drawrect.top = 0;
drawrect.bottom = This->currentDesc.Height;
#if 0
/* TODO: Support clippers */
if (This->clipper)
{
RECT xrc;
HWND hwnd = ((IWineD3DClipperImpl *) This->clipper)->hWnd;
if (hwnd && GetClientRect(hwnd,&xrc))
{
OffsetRect(&xrc,offset.x,offset.y);
IntersectRect(&drawrect,&drawrect,&xrc);
}
}
#endif
if (rc)
{
IntersectRect(&drawrect,&drawrect,rc);
}
else
{
/* Only use this if the caller did not pass a rectangle, since
* due to double locking this could be the wrong one ...
*/
if (This->lockedRect.left != This->lockedRect.right)
{
IntersectRect(&drawrect,&drawrect,&This->lockedRect);
}
}
BitBlt(hDisplayDC,
drawrect.left-offset.x, drawrect.top-offset.y,
drawrect.right-drawrect.left, drawrect.bottom-drawrect.top,
hSurfaceDC,
drawrect.left, drawrect.top,
SRCCOPY);
ReleaseDC(hDisplayWnd, hDisplayDC);
}
}
/*****************************************************************************
* IWineD3DSurface::Release, GDI version
@ -140,7 +47,6 @@ ULONG WINAPI IWineGDISurfaceImpl_Release(IWineD3DSurface *iface) {
ULONG ref = InterlockedDecrement(&This->resource.ref);
TRACE("(%p) : Releasing from %d\n", This, ref + 1);
if (ref == 0) {
IWineD3DDeviceImpl *device = This->resource.wineD3DDevice;
TRACE("(%p) : cleaning up\n", This);
if(This->Flags & SFLAG_DIBSECTION) {
@ -157,8 +63,6 @@ ULONG WINAPI IWineGDISurfaceImpl_Release(IWineD3DSurface *iface) {
HeapFree(GetProcessHeap(), 0, This->palette9);
IWineD3DResourceImpl_CleanUp((IWineD3DResource *)iface);
if(iface == device->ddraw_primary)
device->ddraw_primary = NULL;
if(This->overlay_dest) {
list_remove(&This->overlay_entry);
@ -258,7 +162,7 @@ static HRESULT WINAPI
IWineGDISurfaceImpl_UnlockRect(IWineD3DSurface *iface)
{
IWineD3DSurfaceImpl *This = (IWineD3DSurfaceImpl *)iface;
IWineD3DDeviceImpl *dev = This->resource.wineD3DDevice;
IWineD3DSwapChainImpl *swapchain = NULL;
TRACE("(%p)\n", This);
if (!(This->Flags & SFLAG_LOCKED))
@ -287,10 +191,11 @@ IWineGDISurfaceImpl_UnlockRect(IWineD3DSurface *iface)
}
#endif
/* Update the screen */
if(This == (IWineD3DSurfaceImpl *) dev->ddraw_primary)
{
x11_copy_to_screen(This, &This->lockedRect);
/* Tell the swapchain to update the screen */
IWineD3DSurface_GetContainer(iface, &IID_IWineD3DSwapChain, (void **) &swapchain);
if(swapchain) {
x11_copy_to_screen(swapchain, &This->lockedRect);
IWineD3DSwapChain_Release((IWineD3DSwapChain *) swapchain);
}
This->Flags &= ~SFLAG_LOCKED;
@ -317,101 +222,18 @@ IWineGDISurfaceImpl_Flip(IWineD3DSurface *iface,
IWineD3DSurface *override,
DWORD Flags)
{
IWineD3DSurfaceImpl *This = (IWineD3DSurfaceImpl *) iface;
IWineD3DSurfaceImpl *Target = (IWineD3DSurfaceImpl *) override;
TRACE("(%p)->(%p,%x)\n", This, override, Flags);
IWineD3DSwapChainImpl *swapchain = NULL;
HRESULT hr;
TRACE("(%p) Flipping to surface %p\n", This, Target);
if(Target == NULL)
{
ERR("(%p): Can't flip without a target\n", This);
return WINED3DERR_INVALIDCALL;
IWineD3DSurface_GetContainer(iface, &IID_IWineD3DSwapChain, (void **) &swapchain);
if(!swapchain) {
ERR("Flipped surface is not on a swapchain\n");
return WINEDDERR_NOTFLIPPABLE;
}
/* Flip the DC */
{
HDC tmp;
tmp = This->hDC;
This->hDC = Target->hDC;
Target->hDC = tmp;
}
/* Flip the DIBsection */
{
HBITMAP tmp;
tmp = This->dib.DIBsection;
This->dib.DIBsection = Target->dib.DIBsection;
Target->dib.DIBsection = tmp;
}
/* Flip the surface data */
{
void* tmp;
tmp = This->dib.bitmap_data;
This->dib.bitmap_data = Target->dib.bitmap_data;
Target->dib.bitmap_data = tmp;
tmp = This->resource.allocatedMemory;
This->resource.allocatedMemory = Target->resource.allocatedMemory;
Target->resource.allocatedMemory = tmp;
if(This->resource.heapMemory) {
ERR("GDI Surface %p has heap memory allocated\n", This);
}
if(Target->resource.heapMemory) {
ERR("GDI Surface %p has heap memory allocated\n", Target);
}
}
/* client_memory should not be different, but just in case */
{
BOOL tmp;
tmp = This->dib.client_memory;
This->dib.client_memory = Target->dib.client_memory;
Target->dib.client_memory = tmp;
}
/* Useful for debugging */
#if 0
{
static unsigned int gen = 0;
char buffer[4096];
++gen;
if ((gen % 10) == 0) {
snprintf(buffer, sizeof(buffer), "/tmp/surface%p_type%u_level%u_%u.ppm", This, This->glDescription.target, This->glDescription.level, gen);
IWineD3DSurfaceImpl_SaveSnapshot(iface, buffer);
}
/*
* debugging crash code
if (gen == 250) {
void** test = NULL;
*test = 0;
}
*/
}
#endif
/* Update the screen */
x11_copy_to_screen(This, NULL);
/* FPS support */
if (TRACE_ON(fps))
{
static long prev_time, frames;
DWORD time = GetTickCount();
frames++;
/* every 1.5 seconds */
if (time - prev_time > 1500) {
TRACE_(fps)("@ approx %.2ffps\n", 1000.0*frames/(time - prev_time));
prev_time = time;
frames = 0;
}
}
return WINED3D_OK;
hr = IWineD3DSwapChain_Present((IWineD3DSwapChain *) swapchain, NULL, NULL, 0, NULL, 0);
IWineD3DSwapChain_Release((IWineD3DSwapChain *) swapchain);
return hr;
}
/*****************************************************************************
@ -588,7 +410,10 @@ HRESULT WINAPI IWineGDISurfaceImpl_GetDC(IWineD3DSurface *iface, HDC *pHDC) {
if(This->palette) {
pal = This->palette->palents;
} else {
IWineD3DSurfaceImpl *dds_primary = (IWineD3DSurfaceImpl *)This->resource.wineD3DDevice->ddraw_primary;
IWineD3DSurfaceImpl *dds_primary;
IWineD3DSwapChainImpl *swapchain;
swapchain = (IWineD3DSwapChainImpl *)This->resource.wineD3DDevice->swapchains[0];
dds_primary = (IWineD3DSurfaceImpl *)swapchain->frontBuffer;
if (dds_primary && dds_primary->palette)
pal = dds_primary->palette->palents;
}
@ -637,6 +462,7 @@ HRESULT WINAPI IWineGDISurfaceImpl_RealizePalette(IWineD3DSurface *iface) {
RGBQUAD col[256];
IWineD3DPaletteImpl *pal = This->palette;
unsigned int n;
IWineD3DSwapChainImpl *swapchain;
TRACE("(%p)\n", This);
if (!pal) return WINED3D_OK;
@ -654,8 +480,12 @@ HRESULT WINAPI IWineGDISurfaceImpl_RealizePalette(IWineD3DSurface *iface) {
/* Update the image because of the palette change. Some games like e.g Red Alert
call SetEntries a lot to implement fading. */
if(This == (IWineD3DSurfaceImpl *) This->resource.wineD3DDevice->ddraw_primary)
x11_copy_to_screen(This, NULL);
/* Tell the swapchain to update the screen */
IWineD3DSurface_GetContainer(iface, &IID_IWineD3DSwapChain, (void **) &swapchain);
if(swapchain) {
x11_copy_to_screen(swapchain, &This->lockedRect);
IWineD3DSwapChain_Release((IWineD3DSwapChain *) swapchain);
}
return WINED3D_OK;
}

View File

@ -0,0 +1,264 @@
/*
*IDirect3DSwapChain9 implementation
*
*Copyright 2002-2003 Jason Edmeades
*Copyright 2002-2003 Raphael Junqueira
*Copyright 2005 Oliver Stieber
*Copyright 2007-2008 Stefan Dösinger for CodeWeavers
*
*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., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
*/
#include "config.h"
#include "wined3d_private.h"
WINE_DEFAULT_DEBUG_CHANNEL(d3d);
WINE_DECLARE_DEBUG_CHANNEL(fps);
static void WINAPI IWineGDISwapChainImpl_Destroy(IWineD3DSwapChain *iface, D3DCB_DESTROYSURFACEFN D3DCB_DestroyRenderback) {
IWineD3DSwapChainImpl *This = (IWineD3DSwapChainImpl *)iface;
WINED3DDISPLAYMODE mode;
TRACE("Destroying swapchain %p\n", iface);
IWineD3DSwapChain_SetGammaRamp(iface, 0, &This->orig_gamma);
/* release the ref to the front and back buffer parents */
if(This->frontBuffer) {
IWineD3DSurface_SetContainer(This->frontBuffer, 0);
if(D3DCB_DestroyRenderback(This->frontBuffer) > 0) {
FIXME("(%p) Something's still holding the front buffer\n",This);
}
}
if(This->backBuffer) {
int i;
for(i = 0; i < This->presentParms.BackBufferCount; i++) {
IWineD3DSurface_SetContainer(This->backBuffer[i], 0);
if(D3DCB_DestroyRenderback(This->backBuffer[i]) > 0) {
FIXME("(%p) Something's still holding the back buffer\n",This);
}
}
HeapFree(GetProcessHeap(), 0, This->backBuffer);
}
/* Restore the screen resolution if we rendered in fullscreen
* This will restore the screen resolution to what it was before creating the swapchain. In case of d3d8 and d3d9
* this will be the original desktop resolution. In case of d3d7 this will be a NOP because ddraw sets the resolution
* before starting up Direct3D, thus orig_width and orig_height will be equal to the modes in the presentation params
*/
if(This->presentParms.Windowed == FALSE) {
mode.Width = This->orig_width;
mode.Height = This->orig_height;
mode.RefreshRate = 0;
mode.Format = This->orig_fmt;
IWineD3DDevice_SetDisplayMode((IWineD3DDevice *) This->wineD3DDevice, 0, &mode);
}
HeapFree(GetProcessHeap(), 0, This);
}
/*****************************************************************************
* x11_copy_to_screen
*
* Helper function that blts the front buffer contents to the target window
*
* Params:
* This: Surface to copy from
* rc: Rectangle to copy
*
*****************************************************************************/
void x11_copy_to_screen(IWineD3DSwapChainImpl *This, LPRECT rc) {
IWineD3DSurfaceImpl *front = (IWineD3DSurfaceImpl *) This->frontBuffer;
if(front->resource.usage & WINED3DUSAGE_RENDERTARGET) {
POINT offset = {0,0};
HWND hDisplayWnd;
HDC hDisplayDC;
HDC hSurfaceDC = 0;
RECT drawrect;
TRACE("(%p)->(%p): Copying to screen\n", front, rc);
hSurfaceDC = front->hDC;
hDisplayWnd = front->resource.wineD3DDevice->ddraw_window;
hDisplayDC = GetDCEx(hDisplayWnd, 0, DCX_CLIPSIBLINGS|DCX_CACHE);
if(rc) {
TRACE(" copying rect (%d,%d)->(%d,%d), offset (%d,%d)\n",
rc->left, rc->top, rc->right, rc->bottom, offset.x, offset.y);
}
/* Front buffer coordinates are screen coordinates. Map them to the destination
* window if not fullscreened
*/
if(!front->resource.wineD3DDevice->ddraw_fullscreen) {
ClientToScreen(hDisplayWnd, &offset);
}
#if 0
/* FIXME: This doesn't work... if users really want to run
* X in 8bpp, then we need to call directly into display.drv
* (or Wine's equivalent), and force a private colormap
* without default entries. */
if (front->palette) {
SelectPalette(hDisplayDC, front->palette->hpal, FALSE);
RealizePalette(hDisplayDC); /* sends messages => deadlocks */
}
#endif
drawrect.left = 0;
drawrect.right = front->currentDesc.Width;
drawrect.top = 0;
drawrect.bottom = front->currentDesc.Height;
#if 0
/* TODO: Support clippers */
if (front->clipper)
{
RECT xrc;
HWND hwnd = ((IWineD3DClipperImpl *) front->clipper)->hWnd;
if (hwnd && GetClientRect(hwnd,&xrc))
{
OffsetRect(&xrc,offset.x,offset.y);
IntersectRect(&drawrect,&drawrect,&xrc);
}
}
#endif
if (rc) {
IntersectRect(&drawrect,&drawrect,rc);
}
else {
/* Only use this if the caller did not pass a rectangle, since
* due to double locking this could be the wrong one ...
*/
if (front->lockedRect.left != front->lockedRect.right) {
IntersectRect(&drawrect,&drawrect,&front->lockedRect);
}
}
BitBlt(hDisplayDC,
drawrect.left-offset.x, drawrect.top-offset.y,
drawrect.right-drawrect.left, drawrect.bottom-drawrect.top,
hSurfaceDC,
drawrect.left, drawrect.top,
SRCCOPY);
ReleaseDC(hDisplayWnd, hDisplayDC);
}
}
static HRESULT WINAPI IWineGDISwapChainImpl_Present(IWineD3DSwapChain *iface, CONST RECT *pSourceRect, CONST RECT *pDestRect, HWND hDestWindowOverride, CONST RGNDATA *pDirtyRegion, DWORD dwFlags) {
IWineD3DSwapChainImpl *This = (IWineD3DSwapChainImpl *) iface;
IWineD3DSurfaceImpl *front, *back;
if(!This->backBuffer) {
WARN("Swapchain doesn't have a backbuffer, returning WINED3DERR_INVALIDCALL\n");
return WINED3DERR_INVALIDCALL;
}
front = (IWineD3DSurfaceImpl *) This->frontBuffer;
back = (IWineD3DSurfaceImpl *) This->backBuffer[0];
/* Flip the DC */
{
HDC tmp;
tmp = front->hDC;
front->hDC = back->hDC;
back->hDC = tmp;
}
/* Flip the DIBsection */
{
HBITMAP tmp;
tmp = front->dib.DIBsection;
front->dib.DIBsection = back->dib.DIBsection;
back->dib.DIBsection = tmp;
}
/* Flip the surface data */
{
void* tmp;
tmp = front->dib.bitmap_data;
front->dib.bitmap_data = back->dib.bitmap_data;
back->dib.bitmap_data = tmp;
tmp = front->resource.allocatedMemory;
front->resource.allocatedMemory = back->resource.allocatedMemory;
back->resource.allocatedMemory = tmp;
if(front->resource.heapMemory) {
ERR("GDI Surface %p has heap memory allocated\n", front);
}
if(back->resource.heapMemory) {
ERR("GDI Surface %p has heap memory allocated\n", back);
}
}
/* client_memory should not be different, but just in case */
{
BOOL tmp;
tmp = front->dib.client_memory;
front->dib.client_memory = back->dib.client_memory;
back->dib.client_memory = tmp;
}
/* FPS support */
if (TRACE_ON(fps))
{
static long prev_time, frames;
DWORD time = GetTickCount();
frames++;
/* every 1.5 seconds */
if (time - prev_time > 1500) {
TRACE_(fps)("@ approx %.2ffps\n", 1000.0*frames/(time - prev_time));
prev_time = time;
frames = 0;
}
}
x11_copy_to_screen(This, NULL);
return WINED3D_OK;
}
/* FIXME: This should not be needed, the base version is OK */
HRESULT WINAPI IWineGDIBaseSwapChainImpl_GetDisplayMode(IWineD3DSwapChain *iface, WINED3DDISPLAYMODE*pMode) {
IWineD3DSwapChainImpl *This = (IWineD3DSwapChainImpl *)iface;
IWineD3DDeviceImpl *device = This->wineD3DDevice;
pMode->Width = device->ddraw_width;
pMode->Height = device->ddraw_height;
pMode->Format = device->ddraw_format;
pMode->RefreshRate = 0;
return WINED3D_OK;
}
const IWineD3DSwapChainVtbl IWineGDISwapChain_Vtbl =
{
/* IUnknown */
IWineD3DBaseSwapChainImpl_QueryInterface,
IWineD3DBaseSwapChainImpl_AddRef,
IWineD3DBaseSwapChainImpl_Release,
/* IWineD3DSwapChain */
IWineD3DBaseSwapChainImpl_GetParent,
IWineGDISwapChainImpl_Destroy,
IWineD3DBaseSwapChainImpl_GetDevice,
IWineGDISwapChainImpl_Present,
IWineD3DBaseSwapChainImpl_GetFrontBufferData,
IWineD3DBaseSwapChainImpl_GetBackBuffer,
IWineD3DBaseSwapChainImpl_GetRasterStatus,
IWineD3DBaseSwapChainImpl_GetDisplayMode,
IWineD3DBaseSwapChainImpl_GetPresentParameters,
IWineD3DBaseSwapChainImpl_SetGammaRamp,
IWineD3DBaseSwapChainImpl_GetGammaRamp
};

View File

@ -918,7 +918,6 @@ struct IWineD3DDeviceImpl
/* DirectDraw stuff */
HWND ddraw_window;
IWineD3DSurface *ddraw_primary;
DWORD ddraw_width, ddraw_height;
WINED3DFORMAT ddraw_format;
BOOL ddraw_fullscreen;
@ -1745,6 +1744,8 @@ typedef struct IWineD3DSwapChainImpl
} IWineD3DSwapChainImpl;
extern const IWineD3DSwapChainVtbl IWineD3DSwapChain_Vtbl;
const IWineD3DSwapChainVtbl IWineGDISwapChain_Vtbl;
void x11_copy_to_screen(IWineD3DSwapChainImpl *This, LPRECT rc);
HRESULT WINAPI IWineD3DBaseSwapChainImpl_QueryInterface(IWineD3DSwapChain *iface, REFIID riid, LPVOID *ppobj);
ULONG WINAPI IWineD3DBaseSwapChainImpl_AddRef(IWineD3DSwapChain *iface);

View File

@ -367,14 +367,16 @@ DECLARE_INTERFACE_(IWineD3DDevice,IWineD3DBase)
STDMETHOD(CreateVolume)(THIS_ UINT Width, UINT Height, UINT Depth, DWORD Usage, WINED3DFORMAT Format, WINED3DPOOL Pool, struct IWineD3DVolume** ppVolumeTexture, HANDLE* pSharedHandle, IUnknown *parent) PURE;
STDMETHOD(CreateCubeTexture)(THIS_ UINT EdgeLength, UINT Levels, DWORD Usage, WINED3DFORMAT Format, WINED3DPOOL Pool, struct IWineD3DCubeTexture** ppCubeTexture, HANDLE* pSharedHandle, IUnknown *parent, D3DCB_CREATESURFACEFN pFn) PURE;
STDMETHOD(CreateQuery)(THIS_ WINED3DQUERYTYPE Type, struct IWineD3DQuery **ppQuery, IUnknown *pParent);
STDMETHOD(CreateAdditionalSwapChain)(THIS_ WINED3DPRESENT_PARAMETERS *pPresentationParameters, struct IWineD3DSwapChain **pSwapChain, IUnknown *pParent, D3DCB_CREATERENDERTARGETFN pFn, D3DCB_CREATEDEPTHSTENCILSURFACEFN pFn2);
STDMETHOD(CreateAdditionalSwapChain)(THIS_ WINED3DPRESENT_PARAMETERS *pPresentationParameters, struct IWineD3DSwapChain **pSwapChain, IUnknown *pParent, D3DCB_CREATERENDERTARGETFN pFn, D3DCB_CREATEDEPTHSTENCILSURFACEFN pFn2, WINED3DSURFTYPE surface_type);
STDMETHOD(CreateVertexDeclaration)(THIS_ struct IWineD3DVertexDeclaration** ppDecl, IUnknown* pParent, const WINED3DVERTEXELEMENT *elements, UINT element_count) PURE;
STDMETHOD(CreateVertexDeclarationFromFVF)(THIS_ struct IWineD3DVertexDeclaration** ppDecl, IUnknown* pParent, DWORD Fvf) PURE;
STDMETHOD(CreateVertexShader)(THIS_ struct IWineD3DVertexDeclaration *vertex_declaration, CONST DWORD* pFunction, struct IWineD3DVertexShader** ppShader, IUnknown *pParent) PURE;
STDMETHOD(CreatePixelShader)(THIS_ CONST DWORD* pFunction, struct IWineD3DPixelShader** ppShader, IUnknown *pParent) PURE;
STDMETHOD_(HRESULT,CreatePalette)(THIS_ DWORD Flags, PALETTEENTRY *PalEnt, struct IWineD3DPalette **Palette, IUnknown *Parent);
STDMETHOD(Init3D)(THIS_ WINED3DPRESENT_PARAMETERS* pPresentationParameters, D3DCB_CREATEADDITIONALSWAPCHAIN D3DCB_CreateAdditionalSwapChain);
STDMETHOD(InitGDI)(THIS_ WINED3DPRESENT_PARAMETERS* pPresentationParameters, D3DCB_CREATEADDITIONALSWAPCHAIN D3DCB_CreateAdditionalSwapChain);
STDMETHOD(Uninit3D)(THIS, D3DCB_DESTROYSURFACEFN pFn, D3DCB_DESTROYSWAPCHAINFN pFn2);
STDMETHOD(UninitGDI)(THIS, D3DCB_DESTROYSWAPCHAINFN pFn2);
STDMETHOD_(void, SetFullscreen)(THIS_ BOOL fullscreen);
STDMETHOD_(void, SetMultithreaded)(THIS);
STDMETHOD(EvictManagedResources)(THIS) PURE;
@ -508,14 +510,16 @@ DECLARE_INTERFACE_(IWineD3DDevice,IWineD3DBase)
#define IWineD3DDevice_CreateVolume(p,a,b,c,d,e,f,g,h,i) (p)->lpVtbl->CreateVolume(p,a,b,c,d,e,f,g,h,i)
#define IWineD3DDevice_CreateCubeTexture(p,a,b,c,d,e,f,g,h,i) (p)->lpVtbl->CreateCubeTexture(p,a,b,c,d,e,f,g,h,i)
#define IWineD3DDevice_CreateQuery(p,a,b,c) (p)->lpVtbl->CreateQuery(p,a,b,c)
#define IWineD3DDevice_CreateAdditionalSwapChain(p,a,b,c,d,e) (p)->lpVtbl->CreateAdditionalSwapChain(p,a,b,c,d,e)
#define IWineD3DDevice_CreateAdditionalSwapChain(p,a,b,c,d,e,f) (p)->lpVtbl->CreateAdditionalSwapChain(p,a,b,c,d,e,f)
#define IWineD3DDevice_CreateVertexDeclaration(p,a,b,c,d) (p)->lpVtbl->CreateVertexDeclaration(p,a,b,c,d)
#define IWineD3DDevice_CreateVertexDeclarationFromFVF(p,a,b,c) (p)->lpVtbl->CreateVertexDeclarationFromFVF(p,a,b,c)
#define IWineD3DDevice_CreateVertexShader(p,a,b,c,d) (p)->lpVtbl->CreateVertexShader(p,a,b,c,d)
#define IWineD3DDevice_CreatePixelShader(p,a,b,c) (p)->lpVtbl->CreatePixelShader(p,a,b,c)
#define IWineD3DDevice_CreatePalette(p, a, b, c, d) (p)->lpVtbl->CreatePalette(p, a, b, c, d)
#define IWineD3DDevice_Init3D(p, a, b) (p)->lpVtbl->Init3D(p, a, b)
#define IWineD3DDevice_InitGDI(p, a, b) (p)->lpVtbl->InitGDI(p, a, b)
#define IWineD3DDevice_Uninit3D(p, a, b) (p)->lpVtbl->Uninit3D(p, a, b)
#define IWineD3DDevice_UninitGDI(p, a) (p)->lpVtbl->UninitGDI(p, a)
#define IWineD3DDevice_SetFullscreen(p, a) (p)->lpVtbl->SetFullscreen(p, a)
#define IWineD3DDevice_SetMultithreaded(p) (p)->lpVtbl->SetMultithreaded(p)
#define IWineD3DDevice_EvictManagedResources(p) (p)->lpVtbl->EvictManagedResources(p)