st/nine: Handle Window Occlusion

Apps can know if the window is occluded by checking for
specific error messages. The behaviour is different
for Device9 and Device9Ex.

This allow games to release the mouse and stop rendering
until the focus is restored.

In case of multiple swapchain we do care only of the device one.

Signed-off-by: Patrick Rudolph <siro@das-labor.org>
Reviewed-by: Axel Davy <axel.davy@ens.fr>
This commit is contained in:
Patrick Rudolph
2015-06-20 20:06:11 +02:00
committed by Axel Davy
parent e59908e57f
commit a961ec335d
8 changed files with 108 additions and 6 deletions

View File

@@ -227,6 +227,7 @@ typedef struct _RGNDATA {
#define D3DERR_DRIVERINVALIDCALL MAKE_D3DHRESULT(2157)
#define D3DERR_DEVICEREMOVED MAKE_D3DHRESULT(2160)
#define D3DERR_DEVICEHUNG MAKE_D3DHRESULT(2164)
#define S_PRESENT_OCCLUDED MAKE_D3DSTATUS(2168)
/********************************************************
* Bitmasks *

View File

@@ -69,6 +69,8 @@ typedef struct ID3DPresentVtbl
HRESULT (WINAPI *SetCursor)(ID3DPresent *This, void *pBitmap, POINT *pHotspot, BOOL bShow);
HRESULT (WINAPI *SetGammaRamp)(ID3DPresent *This, const D3DGAMMARAMP *pRamp, HWND hWndOverride);
HRESULT (WINAPI *GetWindowInfo)(ID3DPresent *This, HWND hWnd, int *width, int *height, int *depth);
/* Available since version 1.1 */
BOOL (WINAPI *GetWindowOccluded)(ID3DPresent *This);
} ID3DPresentVtbl;
struct ID3DPresent
@@ -96,6 +98,7 @@ struct ID3DPresent
#define ID3DPresent_SetCursor(p,a,b,c) (p)->lpVtbl->SetCursor(p,a,b,c)
#define ID3DPresent_SetGammaRamp(p,a,b) (p)->lpVtbl->SetGammaRamp(p,a,b)
#define ID3DPresent_GetWindowInfo(p,a,b,c,d) (p)->lpVtbl->GetWindowSize(p,a,b,c,d)
#define ID3DPresent_GetWindowOccluded(p) (p)->lpVtbl->GetWindowOccluded(p)
typedef struct ID3DPresentGroupVtbl
{

View File

@@ -81,7 +81,7 @@ static void nine_setup_fpu(void)
#endif
static void
void
NineDevice9_SetDefaultState( struct NineDevice9 *This, boolean is_reset )
{
struct NineSurface9 *refSurf = NULL;
@@ -527,7 +527,14 @@ NineDevice9_ResumeRecording( struct NineDevice9 *This )
HRESULT WINAPI
NineDevice9_TestCooperativeLevel( struct NineDevice9 *This )
{
return D3D_OK; /* TODO */
if (NineSwapChain9_GetOccluded(This->swapchains[0])) {
This->device_needs_reset = TRUE;
return D3DERR_DEVICELOST;
} else if (This->device_needs_reset) {
return D3DERR_DEVICENOTRESET;
}
return D3D_OK;
}
UINT WINAPI
@@ -766,11 +773,16 @@ NineDevice9_Reset( struct NineDevice9 *This,
DBG("This=%p pPresentationParameters=%p\n", This, pPresentationParameters);
if (NineSwapChain9_GetOccluded(This->swapchains[0])) {
This->device_needs_reset = TRUE;
return D3DERR_DEVICELOST;
}
for (i = 0; i < This->nswapchains; ++i) {
D3DPRESENT_PARAMETERS *params = &pPresentationParameters[i];
hr = NineSwapChain9_Resize(This->swapchains[i], params, NULL);
if (hr != D3D_OK)
return hr;
break;
}
nine_pipe_context_clear(This);
@@ -781,6 +793,7 @@ NineDevice9_Reset( struct NineDevice9 *This,
This, 0, (IDirect3DSurface9 *)This->swapchains[0]->buffers[0]);
/* XXX: better use GetBackBuffer here ? */
This->device_needs_reset = (hr != D3D_OK);
return hr;
}

View File

@@ -137,6 +137,7 @@ struct NineDevice9
/* dummy vbo (containing 0 0 0 0) to bind if vertex shader input
* is not bound to anything by the vertex declaration */
struct pipe_resource *dummy_vbo;
BOOL device_needs_reset;
int minor_version_num;
};
static inline struct NineDevice9 *
@@ -176,6 +177,8 @@ void
NineDevice9_dtor( struct NineDevice9 *This );
/*** Nine private ***/
void
NineDevice9_SetDefaultState( struct NineDevice9 *This, boolean is_reset );
struct pipe_screen *
NineDevice9_GetScreen( struct NineDevice9 *This );

View File

@@ -20,7 +20,9 @@
* OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE
* USE OR OTHER DEALINGS IN THE SOFTWARE. */
#include "device9.h"
#include "device9ex.h"
#include "nine_pipe.h"
#include "swapchain9ex.h"
#include "nine_helpers.h"
@@ -159,6 +161,14 @@ NineDevice9Ex_CheckDeviceState( struct NineDevice9Ex *This,
DBG("This=%p hDestinationWindow=%p\n",
This, hDestinationWindow);
user_assert(!This->base.swapchains[0]->params.Windowed, D3D_OK);
if (This->base.params.hFocusWindow == hDestinationWindow) {
if (NineSwapChain9_GetOccluded(This->base.swapchains[0]))
return S_PRESENT_OCCLUDED;
} else if(!NineSwapChain9_GetOccluded(This->base.swapchains[0])) {
return S_PRESENT_OCCLUDED;
}
/* TODO: handle the other return values */
return D3D_OK;
}
@@ -222,12 +232,37 @@ NineDevice9Ex_ResetEx( struct NineDevice9Ex *This,
if (pFullscreenDisplayMode) mode = &(pFullscreenDisplayMode[i]);
hr = NineSwapChain9_Resize(This->base.swapchains[i], params, mode);
if (FAILED(hr))
return (hr == D3DERR_OUTOFVIDEOMEMORY) ? hr : D3DERR_DEVICELOST;
break;
}
NineDevice9_SetRenderTarget(
(struct NineDevice9 *)This, 0, (IDirect3DSurface9 *)This->base.swapchains[0]->buffers[0]);
return hr;
}
HRESULT WINAPI
NineDevice9Ex_Reset( struct NineDevice9Ex *This,
D3DPRESENT_PARAMETERS *pPresentationParameters )
{
HRESULT hr = D3D_OK;
unsigned i;
DBG("This=%p pPresentationParameters=%p\n", This, pPresentationParameters);
for (i = 0; i < This->base.nswapchains; ++i) {
D3DPRESENT_PARAMETERS *params = &pPresentationParameters[i];
hr = NineSwapChain9_Resize(This->base.swapchains[i], params, NULL);
if (FAILED(hr))
break;
}
nine_pipe_context_clear((struct NineDevice9 *)This);
nine_state_clear(&This->base.state, TRUE);
NineDevice9_SetDefaultState((struct NineDevice9 *)This, TRUE);
NineDevice9_SetRenderTarget(
(struct NineDevice9 *)This, 0, (IDirect3DSurface9 *)This->base.swapchains[0]->buffers[0]);
return hr;
}
@@ -249,11 +284,18 @@ NineDevice9Ex_GetDisplayModeEx( struct NineDevice9Ex *This,
return NineSwapChain9Ex_GetDisplayModeEx(swapchain, pMode, pRotation);
}
HRESULT WINAPI
NineDevice9Ex_TestCooperativeLevel( struct NineDevice9Ex *This )
{
return D3D_OK;
}
IDirect3DDevice9ExVtbl NineDevice9Ex_vtable = {
(void *)NineUnknown_QueryInterface,
(void *)NineUnknown_AddRef,
(void *)NineUnknown_Release,
(void *)NineDevice9_TestCooperativeLevel,
(void *)NineDevice9Ex_TestCooperativeLevel,
(void *)NineDevice9_GetAvailableTextureMem,
(void *)NineDevice9_EvictManagedResources,
(void *)NineDevice9_GetDirect3D,
@@ -266,7 +308,7 @@ IDirect3DDevice9ExVtbl NineDevice9Ex_vtable = {
(void *)NineDevice9_CreateAdditionalSwapChain,
(void *)NineDevice9_GetSwapChain,
(void *)NineDevice9_GetNumberOfSwapChains,
(void *)NineDevice9_Reset,
(void *)NineDevice9Ex_Reset,
(void *)NineDevice9_Present,
(void *)NineDevice9_GetBackBuffer,
(void *)NineDevice9_GetRasterStatus,

View File

@@ -73,6 +73,13 @@ NineDevice9Ex_PresentEx( struct NineDevice9Ex *This,
const RGNDATA *pDirtyRegion,
DWORD dwFlags );
HRESULT WINAPI
NineDevice9Ex_Present( struct NineDevice9Ex *This,
const RECT *pSourceRect,
const RECT *pDestRect,
HWND hDestWindowOverride,
const RGNDATA *pDirtyRegion );
HRESULT WINAPI
NineDevice9Ex_GetGPUThreadPriority( struct NineDevice9Ex *This,
INT *pPriority );
@@ -141,10 +148,17 @@ NineDevice9Ex_ResetEx( struct NineDevice9Ex *This,
D3DPRESENT_PARAMETERS *pPresentationParameters,
D3DDISPLAYMODEEX *pFullscreenDisplayMode );
HRESULT WINAPI
NineDevice9Ex_Reset( struct NineDevice9Ex *This,
D3DPRESENT_PARAMETERS *pPresentationParameters );
HRESULT WINAPI
NineDevice9Ex_GetDisplayModeEx( struct NineDevice9Ex *This,
UINT iSwapChain,
D3DDISPLAYMODEEX *pMode,
D3DDISPLAYROTATION *pRotation );
HRESULT WINAPI
NineDevice9Ex_TestCooperativeLevel( struct NineDevice9Ex *This );
#endif /* _NINE_DEVICE9EX_H_ */

View File

@@ -787,6 +787,19 @@ NineSwapChain9_Present( struct NineSwapChain9 *This,
if (hr == D3DERR_WASSTILLDRAWING)
return hr;
if (This->base.device->ex) {
if (NineSwapChain9_GetOccluded(This)) {
return S_PRESENT_OCCLUDED;
}
} else {
if (NineSwapChain9_GetOccluded(This)) {
This->base.device->device_needs_reset = TRUE;
}
if (This->base.device->device_needs_reset) {
return D3DERR_DEVICELOST;
}
}
switch (This->params.SwapEffect) {
case D3DSWAPEFFECT_FLIP:
UNTESTED(4);
@@ -992,3 +1005,13 @@ NineSwapChain9_new( struct NineDevice9 *pDevice,
implicit, pPresent, pPresentationParameters,
pCTX, hFocusWindow, NULL);
}
BOOL
NineSwapChain9_GetOccluded( struct NineSwapChain9 *This )
{
if (This->base.device->minor_version_num > 0) {
return ID3DPresent_GetWindowOccluded(This->present);
}
return FALSE;
}

View File

@@ -139,4 +139,7 @@ HRESULT WINAPI
NineSwapChain9_GetPresentParameters( struct NineSwapChain9 *This,
D3DPRESENT_PARAMETERS *pPresentationParameters );
BOOL
NineSwapChain9_GetOccluded( struct NineSwapChain9 *This );
#endif /* _NINE_SWAPCHAIN9_H_ */