mirror of
https://github.com/hajimehoshi/ebiten.git
synced 2024-12-24 18:58:54 +01:00
internal/graphicsdriver/directx: use non-flip swap effect for old Windows
Updates #2613 Updates #2619
This commit is contained in:
parent
0cd832f096
commit
d22158b156
@ -16,6 +16,7 @@ package directx
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
"fmt"
|
"fmt"
|
||||||
|
"runtime"
|
||||||
"unsafe"
|
"unsafe"
|
||||||
|
|
||||||
"golang.org/x/sys/windows"
|
"golang.org/x/sys/windows"
|
||||||
@ -23,6 +24,13 @@ import (
|
|||||||
|
|
||||||
const is64bit = unsafe.Sizeof(uintptr(0)) == 8
|
const is64bit = unsafe.Sizeof(uintptr(0)) == 8
|
||||||
|
|
||||||
|
const (
|
||||||
|
_VER_BUILDNUMBER = 0x00000004
|
||||||
|
_VER_GREATER_EQUAL = 3
|
||||||
|
_VER_MAJORVERSION = 0x00000002
|
||||||
|
_VER_MINORVERSION = 0x00000001
|
||||||
|
)
|
||||||
|
|
||||||
type handleError windows.Handle
|
type handleError windows.Handle
|
||||||
|
|
||||||
func (h handleError) Error() string {
|
func (h handleError) Error() string {
|
||||||
@ -40,13 +48,33 @@ func boolToUintptr(v bool) uintptr {
|
|||||||
return 0
|
return 0
|
||||||
}
|
}
|
||||||
|
|
||||||
|
type _OSVERSIONINFOEXW struct {
|
||||||
|
dwOSVersionInfoSize uint32
|
||||||
|
dwMajorVersion uint32
|
||||||
|
dwMinorVersion uint32
|
||||||
|
dwBuildNumber uint32
|
||||||
|
dwPlatformId uint32
|
||||||
|
szCSDVersion [128]uint16
|
||||||
|
wServicePackMajor uint16
|
||||||
|
wServicePackMinor uint16
|
||||||
|
wSuiteMask uint16
|
||||||
|
wProductType byte
|
||||||
|
wReserved byte
|
||||||
|
}
|
||||||
|
|
||||||
type _PAPPSTATE_CHANGE_ROUTINE func(quiesced bool, context unsafe.Pointer) uintptr
|
type _PAPPSTATE_CHANGE_ROUTINE func(quiesced bool, context unsafe.Pointer) uintptr
|
||||||
|
|
||||||
var (
|
var (
|
||||||
// https://github.com/MicrosoftDocs/sdk-api/blob/docs/sdk-api-src/content/appnotify/nf-appnotify-registerappstatechangenotification.md
|
// https://github.com/MicrosoftDocs/sdk-api/blob/docs/sdk-api-src/content/appnotify/nf-appnotify-registerappstatechangenotification.md
|
||||||
appnotify = windows.NewLazySystemDLL("API-MS-Win-Core-psm-appnotify-l1-1-0.dll")
|
appnotify = windows.NewLazySystemDLL("API-MS-Win-Core-psm-appnotify-l1-1-0.dll")
|
||||||
|
kernel32 = windows.NewLazySystemDLL("kernel32.dll")
|
||||||
|
ntdll = windows.NewLazySystemDLL("ntdll.dll")
|
||||||
|
|
||||||
procRegisterAppStateChangeNotification = appnotify.NewProc("RegisterAppStateChangeNotification")
|
procRegisterAppStateChangeNotification = appnotify.NewProc("RegisterAppStateChangeNotification")
|
||||||
|
|
||||||
|
procVerSetConditionMask = kernel32.NewProc("VerSetConditionMask")
|
||||||
|
|
||||||
|
procRtlVerifyVersionInfo = ntdll.NewProc("RtlVerifyVersionInfo")
|
||||||
)
|
)
|
||||||
|
|
||||||
func _RegisterAppStateChangeNotification(routine _PAPPSTATE_CHANGE_ROUTINE, context unsafe.Pointer) (unsafe.Pointer, error) {
|
func _RegisterAppStateChangeNotification(routine _PAPPSTATE_CHANGE_ROUTINE, context unsafe.Pointer) (unsafe.Pointer, error) {
|
||||||
@ -58,3 +86,45 @@ func _RegisterAppStateChangeNotification(routine _PAPPSTATE_CHANGE_ROUTINE, cont
|
|||||||
}
|
}
|
||||||
return registration, nil
|
return registration, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func _RtlVerifyVersionInfo(versionInfo *_OSVERSIONINFOEXW, typeMask uint32, conditionMask uint64) int32 {
|
||||||
|
var r uintptr
|
||||||
|
if is64bit {
|
||||||
|
r, _, _ = procRtlVerifyVersionInfo.Call(uintptr(unsafe.Pointer(versionInfo)), uintptr(typeMask), uintptr(conditionMask))
|
||||||
|
} else {
|
||||||
|
switch runtime.GOARCH {
|
||||||
|
case "386":
|
||||||
|
r, _, _ = procRtlVerifyVersionInfo.Call(uintptr(unsafe.Pointer(versionInfo)), uintptr(typeMask), uintptr(conditionMask), uintptr(conditionMask>>32))
|
||||||
|
case "arm":
|
||||||
|
// Adjust the alignment for ARM.
|
||||||
|
r, _, _ = procRtlVerifyVersionInfo.Call(uintptr(unsafe.Pointer(versionInfo)), uintptr(typeMask), 0, uintptr(conditionMask), uintptr(conditionMask>>32))
|
||||||
|
default:
|
||||||
|
panic(fmt.Sprintf("directx: GOARCH=%s is not supported", runtime.GOARCH))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return int32(r)
|
||||||
|
}
|
||||||
|
|
||||||
|
func _VerSetConditionMask(conditionMask uint64, typeMask uint32, condition byte) uint64 {
|
||||||
|
if is64bit {
|
||||||
|
r, _, _ := procVerSetConditionMask.Call(uintptr(conditionMask), uintptr(typeMask), uintptr(condition))
|
||||||
|
return uint64(r)
|
||||||
|
} else {
|
||||||
|
r1, r2, _ := procVerSetConditionMask.Call(uintptr(conditionMask), uintptr(conditionMask>>32), uintptr(typeMask), uintptr(condition))
|
||||||
|
return uint64(r1) | (uint64(r2) << 32)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func isWindows10OrGreaterWin32() bool {
|
||||||
|
osvi := _OSVERSIONINFOEXW{
|
||||||
|
dwMajorVersion: 10,
|
||||||
|
dwMinorVersion: 0,
|
||||||
|
dwBuildNumber: 0,
|
||||||
|
}
|
||||||
|
osvi.dwOSVersionInfoSize = uint32(unsafe.Sizeof(osvi))
|
||||||
|
var mask uint32 = _VER_MAJORVERSION | _VER_MINORVERSION | _VER_BUILDNUMBER
|
||||||
|
cond := _VerSetConditionMask(0, _VER_MAJORVERSION, _VER_GREATER_EQUAL)
|
||||||
|
cond = _VerSetConditionMask(cond, _VER_MINORVERSION, _VER_GREATER_EQUAL)
|
||||||
|
cond = _VerSetConditionMask(cond, _VER_BUILDNUMBER, _VER_GREATER_EQUAL)
|
||||||
|
return _RtlVerifyVersionInfo(&osvi, mask, cond) == 0
|
||||||
|
}
|
||||||
|
@ -75,7 +75,10 @@ const (
|
|||||||
type _DXGI_SWAP_EFFECT int32
|
type _DXGI_SWAP_EFFECT int32
|
||||||
|
|
||||||
const (
|
const (
|
||||||
_DXGI_SWAP_EFFECT_FLIP_DISCARD _DXGI_SWAP_EFFECT = 4
|
_DXGI_SWAP_EFFECT_DISCARD _DXGI_SWAP_EFFECT = 0
|
||||||
|
_DXGI_SWAP_EFFECT_SEQUENTIAL _DXGI_SWAP_EFFECT = 1
|
||||||
|
_DXGI_SWAP_EFFECT_FLIP_SEQUENTIAL _DXGI_SWAP_EFFECT = 3
|
||||||
|
_DXGI_SWAP_EFFECT_FLIP_DISCARD _DXGI_SWAP_EFFECT = 4
|
||||||
)
|
)
|
||||||
|
|
||||||
type _DXGI_USAGE uint32
|
type _DXGI_USAGE uint32
|
||||||
|
@ -251,6 +251,9 @@ func (g *graphicsInfra) initSwapChain(width, height int, device unsafe.Pointer,
|
|||||||
//
|
//
|
||||||
// IDXGIFactory::CreateSwapChain: Alpha blended swapchains must be created with CreateSwapChainForComposition,
|
// IDXGIFactory::CreateSwapChain: Alpha blended swapchains must be created with CreateSwapChainForComposition,
|
||||||
// or CreateSwapChainForCoreWindow with the DXGI_SWAP_CHAIN_FLAG_FOREGROUND_LAYER flag
|
// or CreateSwapChainForCoreWindow with the DXGI_SWAP_CHAIN_FLAG_FOREGROUND_LAYER flag
|
||||||
|
//
|
||||||
|
// Use *_SEQUENTIAL swap effects to follow the Mozilla way:
|
||||||
|
// https://github.com/mozilla/gecko-dev/blob/0907529ff72c456ddb47839f5f7ba16291f28dce/gfx/layers/d3d11/CompositorD3D11.cpp#L167-L254
|
||||||
desc := &_DXGI_SWAP_CHAIN_DESC{
|
desc := &_DXGI_SWAP_CHAIN_DESC{
|
||||||
BufferDesc: _DXGI_MODE_DESC{
|
BufferDesc: _DXGI_MODE_DESC{
|
||||||
Width: uint32(width),
|
Width: uint32(width),
|
||||||
@ -265,8 +268,15 @@ func (g *graphicsInfra) initSwapChain(width, height int, device unsafe.Pointer,
|
|||||||
BufferCount: frameCount,
|
BufferCount: frameCount,
|
||||||
OutputWindow: window,
|
OutputWindow: window,
|
||||||
Windowed: 1,
|
Windowed: 1,
|
||||||
SwapEffect: _DXGI_SWAP_EFFECT_FLIP_DISCARD,
|
SwapEffect: _DXGI_SWAP_EFFECT_FLIP_SEQUENTIAL,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// DXGI_SWAP_EFFECT_FLIP_SEQUENTIAL/DISCARD are not supported for older Windows than 10 or DirectX 12.
|
||||||
|
// https://learn.microsoft.com/en-us/windows/win32/api/dxgi/ne-dxgi-dxgi_swap_effect
|
||||||
|
if !isWindows10OrGreaterWin32() {
|
||||||
|
desc.SwapEffect = _DXGI_SWAP_EFFECT_SEQUENTIAL
|
||||||
|
}
|
||||||
|
|
||||||
if g.allowTearing {
|
if g.allowTearing {
|
||||||
desc.Flags |= uint32(_DXGI_SWAP_CHAIN_FLAG_ALLOW_TEARING)
|
desc.Flags |= uint32(_DXGI_SWAP_CHAIN_FLAG_ALLOW_TEARING)
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user