internal/graphicsdriver/metal: Bug fix: Disable presentsWithTransaction on fullscreen

Closes #1745
This commit is contained in:
Hajime Hoshi 2021-08-08 15:38:41 +09:00
parent 91395f6285
commit 15ac69b8d5
8 changed files with 48 additions and 6 deletions

View File

@ -47,6 +47,7 @@ type Graphics interface {
NewScreenFramebufferImage(width, height int) (Image, error)
Initialize() error
SetVsyncEnabled(enabled bool)
SetFullscreen(fullscreen bool)
FramebufferYDirection() YDirection
NeedsRestoring() bool
NeedsClearingScreen() bool

View File

@ -1007,6 +1007,10 @@ func (g *Graphics) SetVsyncEnabled(enabled bool) {
g.view.setDisplaySyncEnabled(enabled)
}
func (g *Graphics) SetFullscreen(fullscreen bool) {
g.view.setFullscreen(fullscreen)
}
func (g *Graphics) FramebufferYDirection() driver.YDirection {
return driver.Downward
}

View File

@ -77,3 +77,10 @@ func (v View) SetWantsLayer(wantsLayer bool) {
C.View_SetWantsLayer(v.view, 0)
}
}
// IsInFullScreenMode returns a boolean value indicating whether the view is in full screen mode.
//
// Reference: https://developer.apple.com/documentation/appkit/nsview/1483337-infullscreenmode.
func (v View) IsInFullScreenMode() bool {
return C.View_IsInFullScreenMode(v.view) != 0
}

View File

@ -20,3 +20,4 @@ void *Window_ContentView(uintptr_t window);
void View_SetLayer(void *view, void *layer);
void View_SetWantsLayer(void *view, unsigned char wantsLayer);
uint8_t View_IsInFullScreenMode(void *view);

View File

@ -28,3 +28,7 @@ void View_SetLayer(void *view, void *layer) {
void View_SetWantsLayer(void *view, unsigned char wantsLayer) {
((NSView *)view).wantsLayer = (BOOL)wantsLayer;
}
uint8_t View_IsInFullScreenMode(void *view) {
return ((NSView *)view).isInFullScreenMode;
}

View File

@ -30,6 +30,7 @@ type view struct {
windowChanged bool
vsyncDisabled bool
fullscreen bool
device mtl.Device
ml ca.MetalLayer
@ -54,11 +55,33 @@ func (v *view) setDisplaySyncEnabled(enabled bool) {
func (v *view) forceSetDisplaySyncEnabled(enabled bool) {
v.ml.SetDisplaySyncEnabled(enabled)
v.vsyncDisabled = !enabled
// setting presentsWithTransaction true makes the FPS stable (#1196). We're not sure why...
v.ml.SetPresentsWithTransaction(enabled)
v.updatePresentsWithTransaction()
}
v.vsyncDisabled = !enabled
func (v *view) setFullscreen(fullscreen bool) {
if v.fullscreen == fullscreen {
return
}
v.fullscreen = fullscreen
v.updatePresentsWithTransaction()
}
func (v *view) updatePresentsWithTransaction() {
// Disable presentsWithTransaction on the fullscreen mode (#1745).
pwt := !v.vsyncDisabled && !v.fullscreen
v.ml.SetPresentsWithTransaction(pwt)
// When presentsWithTransaction is YES and triple buffering is enabled, nextDrawing returns immediately once every two times.
// This makes FPS doubled. To avoid this, disable the triple buffering.
if pwt {
v.ml.SetMaximumDrawableCount(2)
} else {
v.ml.SetMaximumDrawableCount(3)
}
}
func (v *view) colorPixelFormat() mtl.PixelFormat {
@ -81,10 +104,6 @@ func (v *view) reset() error {
// MTLPixelFormatBGRA10_XR_sRGB.
v.ml.SetPixelFormat(mtl.PixelFormatBGRA8UNorm)
// When presentsWithTransaction is YES and triple buffering is enabled, nextDrawing returns immediately once every two times.
// This makes FPS doubled. To avoid this, disable the triple buffering.
v.ml.SetMaximumDrawableCount(2)
// The vsync state might be reset. Set the state again (#1364).
v.forceSetDisplaySyncEnabled(!v.vsyncDisabled)
v.ml.SetFramebufferOnly(true)

View File

@ -327,6 +327,10 @@ func (g *Graphics) SetVsyncEnabled(enabled bool) {
// Do nothing
}
func (g *Graphics) SetFullscreen(fullscreen bool) {
// Do nothing
}
func (g *Graphics) FramebufferYDirection() driver.YDirection {
return driver.Upward
}

View File

@ -1180,6 +1180,8 @@ func (u *UserInterface) adjustWindowSizeBasedOnSizeLimitsInDP(width, height int)
func (u *UserInterface) setWindowSize(width, height int, fullscreen bool) {
width, height = u.adjustWindowSizeBasedOnSizeLimits(width, height)
u.Graphics().SetFullscreen(fullscreen || u.isNativeFullscreen())
if u.windowWidth == width && u.windowHeight == height && u.isFullscreen() == fullscreen && u.lastDeviceScaleFactor == u.deviceScaleFactor() {
return
}