[PATCH 3/5] wined3d: Add a separate function for swapchain initialization.

Henri Verbeet hverbeet at codeweavers.com
Thu Dec 10 14:41:54 CST 2009


---
 dlls/wined3d/device.c          |  325 +++-------------------------------------
 dlls/wined3d/swapchain.c       |  278 ++++++++++++++++++++++++++++++++++-
 dlls/wined3d/wined3d_private.h |    5 +-
 3 files changed, 303 insertions(+), 305 deletions(-)

diff --git a/dlls/wined3d/device.c b/dlls/wined3d/device.c
index 029884c..c49f70f 100644
--- a/dlls/wined3d/device.c
+++ b/dlls/wined3d/device.c
@@ -951,9 +951,8 @@ static LONG fullscreen_exStyle(LONG orig_exStyle) {
     return exStyle;
 }
 
-static void IWineD3DDeviceImpl_SetupFullscreenWindow(IWineD3DDevice *iface, HWND window, UINT w, UINT h) {
-    IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
-
+void IWineD3DDeviceImpl_SetupFullscreenWindow(IWineD3DDeviceImpl *This, HWND window, UINT w, UINT h)
+{
     LONG style, exStyle;
     /* Don't do anything if an original style is stored.
      * That shouldn't happen
@@ -1030,314 +1029,36 @@ static void IWineD3DDeviceImpl_RestoreWindow(IWineD3DDevice *iface, HWND window)
                  SWP_FRAMECHANGED | SWP_NOMOVE | SWP_NOSIZE | SWP_NOZORDER);
 }
 
-/* example at http://www.fairyengine.com/articles/dxmultiviews.htm */
 static HRESULT WINAPI IWineD3DDeviceImpl_CreateSwapChain(IWineD3DDevice *iface,
-        WINED3DPRESENT_PARAMETERS *pPresentationParameters, IWineD3DSwapChain **ppSwapChain,
+        WINED3DPRESENT_PARAMETERS *present_parameters, IWineD3DSwapChain **swapchain,
         IUnknown *parent, WINED3DSURFTYPE surface_type)
 {
-    IWineD3DDeviceImpl      *This = (IWineD3DDeviceImpl *)iface;
-
-    HDC                     hDc;
-    IWineD3DSwapChainImpl  *object; /** NOTE: impl ref allowed since this is a create function **/
-    HRESULT                 hr;
-    BOOL                    displaymode_set = FALSE;
-    WINED3DDISPLAYMODE      Mode;
-    const struct GlPixelFormatDesc *format_desc;
-    RECT                    client_rect;
-
-    TRACE("(%p) : Created Additional Swap Chain\n", This);
-
-   /** FIXME: Test under windows to find out what the life cycle of a swap chain is,
-   * does a device hold a reference to a swap chain giving them a lifetime of the device
-   * or does the swap chain notify the device of its destruction.
-    *******************************/
+    IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
+    IWineD3DSwapChainImpl *object;
+    HRESULT hr;
 
-    /* Check the params */
-    if(pPresentationParameters->BackBufferCount > WINED3DPRESENT_BACK_BUFFER_MAX) {
-        ERR("App requested %d back buffers, this is not supported for now\n", pPresentationParameters->BackBufferCount);
-        return WINED3DERR_INVALIDCALL;
-    } else if (pPresentationParameters->BackBufferCount > 1) {
-        FIXME("The app requests more than one back buffer, this can't be supported properly. Please configure the application to use double buffering(=1 back buffer) if possible\n");
-    }
+    TRACE("iface %p, present_parameters %p, swapchain %p, parent %p, surface_type %#x.\n",
+            iface, present_parameters, swapchain, parent, surface_type);
 
     object = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(*object));
-    if(!object)
-    {
-        ERR("Out of memory\n");
-        *ppSwapChain = NULL;
-        return WINED3DERR_OUTOFVIDEOMEMORY;
-    }
-
-    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");
-            HeapFree(GetProcessHeap(), 0, object);
-            return WINED3DERR_INVALIDCALL;
-    }
-    object->device = This;
-    object->parent = parent;
-    object->ref = 1;
-
-    *ppSwapChain = (IWineD3DSwapChain *)object;
-
-    /*********************
-    * Lookup the window Handle and the relating X window handle
-    ********************/
-
-    /* Setup hwnd we are using, plus which display this equates to */
-    object->win_handle = pPresentationParameters->hDeviceWindow;
-    if (!object->win_handle) {
-        object->win_handle = This->createParms.hFocusWindow;
-    }
-    if(!pPresentationParameters->Windowed && object->win_handle) {
-        IWineD3DDeviceImpl_SetupFullscreenWindow(iface, object->win_handle,
-                                                 pPresentationParameters->BackBufferWidth,
-                                                 pPresentationParameters->BackBufferHeight);
-    }
-
-    hDc                = GetDC(object->win_handle);
-    TRACE("Using hDc %p\n", hDc);
-
-    if (NULL == hDc) {
-        WARN("Failed to get a HDc for Window %p\n", object->win_handle);
-        return WINED3DERR_NOTAVAILABLE;
-    }
-
-    /* Get info on the current display setup */
-    IWineD3D_GetAdapterDisplayMode(This->wined3d, This->adapter->ordinal, &Mode);
-    object->orig_width = Mode.Width;
-    object->orig_height = Mode.Height;
-    object->orig_fmt = Mode.Format;
-    format_desc = getFormatDescEntry(Mode.Format, &This->adapter->gl_info);
-
-    GetClientRect(object->win_handle, &client_rect);
-    if (pPresentationParameters->Windowed &&
-        ((pPresentationParameters->BackBufferWidth == 0) ||
-         (pPresentationParameters->BackBufferHeight == 0) ||
-         (pPresentationParameters->BackBufferFormat == WINED3DFMT_UNKNOWN))) {
-
-        if (pPresentationParameters->BackBufferWidth == 0) {
-           pPresentationParameters->BackBufferWidth = client_rect.right;
-           TRACE("Updating width to %d\n", pPresentationParameters->BackBufferWidth);
-        }
-        if (pPresentationParameters->BackBufferHeight == 0) {
-           pPresentationParameters->BackBufferHeight = client_rect.bottom;
-           TRACE("Updating height to %d\n", pPresentationParameters->BackBufferHeight);
-        }
-        if (pPresentationParameters->BackBufferFormat == WINED3DFMT_UNKNOWN) {
-           pPresentationParameters->BackBufferFormat = object->orig_fmt;
-           TRACE("Updating format to %s\n", debug_d3dformat(object->orig_fmt));
-        }
-    }
-
-    if(wined3d_settings.offscreen_rendering_mode == ORM_FBO)
+    if (!object)
     {
-        if(pPresentationParameters->BackBufferWidth != client_rect.right ||
-           pPresentationParameters->BackBufferHeight != client_rect.bottom)
-        {
-            TRACE("Rendering to FBO. Backbuffer %ux%u, window %ux%u\n",
-                pPresentationParameters->BackBufferWidth,
-                pPresentationParameters->BackBufferHeight,
-                client_rect.right, client_rect.bottom);
-            object->render_to_fbo = TRUE;
-        }
-        else
-        {
-            TRACE("Rendering directly to GL_BACK\n");
-        }
-    }
-
-    /* Put the correct figures in the presentation parameters */
-    TRACE("Copying across presentation parameters\n");
-    object->presentParms = *pPresentationParameters;
-
-    TRACE("calling rendertarget CB\n");
-    hr = IWineD3DDeviceParent_CreateRenderTarget(This->device_parent, parent,
-            object->presentParms.BackBufferWidth, object->presentParms.BackBufferHeight,
-            object->presentParms.BackBufferFormat, object->presentParms.MultiSampleType,
-            object->presentParms.MultiSampleQuality, TRUE /* Lockable */, &object->frontBuffer);
-    if (SUCCEEDED(hr)) {
-        IWineD3DSurface_SetContainer(object->frontBuffer, (IWineD3DBase *)object);
-        ((IWineD3DSurfaceImpl *)object->frontBuffer)->Flags |= SFLAG_SWAPCHAIN;
-        if(surface_type == SURFACE_OPENGL) {
-            IWineD3DSurface_ModifyLocation(object->frontBuffer, SFLAG_INDRAWABLE, TRUE);
-        }
-    } else {
-        ERR("Failed to create the front buffer\n");
-        goto error;
-    }
-
-   /*********************
-   * Windowed / Fullscreen
-   *******************/
-
-   /**
-   * TODO: MSDN says that we are only allowed one fullscreen swapchain per device,
-   * so we should really check to see if there is a fullscreen swapchain already
-   * I think Windows and X have different ideas about fullscreen, does a single head count as full screen?
-    **************************************/
-
-   if (!pPresentationParameters->Windowed) {
-        WINED3DDISPLAYMODE mode;
-
-
-        /* Change the display settings */
-        mode.Width = pPresentationParameters->BackBufferWidth;
-        mode.Height = pPresentationParameters->BackBufferHeight;
-        mode.Format = pPresentationParameters->BackBufferFormat;
-        mode.RefreshRate = pPresentationParameters->FullScreen_RefreshRateInHz;
-
-        IWineD3DDevice_SetDisplayMode(iface, 0, &mode);
-        displaymode_set = TRUE;
-    }
-
-        /**
-     * Create an opengl context for the display visual
-     *  NOTE: the visual is chosen as the window is created and the glcontext cannot
-     *     use different properties after that point in time. FIXME: How to handle when requested format
-     *     doesn't match actual visual? Cannot choose one here - code removed as it ONLY works if the one
-     *     it chooses is identical to the one already being used!
-         **********************************/
-    /** FIXME: Handle stencil appropriately via EnableAutoDepthStencil / AutoDepthStencilFormat **/
-
-    object->context = HeapAlloc(GetProcessHeap(), 0, sizeof(object->context));
-    if(!object->context) {
-        ERR("Failed to create the context array\n");
-        hr = E_OUTOFMEMORY;
-        goto error;
+        ERR("Failed to allocate swapchain memory.\n");
+        return E_OUTOFMEMORY;
     }
-    object->num_contexts = 1;
 
-    if (surface_type == SURFACE_OPENGL)
-    {
-        object->context[0] = context_create(This, (IWineD3DSurfaceImpl *)object->frontBuffer,
-                object->win_handle, FALSE /* pbuffer */, pPresentationParameters);
-        if (!object->context[0]) {
-            ERR("Failed to create a new context\n");
-            hr = WINED3DERR_NOTAVAILABLE;
-            goto error;
-        } else {
-            TRACE("Context created (HWND=%p, glContext=%p)\n",
-                object->win_handle, object->context[0]->glCtx);
-        }
-        object->context[0]->render_offscreen = object->render_to_fbo;
-    }
-    else
+    hr = swapchain_init(object, surface_type, This, present_parameters, parent);
+    if (FAILED(hr))
     {
-        object->context[0] = NULL;
-    }
-
-   /*********************
-   * Create the back, front and stencil buffers
-   *******************/
-    if(object->presentParms.BackBufferCount > 0) {
-        UINT i;
-
-        object->backBuffer = HeapAlloc(GetProcessHeap(), 0, sizeof(IWineD3DSurface *) * object->presentParms.BackBufferCount);
-        if(!object->backBuffer) {
-            ERR("Out of memory\n");
-            hr = E_OUTOFMEMORY;
-            goto error;
-        }
-
-        for(i = 0; i < object->presentParms.BackBufferCount; i++) {
-            TRACE("calling rendertarget CB\n");
-            hr = IWineD3DDeviceParent_CreateRenderTarget(This->device_parent, parent,
-                    object->presentParms.BackBufferWidth, object->presentParms.BackBufferHeight,
-                    object->presentParms.BackBufferFormat, object->presentParms.MultiSampleType,
-                    object->presentParms.MultiSampleQuality, TRUE /* Lockable */, &object->backBuffer[i]);
-            if(SUCCEEDED(hr)) {
-                IWineD3DSurface_SetContainer(object->backBuffer[i], (IWineD3DBase *)object);
-                ((IWineD3DSurfaceImpl *)object->backBuffer[i])->Flags |= SFLAG_SWAPCHAIN;
-            } else {
-                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();
-        }
-    }
-
-    if (object->context[0]) context_release(object->context[0]);
-
-    /* Under directX swapchains share the depth stencil, so only create one depth-stencil */
-    if (pPresentationParameters->EnableAutoDepthStencil && surface_type == SURFACE_OPENGL) {
-        TRACE("Creating depth stencil buffer\n");
-        if (This->auto_depth_stencil_buffer == NULL ) {
-            hr = IWineD3DDeviceParent_CreateDepthStencilSurface(This->device_parent, parent,
-                    object->presentParms.BackBufferWidth, object->presentParms.BackBufferHeight,
-                    object->presentParms.AutoDepthStencilFormat, object->presentParms.MultiSampleType,
-                    object->presentParms.MultiSampleQuality, FALSE /* FIXME: Discard */,
-                    &This->auto_depth_stencil_buffer);
-            if (SUCCEEDED(hr)) {
-                IWineD3DSurface_SetContainer(This->auto_depth_stencil_buffer, 0);
-            } else {
-                ERR("Failed to create the auto depth stencil\n");
-                goto error;
-            }
-        }
+        WARN("Failed to initialize swapchain, hr %#x.\n", hr);
+        HeapFree(GetProcessHeap(), 0, object);
+        return hr;
     }
 
-    IWineD3DSwapChain_GetGammaRamp((IWineD3DSwapChain *) object, &object->orig_gamma);
+    TRACE("Created swapchain %p.\n", object);
+    *swapchain = (IWineD3DSwapChain *)object;
 
-    TRACE("Created swapchain %p\n", object);
-    TRACE("FrontBuf @ %p, BackBuf @ %p, DepthStencil %d\n",object->frontBuffer, object->backBuffer ? object->backBuffer[0] : NULL, pPresentationParameters->EnableAutoDepthStencil);
     return WINED3D_OK;
-
-error:
-    if (displaymode_set) {
-        DEVMODEW devmode;
-        RECT     clip_rc;
-
-        SetRect(&clip_rc, 0, 0, object->orig_width, object->orig_height);
-        ClipCursor(NULL);
-
-        /* Change the display settings */
-        memset(&devmode, 0, sizeof(devmode));
-        devmode.dmSize       = sizeof(devmode);
-        devmode.dmFields     = DM_BITSPERPEL | DM_PELSWIDTH | DM_PELSHEIGHT;
-        devmode.dmBitsPerPel = format_desc->byte_count * 8;
-        devmode.dmPelsWidth  = object->orig_width;
-        devmode.dmPelsHeight = object->orig_height;
-        ChangeDisplaySettingsExW(This->adapter->DeviceName, &devmode, NULL, CDS_FULLSCREEN, NULL);
-    }
-
-    if (object->backBuffer) {
-        UINT i;
-        for(i = 0; i < object->presentParms.BackBufferCount; i++) {
-            if (object->backBuffer[i]) IWineD3DSurface_Release(object->backBuffer[i]);
-        }
-        HeapFree(GetProcessHeap(), 0, object->backBuffer);
-        object->backBuffer = NULL;
-    }
-    if(object->context && object->context[0])
-    {
-        context_release(object->context[0]);
-        context_destroy(This, object->context[0]);
-    }
-    if (object->frontBuffer) IWineD3DSurface_Release(object->frontBuffer);
-    HeapFree(GetProcessHeap(), 0, object);
-    return hr;
 }
 
 /** NOTE: These are ahead of the other getters and setters to save using a forward declaration **/
@@ -6880,9 +6601,8 @@ static HRESULT WINAPI IWineD3DDeviceImpl_Reset(IWineD3DDevice* iface, WINED3DPRE
         if(swapchain->win_handle && !pPresentationParameters->Windowed) {
             if(swapchain->presentParms.Windowed) {
                 /* switch from windowed to fs */
-                IWineD3DDeviceImpl_SetupFullscreenWindow(iface, swapchain->win_handle,
-                                                         pPresentationParameters->BackBufferWidth,
-                                                         pPresentationParameters->BackBufferHeight);
+                IWineD3DDeviceImpl_SetupFullscreenWindow(This, swapchain->win_handle,
+                        pPresentationParameters->BackBufferWidth, pPresentationParameters->BackBufferHeight);
             } else {
                 /* Fullscreen -> fullscreen mode change */
                 MoveWindow(swapchain->win_handle, 0, 0,
@@ -6902,9 +6622,8 @@ static HRESULT WINAPI IWineD3DDeviceImpl_Reset(IWineD3DDevice* iface, WINED3DPRE
          */
         This->style = 0;
         This->exStyle = 0;
-        IWineD3DDeviceImpl_SetupFullscreenWindow(iface, swapchain->win_handle,
-                                                 pPresentationParameters->BackBufferWidth,
-                                                 pPresentationParameters->BackBufferHeight);
+        IWineD3DDeviceImpl_SetupFullscreenWindow(This, swapchain->win_handle,
+                pPresentationParameters->BackBufferWidth, pPresentationParameters->BackBufferHeight);
         This->style = style;
         This->exStyle = exStyle;
     }
diff --git a/dlls/wined3d/swapchain.c b/dlls/wined3d/swapchain.c
index 51eaab4..51ee607 100644
--- a/dlls/wined3d/swapchain.c
+++ b/dlls/wined3d/swapchain.c
@@ -536,7 +536,7 @@ static HRESULT WINAPI IWineD3DSwapChainImpl_SetDestWindowOverride(IWineD3DSwapCh
     return WINED3D_OK;
 }
 
-const IWineD3DSwapChainVtbl IWineD3DSwapChain_Vtbl =
+static const IWineD3DSwapChainVtbl IWineD3DSwapChain_Vtbl =
 {
     /* IUnknown */
     IWineD3DBaseSwapChainImpl_QueryInterface,
@@ -557,6 +557,282 @@ const IWineD3DSwapChainVtbl IWineD3DSwapChain_Vtbl =
     IWineD3DBaseSwapChainImpl_GetGammaRamp
 };
 
+HRESULT swapchain_init(IWineD3DSwapChainImpl *swapchain, WINED3DSURFTYPE surface_type,
+        IWineD3DDeviceImpl *device, WINED3DPRESENT_PARAMETERS *present_parameters, IUnknown *parent)
+{
+    const struct wined3d_adapter *adapter = device->adapter;
+    const struct GlPixelFormatDesc *format_desc;
+    BOOL displaymode_set = FALSE;
+    WINED3DDISPLAYMODE mode;
+    RECT client_rect;
+    HWND window;
+    HRESULT hr;
+    UINT i;
+
+    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");
+    }
+
+    switch (surface_type)
+    {
+        case SURFACE_GDI:
+            swapchain->lpVtbl = &IWineGDISwapChain_Vtbl;
+            break;
+
+        case SURFACE_OPENGL:
+            swapchain->lpVtbl = &IWineD3DSwapChain_Vtbl;
+            break;
+
+        case SURFACE_UNKNOWN:
+            FIXME("Caller tried to create a SURFACE_UNKNOWN swapchain.\n");
+            return WINED3DERR_INVALIDCALL;
+    }
+
+    window = present_parameters->hDeviceWindow ? present_parameters->hDeviceWindow : device->createParms.hFocusWindow;
+
+    swapchain->device = device;
+    swapchain->parent = parent;
+    swapchain->ref = 1;
+    swapchain->win_handle = window;
+
+    if (!present_parameters->Windowed && window)
+    {
+        IWineD3DDeviceImpl_SetupFullscreenWindow(device, window, present_parameters->BackBufferWidth,
+                present_parameters->BackBufferHeight);
+    }
+
+    IWineD3D_GetAdapterDisplayMode(device->wined3d, adapter->ordinal, &mode);
+    swapchain->orig_width = mode.Width;
+    swapchain->orig_height = mode.Height;
+    swapchain->orig_fmt = mode.Format;
+    format_desc = getFormatDescEntry(mode.Format, &adapter->gl_info);
+
+    GetClientRect(window, &client_rect);
+    if (present_parameters->Windowed
+            && (!present_parameters->BackBufferWidth || !present_parameters->BackBufferHeight
+            || present_parameters->BackBufferFormat == WINED3DFMT_UNKNOWN))
+    {
+
+        if (!present_parameters->BackBufferWidth)
+        {
+            present_parameters->BackBufferWidth = client_rect.right;
+            TRACE("Updating width to %u.\n", present_parameters->BackBufferWidth);
+        }
+
+        if (!present_parameters->BackBufferHeight)
+        {
+            present_parameters->BackBufferHeight = client_rect.bottom;
+            TRACE("Updating height to %u.\n", present_parameters->BackBufferHeight);
+        }
+
+        if (present_parameters->BackBufferFormat == WINED3DFMT_UNKNOWN)
+        {
+            present_parameters->BackBufferFormat = swapchain->orig_fmt;
+            TRACE("Updating format to %s.\n", debug_d3dformat(swapchain->orig_fmt));
+        }
+    }
+    swapchain->presentParms = *present_parameters;
+
+    if (wined3d_settings.offscreen_rendering_mode == ORM_FBO
+            && (present_parameters->BackBufferWidth != client_rect.right
+            || present_parameters->BackBufferHeight != client_rect.bottom))
+    {
+        TRACE("Rendering to FBO. Backbuffer %ux%u, window %ux%u.\n",
+                present_parameters->BackBufferWidth,
+                present_parameters->BackBufferHeight,
+                client_rect.right, client_rect.bottom);
+        swapchain->render_to_fbo = TRUE;
+    }
+
+    TRACE("Creating front buffer.\n");
+    hr = IWineD3DDeviceParent_CreateRenderTarget(device->device_parent, parent,
+            swapchain->presentParms.BackBufferWidth, swapchain->presentParms.BackBufferHeight,
+            swapchain->presentParms.BackBufferFormat, swapchain->presentParms.MultiSampleType,
+            swapchain->presentParms.MultiSampleQuality, TRUE /* Lockable */, &swapchain->frontBuffer);
+    if (FAILED(hr))
+    {
+        WARN("Failed to create front buffer, hr %#x.\n", hr);
+        goto err;
+    }
+
+    IWineD3DSurface_SetContainer(swapchain->frontBuffer, (IWineD3DBase *)swapchain);
+    ((IWineD3DSurfaceImpl *)swapchain->frontBuffer)->Flags |= SFLAG_SWAPCHAIN;
+    if (surface_type == SURFACE_OPENGL)
+    {
+        IWineD3DSurface_ModifyLocation(swapchain->frontBuffer, SFLAG_INDRAWABLE, TRUE);
+    }
+
+    /* MSDN says we're only allowed a single fullscreen swapchain per device,
+     * so we should really check to see if there is a fullscreen swapchain
+     * already. Does a single head count as full screen? */
+
+    if (!present_parameters->Windowed)
+    {
+        WINED3DDISPLAYMODE mode;
+
+        /* Change the display settings */
+        mode.Width = present_parameters->BackBufferWidth;
+        mode.Height = present_parameters->BackBufferHeight;
+        mode.Format = present_parameters->BackBufferFormat;
+        mode.RefreshRate = present_parameters->FullScreen_RefreshRateInHz;
+
+        hr = IWineD3DDevice_SetDisplayMode((IWineD3DDevice *)device, 0, &mode);
+        if (FAILED(hr))
+        {
+            WARN("Failed to set display mode, hr %#x.\n", hr);
+            goto err;
+        }
+        displaymode_set = TRUE;
+    }
+
+    swapchain->context = HeapAlloc(GetProcessHeap(), 0, sizeof(swapchain->context));
+    if (!swapchain->context)
+    {
+        ERR("Failed to create the context array.\n");
+        hr = E_OUTOFMEMORY;
+        goto err;
+    }
+    swapchain->num_contexts = 1;
+
+    if (surface_type == SURFACE_OPENGL)
+    {
+        swapchain->context[0] = context_create(device, (IWineD3DSurfaceImpl *)swapchain->frontBuffer,
+                window, FALSE /* pbuffer */, present_parameters);
+        if (!swapchain->context[0])
+        {
+            WARN("Failed to create context.\n");
+            hr = WINED3DERR_NOTAVAILABLE;
+            goto err;
+        }
+
+        swapchain->context[0]->render_offscreen = swapchain->render_to_fbo;
+    }
+    else
+    {
+        swapchain->context[0] = NULL;
+    }
+
+    if (swapchain->presentParms.BackBufferCount > 0)
+    {
+        swapchain->backBuffer = HeapAlloc(GetProcessHeap(), 0,
+                sizeof(*swapchain->backBuffer) * swapchain->presentParms.BackBufferCount);
+        if (!swapchain->backBuffer)
+        {
+            ERR("Failed to allocate backbuffer array memory.\n");
+            hr = E_OUTOFMEMORY;
+            goto err;
+        }
+
+        for (i = 0; i < swapchain->presentParms.BackBufferCount; ++i)
+        {
+            TRACE("Creating back buffer %u.\n", i);
+            hr = IWineD3DDeviceParent_CreateRenderTarget(device->device_parent, parent,
+                    swapchain->presentParms.BackBufferWidth, swapchain->presentParms.BackBufferHeight,
+                    swapchain->presentParms.BackBufferFormat, swapchain->presentParms.MultiSampleType,
+                    swapchain->presentParms.MultiSampleQuality, TRUE /* Lockable */, &swapchain->backBuffer[i]);
+            if (FAILED(hr))
+            {
+                WARN("Failed to create back buffer %u, hr %#x.\n", i, hr);
+                goto err;
+            }
+
+            IWineD3DSurface_SetContainer(swapchain->backBuffer[i], (IWineD3DBase *)swapchain);
+            ((IWineD3DSurfaceImpl *)swapchain->backBuffer[i])->Flags |= SFLAG_SWAPCHAIN;
+
+            if (surface_type == SURFACE_OPENGL)
+            {
+                ENTER_GL();
+                glDrawBuffer(GL_BACK);
+                checkGLcall("glDrawBuffer(GL_BACK)");
+                LEAVE_GL();
+            }
+        }
+    }
+    else
+    {
+        /* Single buffering - draw to front buffer */
+        if (surface_type == SURFACE_OPENGL)
+        {
+            ENTER_GL();
+            glDrawBuffer(GL_FRONT);
+            checkGLcall("glDrawBuffer(GL_FRONT)");
+            LEAVE_GL();
+        }
+    }
+
+    if (swapchain->context[0]) context_release(swapchain->context[0]);
+
+    /* Swapchains share the depth/stencil buffer, so only create a single depthstencil surface. */
+    if (present_parameters->EnableAutoDepthStencil && surface_type == SURFACE_OPENGL)
+    {
+        TRACE("Creating depth/stencil buffer.\n");
+        if (!device->auto_depth_stencil_buffer)
+        {
+            hr = IWineD3DDeviceParent_CreateDepthStencilSurface(device->device_parent, parent,
+                    swapchain->presentParms.BackBufferWidth, swapchain->presentParms.BackBufferHeight,
+                    swapchain->presentParms.AutoDepthStencilFormat, swapchain->presentParms.MultiSampleType,
+                    swapchain->presentParms.MultiSampleQuality, FALSE /* FIXME: Discard */,
+                    &device->auto_depth_stencil_buffer);
+            if (FAILED(hr))
+            {
+                WARN("Failed to create the auto depth stencil, hr %#x.\n", hr);
+                goto err;
+            }
+
+            IWineD3DSurface_SetContainer(device->auto_depth_stencil_buffer, NULL);
+        }
+    }
+
+    IWineD3DSwapChain_GetGammaRamp((IWineD3DSwapChain *)swapchain, &swapchain->orig_gamma);
+
+    return WINED3D_OK;
+
+err:
+    if (displaymode_set)
+    {
+        DEVMODEW devmode;
+
+        ClipCursor(NULL);
+
+        /* Change the display settings */
+        memset(&devmode, 0, sizeof(devmode));
+        devmode.dmSize = sizeof(devmode);
+        devmode.dmFields = DM_BITSPERPEL | DM_PELSWIDTH | DM_PELSHEIGHT;
+        devmode.dmBitsPerPel = format_desc->byte_count * 8;
+        devmode.dmPelsWidth = swapchain->orig_width;
+        devmode.dmPelsHeight = swapchain->orig_height;
+        ChangeDisplaySettingsExW(adapter->DeviceName, &devmode, NULL, CDS_FULLSCREEN, NULL);
+    }
+
+    if (swapchain->backBuffer)
+    {
+        for (i = 0; i < swapchain->presentParms.BackBufferCount; ++i)
+        {
+            if (swapchain->backBuffer[i]) IWineD3DSurface_Release(swapchain->backBuffer[i]);
+        }
+        HeapFree(GetProcessHeap(), 0, swapchain->backBuffer);
+    }
+
+    if (swapchain->context && swapchain->context[0])
+    {
+        context_release(swapchain->context[0]);
+        context_destroy(device, swapchain->context[0]);
+    }
+
+    if (swapchain->frontBuffer) IWineD3DSurface_Release(swapchain->frontBuffer);
+
+    return hr;
+}
+
 struct wined3d_context *swapchain_create_context_for_thread(IWineD3DSwapChain *iface)
 {
     IWineD3DSwapChainImpl *This = (IWineD3DSwapChainImpl *) iface;
diff --git a/dlls/wined3d/wined3d_private.h b/dlls/wined3d/wined3d_private.h
index 9cecc97..65e6e18 100644
--- a/dlls/wined3d/wined3d_private.h
+++ b/dlls/wined3d/wined3d_private.h
@@ -1598,6 +1598,8 @@ HRESULT IWineD3DDeviceImpl_ClearSurface(IWineD3DDeviceImpl *This, IWineD3DSurfac
         const WINED3DRECT *pRects, DWORD Flags, WINED3DCOLOR Color, float Z, DWORD Stencil) DECLSPEC_HIDDEN;
 void IWineD3DDeviceImpl_FindTexUnitMap(IWineD3DDeviceImpl *This) DECLSPEC_HIDDEN;
 void IWineD3DDeviceImpl_MarkStateDirty(IWineD3DDeviceImpl *This, DWORD state) DECLSPEC_HIDDEN;
+void IWineD3DDeviceImpl_SetupFullscreenWindow(IWineD3DDeviceImpl *This, HWND window, UINT w, UINT h) DECLSPEC_HIDDEN;
+
 static inline BOOL isStateDirty(struct wined3d_context *context, DWORD state)
 {
     DWORD idx = state >> 5;
@@ -2423,7 +2425,6 @@ typedef struct IWineD3DSwapChainImpl
     HWND                    win_handle;
 } IWineD3DSwapChainImpl;
 
-extern const IWineD3DSwapChainVtbl IWineD3DSwapChain_Vtbl DECLSPEC_HIDDEN;
 const IWineD3DSwapChainVtbl IWineGDISwapChain_Vtbl DECLSPEC_HIDDEN;
 void x11_copy_to_screen(IWineD3DSwapChainImpl *This, const RECT *rc) DECLSPEC_HIDDEN;
 
@@ -2450,6 +2451,8 @@ HRESULT WINAPI IWineD3DBaseSwapChainImpl_GetGammaRamp(IWineD3DSwapChain *iface,
         WINED3DGAMMARAMP *pRamp) DECLSPEC_HIDDEN;
 
 struct wined3d_context *swapchain_create_context_for_thread(IWineD3DSwapChain *iface) DECLSPEC_HIDDEN;
+HRESULT swapchain_init(IWineD3DSwapChainImpl *swapchain, WINED3DSURFTYPE surface_type,
+        IWineD3DDeviceImpl *device, WINED3DPRESENT_PARAMETERS *present_parameters, IUnknown *parent) DECLSPEC_HIDDEN;
 
 #define DEFAULT_REFRESH_RATE 0
 
-- 
1.6.4.4




More information about the wine-patches mailing list