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:

committed by
Axel Davy

parent
e59908e57f
commit
a961ec335d
@@ -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 *
|
||||
|
@@ -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
|
||||
{
|
||||
|
@@ -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;
|
||||
}
|
||||
|
||||
|
@@ -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 );
|
||||
|
@@ -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,
|
||||
|
@@ -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_ */
|
||||
|
@@ -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;
|
||||
}
|
||||
|
@@ -139,4 +139,7 @@ HRESULT WINAPI
|
||||
NineSwapChain9_GetPresentParameters( struct NineSwapChain9 *This,
|
||||
D3DPRESENT_PARAMETERS *pPresentationParameters );
|
||||
|
||||
BOOL
|
||||
NineSwapChain9_GetOccluded( struct NineSwapChain9 *This );
|
||||
|
||||
#endif /* _NINE_SWAPCHAIN9_H_ */
|
||||
|
Reference in New Issue
Block a user