📄 swapchain.c
字号:
/* Both memory copies of the surfaces are ok, flip them around too instead of dirtifying */
IWineD3DSurfaceImpl *front = (IWineD3DSurfaceImpl *) This->frontBuffer;
IWineD3DSurfaceImpl *back = (IWineD3DSurfaceImpl *) This->backBuffer[0];
BOOL frontuptodate = front->Flags & SFLAG_INSYSMEM;
BOOL backuptodate = back->Flags & SFLAG_INSYSMEM;
if(front->resource.size == back->resource.size) {
/* Flip the DC */
{
HDC tmp;
tmp = front->hDC;
front->hDC = back->hDC;
back->hDC = tmp;
}
/* Flip the DIBsection */
{
HBITMAP tmp;
BOOL hasDib = front->Flags & SFLAG_DIBSECTION;
tmp = front->dib.DIBsection;
front->dib.DIBsection = back->dib.DIBsection;
back->dib.DIBsection = tmp;
if(back->Flags & SFLAG_DIBSECTION) front->Flags |= SFLAG_DIBSECTION;
else front->Flags &= ~SFLAG_DIBSECTION;
if(hasDib) back->Flags |= SFLAG_DIBSECTION;
else back->Flags &= ~SFLAG_DIBSECTION;
}
/* 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;
}
/* 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;
}
if(frontuptodate) back->Flags |= SFLAG_INSYSMEM;
else back->Flags &= ~SFLAG_INSYSMEM;
if(backuptodate) front->Flags |= SFLAG_INSYSMEM;
else front->Flags &= ~SFLAG_INSYSMEM;
} else {
back->Flags &= ~SFLAG_INSYSMEM;
front->Flags &= ~SFLAG_INSYSMEM;
}
}
if(This->presentParms.PresentationInterval != WINED3DPRESENT_INTERVAL_IMMEDIATE && GL_SUPPORT(SGI_VIDEO_SYNC)) {
retval = GL_EXTCALL(glXGetVideoSyncSGI(&sync));
if(retval != 0) {
ERR("glXGetVideoSyncSGI failed(retval = %d\n", retval);
}
switch(This->presentParms.PresentationInterval) {
case WINED3DPRESENT_INTERVAL_DEFAULT:
case WINED3DPRESENT_INTERVAL_ONE:
if(sync <= This->vSyncCounter) {
retval = GL_EXTCALL(glXWaitVideoSyncSGI(1, 0, &This->vSyncCounter));
} else {
This->vSyncCounter = sync;
}
break;
case WINED3DPRESENT_INTERVAL_TWO:
if(sync <= This->vSyncCounter + 1) {
retval = GL_EXTCALL(glXWaitVideoSyncSGI(2, This->vSyncCounter & 0x1, &This->vSyncCounter));
} else {
This->vSyncCounter = sync;
}
break;
case WINED3DPRESENT_INTERVAL_THREE:
if(sync <= This->vSyncCounter + 2) {
retval = GL_EXTCALL(glXWaitVideoSyncSGI(3, This->vSyncCounter % 0x3, &This->vSyncCounter));
} else {
This->vSyncCounter = sync;
}
break;
case WINED3DPRESENT_INTERVAL_FOUR:
if(sync <= This->vSyncCounter + 3) {
retval = GL_EXTCALL(glXWaitVideoSyncSGI(4, This->vSyncCounter & 0x3, &This->vSyncCounter));
} else {
This->vSyncCounter = sync;
}
break;
default:
FIXME("Unknown presentation interval %08x\n", This->presentParms.PresentationInterval);
}
}
TRACE("returning\n");
return WINED3D_OK;
}
static HRESULT WINAPI IWineD3DSwapChainImpl_GetFrontBufferData(IWineD3DSwapChain *iface, IWineD3DSurface *pDestSurface) {
IWineD3DSwapChainImpl *This = (IWineD3DSwapChainImpl *)iface;
POINT start;
TRACE("(%p) : iface(%p) pDestSurface(%p)\n", This, iface, pDestSurface);
start.x = 0;
start.y = 0;
if (This->presentParms.Windowed) {
MapWindowPoints(This->win_handle, NULL, &start, 1);
}
IWineD3DSurface_BltFast(pDestSurface, start.x, start.y, This->frontBuffer, NULL, 0);
return WINED3D_OK;
}
static HRESULT WINAPI IWineD3DSwapChainImpl_GetBackBuffer(IWineD3DSwapChain *iface, UINT iBackBuffer, WINED3DBACKBUFFER_TYPE Type, IWineD3DSurface **ppBackBuffer) {
IWineD3DSwapChainImpl *This = (IWineD3DSwapChainImpl *)iface;
if (iBackBuffer > This->presentParms.BackBufferCount - 1) {
TRACE("Back buffer count out of range\n");
/* Native d3d9 doesn't set NULL here, just as wine's d3d9. But set it here
* in wined3d to avoid problems in other libs
*/
*ppBackBuffer = NULL;
return WINED3DERR_INVALIDCALL;
}
*ppBackBuffer = This->backBuffer[iBackBuffer];
TRACE("(%p) : BackBuf %d Type %d returning %p\n", This, iBackBuffer, Type, *ppBackBuffer);
/* Note inc ref on returned surface */
if(*ppBackBuffer) IWineD3DSurface_AddRef(*ppBackBuffer);
return WINED3D_OK;
}
static HRESULT WINAPI IWineD3DSwapChainImpl_GetRasterStatus(IWineD3DSwapChain *iface, WINED3DRASTER_STATUS *pRasterStatus) {
IWineD3DSwapChainImpl *This = (IWineD3DSwapChainImpl *)iface;
static BOOL showFixmes = TRUE;
pRasterStatus->InVBlank = TRUE;
pRasterStatus->ScanLine = 0;
/* No openGL equivalent */
if(showFixmes) {
FIXME("(%p) : stub (once)\n", This);
showFixmes = FALSE;
}
return WINED3D_OK;
}
static HRESULT WINAPI IWineD3DSwapChainImpl_GetDisplayMode(IWineD3DSwapChain *iface, WINED3DDISPLAYMODE*pMode) {
IWineD3DSwapChainImpl *This = (IWineD3DSwapChainImpl *)iface;
HDC hdc;
int bpp = 0;
pMode->Width = GetSystemMetrics(SM_CXSCREEN);
pMode->Height = GetSystemMetrics(SM_CYSCREEN);
pMode->RefreshRate = 85; /* FIXME: How to identify? */
hdc = GetDC(0);
bpp = GetDeviceCaps(hdc, BITSPIXEL);
ReleaseDC(0, hdc);
switch (bpp) {
case 8: pMode->Format = WINED3DFMT_R8G8B8; break;
case 16: pMode->Format = WINED3DFMT_R5G6B5; break;
case 24: /*pMode->Format = WINED3DFMT_R8G8B8; break; */ /* 32bpp and 24bpp can be aliased for X */
case 32: pMode->Format = WINED3DFMT_A8R8G8B8; break;
default:
FIXME("Unrecognized display mode format\n");
pMode->Format = WINED3DFMT_UNKNOWN;
}
TRACE("(%p) : returning w(%d) h(%d) rr(%d) fmt(%u,%s)\n", This, pMode->Width, pMode->Height, pMode->RefreshRate,
pMode->Format, debug_d3dformat(pMode->Format));
return WINED3D_OK;
}
static HRESULT WINAPI IWineD3DSwapChainImpl_GetDevice(IWineD3DSwapChain *iface, IWineD3DDevice**ppDevice) {
IWineD3DSwapChainImpl *This = (IWineD3DSwapChainImpl *)iface;
*ppDevice = (IWineD3DDevice *) This->wineD3DDevice;
/* Note Calling this method will increase the internal reference count
on the IDirect3DDevice9 interface. */
IWineD3DDevice_AddRef(*ppDevice);
TRACE("(%p) : returning %p\n", This, *ppDevice);
return WINED3D_OK;
}
static HRESULT WINAPI IWineD3DSwapChainImpl_GetPresentParameters(IWineD3DSwapChain *iface, WINED3DPRESENT_PARAMETERS *pPresentationParameters) {
IWineD3DSwapChainImpl *This = (IWineD3DSwapChainImpl *)iface;
TRACE("(%p)\n", This);
*pPresentationParameters = This->presentParms;
return WINED3D_OK;
}
static HRESULT WINAPI IWineD3DSwapChainImpl_SetGammaRamp(IWineD3DSwapChain *iface, DWORD Flags, CONST WINED3DGAMMARAMP *pRamp){
IWineD3DSwapChainImpl *This = (IWineD3DSwapChainImpl *)iface;
HDC hDC;
TRACE("(%p) : pRamp@%p flags(%d)\n", This, pRamp, Flags);
hDC = GetDC(This->win_handle);
SetDeviceGammaRamp(hDC, (LPVOID)pRamp);
ReleaseDC(This->win_handle, hDC);
return WINED3D_OK;
}
static HRESULT WINAPI IWineD3DSwapChainImpl_GetGammaRamp(IWineD3DSwapChain *iface, WINED3DGAMMARAMP *pRamp){
IWineD3DSwapChainImpl *This = (IWineD3DSwapChainImpl *)iface;
HDC hDC;
TRACE("(%p) : pRamp@%p\n", This, pRamp);
hDC = GetDC(This->win_handle);
GetDeviceGammaRamp(hDC, pRamp);
ReleaseDC(This->win_handle, hDC);
return WINED3D_OK;
}
const IWineD3DSwapChainVtbl IWineD3DSwapChain_Vtbl =
{
/* IUnknown */
IWineD3DSwapChainImpl_QueryInterface,
IWineD3DSwapChainImpl_AddRef,
IWineD3DSwapChainImpl_Release,
/* IWineD3DSwapChain */
IWineD3DSwapChainImpl_GetParent,
IWineD3DSwapChainImpl_Destroy,
IWineD3DSwapChainImpl_GetDevice,
IWineD3DSwapChainImpl_Present,
IWineD3DSwapChainImpl_GetFrontBufferData,
IWineD3DSwapChainImpl_GetBackBuffer,
IWineD3DSwapChainImpl_GetRasterStatus,
IWineD3DSwapChainImpl_GetDisplayMode,
IWineD3DSwapChainImpl_GetPresentParameters,
IWineD3DSwapChainImpl_SetGammaRamp,
IWineD3DSwapChainImpl_GetGammaRamp
};
WineD3DContext *IWineD3DSwapChainImpl_CreateContextForThread(IWineD3DSwapChain *iface) {
WineD3DContext *ctx;
IWineD3DSwapChainImpl *This = (IWineD3DSwapChainImpl *) iface;
WineD3DContext **newArray;
TRACE("Creating a new context for swapchain %p, thread %d\n", This, GetCurrentThreadId());
ctx = CreateContext(This->wineD3DDevice, (IWineD3DSurfaceImpl *) This->frontBuffer,
This->context[0]->win_handle, FALSE /* pbuffer */, &This->presentParms);
if(!ctx) {
ERR("Failed to create a new context for the swapchain\n");
return NULL;
}
newArray = HeapAlloc(GetProcessHeap(), 0, sizeof(*newArray) * This->num_contexts + 1);
if(!newArray) {
ERR("Out of memory when trying to allocate a new context array\n");
DestroyContext(This->wineD3DDevice, ctx);
return NULL;
}
memcpy(newArray, This->context, sizeof(*newArray) * This->num_contexts);
HeapFree(GetProcessHeap(), 0, This->context);
newArray[This->num_contexts] = ctx;
This->context = newArray;
This->num_contexts++;
TRACE("Returning context %p\n", ctx);
return ctx;
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -