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



Reply via email to