mirror of
https://github.com/hajimehoshi/ebiten.git
synced 2024-12-24 18:58:54 +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
|
type _DXGI_PRESENT uint32
|
||||||
|
|
||||||
const (
|
const (
|
||||||
|
_DXGI_PRESENT_TEST _DXGI_PRESENT = 0x00000001
|
||||||
_DXGI_PRESENT_ALLOW_TEARING _DXGI_PRESENT = 0x00000200
|
_DXGI_PRESENT_ALLOW_TEARING _DXGI_PRESENT = 0x00000200
|
||||||
)
|
)
|
||||||
|
|
||||||
@ -2684,16 +2685,16 @@ func (i *_IDXGISwapChain4) GetCurrentBackBufferIndex() uint32 {
|
|||||||
return uint32(r)
|
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))
|
r, _, _ := syscall.Syscall(i.vtbl.Present, 3, uintptr(unsafe.Pointer(i)), uintptr(syncInterval), uintptr(flags))
|
||||||
if uint32(r) != uint32(windows.S_OK) {
|
if uint32(r) != uint32(windows.S_OK) {
|
||||||
// During a screen lock, Present fails (#2179).
|
// During a screen lock, Present fails (#2179).
|
||||||
if uint32(r) == uint32(windows.DXGI_STATUS_OCCLUDED) {
|
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 {
|
func (i *_IDXGISwapChain4) ResizeBuffers(bufferCount uint32, width uint32, height uint32, newFormat _DXGI_FORMAT, swapChainFlags uint32) error {
|
||||||
|
@ -20,6 +20,7 @@ import (
|
|||||||
"os"
|
"os"
|
||||||
"reflect"
|
"reflect"
|
||||||
"strings"
|
"strings"
|
||||||
|
"time"
|
||||||
"unsafe"
|
"unsafe"
|
||||||
|
|
||||||
"golang.org/x/sys/windows"
|
"golang.org/x/sys/windows"
|
||||||
@ -150,6 +151,12 @@ type Graphics struct {
|
|||||||
vsyncEnabled bool
|
vsyncEnabled bool
|
||||||
transparent 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
|
pipelineStates
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -825,14 +832,32 @@ func (g *Graphics) presentDesktop() error {
|
|||||||
|
|
||||||
var syncInterval uint32
|
var syncInterval uint32
|
||||||
var flags _DXGI_PRESENT
|
var flags _DXGI_PRESENT
|
||||||
if g.vsyncEnabled {
|
if g.occluded {
|
||||||
syncInterval = 1
|
// The screen is not visible. Test whether we can resume.
|
||||||
} else if g.allowTearing {
|
flags |= _DXGI_PRESENT_TEST
|
||||||
flags |= _DXGI_PRESENT_ALLOW_TEARING
|
} 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
|
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
|
return nil
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user