From a9f2613d13a70c9152f1d72bce02287ccd8147f8 Mon Sep 17 00:00:00 2001 From: Henri Verbeet Date: Thu, 10 Dec 2009 21:41:54 +0100 Subject: [PATCH] wined3d: Add a separate function for swapchain initialization. --- 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 029884c3333..c49f70f055b 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; + 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 @@ 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 51eaab45731..51ee607a50f 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 9cecc970590..65e6e188999 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