058c0c53c37f5cb271aeb3c385c10766f84f4aefvboxsync * Copyright 2002-2003 Jason Edmeades
058c0c53c37f5cb271aeb3c385c10766f84f4aefvboxsync * Copyright 2002-2003 Raphael Junqueira
058c0c53c37f5cb271aeb3c385c10766f84f4aefvboxsync * Copyright 2005 Oliver Stieber
058c0c53c37f5cb271aeb3c385c10766f84f4aefvboxsync * Copyright 2007-2008 Stefan Dösinger for CodeWeavers
058c0c53c37f5cb271aeb3c385c10766f84f4aefvboxsync * Copyright 2011 Henri Verbeet for CodeWeavers
058c0c53c37f5cb271aeb3c385c10766f84f4aefvboxsync * This library is free software; you can redistribute it and/or
058c0c53c37f5cb271aeb3c385c10766f84f4aefvboxsync * modify it under the terms of the GNU Lesser General Public
058c0c53c37f5cb271aeb3c385c10766f84f4aefvboxsync * License as published by the Free Software Foundation; either
058c0c53c37f5cb271aeb3c385c10766f84f4aefvboxsync * version 2.1 of the License, or (at your option) any later version.
058c0c53c37f5cb271aeb3c385c10766f84f4aefvboxsync * This library is distributed in the hope that it will be useful,
058c0c53c37f5cb271aeb3c385c10766f84f4aefvboxsync * but WITHOUT ANY WARRANTY; without even the implied warranty of
058c0c53c37f5cb271aeb3c385c10766f84f4aefvboxsync * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
058c0c53c37f5cb271aeb3c385c10766f84f4aefvboxsync * Lesser General Public License for more details.
058c0c53c37f5cb271aeb3c385c10766f84f4aefvboxsync * You should have received a copy of the GNU Lesser General Public
058c0c53c37f5cb271aeb3c385c10766f84f4aefvboxsync * License along with this library; if not, write to the Free Software
058c0c53c37f5cb271aeb3c385c10766f84f4aefvboxsync * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
4237d5a79f48789aacc67dc43378d2d7813a39f4vboxsync * Oracle LGPL Disclaimer: For the avoidance of doubt, except that if any license choice
4237d5a79f48789aacc67dc43378d2d7813a39f4vboxsync * other than GPL or LGPL is available it will apply instead, Oracle elects to use only
4237d5a79f48789aacc67dc43378d2d7813a39f4vboxsync * the Lesser General Public License version 2.1 (LGPLv2) at this time for any software where
4237d5a79f48789aacc67dc43378d2d7813a39f4vboxsync * a choice of LGPL license versions is made available with the language indicating
4237d5a79f48789aacc67dc43378d2d7813a39f4vboxsync * that LGPLv2 or any later version may be used, or where a choice of which version
4237d5a79f48789aacc67dc43378d2d7813a39f4vboxsync * of the LGPL is applied is otherwise unspecified.
058c0c53c37f5cb271aeb3c385c10766f84f4aefvboxsyncstatic VOID swapchain_cleanup_rt_refs(struct wined3d_swapchain *swapchain, struct wined3d_surface * rt, int iBb)
058c0c53c37f5cb271aeb3c385c10766f84f4aefvboxsync struct wined3d_device * device = swapchain->device;
058c0c53c37f5cb271aeb3c385c10766f84f4aefvboxsync struct wined3d_swapchain *default_swapchain = (struct wined3d_swapchain*)device->swapchains[0];
058c0c53c37f5cb271aeb3c385c10766f84f4aefvboxsync for (i = 0; i < device->adapter->gl_info.limits.buffers; ++i)
058c0c53c37f5cb271aeb3c385c10766f84f4aefvboxsync new_rt = default_swapchain->back_buffers ? default_swapchain->back_buffers[0] : default_swapchain->front_buffer;
058c0c53c37f5cb271aeb3c385c10766f84f4aefvboxsync wined3d_device_set_render_target(device, i, new_rt, TRUE);
058c0c53c37f5cb271aeb3c385c10766f84f4aefvboxsyncstatic VOID swapchain_cleanup_refs(struct wined3d_swapchain *swapchain)
058c0c53c37f5cb271aeb3c385c10766f84f4aefvboxsync /* first make sure the swapchain is not used by anyone */
058c0c53c37f5cb271aeb3c385c10766f84f4aefvboxsync struct wined3d_device * device = swapchain->device;
058c0c53c37f5cb271aeb3c385c10766f84f4aefvboxsync /* Release the swapchain's draw buffers. Make sure swapchain->back_buffers[0]
058c0c53c37f5cb271aeb3c385c10766f84f4aefvboxsync * is the last buffer to be destroyed, FindContext() depends on that. */
058c0c53c37f5cb271aeb3c385c10766f84f4aefvboxsync surface_set_swapchain(swapchain->front_buffer, NULL);
058c0c53c37f5cb271aeb3c385c10766f84f4aefvboxsync if (wined3d_surface_decref(swapchain->front_buffer))
058c0c53c37f5cb271aeb3c385c10766f84f4aefvboxsync WARN("Something's still holding the front buffer (%p).\n", swapchain->front_buffer);
058c0c53c37f5cb271aeb3c385c10766f84f4aefvboxsync while (i--)
058c0c53c37f5cb271aeb3c385c10766f84f4aefvboxsync surface_set_swapchain(swapchain->back_buffers[i], NULL);
058c0c53c37f5cb271aeb3c385c10766f84f4aefvboxsync if (wined3d_surface_decref(swapchain->back_buffers[i]))
058c0c53c37f5cb271aeb3c385c10766f84f4aefvboxsync WARN("Something's still holding back buffer %u (%p).\n", i, swapchain->back_buffers[i]);
058c0c53c37f5cb271aeb3c385c10766f84f4aefvboxsync HeapFree(GetProcessHeap(), 0, swapchain->back_buffers);
058c0c53c37f5cb271aeb3c385c10766f84f4aefvboxsync /* pretty hacky, @todo: check if the context is acquired and re-acquire it with a new swapchain */
058c0c53c37f5cb271aeb3c385c10766f84f4aefvboxsync// if (swapchain->front_buffer)
058c0c53c37f5cb271aeb3c385c10766f84f4aefvboxsync// swapchain_cleanup_rt_refs(swapchain, swapchain->front_buffer, -1);
058c0c53c37f5cb271aeb3c385c10766f84f4aefvboxsync// if (swapchain->back_buffers)
058c0c53c37f5cb271aeb3c385c10766f84f4aefvboxsync// for (i = 0; i < swapchain->desc.backbuffer_count; ++i)
058c0c53c37f5cb271aeb3c385c10766f84f4aefvboxsync// swapchain_cleanup_rt_refs(swapchain, swapchain->back_buffers[i], i);
058c0c53c37f5cb271aeb3c385c10766f84f4aefvboxsyncstruct wined3d_swapchain * swapchain_find(struct wined3d_device * device, HWND hWnd)
058c0c53c37f5cb271aeb3c385c10766f84f4aefvboxsync struct wined3d_swapchain *swapchain = device->swapchains[i];
058c0c53c37f5cb271aeb3c385c10766f84f4aefvboxsyncstatic VOID swapchain_invalidate(struct wined3d_swapchain *swapchain)
058c0c53c37f5cb271aeb3c385c10766f84f4aefvboxsync/* Do not call while under the GL lock. */
058c0c53c37f5cb271aeb3c385c10766f84f4aefvboxsyncstatic void swapchain_cleanup(struct wined3d_swapchain *swapchain)
058c0c53c37f5cb271aeb3c385c10766f84f4aefvboxsync wined3d_swapchain_set_gamma_ramp(swapchain, 0, &swapchain->orig_gamma);
058c0c53c37f5cb271aeb3c385c10766f84f4aefvboxsync /* Release the swapchain's draw buffers. Make sure swapchain->back_buffers[0]
058c0c53c37f5cb271aeb3c385c10766f84f4aefvboxsync * is the last buffer to be destroyed, FindContext() depends on that. */
058c0c53c37f5cb271aeb3c385c10766f84f4aefvboxsync surface_set_swapchain(swapchain->front_buffer, NULL);
058c0c53c37f5cb271aeb3c385c10766f84f4aefvboxsync if (wined3d_surface_decref(swapchain->front_buffer))
058c0c53c37f5cb271aeb3c385c10766f84f4aefvboxsync WARN("Something's still holding the front buffer (%p).\n", swapchain->front_buffer);
058c0c53c37f5cb271aeb3c385c10766f84f4aefvboxsync while (i--)
058c0c53c37f5cb271aeb3c385c10766f84f4aefvboxsync surface_set_swapchain(swapchain->back_buffers[i], NULL);
058c0c53c37f5cb271aeb3c385c10766f84f4aefvboxsync if (wined3d_surface_decref(swapchain->back_buffers[i]))
058c0c53c37f5cb271aeb3c385c10766f84f4aefvboxsync WARN("Something's still holding back buffer %u (%p).\n", i, swapchain->back_buffers[i]);
058c0c53c37f5cb271aeb3c385c10766f84f4aefvboxsync HeapFree(GetProcessHeap(), 0, swapchain->back_buffers);
058c0c53c37f5cb271aeb3c385c10766f84f4aefvboxsync context_destroy(swapchain->device, swapchain->context[i]);
058c0c53c37f5cb271aeb3c385c10766f84f4aefvboxsync /* Restore the screen resolution if we rendered in fullscreen.
058c0c53c37f5cb271aeb3c385c10766f84f4aefvboxsync * This will restore the screen resolution to what it was before creating
058c0c53c37f5cb271aeb3c385c10766f84f4aefvboxsync * the swapchain. In case of d3d8 and d3d9 this will be the original
058c0c53c37f5cb271aeb3c385c10766f84f4aefvboxsync * desktop resolution. In case of d3d7 this will be a NOP because ddraw
058c0c53c37f5cb271aeb3c385c10766f84f4aefvboxsync * sets the resolution before starting up Direct3D, thus orig_width and
058c0c53c37f5cb271aeb3c385c10766f84f4aefvboxsync * orig_height will be equal to the modes in the presentation params. */
058c0c53c37f5cb271aeb3c385c10766f84f4aefvboxsync if (!swapchain->desc.windowed && swapchain->desc.auto_restore_display_mode)
058c0c53c37f5cb271aeb3c385c10766f84f4aefvboxsync if (FAILED(hr = wined3d_set_adapter_display_mode(swapchain->device->wined3d,
76f3927069cc452e77bf72f32d9175c0256ed3b3vboxsync swapchain->device->adapter->ordinal, &swapchain->original_mode)))
058c0c53c37f5cb271aeb3c385c10766f84f4aefvboxsync ERR("Failed to restore display mode, hr %#x.\n", hr);
058c0c53c37f5cb271aeb3c385c10766f84f4aefvboxsync TRACE("Destroying backup wined3d window %p, dc %p.\n", swapchain->backup_wnd, swapchain->backup_dc);
76f3927069cc452e77bf72f32d9175c0256ed3b3vboxsync wined3d_release_dc(swapchain->backup_wnd, swapchain->backup_dc);
058c0c53c37f5cb271aeb3c385c10766f84f4aefvboxsync VBoxExtWndDestroy(swapchain->win_handle, swapchain->hDC);
058c0c53c37f5cb271aeb3c385c10766f84f4aefvboxsyncULONG CDECL wined3d_swapchain_incref(struct wined3d_swapchain *swapchain)
058c0c53c37f5cb271aeb3c385c10766f84f4aefvboxsync ULONG refcount = InterlockedIncrement(&swapchain->ref);
058c0c53c37f5cb271aeb3c385c10766f84f4aefvboxsync TRACE("%p increasing refcount to %u.\n", swapchain, refcount);
058c0c53c37f5cb271aeb3c385c10766f84f4aefvboxsync/* Do not call while under the GL lock. */
058c0c53c37f5cb271aeb3c385c10766f84f4aefvboxsyncULONG CDECL wined3d_swapchain_decref(struct wined3d_swapchain *swapchain)
058c0c53c37f5cb271aeb3c385c10766f84f4aefvboxsync ULONG refcount = InterlockedDecrement(&swapchain->ref);
058c0c53c37f5cb271aeb3c385c10766f84f4aefvboxsync TRACE("%p decreasing refcount to %u.\n", swapchain, refcount);
058c0c53c37f5cb271aeb3c385c10766f84f4aefvboxsync swapchain->parent_ops->wined3d_object_destroyed(swapchain->parent);
058c0c53c37f5cb271aeb3c385c10766f84f4aefvboxsyncvoid * CDECL wined3d_swapchain_get_parent(const struct wined3d_swapchain *swapchain)
058c0c53c37f5cb271aeb3c385c10766f84f4aefvboxsyncvoid CDECL wined3d_swapchain_set_window(struct wined3d_swapchain *swapchain, HWND window)
058c0c53c37f5cb271aeb3c385c10766f84f4aefvboxsync TRACE("Setting swapchain %p window from %p to %p.\n",
058c0c53c37f5cb271aeb3c385c10766f84f4aefvboxsyncHRESULT CDECL wined3d_swapchain_present(struct wined3d_swapchain *swapchain,
058c0c53c37f5cb271aeb3c385c10766f84f4aefvboxsync const RECT *src_rect, const RECT *dst_rect, HWND dst_window_override,
058c0c53c37f5cb271aeb3c385c10766f84f4aefvboxsync TRACE("swapchain %p, src_rect %s, dst_rect %s, dst_window_override %p, dirty_region %p, flags %#x.\n",
058c0c53c37f5cb271aeb3c385c10766f84f4aefvboxsync swapchain, wine_dbgstr_rect(src_rect), wine_dbgstr_rect(dst_rect),
058c0c53c37f5cb271aeb3c385c10766f84f4aefvboxsync WARN("Swapchain doesn't have a backbuffer, returning WINED3DERR_INVALIDCALL\n");
058c0c53c37f5cb271aeb3c385c10766f84f4aefvboxsync wined3d_swapchain_set_window(swapchain, dst_window_override);
058c0c53c37f5cb271aeb3c385c10766f84f4aefvboxsync swapchain->swapchain_ops->swapchain_present(swapchain, src_rect, dst_rect, dirty_region, flags);
058c0c53c37f5cb271aeb3c385c10766f84f4aefvboxsyncHRESULT CDECL wined3d_swapchain_get_front_buffer_data(const struct wined3d_swapchain *swapchain,
058c0c53c37f5cb271aeb3c385c10766f84f4aefvboxsync TRACE("swapchain %p, dst_surface %p.\n", swapchain, dst_surface);
058c0c53c37f5cb271aeb3c385c10766f84f4aefvboxsync SetRect(&src_rect, 0, 0, src_surface->resource.width, src_surface->resource.height);
058c0c53c37f5cb271aeb3c385c10766f84f4aefvboxsync MapWindowPoints(swapchain->win_handle, NULL, (POINT *)&dst_rect, 2);
058c0c53c37f5cb271aeb3c385c10766f84f4aefvboxsync FIXME("Using destination rect %s in windowed mode, this is likely wrong.\n",
058c0c53c37f5cb271aeb3c385c10766f84f4aefvboxsync return wined3d_surface_blt(dst_surface, &dst_rect, src_surface, &src_rect, 0, NULL, WINED3D_TEXF_POINT);
058c0c53c37f5cb271aeb3c385c10766f84f4aefvboxsyncstruct wined3d_surface * CDECL wined3d_swapchain_get_back_buffer(const struct wined3d_swapchain *swapchain,
058c0c53c37f5cb271aeb3c385c10766f84f4aefvboxsync UINT back_buffer_idx, enum wined3d_backbuffer_type type)
058c0c53c37f5cb271aeb3c385c10766f84f4aefvboxsync TRACE("swapchain %p, back_buffer_idx %u, type %#x.\n",
058c0c53c37f5cb271aeb3c385c10766f84f4aefvboxsync /* Return invalid if there is no backbuffer array, otherwise it will
058c0c53c37f5cb271aeb3c385c10766f84f4aefvboxsync * crash when ddraw is used (there swapchain->back_buffers is always
058c0c53c37f5cb271aeb3c385c10766f84f4aefvboxsync * NULL). We need this because this function is called from
058c0c53c37f5cb271aeb3c385c10766f84f4aefvboxsync * stateblock_init_default_state() to get the default scissorrect
058c0c53c37f5cb271aeb3c385c10766f84f4aefvboxsync * dimensions. */
058c0c53c37f5cb271aeb3c385c10766f84f4aefvboxsync if (!swapchain->back_buffers || back_buffer_idx >= swapchain->desc.backbuffer_count)
058c0c53c37f5cb271aeb3c385c10766f84f4aefvboxsync /* Native d3d9 doesn't set NULL here, just as wine's d3d9. But set it
058c0c53c37f5cb271aeb3c385c10766f84f4aefvboxsync * here in wined3d to avoid problems in other libs. */
058c0c53c37f5cb271aeb3c385c10766f84f4aefvboxsync TRACE("Returning back buffer %p.\n", swapchain->back_buffers[back_buffer_idx]);
058c0c53c37f5cb271aeb3c385c10766f84f4aefvboxsyncHRESULT CDECL wined3d_swapchain_get_raster_status(const struct wined3d_swapchain *swapchain,
058c0c53c37f5cb271aeb3c385c10766f84f4aefvboxsync TRACE("swapchain %p, raster_status %p.\n", swapchain, raster_status);
058c0c53c37f5cb271aeb3c385c10766f84f4aefvboxsync return wined3d_get_adapter_raster_status(swapchain->device->wined3d,
058c0c53c37f5cb271aeb3c385c10766f84f4aefvboxsync swapchain->device->adapter->ordinal, raster_status);
058c0c53c37f5cb271aeb3c385c10766f84f4aefvboxsyncHRESULT CDECL wined3d_swapchain_get_display_mode(const struct wined3d_swapchain *swapchain,
058c0c53c37f5cb271aeb3c385c10766f84f4aefvboxsync struct wined3d_display_mode *mode, enum wined3d_display_rotation *rotation)
058c0c53c37f5cb271aeb3c385c10766f84f4aefvboxsync TRACE("swapchain %p, mode %p, rotation %p.\n", swapchain, mode, rotation);
058c0c53c37f5cb271aeb3c385c10766f84f4aefvboxsync hr = wined3d_get_adapter_display_mode(swapchain->device->wined3d,
058c0c53c37f5cb271aeb3c385c10766f84f4aefvboxsync swapchain->device->adapter->ordinal, mode, rotation);
058c0c53c37f5cb271aeb3c385c10766f84f4aefvboxsync TRACE("Returning w %u, h %u, refresh rate %u, format %s.\n",
058c0c53c37f5cb271aeb3c385c10766f84f4aefvboxsync mode->width, mode->height, mode->refresh_rate, debug_d3dformat(mode->format_id));
058c0c53c37f5cb271aeb3c385c10766f84f4aefvboxsyncstruct wined3d_device * CDECL wined3d_swapchain_get_device(const struct wined3d_swapchain *swapchain)
058c0c53c37f5cb271aeb3c385c10766f84f4aefvboxsyncvoid CDECL wined3d_swapchain_get_desc(const struct wined3d_swapchain *swapchain,
058c0c53c37f5cb271aeb3c385c10766f84f4aefvboxsync TRACE("swapchain %p, desc %p.\n", swapchain, desc);
058c0c53c37f5cb271aeb3c385c10766f84f4aefvboxsyncHRESULT CDECL wined3d_swapchain_set_gamma_ramp(const struct wined3d_swapchain *swapchain,
058c0c53c37f5cb271aeb3c385c10766f84f4aefvboxsync DWORD flags, const struct wined3d_gamma_ramp *ramp)
058c0c53c37f5cb271aeb3c385c10766f84f4aefvboxsync TRACE("swapchain %p, flags %#x, ramp %p.\n", swapchain, flags, ramp);
058c0c53c37f5cb271aeb3c385c10766f84f4aefvboxsyncHRESULT CDECL wined3d_swapchain_get_gamma_ramp(const struct wined3d_swapchain *swapchain,
058c0c53c37f5cb271aeb3c385c10766f84f4aefvboxsync TRACE("swapchain %p, ramp %p.\n", swapchain, ramp);
058c0c53c37f5cb271aeb3c385c10766f84f4aefvboxsync/* A GL context is provided by the caller */
058c0c53c37f5cb271aeb3c385c10766f84f4aefvboxsyncstatic void swapchain_blit(const struct wined3d_swapchain *swapchain,
058c0c53c37f5cb271aeb3c385c10766f84f4aefvboxsync struct wined3d_context *context, const RECT *src_rect, const RECT *dst_rect)
058c0c53c37f5cb271aeb3c385c10766f84f4aefvboxsync struct wined3d_surface *backbuffer = swapchain->back_buffers[0];
058c0c53c37f5cb271aeb3c385c10766f84f4aefvboxsync const struct wined3d_gl_info *gl_info = context->gl_info;
058c0c53c37f5cb271aeb3c385c10766f84f4aefvboxsync TRACE("swapchain %p, context %p, src_rect %s, dst_rect %s.\n",
058c0c53c37f5cb271aeb3c385c10766f84f4aefvboxsync swapchain, context, wine_dbgstr_rect(src_rect), wine_dbgstr_rect(dst_rect));
058c0c53c37f5cb271aeb3c385c10766f84f4aefvboxsync if (src_w == dst_rect->right - dst_rect->left && src_h == dst_rect->bottom - dst_rect->top)
058c0c53c37f5cb271aeb3c385c10766f84f4aefvboxsync if (gl_info->fbo_ops.glBlitFramebuffer && is_identity_fixup(backbuffer->resource.format->color_fixup))
058c0c53c37f5cb271aeb3c385c10766f84f4aefvboxsync context_apply_fbo_state_blit(context, GL_READ_FRAMEBUFFER, backbuffer, NULL, location);
058c0c53c37f5cb271aeb3c385c10766f84f4aefvboxsync gl_info->gl_ops.gl.p_glReadBuffer(GL_COLOR_ATTACHMENT0);
058c0c53c37f5cb271aeb3c385c10766f84f4aefvboxsync context_check_fbo_status(context, GL_READ_FRAMEBUFFER);
058c0c53c37f5cb271aeb3c385c10766f84f4aefvboxsync context_apply_fbo_state_blit(context, GL_DRAW_FRAMEBUFFER, swapchain->front_buffer, NULL, SFLAG_INDRAWABLE);
058c0c53c37f5cb271aeb3c385c10766f84f4aefvboxsync context_invalidate_state(context, STATE_FRAMEBUFFER);
058c0c53c37f5cb271aeb3c385c10766f84f4aefvboxsync gl_info->gl_ops.gl.p_glColorMask(GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE);
058c0c53c37f5cb271aeb3c385c10766f84f4aefvboxsync context_invalidate_state(context, STATE_RENDER(WINED3D_RS_COLORWRITEENABLE));
058c0c53c37f5cb271aeb3c385c10766f84f4aefvboxsync context_invalidate_state(context, STATE_RENDER(WINED3D_RS_COLORWRITEENABLE1));
058c0c53c37f5cb271aeb3c385c10766f84f4aefvboxsync context_invalidate_state(context, STATE_RENDER(WINED3D_RS_COLORWRITEENABLE2));
058c0c53c37f5cb271aeb3c385c10766f84f4aefvboxsync context_invalidate_state(context, STATE_RENDER(WINED3D_RS_COLORWRITEENABLE3));
058c0c53c37f5cb271aeb3c385c10766f84f4aefvboxsync context_invalidate_state(context, STATE_RENDER(WINED3D_RS_SCISSORTESTENABLE));
058c0c53c37f5cb271aeb3c385c10766f84f4aefvboxsync /* Note that the texture is upside down */
058c0c53c37f5cb271aeb3c385c10766f84f4aefvboxsync gl_info->fbo_ops.glBlitFramebuffer(src_rect->left, src_rect->top, src_rect->right, src_rect->bottom,
058c0c53c37f5cb271aeb3c385c10766f84f4aefvboxsync dst_rect->left, win_h - dst_rect->top, dst_rect->right, win_h - dst_rect->bottom,
058c0c53c37f5cb271aeb3c385c10766f84f4aefvboxsync checkGLcall("Swapchain present blit(EXT_framebuffer_blit)\n");
058c0c53c37f5cb271aeb3c385c10766f84f4aefvboxsync context2 = context_acquire(device, swapchain->back_buffers[0]);
058c0c53c37f5cb271aeb3c385c10766f84f4aefvboxsync if (is_complex_fixup(backbuffer->resource.format->color_fixup))
058c0c53c37f5cb271aeb3c385c10766f84f4aefvboxsync context_apply_fbo_state_blit(context2, GL_FRAMEBUFFER, swapchain->front_buffer, NULL, SFLAG_INDRAWABLE);
058c0c53c37f5cb271aeb3c385c10766f84f4aefvboxsync context_bind_texture(context2, backbuffer->texture_target, backbuffer->texture_name);
058c0c53c37f5cb271aeb3c385c10766f84f4aefvboxsync /* Set up the texture. The surface is not in a wined3d_texture
058c0c53c37f5cb271aeb3c385c10766f84f4aefvboxsync * container, so there are no D3D texture settings to dirtify. */
058c0c53c37f5cb271aeb3c385c10766f84f4aefvboxsync device->blitter->set_shader(device->blit_priv, context2, backbuffer);
058c0c53c37f5cb271aeb3c385c10766f84f4aefvboxsync gl_info->gl_ops.gl.p_glTexParameteri(backbuffer->texture_target, GL_TEXTURE_MIN_FILTER, gl_filter);
058c0c53c37f5cb271aeb3c385c10766f84f4aefvboxsync gl_info->gl_ops.gl.p_glTexParameteri(backbuffer->texture_target, GL_TEXTURE_MAG_FILTER, gl_filter);
058c0c53c37f5cb271aeb3c385c10766f84f4aefvboxsync /* Set the viewport to the destination rectandle, disable any projection
058c0c53c37f5cb271aeb3c385c10766f84f4aefvboxsync * transformation set up by context_apply_blit_state(), and draw a
058c0c53c37f5cb271aeb3c385c10766f84f4aefvboxsync * (-1,-1)-(1,1) quad.
058c0c53c37f5cb271aeb3c385c10766f84f4aefvboxsync * Back up viewport and matrix to avoid breaking last_was_blit
058c0c53c37f5cb271aeb3c385c10766f84f4aefvboxsync * Note that context_apply_blit_state() set up viewport and ortho to
058c0c53c37f5cb271aeb3c385c10766f84f4aefvboxsync * match the surface size - we want the GL drawable(=window) size. */
058c0c53c37f5cb271aeb3c385c10766f84f4aefvboxsync gl_info->gl_ops.gl.p_glPushAttrib(GL_VIEWPORT_BIT);
058c0c53c37f5cb271aeb3c385c10766f84f4aefvboxsync gl_info->gl_ops.gl.p_glViewport(dst_rect->left, win_h - dst_rect->bottom,
058c0c53c37f5cb271aeb3c385c10766f84f4aefvboxsync /* bottom left */
058c0c53c37f5cb271aeb3c385c10766f84f4aefvboxsync gl_info->gl_ops.gl.p_glTexCoord2f(tex_left, tex_bottom);
058c0c53c37f5cb271aeb3c385c10766f84f4aefvboxsync /* top left */
058c0c53c37f5cb271aeb3c385c10766f84f4aefvboxsync gl_info->gl_ops.gl.p_glTexCoord2f(tex_left, tex_top);
058c0c53c37f5cb271aeb3c385c10766f84f4aefvboxsync /* top right */
058c0c53c37f5cb271aeb3c385c10766f84f4aefvboxsync gl_info->gl_ops.gl.p_glTexCoord2f(tex_right, tex_top);
058c0c53c37f5cb271aeb3c385c10766f84f4aefvboxsync /* bottom right */
058c0c53c37f5cb271aeb3c385c10766f84f4aefvboxsync gl_info->gl_ops.gl.p_glTexCoord2f(tex_right, tex_bottom);
058c0c53c37f5cb271aeb3c385c10766f84f4aefvboxsyncstatic void swapchain_gl_present(struct wined3d_swapchain *swapchain, const RECT *src_rect_in,
058c0c53c37f5cb271aeb3c385c10766f84f4aefvboxsync const RECT *dst_rect_in, const RGNDATA *dirty_region, DWORD flags)
058c0c53c37f5cb271aeb3c385c10766f84f4aefvboxsync struct wined3d_surface *back_buffer = swapchain->back_buffers[0];
058c0c53c37f5cb271aeb3c385c10766f84f4aefvboxsync const struct wined3d_fb_state *fb = &swapchain->device->fb;
058c0c53c37f5cb271aeb3c385c10766f84f4aefvboxsync context = context_acquire(swapchain->device, back_buffer);
058c0c53c37f5cb271aeb3c385c10766f84f4aefvboxsync /* Render the cursor onto the back buffer, using our nifty directdraw blitting code :-) */
058c0c53c37f5cb271aeb3c385c10766f84f4aefvboxsync swapchain->device->xScreenSpace - swapchain->device->xHotSpot,
058c0c53c37f5cb271aeb3c385c10766f84f4aefvboxsync swapchain->device->yScreenSpace - swapchain->device->yHotSpot,
058c0c53c37f5cb271aeb3c385c10766f84f4aefvboxsync swapchain->device->xScreenSpace + swapchain->device->cursorWidth - swapchain->device->xHotSpot,
058c0c53c37f5cb271aeb3c385c10766f84f4aefvboxsync swapchain->device->yScreenSpace + swapchain->device->cursorHeight - swapchain->device->yHotSpot,
058c0c53c37f5cb271aeb3c385c10766f84f4aefvboxsync TRACE("Rendering the cursor. Creating fake surface at %p\n", &cursor);
058c0c53c37f5cb271aeb3c385c10766f84f4aefvboxsync /* Build a fake surface to call the Blitting code. It is not possible to use the interface passed by
058c0c53c37f5cb271aeb3c385c10766f84f4aefvboxsync * the application because we are only supposed to copy the information out. Using a fake surface
058c0c53c37f5cb271aeb3c385c10766f84f4aefvboxsync * allows us to use the Blitting engine and avoid copying the whole texture -> render target blitting code.
058c0c53c37f5cb271aeb3c385c10766f84f4aefvboxsync cursor.resource.format = wined3d_get_format(gl_info, WINED3DFMT_B8G8R8A8_UNORM);
058c0c53c37f5cb271aeb3c385c10766f84f4aefvboxsync cursor.texture_name = swapchain->device->cursorTexture;
058c0c53c37f5cb271aeb3c385c10766f84f4aefvboxsync cursor.resource.width = swapchain->device->cursorWidth;
058c0c53c37f5cb271aeb3c385c10766f84f4aefvboxsync cursor.resource.height = swapchain->device->cursorHeight;
058c0c53c37f5cb271aeb3c385c10766f84f4aefvboxsync /* The cursor must have pow2 sizes */
058c0c53c37f5cb271aeb3c385c10766f84f4aefvboxsync /* The surface is in the texture */
058c0c53c37f5cb271aeb3c385c10766f84f4aefvboxsync /* DDBLT_KEYSRC will cause BltOverride to enable the alpha test with GL_NOTEQUAL, 0.0,
058c0c53c37f5cb271aeb3c385c10766f84f4aefvboxsync * which is exactly what we want :-)
058c0c53c37f5cb271aeb3c385c10766f84f4aefvboxsync MapWindowPoints(NULL, swapchain->win_handle, (POINT *)&destRect, 2);
058c0c53c37f5cb271aeb3c385c10766f84f4aefvboxsync wined3d_surface_blt(back_buffer, &destRect, &cursor, NULL, WINEDDBLT_KEYSRC,
058c0c53c37f5cb271aeb3c385c10766f84f4aefvboxsync struct wined3d_surface *src_surface = swapchain->device->logo_surface;
058c0c53c37f5cb271aeb3c385c10766f84f4aefvboxsync RECT rect = {0, 0, src_surface->resource.width, src_surface->resource.height};
058c0c53c37f5cb271aeb3c385c10766f84f4aefvboxsync /* Blit the logo into the upper left corner of the drawable. */
058c0c53c37f5cb271aeb3c385c10766f84f4aefvboxsync wined3d_surface_blt(back_buffer, &rect, src_surface, &rect, WINEDDBLT_KEYSRC,
058c0c53c37f5cb271aeb3c385c10766f84f4aefvboxsync TRACE("Presenting HDC %p.\n", context->swapchain->hDC);
058c0c53c37f5cb271aeb3c385c10766f84f4aefvboxsync if (!render_to_fbo && (src_rect.left || src_rect.top
058c0c53c37f5cb271aeb3c385c10766f84f4aefvboxsync || src_rect.right != swapchain->desc.backbuffer_width
058c0c53c37f5cb271aeb3c385c10766f84f4aefvboxsync || src_rect.bottom != swapchain->desc.backbuffer_height))
058c0c53c37f5cb271aeb3c385c10766f84f4aefvboxsync src_rect.bottom = swapchain->desc.backbuffer_height;
058c0c53c37f5cb271aeb3c385c10766f84f4aefvboxsync if (!render_to_fbo && (dst_rect.left || dst_rect.top
058c0c53c37f5cb271aeb3c385c10766f84f4aefvboxsync || dst_rect.right != swapchain->desc.backbuffer_width
058c0c53c37f5cb271aeb3c385c10766f84f4aefvboxsync || dst_rect.bottom != swapchain->desc.backbuffer_height))
058c0c53c37f5cb271aeb3c385c10766f84f4aefvboxsync /* Rendering to a window of different size, presenting partial rectangles,
058c0c53c37f5cb271aeb3c385c10766f84f4aefvboxsync * or rendering to a different window needs help from FBO_blit or a textured
058c0c53c37f5cb271aeb3c385c10766f84f4aefvboxsync * draw. Render the swapchain to a FBO in the future.
058c0c53c37f5cb271aeb3c385c10766f84f4aefvboxsync * Note that FBO_blit from the backbuffer to the frontbuffer cannot solve
058c0c53c37f5cb271aeb3c385c10766f84f4aefvboxsync * all these issues - this fails if the window is smaller than the backbuffer.
058c0c53c37f5cb271aeb3c385c10766f84f4aefvboxsync if (!swapchain->render_to_fbo && render_to_fbo && wined3d_settings.offscreen_rendering_mode == ORM_FBO)
058c0c53c37f5cb271aeb3c385c10766f84f4aefvboxsync surface_load_location(back_buffer, SFLAG_INTEXTURE, NULL);
058c0c53c37f5cb271aeb3c385c10766f84f4aefvboxsync surface_modify_location(back_buffer, SFLAG_INDRAWABLE, FALSE);
058c0c53c37f5cb271aeb3c385c10766f84f4aefvboxsync surface_load_location(back_buffer, back_buffer->draw_binding, NULL);
058c0c53c37f5cb271aeb3c385c10766f84f4aefvboxsync /* This codepath should only be hit with the COPY swapeffect. Otherwise a backbuffer-
058c0c53c37f5cb271aeb3c385c10766f84f4aefvboxsync * window size mismatch is impossible(fullscreen) and src and dst rectangles are
058c0c53c37f5cb271aeb3c385c10766f84f4aefvboxsync * not allowed(they need the COPY swapeffect)
058c0c53c37f5cb271aeb3c385c10766f84f4aefvboxsync * The DISCARD swap effect is ok as well since any backbuffer content is allowed after
058c0c53c37f5cb271aeb3c385c10766f84f4aefvboxsync * the swap. */
058c0c53c37f5cb271aeb3c385c10766f84f4aefvboxsync if (swapchain->desc.swap_effect == WINED3D_SWAP_EFFECT_FLIP)
058c0c53c37f5cb271aeb3c385c10766f84f4aefvboxsync FIXME("Render-to-fbo with WINED3D_SWAP_EFFECT_FLIP\n");
058c0c53c37f5cb271aeb3c385c10766f84f4aefvboxsync swapchain_blit(swapchain, context, &src_rect, &dst_rect);
058c0c53c37f5cb271aeb3c385c10766f84f4aefvboxsync /* call wglSwapBuffers through the gl table to avoid confusing the Steam overlay */
058c0c53c37f5cb271aeb3c385c10766f84f4aefvboxsync gl_info->gl_ops.wgl.p_wglSwapBuffers(context->swapchain->hDC); /* TODO: cycle through the swapchain buffers */
058c0c53c37f5cb271aeb3c385c10766f84f4aefvboxsync /* call wglSwapBuffers through the gl table to avoid confusing the Steam overlay */
058c0c53c37f5cb271aeb3c385c10766f84f4aefvboxsync gl_info->gl_ops.wgl.p_wglSwapBuffers(context->hdc); /* TODO: cycle through the swapchain buffers */
058c0c53c37f5cb271aeb3c385c10766f84f4aefvboxsync /* FPS support */
058c0c53c37f5cb271aeb3c385c10766f84f4aefvboxsync /* every 1.5 seconds */
058c0c53c37f5cb271aeb3c385c10766f84f4aefvboxsync swapchain, 1000.0 * swapchain->frames / (time - swapchain->prev_time));
058c0c53c37f5cb271aeb3c385c10766f84f4aefvboxsync /* This is disabled, but the code left in for debug purposes.
058c0c53c37f5cb271aeb3c385c10766f84f4aefvboxsync * Since we're allowed to modify the new back buffer on a D3DSWAPEFFECT_DISCARD flip,
058c0c53c37f5cb271aeb3c385c10766f84f4aefvboxsync * we can clear it with some ugly color to make bad drawing visible and ease debugging.
058c0c53c37f5cb271aeb3c385c10766f84f4aefvboxsync * The Debug runtime does the same on Windows. However, a few games do not redraw the
058c0c53c37f5cb271aeb3c385c10766f84f4aefvboxsync * screen properly, like Max Payne 2, which leaves a few pixels undefined.
058c0c53c37f5cb271aeb3c385c10766f84f4aefvboxsync * Tests show that the content of the back buffer after a discard flip is indeed not
058c0c53c37f5cb271aeb3c385c10766f84f4aefvboxsync * reliable, so no game can depend on the exact content. However, it resembles the
058c0c53c37f5cb271aeb3c385c10766f84f4aefvboxsync * old contents in some way, for example by showing fragments at other locations. In
058c0c53c37f5cb271aeb3c385c10766f84f4aefvboxsync * general, the color theme is still intact. So Max payne, which draws rather dark scenes
058c0c53c37f5cb271aeb3c385c10766f84f4aefvboxsync * gets a dark background image. If we clear it with a bright ugly color, the game's
058c0c53c37f5cb271aeb3c385c10766f84f4aefvboxsync * bug shows up much more than it does on Windows, and the players see single pixels
058c0c53c37f5cb271aeb3c385c10766f84f4aefvboxsync * with wrong colors.
058c0c53c37f5cb271aeb3c385c10766f84f4aefvboxsync * (The Max Payne bug has been confirmed on Windows with the debug runtime) */
058c0c53c37f5cb271aeb3c385c10766f84f4aefvboxsync if (FALSE && swapchain->desc.swap_effect == WINED3D_SWAP_EFFECT_DISCARD)
058c0c53c37f5cb271aeb3c385c10766f84f4aefvboxsync static const struct wined3d_color cyan = {0.0f, 1.0f, 1.0f, 1.0f};
058c0c53c37f5cb271aeb3c385c10766f84f4aefvboxsync TRACE("Clearing the color buffer with cyan color\n");
058c0c53c37f5cb271aeb3c385c10766f84f4aefvboxsync if (!swapchain->render_to_fbo && ((swapchain->front_buffer->flags & SFLAG_INSYSMEM)
058c0c53c37f5cb271aeb3c385c10766f84f4aefvboxsync /* Both memory copies of the surfaces are ok, flip them around too instead of dirtifying
058c0c53c37f5cb271aeb3c385c10766f84f4aefvboxsync * Doesn't work with render_to_fbo because we're not flipping
058c0c53c37f5cb271aeb3c385c10766f84f4aefvboxsync struct wined3d_surface *front = swapchain->front_buffer;
058c0c53c37f5cb271aeb3c385c10766f84f4aefvboxsync if (front->resource.size == back_buffer->resource.size)
058c0c53c37f5cb271aeb3c385c10766f84f4aefvboxsync /* Tell the front buffer surface that is has been modified. However,
058c0c53c37f5cb271aeb3c385c10766f84f4aefvboxsync * the other locations were preserved during that, so keep the flags.
058c0c53c37f5cb271aeb3c385c10766f84f4aefvboxsync * This serves to update the emulated overlay, if any. */
058c0c53c37f5cb271aeb3c385c10766f84f4aefvboxsync surface_modify_location(front, SFLAG_INDRAWABLE, TRUE);
058c0c53c37f5cb271aeb3c385c10766f84f4aefvboxsync surface_modify_location(front, SFLAG_INDRAWABLE, TRUE);
058c0c53c37f5cb271aeb3c385c10766f84f4aefvboxsync surface_modify_location(back_buffer, SFLAG_INDRAWABLE, TRUE);
058c0c53c37f5cb271aeb3c385c10766f84f4aefvboxsync surface_modify_location(swapchain->front_buffer, SFLAG_INDRAWABLE, TRUE);
058c0c53c37f5cb271aeb3c385c10766f84f4aefvboxsync /* If the swapeffect is DISCARD, the back buffer is undefined. That means the SYSMEM
058c0c53c37f5cb271aeb3c385c10766f84f4aefvboxsync * and INTEXTURE copies can keep their old content if they have any defined content.
058c0c53c37f5cb271aeb3c385c10766f84f4aefvboxsync * If the swapeffect is COPY, the content remains the same. If it is FLIP however,
058c0c53c37f5cb271aeb3c385c10766f84f4aefvboxsync * the texture / sysmem copy needs to be reloaded from the drawable
058c0c53c37f5cb271aeb3c385c10766f84f4aefvboxsync if (swapchain->desc.swap_effect == WINED3D_SWAP_EFFECT_FLIP)
058c0c53c37f5cb271aeb3c385c10766f84f4aefvboxsync surface_modify_location(back_buffer, back_buffer->draw_binding, TRUE);
058c0c53c37f5cb271aeb3c385c10766f84f4aefvboxsync if (swapchain->desc.flags & WINED3DPRESENTFLAG_DISCARD_DEPTHSTENCIL
058c0c53c37f5cb271aeb3c385c10766f84f4aefvboxsync surface_modify_ds_location(fb->depth_stencil, SFLAG_DISCARDED,
058c0c53c37f5cb271aeb3c385c10766f84f4aefvboxsync if (fb->depth_stencil == swapchain->device->onscreen_depth_stencil)
058c0c53c37f5cb271aeb3c385c10766f84f4aefvboxsync wined3d_surface_decref(swapchain->device->onscreen_depth_stencil);
058c0c53c37f5cb271aeb3c385c10766f84f4aefvboxsyncstatic const struct wined3d_swapchain_ops swapchain_gl_ops =
058c0c53c37f5cb271aeb3c385c10766f84f4aefvboxsync/* Helper function that blits the front buffer contents to the target window. */
058c0c53c37f5cb271aeb3c385c10766f84f4aefvboxsyncvoid x11_copy_to_screen(const struct wined3d_swapchain *swapchain, const RECT *rect)
058c0c53c37f5cb271aeb3c385c10766f84f4aefvboxsync TRACE("swapchain %p, rect %s.\n", swapchain, wine_dbgstr_rect(rect));
058c0c53c37f5cb271aeb3c385c10766f84f4aefvboxsync if (!(front->resource.usage & WINED3DUSAGE_RENDERTARGET))
058c0c53c37f5cb271aeb3c385c10766f84f4aefvboxsync dst_dc = GetDCEx(window, 0, DCX_CLIPSIBLINGS | DCX_CACHE);
058c0c53c37f5cb271aeb3c385c10766f84f4aefvboxsync /* Front buffer coordinates are screen coordinates. Map them to the
058c0c53c37f5cb271aeb3c385c10766f84f4aefvboxsync * destination window if not fullscreened. */
058c0c53c37f5cb271aeb3c385c10766f84f4aefvboxsync BitBlt(dst_dc, draw_rect.left - offset.x, draw_rect.top - offset.y,
058c0c53c37f5cb271aeb3c385c10766f84f4aefvboxsync draw_rect.right - draw_rect.left, draw_rect.bottom - draw_rect.top,
058c0c53c37f5cb271aeb3c385c10766f84f4aefvboxsyncstatic void swapchain_gdi_present(struct wined3d_swapchain *swapchain, const RECT *src_rect_in,
058c0c53c37f5cb271aeb3c385c10766f84f4aefvboxsync const RECT *dst_rect_in, const RGNDATA *dirty_region, DWORD flags)
058c0c53c37f5cb271aeb3c385c10766f84f4aefvboxsync /* Flip the DC. */
058c0c53c37f5cb271aeb3c385c10766f84f4aefvboxsync /* Flip the DIBsection. */
058c0c53c37f5cb271aeb3c385c10766f84f4aefvboxsync /* Flip the surface data. */
058c0c53c37f5cb271aeb3c385c10766f84f4aefvboxsync front->resource.allocatedMemory = back->resource.allocatedMemory;
058c0c53c37f5cb271aeb3c385c10766f84f4aefvboxsync ERR("GDI Surface %p has heap memory allocated.\n", front);
058c0c53c37f5cb271aeb3c385c10766f84f4aefvboxsync ERR("GDI Surface %p has heap memory allocated.\n", back);
058c0c53c37f5cb271aeb3c385c10766f84f4aefvboxsync /* FPS support */
058c0c53c37f5cb271aeb3c385c10766f84f4aefvboxsync /* every 1.5 seconds */
058c0c53c37f5cb271aeb3c385c10766f84f4aefvboxsync TRACE_(fps)("@ approx %.2ffps\n", 1000.0 * frames / (time - prev_time));
058c0c53c37f5cb271aeb3c385c10766f84f4aefvboxsyncstatic const struct wined3d_swapchain_ops swapchain_gdi_ops =
058c0c53c37f5cb271aeb3c385c10766f84f4aefvboxsyncvoid swapchain_update_render_to_fbo(struct wined3d_swapchain *swapchain)
058c0c53c37f5cb271aeb3c385c10766f84f4aefvboxsync if (wined3d_settings.offscreen_rendering_mode != ORM_FBO)
058c0c53c37f5cb271aeb3c385c10766f84f4aefvboxsync GetClientRect(swapchain->win_handle, &client_rect);
058c0c53c37f5cb271aeb3c385c10766f84f4aefvboxsync if (!wined3d_settings.always_offscreen && !swapchain->desc.multisample_type
058c0c53c37f5cb271aeb3c385c10766f84f4aefvboxsync && swapchain->desc.backbuffer_width == client_rect.right
058c0c53c37f5cb271aeb3c385c10766f84f4aefvboxsync && swapchain->desc.backbuffer_height == client_rect.bottom)
058c0c53c37f5cb271aeb3c385c10766f84f4aefvboxsync TRACE("Backbuffer dimensions match window dimensions, rendering onscreen.\n");
058c0c53c37f5cb271aeb3c385c10766f84f4aefvboxsync/* Do not call while under the GL lock. */
058c0c53c37f5cb271aeb3c385c10766f84f4aefvboxsyncstatic HRESULT swapchain_init(struct wined3d_swapchain *swapchain, struct wined3d_device *device,
058c0c53c37f5cb271aeb3c385c10766f84f4aefvboxsync struct wined3d_swapchain_desc *desc, void *parent, const struct wined3d_parent_ops *parent_ops)
058c0c53c37f5cb271aeb3c385c10766f84f4aefvboxsync const struct wined3d_adapter *adapter = device->adapter;
058c0c53c37f5cb271aeb3c385c10766f84f4aefvboxsync struct wined3d_swapchain *overriden_swapchain = NULL;
058c0c53c37f5cb271aeb3c385c10766f84f4aefvboxsync if (desc->backbuffer_count > WINED3DPRESENT_BACK_BUFFER_MAX)
058c0c53c37f5cb271aeb3c385c10766f84f4aefvboxsync FIXME("The application requested %u back buffers, this is not supported.\n",
058c0c53c37f5cb271aeb3c385c10766f84f4aefvboxsync FIXME("The application requested more than one back buffer, this is not properly supported.\n"
058c0c53c37f5cb271aeb3c385c10766f84f4aefvboxsync "Please configure the application to use double buffering (1 back buffer) if possible.\n");
058c0c53c37f5cb271aeb3c385c10766f84f4aefvboxsync window = desc->device_window ? desc->device_window : device->create_parms.focus_window;
058c0c53c37f5cb271aeb3c385c10766f84f4aefvboxsync overriden_swapchain = swapchain_find(device, desc->device_window);
058c0c53c37f5cb271aeb3c385c10766f84f4aefvboxsync hr = VBoxExtWndCreate(desc->backbuffer_width, desc->backbuffer_height, &window, &hDC);
76f3927069cc452e77bf72f32d9175c0256ed3b3vboxsync if (FAILED(hr = wined3d_get_adapter_display_mode(device->wined3d,
76f3927069cc452e77bf72f32d9175c0256ed3b3vboxsync adapter->ordinal, &swapchain->original_mode, NULL)))
76f3927069cc452e77bf72f32d9175c0256ed3b3vboxsync ERR("Failed to get current display mode, hr %#x.\n", hr);
058c0c53c37f5cb271aeb3c385c10766f84f4aefvboxsync && (!desc->backbuffer_width || !desc->backbuffer_height
058c0c53c37f5cb271aeb3c385c10766f84f4aefvboxsync TRACE("Updating width to %u.\n", desc->backbuffer_width);
058c0c53c37f5cb271aeb3c385c10766f84f4aefvboxsync TRACE("Updating height to %u.\n", desc->backbuffer_height);
76f3927069cc452e77bf72f32d9175c0256ed3b3vboxsync desc->backbuffer_format = swapchain->original_mode.format_id;
76f3927069cc452e77bf72f32d9175c0256ed3b3vboxsync TRACE("Updating format to %s.\n", debug_d3dformat(swapchain->original_mode.format_id));
058c0c53c37f5cb271aeb3c385c10766f84f4aefvboxsync surface_desc.resource_type = WINED3D_RTYPE_SURFACE;
058c0c53c37f5cb271aeb3c385c10766f84f4aefvboxsync surface_desc.format = swapchain->desc.backbuffer_format;
058c0c53c37f5cb271aeb3c385c10766f84f4aefvboxsync surface_desc.multisample_type = swapchain->desc.multisample_type;
058c0c53c37f5cb271aeb3c385c10766f84f4aefvboxsync surface_desc.multisample_quality = swapchain->desc.multisample_quality;
058c0c53c37f5cb271aeb3c385c10766f84f4aefvboxsync surface_desc.width = swapchain->desc.backbuffer_width;
058c0c53c37f5cb271aeb3c385c10766f84f4aefvboxsync surface_desc.height = swapchain->desc.backbuffer_height;
058c0c53c37f5cb271aeb3c385c10766f84f4aefvboxsync if (FAILED(hr = device->device_parent->ops->create_swapchain_surface(device->device_parent,
058c0c53c37f5cb271aeb3c385c10766f84f4aefvboxsync WARN("Failed to create front buffer, hr %#x.\n", hr);
058c0c53c37f5cb271aeb3c385c10766f84f4aefvboxsync surface_set_swapchain(swapchain->front_buffer, swapchain);
058c0c53c37f5cb271aeb3c385c10766f84f4aefvboxsync surface_modify_location(swapchain->front_buffer, SFLAG_INDRAWABLE, TRUE);
058c0c53c37f5cb271aeb3c385c10766f84f4aefvboxsync /* MSDN says we're only allowed a single fullscreen swapchain per device,
058c0c53c37f5cb271aeb3c385c10766f84f4aefvboxsync * so we should really check to see if there is a fullscreen swapchain
058c0c53c37f5cb271aeb3c385c10766f84f4aefvboxsync * already. Does a single head count as full screen? */
058c0c53c37f5cb271aeb3c385c10766f84f4aefvboxsync /* Change the display settings */
058c0c53c37f5cb271aeb3c385c10766f84f4aefvboxsync mode.scanline_ordering = WINED3D_SCANLINE_ORDERING_UNKNOWN;
76f3927069cc452e77bf72f32d9175c0256ed3b3vboxsync if (FAILED(hr = wined3d_set_adapter_display_mode(device->wined3d, adapter->ordinal, &mode)))
76f3927069cc452e77bf72f32d9175c0256ed3b3vboxsync const struct wined3d_gl_info *gl_info = &adapter->gl_info;
058c0c53c37f5cb271aeb3c385c10766f84f4aefvboxsync swapchain->context = HeapAlloc(GetProcessHeap(), 0, sizeof(*swapchain->context));
058c0c53c37f5cb271aeb3c385c10766f84f4aefvboxsync /* In WGL both color, depth and stencil are features of a pixel format. In case of D3D they are separate.
058c0c53c37f5cb271aeb3c385c10766f84f4aefvboxsync * You are able to add a depth + stencil surface at a later stage when you need it.
058c0c53c37f5cb271aeb3c385c10766f84f4aefvboxsync * In order to support this properly in WineD3D we need the ability to recreate the opengl context and
058c0c53c37f5cb271aeb3c385c10766f84f4aefvboxsync * drawable when this is required. This is very tricky as we need to reapply ALL opengl states for the new
058c0c53c37f5cb271aeb3c385c10766f84f4aefvboxsync * context, need torecreate shaders, textures and other resources.
058c0c53c37f5cb271aeb3c385c10766f84f4aefvboxsync * The context manager already takes care of the state problem and for the other tasks code from Reset
058c0c53c37f5cb271aeb3c385c10766f84f4aefvboxsync * can be used. These changes are way to risky during the 1.0 code freeze which is taking place right now.
058c0c53c37f5cb271aeb3c385c10766f84f4aefvboxsync * Likely a lot of other new bugs will be exposed. For that reason request a depth stencil surface all the
058c0c53c37f5cb271aeb3c385c10766f84f4aefvboxsync * time. It can cause a slight performance hit but fixes a lot of regressions. A fixme reminds of that this
058c0c53c37f5cb271aeb3c385c10766f84f4aefvboxsync * issue needs to be fixed. */
058c0c53c37f5cb271aeb3c385c10766f84f4aefvboxsync for (i = 0; i < (sizeof(formats) / sizeof(*formats)); i++)
058c0c53c37f5cb271aeb3c385c10766f84f4aefvboxsync swapchain->ds_format = wined3d_get_format(gl_info, formats[i]);
058c0c53c37f5cb271aeb3c385c10766f84f4aefvboxsync swapchain->context[0] = context_create(swapchain, swapchain->front_buffer, swapchain->ds_format);
058c0c53c37f5cb271aeb3c385c10766f84f4aefvboxsync TRACE("Depth stencil format %s is not supported, trying next format\n",
058c0c53c37f5cb271aeb3c385c10766f84f4aefvboxsync swapchain->ds_format = wined3d_get_format(&device->adapter->gl_info, WINED3DFMT_D24_UNORM_S8_UINT);
058c0c53c37f5cb271aeb3c385c10766f84f4aefvboxsync swapchain_context = context_find_create(device, swapchain, swapchain->ds_format);
058c0c53c37f5cb271aeb3c385c10766f84f4aefvboxsync if (wined3d_settings.offscreen_rendering_mode != ORM_FBO
058c0c53c37f5cb271aeb3c385c10766f84f4aefvboxsync || swapchain->desc.auto_depth_stencil_format != swapchain->ds_format->id))
058c0c53c37f5cb271aeb3c385c10766f84f4aefvboxsync FIXME("Add OpenGL context recreation support to context_validate_onscreen_formats\n");
058c0c53c37f5cb271aeb3c385c10766f84f4aefvboxsync swapchain->back_buffers = HeapAlloc(GetProcessHeap(), 0,
058c0c53c37f5cb271aeb3c385c10766f84f4aefvboxsync sizeof(*swapchain->back_buffers) * swapchain->desc.backbuffer_count);
058c0c53c37f5cb271aeb3c385c10766f84f4aefvboxsync ERR("Failed to allocate backbuffer array memory.\n");
058c0c53c37f5cb271aeb3c385c10766f84f4aefvboxsync for (i = 0; i < swapchain->desc.backbuffer_count; ++i)
058c0c53c37f5cb271aeb3c385c10766f84f4aefvboxsync if (FAILED(hr = device->device_parent->ops->create_swapchain_surface(device->device_parent,
058c0c53c37f5cb271aeb3c385c10766f84f4aefvboxsync parent, &surface_desc, &swapchain->back_buffers[i])))
058c0c53c37f5cb271aeb3c385c10766f84f4aefvboxsync WARN("Failed to create back buffer %u, hr %#x.\n", i, hr);
058c0c53c37f5cb271aeb3c385c10766f84f4aefvboxsync surface_set_swapchain(swapchain->back_buffers[i], swapchain);
058c0c53c37f5cb271aeb3c385c10766f84f4aefvboxsync /* Swapchains share the depth/stencil buffer, so only create a single depthstencil surface. */
058c0c53c37f5cb271aeb3c385c10766f84f4aefvboxsync if (desc->enable_auto_depth_stencil && !(device->wined3d->flags & WINED3D_NO3D))
058c0c53c37f5cb271aeb3c385c10766f84f4aefvboxsync surface_desc.format = swapchain->desc.auto_depth_stencil_format;
058c0c53c37f5cb271aeb3c385c10766f84f4aefvboxsync if (FAILED(hr = device->device_parent->ops->create_swapchain_surface(device->device_parent,
058c0c53c37f5cb271aeb3c385c10766f84f4aefvboxsync device->device_parent, &surface_desc, &device->auto_depth_stencil)))
058c0c53c37f5cb271aeb3c385c10766f84f4aefvboxsync WARN("Failed to create the auto depth stencil, hr %#x.\n", hr);
058c0c53c37f5cb271aeb3c385c10766f84f4aefvboxsync wined3d_swapchain_get_gamma_ramp(swapchain, &swapchain->orig_gamma);
76f3927069cc452e77bf72f32d9175c0256ed3b3vboxsync if (FAILED(wined3d_set_adapter_display_mode(device->wined3d,
058c0c53c37f5cb271aeb3c385c10766f84f4aefvboxsync for (i = 0; i < swapchain->desc.backbuffer_count; ++i)
058c0c53c37f5cb271aeb3c385c10766f84f4aefvboxsync surface_set_swapchain(swapchain->back_buffers[i], NULL);
058c0c53c37f5cb271aeb3c385c10766f84f4aefvboxsync wined3d_surface_decref(swapchain->back_buffers[i]);
058c0c53c37f5cb271aeb3c385c10766f84f4aefvboxsync HeapFree(GetProcessHeap(), 0, swapchain->back_buffers);
058c0c53c37f5cb271aeb3c385c10766f84f4aefvboxsync surface_set_swapchain(swapchain->front_buffer, NULL);
058c0c53c37f5cb271aeb3c385c10766f84f4aefvboxsync VBoxExtWndDestroy(swapchain->win_handle, swapchain->hDC);
058c0c53c37f5cb271aeb3c385c10766f84f4aefvboxsync/* Do not call while under the GL lock. */
058c0c53c37f5cb271aeb3c385c10766f84f4aefvboxsyncHRESULT CDECL wined3d_swapchain_create(struct wined3d_device *device, struct wined3d_swapchain_desc *desc,
058c0c53c37f5cb271aeb3c385c10766f84f4aefvboxsync void *parent, const struct wined3d_parent_ops *parent_ops, struct wined3d_swapchain **swapchain)
058c0c53c37f5cb271aeb3c385c10766f84f4aefvboxsync TRACE("device %p, desc %p, parent %p, parent_ops %p, swapchain %p.\n",
058c0c53c37f5cb271aeb3c385c10766f84f4aefvboxsync object = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(*object));
058c0c53c37f5cb271aeb3c385c10766f84f4aefvboxsync hr = swapchain_init(object, device, desc, parent, parent_ops);
058c0c53c37f5cb271aeb3c385c10766f84f4aefvboxsync WARN("Failed to initialize swapchain, hr %#x.\n", hr);
058c0c53c37f5cb271aeb3c385c10766f84f4aefvboxsync/* Do not call while under the GL lock. */
058c0c53c37f5cb271aeb3c385c10766f84f4aefvboxsyncstatic struct wined3d_context *swapchain_create_context(struct wined3d_swapchain *swapchain)
058c0c53c37f5cb271aeb3c385c10766f84f4aefvboxsync TRACE("Creating a new context for swapchain %p, thread %u.\n", swapchain, GetCurrentThreadId());
058c0c53c37f5cb271aeb3c385c10766f84f4aefvboxsync if (!(ctx = context_create(swapchain, swapchain->front_buffer, swapchain->ds_format)))
058c0c53c37f5cb271aeb3c385c10766f84f4aefvboxsync ERR("Failed to create a new context for the swapchain\n");
058c0c53c37f5cb271aeb3c385c10766f84f4aefvboxsync newArray = HeapAlloc(GetProcessHeap(), 0, sizeof(*newArray) * (swapchain->num_contexts + 1));
058c0c53c37f5cb271aeb3c385c10766f84f4aefvboxsync ERR("Out of memory when trying to allocate a new context array\n");
058c0c53c37f5cb271aeb3c385c10766f84f4aefvboxsync memcpy(newArray, swapchain->context, sizeof(*newArray) * swapchain->num_contexts);
058c0c53c37f5cb271aeb3c385c10766f84f4aefvboxsyncvoid swapchain_destroy_contexts(struct wined3d_swapchain *swapchain)
058c0c53c37f5cb271aeb3c385c10766f84f4aefvboxsync unsigned int i;
058c0c53c37f5cb271aeb3c385c10766f84f4aefvboxsync context_destroy(swapchain->device, swapchain->context[i]);
058c0c53c37f5cb271aeb3c385c10766f84f4aefvboxsyncstruct wined3d_context *swapchain_get_context(struct wined3d_swapchain *swapchain)
058c0c53c37f5cb271aeb3c385c10766f84f4aefvboxsync unsigned int i;
058c0c53c37f5cb271aeb3c385c10766f84f4aefvboxsync /* Create a new context for the thread */
058c0c53c37f5cb271aeb3c385c10766f84f4aefvboxsync#else /* if defined VBOX_WINE_WITH_SINGLE_CONTEXT */
058c0c53c37f5cb271aeb3c385c10766f84f4aefvboxsyncstruct wined3d_context *swapchain_get_context(struct wined3d_swapchain *swapchain)
058c0c53c37f5cb271aeb3c385c10766f84f4aefvboxsync struct wined3d_context * context = swapchain->device->contexts[0];
058c0c53c37f5cb271aeb3c385c10766f84f4aefvboxsyncvoid get_drawable_size_swapchain(const struct wined3d_context *context, UINT *width, UINT *height)
058c0c53c37f5cb271aeb3c385c10766f84f4aefvboxsync /* The drawable size of an onscreen drawable is the surface size.
058c0c53c37f5cb271aeb3c385c10766f84f4aefvboxsync * (Actually: The window size, but the surface is created in window size) */
058c0c53c37f5cb271aeb3c385c10766f84f4aefvboxsyncHDC swapchain_get_backup_dc(struct wined3d_swapchain *swapchain)
058c0c53c37f5cb271aeb3c385c10766f84f4aefvboxsync TRACE("Creating the backup window for swapchain %p.\n", swapchain);
058c0c53c37f5cb271aeb3c385c10766f84f4aefvboxsync if (!(swapchain->backup_wnd = CreateWindowA(WINED3D_OPENGL_WINDOW_CLASS_NAME, "WineD3D fake window",
058c0c53c37f5cb271aeb3c385c10766f84f4aefvboxsync WS_OVERLAPPEDWINDOW, 10, 10, 10, 10, NULL, NULL, NULL, NULL)))
058c0c53c37f5cb271aeb3c385c10766f84f4aefvboxsync if (!(swapchain->backup_dc = GetDC(swapchain->backup_wnd)))
058c0c53c37f5cb271aeb3c385c10766f84f4aefvboxsyncvoid swapchain_update_draw_bindings(struct wined3d_swapchain *swapchain)
058c0c53c37f5cb271aeb3c385c10766f84f4aefvboxsync surface_update_draw_binding(swapchain->front_buffer);
058c0c53c37f5cb271aeb3c385c10766f84f4aefvboxsync for (i = 0; i < swapchain->desc.backbuffer_count; ++i)
058c0c53c37f5cb271aeb3c385c10766f84f4aefvboxsync surface_update_draw_binding(swapchain->back_buffers[i]);
058c0c53c37f5cb271aeb3c385c10766f84f4aefvboxsyncHRESULT CDECL wined3d_swapchain_present_rt(struct wined3d_swapchain *swapchain, struct wined3d_surface *rt)
058c0c53c37f5cb271aeb3c385c10766f84f4aefvboxsync struct wined3d_surface *bb = swapchain->back_buffers[0];
058c0c53c37f5cb271aeb3c385c10766f84f4aefvboxsync HRESULT hr = wined3d_surface_blt(bb, NULL, rt, NULL, 0, NULL, 0);
058c0c53c37f5cb271aeb3c385c10766f84f4aefvboxsync hr = wined3d_swapchain_present(swapchain, NULL, NULL, NULL, NULL, 0);
058c0c53c37f5cb271aeb3c385c10766f84f4aefvboxsync ERR("wined3d_swapchain_present failed with hr(%d)", hr);
ea1cc8df95dba6fca9c36c94f565ef95c7802a36vboxsyncHRESULT CDECL wined3d_swapchain_get_host_win_id(struct wined3d_swapchain *swapchain, int32_t *pi32Id)
7b6926b2bf44f326f40e1d9d1ce33a4dff0a2c67vboxsync ERR("failed to get id for hdc 0x%x", swapchain->hDC);