diff --git a/dlls/wined3d/context.c b/dlls/wined3d/context.c index 91f647bb89c..4d28cd45ef1 100644 --- a/dlls/wined3d/context.c +++ b/dlls/wined3d/context.c @@ -688,6 +688,49 @@ static BOOL context_set_pixel_format(const struct wined3d_gl_info *gl_info, HDC return TRUE; } +static void context_update_window(struct wined3d_context *context) +{ + TRACE("Updating context %p window from %p to %p.\n", + context, context->win_handle, context->swapchain->win_handle); + + if (context->valid) + { + if (!ReleaseDC(context->win_handle, context->hdc)) + { + ERR("Failed to release device context %p, last error %#x.\n", + context->hdc, GetLastError()); + } + } + else context->valid = 1; + + context->win_handle = context->swapchain->win_handle; + + if (!(context->hdc = GetDC(context->win_handle))) + { + ERR("Failed to get a device context for window %p.\n", context->win_handle); + goto err; + } + + if (!context_set_pixel_format(context->gl_info, context->hdc, context->pixel_format)) + { + ERR("Failed to set pixel format %d on device context %p.\n", + context->pixel_format, context->hdc); + goto err; + } + + if (!pwglMakeCurrent(context->hdc, context->glCtx)) + { + ERR("Failed to make GL context %p current on device context %p, last error %#x.\n", + context->glCtx, context->hdc, GetLastError()); + goto err; + } + + return; + +err: + context->valid = 0; +} + static void context_validate(struct wined3d_context *context) { HWND wnd = WindowFromDC(context->hdc); @@ -698,6 +741,9 @@ static void context_validate(struct wined3d_context *context) context->hdc, wnd, context->win_handle); context->valid = 0; } + + if (context->win_handle != context->swapchain->win_handle) + context_update_window(context); } static void context_destroy_gl_resources(struct wined3d_context *context) @@ -1298,6 +1344,7 @@ struct wined3d_context *context_create(IWineD3DSwapChainImpl *swapchain, IWineD3 ret->glCtx = ctx; ret->win_handle = swapchain->win_handle; ret->hdc = hdc; + ret->pixel_format = pixel_format; if (device->shader_backend->shader_dirtifyable_constants((IWineD3DDevice *)device)) { diff --git a/dlls/wined3d/swapchain.c b/dlls/wined3d/swapchain.c index 43a0713aebe..79c2bd8b448 100644 --- a/dlls/wined3d/swapchain.c +++ b/dlls/wined3d/swapchain.c @@ -514,46 +514,16 @@ static HRESULT WINAPI IWineD3DSwapChainImpl_Present(IWineD3DSwapChain *iface, CO return WINED3D_OK; } -static HRESULT WINAPI IWineD3DSwapChainImpl_SetDestWindowOverride(IWineD3DSwapChain *iface, HWND window) { - IWineD3DSwapChainImpl *This = (IWineD3DSwapChainImpl *)iface; - WINED3DLOCKED_RECT r; - BYTE *mem; +static HRESULT WINAPI IWineD3DSwapChainImpl_SetDestWindowOverride(IWineD3DSwapChain *iface, HWND window) +{ + IWineD3DSwapChainImpl *swapchain = (IWineD3DSwapChainImpl *)iface; - if (!window || window == This->win_handle) return WINED3D_OK; + if (!window) window = swapchain->device_window; + if (window == swapchain->win_handle) return WINED3D_OK; - TRACE("Performing dest override of swapchain %p from window %p to %p\n", This, This->win_handle, window); - if (This->context[0] == This->device->contexts[0]) - { - /* The primary context 'owns' all the opengl resources. Destroying and recreating that context requires downloading - * all opengl resources, deleting the gl resources, destroying all other contexts, then recreating all other contexts - * and reload the resources - */ - delete_opengl_contexts((IWineD3DDevice *)This->device, iface); - This->win_handle = window; - create_primary_opengl_context((IWineD3DDevice *)This->device, iface); - } - else - { - This->win_handle = window; + TRACE("Setting swapchain %p window from %p to %p\n", swapchain, swapchain->win_handle, window); + swapchain->win_handle = window; - /* The old back buffer has to be copied over to the new back buffer. A lockrect - switchcontext - unlockrect - * would suffice in theory, but it is rather nasty and may cause troubles with future changes of the locking code - * So lock read only, copy the surface out, then lock with the discard flag and write back - */ - IWineD3DSurface_LockRect(This->backBuffer[0], &r, NULL, WINED3DLOCK_READONLY); - mem = HeapAlloc(GetProcessHeap(), 0, r.Pitch * ((IWineD3DSurfaceImpl *) This->backBuffer[0])->currentDesc.Height); - memcpy(mem, r.pBits, r.Pitch * ((IWineD3DSurfaceImpl *) This->backBuffer[0])->currentDesc.Height); - IWineD3DSurface_UnlockRect(This->backBuffer[0]); - - context_destroy(This->device, This->context[0]); - This->context[0] = context_create(This, (IWineD3DSurfaceImpl *)This->frontBuffer); - context_release(This->context[0]); - - IWineD3DSurface_LockRect(This->backBuffer[0], &r, NULL, WINED3DLOCK_DISCARD); - memcpy(r.pBits, mem, r.Pitch * ((IWineD3DSurfaceImpl *) This->backBuffer[0])->currentDesc.Height); - HeapFree(GetProcessHeap(), 0, mem); - IWineD3DSurface_UnlockRect(This->backBuffer[0]); - } return WINED3D_OK; } diff --git a/dlls/wined3d/wined3d_private.h b/dlls/wined3d/wined3d_private.h index 66a7afac914..3c362bf4f00 100644 --- a/dlls/wined3d/wined3d_private.h +++ b/dlls/wined3d/wined3d_private.h @@ -1088,6 +1088,7 @@ struct wined3d_context HGLRC glCtx; HWND win_handle; HDC hdc; + int pixel_format; GLint aux_buffers; /* FBOs */