📄 device.c
字号:
/*
* IDirect3DDevice8 implementation
*
* Copyright 2002-2004 Jason Edmeades
* Copyright 2004 Christian Costa
*
* 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 <math.h>
#include <stdarg.h>
#define NONAMELESSUNION
#define NONAMELESSSTRUCT
#include "windef.h"
#include "winbase.h"
#include "winuser.h"
#include "wingdi.h"
#include "wine/debug.h"
#include "d3d8_private.h"
WINE_DEFAULT_DEBUG_CHANNEL(d3d8);
/* Shader handle functions */
static shader_handle *alloc_shader_handle(IDirect3DDevice8Impl *This) {
if (This->free_shader_handles) {
/* Use a free handle */
shader_handle *handle = This->free_shader_handles;
This->free_shader_handles = *handle;
return handle;
}
if (!(This->allocated_shader_handles < This->shader_handle_table_size)) {
/* Grow the table */
DWORD new_size = This->shader_handle_table_size + (This->shader_handle_table_size >> 1);
shader_handle *new_handles = HeapReAlloc(GetProcessHeap(), 0, This->shader_handles, new_size * sizeof(shader_handle));
if (!new_handles) return NULL;
This->shader_handles = new_handles;
This->shader_handle_table_size = new_size;
}
return &This->shader_handles[This->allocated_shader_handles++];
}
static void free_shader_handle(IDirect3DDevice8Impl *This, shader_handle *handle) {
*handle = This->free_shader_handles;
This->free_shader_handles = handle;
}
/* IDirect3D IUnknown parts follow: */
static HRESULT WINAPI IDirect3DDevice8Impl_QueryInterface(LPDIRECT3DDEVICE8 iface,REFIID riid,LPVOID *ppobj)
{
IDirect3DDevice8Impl *This = (IDirect3DDevice8Impl *)iface;
if (IsEqualGUID(riid, &IID_IUnknown)
|| IsEqualGUID(riid, &IID_IDirect3DDevice8)) {
IUnknown_AddRef(iface);
*ppobj = This;
return S_OK;
}
WARN("(%p)->(%s,%p),not found\n", This, debugstr_guid(riid), ppobj);
*ppobj = NULL;
return E_NOINTERFACE;
}
static ULONG WINAPI IDirect3DDevice8Impl_AddRef(LPDIRECT3DDEVICE8 iface) {
IDirect3DDevice8Impl *This = (IDirect3DDevice8Impl *)iface;
ULONG ref = InterlockedIncrement(&This->ref);
TRACE("(%p) : AddRef from %d\n", This, ref - 1);
return ref;
}
static ULONG WINAPI IDirect3DDevice8Impl_Release(LPDIRECT3DDEVICE8 iface) {
IDirect3DDevice8Impl *This = (IDirect3DDevice8Impl *)iface;
ULONG ref;
if (This->inDestruction) return 0;
ref = InterlockedDecrement(&This->ref);
TRACE("(%p) : ReleaseRef to %d\n", This, ref);
if (ref == 0) {
int i;
TRACE("Releasing wined3d device %p\n", This->WineD3DDevice);
EnterCriticalSection(&d3d8_cs);
This->inDestruction = TRUE;
for(i = 0; i < This->numConvertedDecls; i++) {
IWineD3DVertexDeclaration_Release(This->decls[i].decl);
}
IWineD3DDevice_Uninit3D(This->WineD3DDevice, D3D8CB_DestroyDepthStencilSurface, D3D8CB_DestroySwapChain);
IWineD3DDevice_Release(This->WineD3DDevice);
HeapFree(GetProcessHeap(), 0, This->shader_handles);
HeapFree(GetProcessHeap(), 0, This);
LeaveCriticalSection(&d3d8_cs);
}
return ref;
}
/* IDirect3DDevice Interface follow: */
static HRESULT WINAPI IDirect3DDevice8Impl_TestCooperativeLevel(LPDIRECT3DDEVICE8 iface) {
IDirect3DDevice8Impl *This = (IDirect3DDevice8Impl *)iface;
HRESULT hr;
TRACE("(%p) : Relay\n", This);
EnterCriticalSection(&d3d8_cs);
hr = IWineD3DDevice_TestCooperativeLevel(This->WineD3DDevice);
LeaveCriticalSection(&d3d8_cs);
return hr;
}
static UINT WINAPI IDirect3DDevice8Impl_GetAvailableTextureMem(LPDIRECT3DDEVICE8 iface) {
IDirect3DDevice8Impl *This = (IDirect3DDevice8Impl *)iface;
HRESULT hr;
TRACE("(%p) Relay\n", This);
EnterCriticalSection(&d3d8_cs);
hr = IWineD3DDevice_GetAvailableTextureMem(This->WineD3DDevice);
LeaveCriticalSection(&d3d8_cs);
return hr;
}
static HRESULT WINAPI IDirect3DDevice8Impl_ResourceManagerDiscardBytes(LPDIRECT3DDEVICE8 iface, DWORD Bytes) {
IDirect3DDevice8Impl *This = (IDirect3DDevice8Impl *)iface;
HRESULT hr;
TRACE("(%p) : Relay bytes(%d)\n", This, Bytes);
EnterCriticalSection(&d3d8_cs);
hr = IWineD3DDevice_EvictManagedResources(This->WineD3DDevice);
LeaveCriticalSection(&d3d8_cs);
return hr;
}
static HRESULT WINAPI IDirect3DDevice8Impl_GetDirect3D(LPDIRECT3DDEVICE8 iface, IDirect3D8** ppD3D8) {
IDirect3DDevice8Impl *This = (IDirect3DDevice8Impl *)iface;
HRESULT hr = D3D_OK;
IWineD3D* pWineD3D;
TRACE("(%p) Relay\n", This);
if (NULL == ppD3D8) {
return D3DERR_INVALIDCALL;
}
EnterCriticalSection(&d3d8_cs);
hr = IWineD3DDevice_GetDirect3D(This->WineD3DDevice, &pWineD3D);
if (hr == D3D_OK && pWineD3D != NULL)
{
IWineD3D_GetParent(pWineD3D,(IUnknown **)ppD3D8);
IWineD3D_Release(pWineD3D);
} else {
FIXME("Call to IWineD3DDevice_GetDirect3D failed\n");
*ppD3D8 = NULL;
}
TRACE("(%p) returning %p\n",This , *ppD3D8);
LeaveCriticalSection(&d3d8_cs);
return hr;
}
static HRESULT WINAPI IDirect3DDevice8Impl_GetDeviceCaps(LPDIRECT3DDEVICE8 iface, D3DCAPS8* pCaps) {
IDirect3DDevice8Impl *This = (IDirect3DDevice8Impl *)iface;
HRESULT hrc = D3D_OK;
WINED3DCAPS *pWineCaps;
TRACE("(%p) : Relay pCaps %p\n", This, pCaps);
if(NULL == pCaps){
return D3DERR_INVALIDCALL;
}
pWineCaps = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(WINED3DCAPS));
if(pWineCaps == NULL){
return D3DERR_INVALIDCALL; /* well this is what MSDN says to return */
}
D3D8CAPSTOWINECAPS(pCaps, pWineCaps)
EnterCriticalSection(&d3d8_cs);
hrc = IWineD3DDevice_GetDeviceCaps(This->WineD3DDevice, pWineCaps);
LeaveCriticalSection(&d3d8_cs);
HeapFree(GetProcessHeap(), 0, pWineCaps);
/* D3D8 doesn't support SM 2.0 or higher, so clamp to 1.x */
if(pCaps->PixelShaderVersion > D3DPS_VERSION(1,4)){
pCaps->PixelShaderVersion = D3DPS_VERSION(1,4);
}
if(pCaps->VertexShaderVersion > D3DVS_VERSION(1,1)){
pCaps->VertexShaderVersion = D3DVS_VERSION(1,1);
}
TRACE("Returning %p %p\n", This, pCaps);
return hrc;
}
static HRESULT WINAPI IDirect3DDevice8Impl_GetDisplayMode(LPDIRECT3DDEVICE8 iface, D3DDISPLAYMODE* pMode) {
IDirect3DDevice8Impl *This = (IDirect3DDevice8Impl *)iface;
HRESULT hr;
TRACE("(%p) Relay\n", This);
EnterCriticalSection(&d3d8_cs);
hr = IWineD3DDevice_GetDisplayMode(This->WineD3DDevice, 0, (WINED3DDISPLAYMODE *) pMode);
LeaveCriticalSection(&d3d8_cs);
return hr;
}
static HRESULT WINAPI IDirect3DDevice8Impl_GetCreationParameters(LPDIRECT3DDEVICE8 iface, D3DDEVICE_CREATION_PARAMETERS *pParameters) {
IDirect3DDevice8Impl *This = (IDirect3DDevice8Impl *)iface;
HRESULT hr;
TRACE("(%p) Relay\n", This);
EnterCriticalSection(&d3d8_cs);
hr = IWineD3DDevice_GetCreationParameters(This->WineD3DDevice, (WINED3DDEVICE_CREATION_PARAMETERS *) pParameters);
LeaveCriticalSection(&d3d8_cs);
return hr;
}
static HRESULT WINAPI IDirect3DDevice8Impl_SetCursorProperties(LPDIRECT3DDEVICE8 iface, UINT XHotSpot, UINT YHotSpot, IDirect3DSurface8* pCursorBitmap) {
IDirect3DDevice8Impl *This = (IDirect3DDevice8Impl *)iface;
IDirect3DSurface8Impl *pSurface = (IDirect3DSurface8Impl*)pCursorBitmap;
HRESULT hr;
TRACE("(%p) Relay\n", This);
if(!pCursorBitmap) {
WARN("No cursor bitmap, returning WINED3DERR_INVALIDCALL\n");
return WINED3DERR_INVALIDCALL;
}
EnterCriticalSection(&d3d8_cs);
hr = IWineD3DDevice_SetCursorProperties(This->WineD3DDevice,XHotSpot,YHotSpot,(IWineD3DSurface*)pSurface->wineD3DSurface);
LeaveCriticalSection(&d3d8_cs);
return hr;
}
static void WINAPI IDirect3DDevice8Impl_SetCursorPosition(LPDIRECT3DDEVICE8 iface, UINT XScreenSpace, UINT YScreenSpace, DWORD Flags) {
IDirect3DDevice8Impl *This = (IDirect3DDevice8Impl *)iface;
TRACE("(%p) Relay\n", This);
EnterCriticalSection(&d3d8_cs);
IWineD3DDevice_SetCursorPosition(This->WineD3DDevice, XScreenSpace, YScreenSpace, Flags);
LeaveCriticalSection(&d3d8_cs);
}
static BOOL WINAPI IDirect3DDevice8Impl_ShowCursor(LPDIRECT3DDEVICE8 iface, BOOL bShow) {
IDirect3DDevice8Impl *This = (IDirect3DDevice8Impl *)iface;
BOOL ret;
TRACE("(%p) Relay\n", This);
EnterCriticalSection(&d3d8_cs);
ret = IWineD3DDevice_ShowCursor(This->WineD3DDevice, bShow);
LeaveCriticalSection(&d3d8_cs);
return ret;
}
static HRESULT WINAPI IDirect3DDevice8Impl_CreateAdditionalSwapChain(LPDIRECT3DDEVICE8 iface, D3DPRESENT_PARAMETERS* pPresentationParameters, IDirect3DSwapChain8** pSwapChain) {
IDirect3DDevice8Impl *This = (IDirect3DDevice8Impl *)iface;
IDirect3DSwapChain8Impl* object;
HRESULT hrc = D3D_OK;
WINED3DPRESENT_PARAMETERS localParameters;
TRACE("(%p) Relay\n", This);
/* Fix the back buffer count */
if(pPresentationParameters->BackBufferCount == 0) {
pPresentationParameters->BackBufferCount = 1;
}
object = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(*object));
if (NULL == object) {
FIXME("Allocation of memory failed\n");
*pSwapChain = NULL;
return D3DERR_OUTOFVIDEOMEMORY;
}
object->ref = 1;
object->lpVtbl = &Direct3DSwapChain8_Vtbl;
/* Allocate an associated WineD3DDevice object */
localParameters.BackBufferWidth = pPresentationParameters->BackBufferWidth;
localParameters.BackBufferHeight = pPresentationParameters->BackBufferHeight;
localParameters.BackBufferFormat = pPresentationParameters->BackBufferFormat;
localParameters.BackBufferCount = pPresentationParameters->BackBufferCount;
localParameters.MultiSampleType = pPresentationParameters->MultiSampleType;
localParameters.MultiSampleQuality = 0; /* d3d9 only */
localParameters.SwapEffect = pPresentationParameters->SwapEffect;
localParameters.hDeviceWindow = pPresentationParameters->hDeviceWindow;
localParameters.Windowed = pPresentationParameters->Windowed;
localParameters.EnableAutoDepthStencil = pPresentationParameters->EnableAutoDepthStencil;
localParameters.AutoDepthStencilFormat = pPresentationParameters->AutoDepthStencilFormat;
localParameters.Flags = pPresentationParameters->Flags;
localParameters.FullScreen_RefreshRateInHz = pPresentationParameters->FullScreen_RefreshRateInHz;
localParameters.PresentationInterval = pPresentationParameters->FullScreen_PresentationInterval;
EnterCriticalSection(&d3d8_cs);
hrc = IWineD3DDevice_CreateAdditionalSwapChain(This->WineD3DDevice, &localParameters, &object->wineD3DSwapChain, (IUnknown*)object, D3D8CB_CreateRenderTarget, D3D8CB_CreateDepthStencilSurface);
LeaveCriticalSection(&d3d8_cs);
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -