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) NewScreenFramebufferImage(width, height int) (Image, error)
Initialize() error Initialize() error
SetVsyncEnabled(enabled bool) SetVsyncEnabled(enabled bool)
SetFullscreen(fullscreen bool)
FramebufferYDirection() YDirection FramebufferYDirection() YDirection
NeedsRestoring() bool NeedsRestoring() bool
NeedsClearingScreen() bool NeedsClearingScreen() bool

View File

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

View File

@ -77,3 +77,10 @@ func (v View) SetWantsLayer(wantsLayer bool) {
C.View_SetWantsLayer(v.view, 0) 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_SetLayer(void *view, void *layer);
void View_SetWantsLayer(void *view, unsigned char wantsLayer); 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) { void View_SetWantsLayer(void *view, unsigned char wantsLayer) {
((NSView *)view).wantsLayer = (BOOL)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 windowChanged bool
vsyncDisabled bool vsyncDisabled bool
fullscreen bool
device mtl.Device device mtl.Device
ml ca.MetalLayer ml ca.MetalLayer
@ -54,11 +55,33 @@ func (v *view) setDisplaySyncEnabled(enabled bool) {
func (v *view) forceSetDisplaySyncEnabled(enabled bool) { func (v *view) forceSetDisplaySyncEnabled(enabled bool) {
v.ml.SetDisplaySyncEnabled(enabled) v.ml.SetDisplaySyncEnabled(enabled)
v.vsyncDisabled = !enabled
// setting presentsWithTransaction true makes the FPS stable (#1196). We're not sure why... // 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 { func (v *view) colorPixelFormat() mtl.PixelFormat {
@ -81,10 +104,6 @@ func (v *view) reset() error {
// MTLPixelFormatBGRA10_XR_sRGB. // MTLPixelFormatBGRA10_XR_sRGB.
v.ml.SetPixelFormat(mtl.PixelFormatBGRA8UNorm) 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). // The vsync state might be reset. Set the state again (#1364).
v.forceSetDisplaySyncEnabled(!v.vsyncDisabled) v.forceSetDisplaySyncEnabled(!v.vsyncDisabled)
v.ml.SetFramebufferOnly(true) v.ml.SetFramebufferOnly(true)

View File

@ -327,6 +327,10 @@ func (g *Graphics) SetVsyncEnabled(enabled bool) {
// Do nothing // Do nothing
} }
func (g *Graphics) SetFullscreen(fullscreen bool) {
// Do nothing
}
func (g *Graphics) FramebufferYDirection() driver.YDirection { func (g *Graphics) FramebufferYDirection() driver.YDirection {
return driver.Upward 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) { func (u *UserInterface) setWindowSize(width, height int, fullscreen bool) {
width, height = u.adjustWindowSizeBasedOnSizeLimits(width, height) 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() { if u.windowWidth == width && u.windowHeight == height && u.isFullscreen() == fullscreen && u.lastDeviceScaleFactor == u.deviceScaleFactor() {
return return
} }