ddraw: Use BitBlt() for exclusive mode frontbuffer updates if the swapchain window is not in the foreground.
Signed-off-by: Henri Verbeet <hverbeet@codeweavers.com> Signed-off-by: Alexandre Julliard <julliard@winehq.org>
This commit is contained in:
parent
92dacb1d68
commit
4ce1d7f93a
|
@ -39,6 +39,16 @@ static BOOL ddraw_surface_is_lost(const struct ddraw_surface *surface)
|
||||||
&& (surface->ddraw->device_state != DDRAW_DEVICE_STATE_OK || surface->is_lost);
|
&& (surface->ddraw->device_state != DDRAW_DEVICE_STATE_OK || surface->is_lost);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static BOOL ddraw_gdi_is_front(struct ddraw *ddraw)
|
||||||
|
{
|
||||||
|
struct ddraw_surface *surface;
|
||||||
|
|
||||||
|
if (!ddraw->gdi_surface || !(surface = wined3d_texture_get_sub_resource_parent(ddraw->gdi_surface, 0)))
|
||||||
|
return FALSE;
|
||||||
|
|
||||||
|
return surface->surface_desc.ddsCaps.dwCaps & DDSCAPS_FRONTBUFFER;
|
||||||
|
}
|
||||||
|
|
||||||
/* This is slow, of course. Also, in case of locks, we can't prevent other
|
/* This is slow, of course. Also, in case of locks, we can't prevent other
|
||||||
* applications from drawing to the screen while we've locked the frontbuffer.
|
* applications from drawing to the screen while we've locked the frontbuffer.
|
||||||
* We'd like to do this in wined3d instead, but for that to work wined3d needs
|
* We'd like to do this in wined3d instead, but for that to work wined3d needs
|
||||||
|
@ -46,6 +56,7 @@ static BOOL ddraw_surface_is_lost(const struct ddraw_surface *surface)
|
||||||
HRESULT ddraw_surface_update_frontbuffer(struct ddraw_surface *surface,
|
HRESULT ddraw_surface_update_frontbuffer(struct ddraw_surface *surface,
|
||||||
const RECT *rect, BOOL read, unsigned int swap_interval)
|
const RECT *rect, BOOL read, unsigned int swap_interval)
|
||||||
{
|
{
|
||||||
|
struct ddraw *ddraw = surface->ddraw;
|
||||||
struct wined3d_texture *dst_texture;
|
struct wined3d_texture *dst_texture;
|
||||||
HDC surface_dc, screen_dc;
|
HDC surface_dc, screen_dc;
|
||||||
int x, y, w, h;
|
int x, y, w, h;
|
||||||
|
@ -53,9 +64,9 @@ HRESULT ddraw_surface_update_frontbuffer(struct ddraw_surface *surface,
|
||||||
BOOL ret;
|
BOOL ret;
|
||||||
RECT r;
|
RECT r;
|
||||||
|
|
||||||
if (surface->ddraw->flags & DDRAW_SWAPPED && !read)
|
if (ddraw->flags & DDRAW_SWAPPED && !read)
|
||||||
{
|
{
|
||||||
surface->ddraw->flags &= ~DDRAW_SWAPPED;
|
ddraw->flags &= ~DDRAW_SWAPPED;
|
||||||
rect = NULL;
|
rect = NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -73,7 +84,23 @@ HRESULT ddraw_surface_update_frontbuffer(struct ddraw_surface *surface,
|
||||||
if (w <= 0 || h <= 0)
|
if (w <= 0 || h <= 0)
|
||||||
return DD_OK;
|
return DD_OK;
|
||||||
|
|
||||||
if (surface->ddraw->swapchain_window)
|
/* The interaction between ddraw and GDI drawing is not all that well
|
||||||
|
* documented, and somewhat arcane. In ddraw exclusive mode, GDI draws
|
||||||
|
* seemingly go to the *original* frontbuffer/primary surface, while ddraw
|
||||||
|
* draws/flips go to the *current* frontbuffer surface. The bottom line is
|
||||||
|
* that if the current frontbuffer is not the GDI frontbuffer, and there's
|
||||||
|
* e.g. a popup window in front of the ddraw swapchain window, we can't
|
||||||
|
* use wined3d_swapchain_present() to get the ddraw contents to the screen
|
||||||
|
* while in exclusive mode, since it would get obscured by the popup
|
||||||
|
* window. On the other hand, if the current frontbuffer *is* the GDI
|
||||||
|
* frontbuffer, that's what's supposed to happen; the popup should obscure
|
||||||
|
* (oart of) the ddraw swapchain window.
|
||||||
|
*
|
||||||
|
* This affects the "Deer Hunter" demo, which uses a popup window and GDI
|
||||||
|
* draws to draw part of the user interface. See also the "fswindow"
|
||||||
|
* sample is the DirectX 7 SDK. */
|
||||||
|
if (ddraw->swapchain_window && (!(ddraw->cooperative_level & DDSCL_EXCLUSIVE)
|
||||||
|
|| ddraw->swapchain_window == GetForegroundWindow() || ddraw_gdi_is_front(ddraw)))
|
||||||
{
|
{
|
||||||
/* Nothing to do, we control the frontbuffer, or at least the parts we
|
/* Nothing to do, we control the frontbuffer, or at least the parts we
|
||||||
* care about. */
|
* care about. */
|
||||||
|
@ -81,15 +108,15 @@ HRESULT ddraw_surface_update_frontbuffer(struct ddraw_surface *surface,
|
||||||
return DD_OK;
|
return DD_OK;
|
||||||
|
|
||||||
if (swap_interval)
|
if (swap_interval)
|
||||||
dst_texture = wined3d_swapchain_get_back_buffer(surface->ddraw->wined3d_swapchain, 0);
|
dst_texture = wined3d_swapchain_get_back_buffer(ddraw->wined3d_swapchain, 0);
|
||||||
else
|
else
|
||||||
dst_texture = surface->ddraw->wined3d_frontbuffer;
|
dst_texture = ddraw->wined3d_frontbuffer;
|
||||||
|
|
||||||
if (SUCCEEDED(hr = wined3d_texture_blt(dst_texture, 0, rect, surface->wined3d_texture,
|
if (SUCCEEDED(hr = wined3d_texture_blt(dst_texture, 0, rect, surface->wined3d_texture,
|
||||||
surface->sub_resource_idx, rect, 0, NULL, WINED3D_TEXF_POINT)) && swap_interval)
|
surface->sub_resource_idx, rect, 0, NULL, WINED3D_TEXF_POINT)) && swap_interval)
|
||||||
{
|
{
|
||||||
hr = wined3d_swapchain_present(surface->ddraw->wined3d_swapchain, rect, rect, NULL, swap_interval, 0);
|
hr = wined3d_swapchain_present(ddraw->wined3d_swapchain, rect, rect, NULL, swap_interval, 0);
|
||||||
surface->ddraw->flags |= DDRAW_SWAPPED;
|
ddraw->flags |= DDRAW_SWAPPED;
|
||||||
}
|
}
|
||||||
return hr;
|
return hr;
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue