wined3d: Add a separate function for swapchain initialization.
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 @@
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 @@
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;
+ IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
+ IWineD3DSwapChainImpl *object;
+ HRESULT hr;
- 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.
- *******************************/
-
- /* 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)
+ if (!object)
{
- ERR("Out of memory\n");
- *ppSwapChain = NULL;
- return WINED3DERR_OUTOFVIDEOMEMORY;
+ ERR("Failed to allocate swapchain memory.\n");
+ return E_OUTOFMEMORY;
}
- 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)
+ hr = swapchain_init(object, surface_type, This, present_parameters, parent);
+ if (FAILED(hr))
{
- 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");
- }
+ WARN("Failed to initialize swapchain, hr %#x.\n", hr);
+ HeapFree(GetProcessHeap(), 0, object);
+ return hr;
}
- /* Put the correct figures in the presentation parameters */
- TRACE("Copying across presentation parameters\n");
- object->presentParms = *pPresentationParameters;
+ TRACE("Created swapchain %p.\n", object);
+ *swapchain = (IWineD3DSwapChain *)object;
- 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;
- }
- 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
- {
- 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;
- }
- }
- }
-
- IWineD3DSwapChain_GetGammaRamp((IWineD3DSwapChain *) object, &object->orig_gamma);
-
- 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 @@
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 @@
*/
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 @@
return WINED3D_OK;
}
-const IWineD3DSwapChainVtbl IWineD3DSwapChain_Vtbl =
+static const IWineD3DSwapChainVtbl IWineD3DSwapChain_Vtbl =
{
/* IUnknown */
IWineD3DBaseSwapChainImpl_QueryInterface,
@@ -557,6 +557,282 @@
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 @@
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 @@
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 @@
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