I had patched IWineGDISwapChainImpl_Present, which can now fully support looping behavior on swapchain for more than one backbuffer. Patch 2/3 allows more backbuffers creation for GDI surfaces, and last patch is test to ddraw.
From 6dc3ea954a4241147ba8060d1a3272c3c762c013 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Pavel=20Proch=C3=A1zka?= <pavelvonlost...@seznam.cz> Date: Thu, 18 Nov 2010 10:45:57 +0100 Subject: [RFC:][1/3] wined3d: Implement flipping with more than one backbuffer for gdi surfaces.
--- dlls/wined3d/swapchain_gdi.c | 66 ++++++++++++++++++++++++++---------------- 1 files changed, 41 insertions(+), 25 deletions(-) diff --git a/dlls/wined3d/swapchain_gdi.c b/dlls/wined3d/swapchain_gdi.c index 8920cae..cfc75c4 100644 --- a/dlls/wined3d/swapchain_gdi.c +++ b/dlls/wined3d/swapchain_gdi.c @@ -174,7 +174,9 @@ static HRESULT WINAPI IWineGDISwapChainImpl_SetDestWindowOverride(IWineD3DSwapCh 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; + IWineD3DSurfaceImpl *front,*hlp1,*hlp2; + IWineD3DSurfaceImpl back; + UINT i; if (!This->back_buffers) { @@ -182,50 +184,64 @@ static HRESULT WINAPI IWineGDISwapChainImpl_Present(IWineD3DSwapChain *iface, CO return WINED3DERR_INVALIDCALL; } front = This->front_buffer; - back = This->back_buffers[0]; + back = *((IWineD3DSurfaceImpl *)This->back_buffers[0]); + + /* Presentation algorithm: + ^<<<<<<<<<<<<<^<<<<<<<<<<<^ + | | | + |front_buffer| |back_buffer0|back_buffer1|back_buffer2|....|back_bufferN| + ^ v + |<<<<<<<<<<<<<<<<<<<<<| + ^ ^ + |>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>| + + */ + + for(i=0;i<This->presentParms.BackBufferCount-1;i++) + { + hlp1 = (IWineD3DSurfaceImpl *)This->back_buffers[i]; + hlp2 = (IWineD3DSurfaceImpl *)This->back_buffers[i+1]; + hlp1->hDC = hlp2->hDC; + hlp1->dib.DIBsection = hlp2->dib.DIBsection; + hlp1->dib.bitmap_data = hlp2->dib.bitmap_data; + hlp1->resource.allocatedMemory = hlp2->resource.allocatedMemory; + hlp1->dib.client_memory = hlp2->dib.client_memory; + } + + /* move data from front buffer to end of back_buffers array */ + hlp1 = (IWineD3DSurfaceImpl *)This->back_buffers[i]; + hlp1->hDC = front->hDC; + hlp1->dib.DIBsection = front->dib.DIBsection; + hlp1->dib.bitmap_data = front->dib.bitmap_data; + hlp1->resource.allocatedMemory = front->resource.allocatedMemory; + hlp1->dib.client_memory = front->dib.client_memory; /* Flip the DC */ { - HDC tmp; - tmp = front->hDC; - front->hDC = back->hDC; - back->hDC = tmp; + front->hDC = back.hDC; } /* Flip the DIBsection */ { - HBITMAP tmp; - tmp = front->dib.DIBsection; - front->dib.DIBsection = back->dib.DIBsection; - back->dib.DIBsection = tmp; + front->dib.DIBsection = back.dib.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; + front->dib.bitmap_data = back.dib.bitmap_data; + front->resource.allocatedMemory = back.resource.allocatedMemory; 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); + 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; + front->dib.client_memory = back.dib.client_memory; } /* FPS support */ -- 1.7.1
From d711a1e7f258732adeec7a974619c8a60afd01a1 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Pavel=20Proch=C3=A1zka?= <pavelvonlost...@seznam.cz> Date: Thu, 18 Nov 2010 10:48:42 +0100 Subject: [RFC:][2/3] wined3d: Allow any count of backbuffers for gdi surfaces. --- dlls/wined3d/swapchain.c | 21 ++++++++++++--------- 1 files changed, 12 insertions(+), 9 deletions(-) diff --git a/dlls/wined3d/swapchain.c b/dlls/wined3d/swapchain.c index a29eeb4..b6b8f0b 100644 --- a/dlls/wined3d/swapchain.c +++ b/dlls/wined3d/swapchain.c @@ -544,17 +544,20 @@ HRESULT swapchain_init(IWineD3DSwapChainImpl *swapchain, WINED3DSURFTYPE surface HRESULT hr; UINT i; - if (present_parameters->BackBufferCount > WINED3DPRESENT_BACK_BUFFER_MAX) + if( surface_type != SURFACE_GDI ) { - FIXME("The application requested %u back buffers, this is not supported.\n", - present_parameters->BackBufferCount); - return WINED3DERR_INVALIDCALL; - } + if (present_parameters->BackBufferCount > WINED3DPRESENT_BACK_BUFFER_MAX) + { + FIXME("The application requested %u back buffers, this is not supported.\n", + present_parameters->BackBufferCount); + return WINED3DERR_INVALIDCALL; + } - if (present_parameters->BackBufferCount > 1) - { - FIXME("The application requested more than one back buffer, this is not properly supported.\n" - "Please configure the application to use double buffering (1 back buffer) if possible.\n"); + if (present_parameters->BackBufferCount > 1) + { + FIXME("The application requested more than one back buffer, this is not properly supported.\n" + "Please configure the application to use double buffering (1 back buffer) if possible.\n"); + } } switch (surface_type) -- 1.7.1
From 03ff9f013d79fcc74aa7473c924e1db19a29fca6 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Pavel=20Proch=C3=A1zka?= <pavelvonlost...@seznam.cz> Date: Thu, 18 Nov 2010 10:50:54 +0100 Subject: [RFC:][3/3] ddraw/tests: Add test for flipping more than one backbuffer - multibuffering. --- dlls/ddraw/tests/visual.c | 171 +++++++++++++++++++++++++++++++++++++++++++++ 1 files changed, 171 insertions(+), 0 deletions(-) diff --git a/dlls/ddraw/tests/visual.c b/dlls/ddraw/tests/visual.c index c756bac..33060e6 100644 --- a/dlls/ddraw/tests/visual.c +++ b/dlls/ddraw/tests/visual.c @@ -24,12 +24,16 @@ #include "ddraw.h" #include "d3d.h" +#define BACKBUFFERCOUNT 3 + + static HWND window; static IDirectDraw7 *DirectDraw; static IDirectDrawSurface7 *Surface; static IDirectDrawSurface7 *depth_buffer; static IDirect3D7 *Direct3D; static IDirect3DDevice7 *Direct3DDevice; +static LPDIRECTDRAW lpMultiDD = NULL; static IDirectDraw *DirectDraw1; static IDirectDrawSurface *Surface1; @@ -3041,10 +3045,177 @@ static void DX1_BackBufferFlipTest(void) if (window) DestroyWindow(window); } +/* Multibuffering test: + this will test proper cycling through multiple backbuffers and frontbuffer when flipping +*/ +static DWORD getColor (IDirectDrawSurface *p) +{ + DDSURFACEDESC ddsd; + DWORD color; + memset(&ddsd, 0, sizeof(ddsd)); + ddsd.dwSize = sizeof(ddsd); + + IDirectDrawSurface_Lock(p,NULL,&ddsd,DDLOCK_READONLY,NULL); + color = *((DWORD*)ddsd.lpSurface + (480/2*640) - 320); /* aproximatively center from surface 640 x 480 */ + IDirectDrawSurface_Unlock(p,NULL); + return color; +} + +static void ReleaseDirectDrawMulti(void) +{ + if( lpMultiDD != NULL ) + { + IDirectDrawSurface_Release(lpMultiDD); + } + if(window) + { + DestroyWindow(window); + } + + Surface1 = NULL; + window = NULL; + lpMultiDD = NULL; +} + +static HRESULT TestMultibuffering(void) +{ + IDirectDrawSurface *pFront,*pBack; + HRESULT ret; + UINT i,k; + COLORREF colors [BACKBUFFERCOUNT+1]; + DDSURFACEDESC SurfaceDesc; + DDSCAPS SurfaceCaps; + DDBLTFX ddbltfx; + + memset((void*)&ddbltfx,0,sizeof(DDBLTFX)); + ddbltfx.dwSize = sizeof(DDBLTFX); + memset((void*)&SurfaceDesc,0,sizeof(DDSURFACEDESC)); + + pFront = Surface1; + pFront = NULL; + + colors[0] = 0x00ffffff; + colors[1] = 0x00ff0000; + colors[2] = 0x0000ff00; + colors[3] = 0x000000ff; + + SurfaceDesc.dwSize = sizeof(SurfaceDesc); + SurfaceDesc.dwFlags = DDSD_CAPS | DDSD_BACKBUFFERCOUNT; + SurfaceDesc.ddsCaps.dwCaps = DDSCAPS_PRIMARYSURFACE | DDSCAPS_COMPLEX | DDSCAPS_FLIP; + SurfaceDesc.dwBackBufferCount = BACKBUFFERCOUNT; + + ret=IDirectDraw_CreateSurface(lpMultiDD, &SurfaceDesc, &pFront, NULL); + ok(ret == DD_OK,"IDirectDraw_CreateSurface returned: %x\n",ret); + + if(ret != DD_OK) + { + return ret; + } + + ddbltfx.dwFillColor = colors[1]; + + memset((void*)&SurfaceCaps, 0, sizeof(DDSCAPS)); + SurfaceCaps.dwCaps = DDSCAPS_BACKBUFFER; + + /* Get first backbuffer */ + ret=IDirectDrawSurface_GetAttachedSurface(pFront, &SurfaceCaps, &pBack); + IDirectDrawSurface_Blt(pBack, NULL, NULL, NULL,DDBLT_COLORFILL, &ddbltfx); + ddbltfx.dwFillColor = colors[0]; + IDirectDrawSurface_Blt(pFront, NULL, NULL, NULL, DDBLT_COLORFILL, &ddbltfx); + SurfaceCaps.dwCaps = DDSCAPS_FLIP; + + for(i=1;i<BACKBUFFERCOUNT;i++) + { + ok(ret == DD_OK,"IDirectDrawSurface_GetAttachedSurface returned: %x\n",ret); + if(ret != DD_OK) + return ret; + + ddbltfx.dwFillColor = colors[i+1]; + ret = IDirectDrawSurface_GetAttachedSurface(pBack, &SurfaceCaps, &pBack); + if(pBack) + IDirectDrawSurface_Blt(pBack, NULL, NULL, NULL, DDBLT_COLORFILL, &ddbltfx); + } + + for(i=0; i<15; i++) /* we will flip 15-times for example - it must work properly for every count of flips */ + { + ret = IDirectDrawSurface_Flip(pFront,0,DDFLIP_WAIT); + ok(ret == DD_OK,"IDirectDrawSurface_Flip returned: %x\n when MULTIBUFFERING",ret); + if(ret != DD_OK) + { + IDirectDraw_Release(pFront); + return ret; + } + } + + /* verify Front buffer color */ + ok(getColor(pFront) == colors[i%(BACKBUFFERCOUNT+1)],"front_buffer color should be %x but current is: %x\n",colors[i%(BACKBUFFERCOUNT+1)],getColor(pFront)); + IDirectDrawSurface_GetAttachedSurface(pFront, &SurfaceCaps, &pBack); + i += 1; + + /* verify colors in backbuffers */ + for(k=1; k<BACKBUFFERCOUNT; k++) + { + ok(getColor(pBack) == colors[i%(BACKBUFFERCOUNT+1)],"back_buffer[%d] color should be %x but current is: %x\n", k, colors[i%(BACKBUFFERCOUNT+1)], getColor(pBack)); + IDirectDrawSurface_GetAttachedSurface(pBack, &SurfaceCaps, &pBack); + i += 1; + } + + IDirectDraw_Release(pFront); + return ret; +} + +static BOOL StartMultibuffering(void) +{ + HRESULT ret; + WNDCLASS wc = {0}; + const TCHAR szAppName [] = TEXT("multibuffering_test"); + + ret = DirectDrawCreate(NULL, &lpMultiDD, NULL); + + ok(ret == DD_OK || ret == DDERR_NODIRECTDRAWSUPPORT, "DirectDrawCreate returned: %x\n", ret); + if (!lpMultiDD) { + trace("DirectDrawCreateEx() failed with an error %x\n", ret); + return FALSE; + } + + wc.lpfnWndProc = DefWindowProc; + wc.lpszClassName = szAppName; + + RegisterClass(&wc); + window = CreateWindow(szAppName, TEXT("multibuffering_wnd"), WS_VISIBLE, 0, 0, 640, 480, 0, 0, 0, 0); + ret = IDirectDraw_SetCooperativeLevel(lpMultiDD, window, DDSCL_EXCLUSIVE | DDSCL_ALLOWREBOOT | DDSCL_FULLSCREEN ); + + if(ret != DD_OK) + { + trace("SetCooperativeLevel failed with an error %x\n", ret); + return FALSE; + } + + ret = IDirectDraw_SetDisplayMode(lpMultiDD, 640, 480, 32); + + ret = TestMultibuffering(); + ok(ret == DD_OK, "TestMultibuffering returned: %x\n", ret); + + if(ret != DD_OK) + { + ReleaseDirectDrawMulti(); + return FALSE; + } + + ReleaseDirectDrawMulti(); + return TRUE; +} + START_TEST(visual) { HRESULT hr; DWORD color; + + if(!StartMultibuffering()) + { + skip("An error when initializing multibuffering device, skipping\n"); + } + if(!createObjects()) { skip("Cannot initialize DirectDraw and Direct3D, skipping\n"); -- 1.7.1