mirror of
https://github.com/hajimehoshi/ebiten.git
synced 2024-12-24 10:48:53 +01:00
internal/graphicsdriver/directx: use DXGI_PRESENT_TEST when the screen is invisible
This change also reduces FPS to about 10 when the screen is invisible in order to save CPU power. Closes #2181
This commit is contained in:
parent
9bd46cb2b5
commit
bb2df24f83
@ -608,6 +608,7 @@ type _DXGI_MODE_SCALING int32
|
||||
type _DXGI_PRESENT uint32
|
||||
|
||||
const (
|
||||
_DXGI_PRESENT_TEST _DXGI_PRESENT = 0x00000001
|
||||
_DXGI_PRESENT_ALLOW_TEARING _DXGI_PRESENT = 0x00000200
|
||||
)
|
||||
|
||||
@ -2684,16 +2685,16 @@ func (i *_IDXGISwapChain4) GetCurrentBackBufferIndex() uint32 {
|
||||
return uint32(r)
|
||||
}
|
||||
|
||||
func (i *_IDXGISwapChain4) Present(syncInterval uint32, flags uint32) error {
|
||||
func (i *_IDXGISwapChain4) Present(syncInterval uint32, flags uint32) (occluded bool, err error) {
|
||||
r, _, _ := syscall.Syscall(i.vtbl.Present, 3, uintptr(unsafe.Pointer(i)), uintptr(syncInterval), uintptr(flags))
|
||||
if uint32(r) != uint32(windows.S_OK) {
|
||||
// During a screen lock, Present fails (#2179).
|
||||
if uint32(r) == uint32(windows.DXGI_STATUS_OCCLUDED) {
|
||||
return nil
|
||||
return true, nil
|
||||
}
|
||||
return fmt.Errorf("directx: IDXGISwapChain4::Present failed: HRESULT(%d)", uint32(r))
|
||||
return false, fmt.Errorf("directx: IDXGISwapChain4::Present failed: HRESULT(%d)", uint32(r))
|
||||
}
|
||||
return nil
|
||||
return false, nil
|
||||
}
|
||||
|
||||
func (i *_IDXGISwapChain4) ResizeBuffers(bufferCount uint32, width uint32, height uint32, newFormat _DXGI_FORMAT, swapChainFlags uint32) error {
|
||||
|
@ -20,6 +20,7 @@ import (
|
||||
"os"
|
||||
"reflect"
|
||||
"strings"
|
||||
"time"
|
||||
"unsafe"
|
||||
|
||||
"golang.org/x/sys/windows"
|
||||
@ -150,6 +151,12 @@ type Graphics struct {
|
||||
vsyncEnabled bool
|
||||
transparent bool
|
||||
|
||||
// occluded reports whether the screen is invisible or not.
|
||||
occluded bool
|
||||
|
||||
// lastTime is the last time for rendering.
|
||||
lastTime time.Time
|
||||
|
||||
pipelineStates
|
||||
}
|
||||
|
||||
@ -825,14 +832,32 @@ func (g *Graphics) presentDesktop() error {
|
||||
|
||||
var syncInterval uint32
|
||||
var flags _DXGI_PRESENT
|
||||
if g.vsyncEnabled {
|
||||
syncInterval = 1
|
||||
} else if g.allowTearing {
|
||||
flags |= _DXGI_PRESENT_ALLOW_TEARING
|
||||
if g.occluded {
|
||||
// The screen is not visible. Test whether we can resume.
|
||||
flags |= _DXGI_PRESENT_TEST
|
||||
} else {
|
||||
// Do actual rendering only when the screen is visible.
|
||||
if g.vsyncEnabled {
|
||||
syncInterval = 1
|
||||
} else if g.allowTearing {
|
||||
flags |= _DXGI_PRESENT_ALLOW_TEARING
|
||||
}
|
||||
}
|
||||
if err := g.swapChain.Present(syncInterval, uint32(flags)); err != nil {
|
||||
|
||||
occluded, err := g.swapChain.Present(syncInterval, uint32(flags))
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
g.occluded = occluded
|
||||
|
||||
// Reduce FPS when the screen is invisible.
|
||||
now := time.Now()
|
||||
if g.occluded {
|
||||
if delta := 100*time.Millisecond - now.Sub(g.lastTime); delta > 0 {
|
||||
time.Sleep(delta)
|
||||
}
|
||||
}
|
||||
g.lastTime = now
|
||||
|
||||
return nil
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user