From 3c7bcf3035f11b8e4299d8254154ec5ddd86693e Mon Sep 17 00:00:00 2001 From: Hajime Hoshi Date: Tue, 2 Jan 2024 22:13:57 +0900 Subject: [PATCH] internal/graphicsdriver/metal: bug fix: use 3 drawables for fullscreen Closes #2880 --- internal/graphicsdriver/metal/view_darwin.go | 24 +++++++++++----- internal/graphicsdriver/metal/view_ios.go | 8 ++++++ internal/graphicsdriver/metal/view_macos.go | 29 ++++++++++++++------ 3 files changed, 46 insertions(+), 15 deletions(-) diff --git a/internal/graphicsdriver/metal/view_darwin.go b/internal/graphicsdriver/metal/view_darwin.go index 910f97168..ecb0d180c 100644 --- a/internal/graphicsdriver/metal/view_darwin.go +++ b/internal/graphicsdriver/metal/view_darwin.go @@ -22,16 +22,16 @@ import ( ) type view struct { - window uintptr - uiview uintptr - - windowChanged bool vsyncDisabled bool device mtl.Device ml ca.MetalLayer + maximumDrawableCount int + once sync.Once + + viewPlatform } func (v *view) setDrawableSize(width, height int) { @@ -52,14 +52,24 @@ func (v *view) setDisplaySyncEnabled(enabled bool) { func (v *view) forceSetDisplaySyncEnabled(enabled bool) { v.ml.SetDisplaySyncEnabled(enabled) v.vsyncDisabled = !enabled + v.updateMaximumDrawableCount() +} - if v.vsyncDisabled { +func (v *view) updateMaximumDrawableCount() { + var count int + if v.vsyncDisabled || v.isFullscreen() { // Apparently 2 makes FPS half. Use 3. - v.ml.SetMaximumDrawableCount(3) + count = 3 } else { // Use 2 in a usual case not to cause rendering delays (#2822). - v.ml.SetMaximumDrawableCount(2) + count = 2 } + + if v.maximumDrawableCount == count { + return + } + v.ml.SetMaximumDrawableCount(count) + v.maximumDrawableCount = count } func (v *view) colorPixelFormat() mtl.PixelFormat { diff --git a/internal/graphicsdriver/metal/view_ios.go b/internal/graphicsdriver/metal/view_ios.go index dff20eb87..ca821e909 100644 --- a/internal/graphicsdriver/metal/view_ios.go +++ b/internal/graphicsdriver/metal/view_ios.go @@ -42,6 +42,10 @@ import ( "github.com/hajimehoshi/ebiten/v2/internal/graphicsdriver/metal/mtl" ) +type viewPlatform struct { + uiview uintptr +} + func (v *view) setWindow(window uintptr) { panic("metal: setWindow is not available on iOS") } @@ -60,6 +64,10 @@ func (v *view) update() { C.setFrame(v.ml.Layer(), unsafe.Pointer(v.uiview)) } +func (v *view) isFullscreen() bool { + return false +} + const ( storageMode = mtl.StorageModeShared resourceStorageMode = mtl.ResourceStorageModeShared diff --git a/internal/graphicsdriver/metal/view_macos.go b/internal/graphicsdriver/metal/view_macos.go index cb8fa41fc..ea5b44ed0 100644 --- a/internal/graphicsdriver/metal/view_macos.go +++ b/internal/graphicsdriver/metal/view_macos.go @@ -23,9 +23,15 @@ import ( "github.com/hajimehoshi/ebiten/v2/internal/graphicsdriver/metal/mtl" ) +type viewPlatform struct { + window cocoa.NSWindow + windowChanged bool + fullscreen bool +} + func (v *view) setWindow(window uintptr) { // NSView can be updated e.g., fullscreen-state is switched. - v.window = window + v.window = cocoa.NSWindow{ID: objc.ID(window)} v.windowChanged = true } @@ -34,15 +40,22 @@ func (v *view) setUIView(uiview uintptr) { } func (v *view) update() { - if !v.windowChanged { - return + if v.windowChanged { + // TODO: Should this be called on the main thread? + v.window.ContentView().SetLayer(uintptr(v.ml.Layer())) + v.window.ContentView().SetWantsLayer(true) + v.windowChanged = false } - // TODO: Should this be called on the main thread? - cocoaWindow := cocoa.NSWindow{ID: objc.ID(v.window)} - cocoaWindow.ContentView().SetLayer(uintptr(v.ml.Layer())) - cocoaWindow.ContentView().SetWantsLayer(true) - v.windowChanged = false + fullscreen := v.window.StyleMask()&cocoa.NSWindowStyleMaskFullScreen != 0 + if v.fullscreen != fullscreen { + v.fullscreen = fullscreen + v.updateMaximumDrawableCount() + } +} + +func (v *view) isFullscreen() bool { + return v.fullscreen } const (