view.go (2938B)
1 // Copyright 2019 The Ebiten Authors 2 // 3 // Licensed under the Apache License, Version 2.0 (the "License"); 4 // you may not use this file except in compliance with the License. 5 // You may obtain a copy of the License at 6 // 7 // http://www.apache.org/licenses/LICENSE-2.0 8 // 9 // Unless required by applicable law or agreed to in writing, software 10 // distributed under the License is distributed on an "AS IS" BASIS, 11 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 // See the License for the specific language governing permissions and 13 // limitations under the License. 14 15 //go:build darwin 16 // +build darwin 17 18 package metal 19 20 import ( 21 "sync" 22 23 "github.com/hajimehoshi/ebiten/v2/internal/graphicsdriver/metal/ca" 24 "github.com/hajimehoshi/ebiten/v2/internal/graphicsdriver/metal/mtl" 25 ) 26 27 type view struct { 28 window uintptr 29 uiview uintptr 30 31 windowChanged bool 32 vsyncDisabled bool 33 fullscreen bool 34 35 device mtl.Device 36 ml ca.MetalLayer 37 38 once sync.Once 39 } 40 41 func (v *view) setDrawableSize(width, height int) { 42 v.ml.SetDrawableSize(width, height) 43 } 44 45 func (v *view) getMTLDevice() mtl.Device { 46 return v.device 47 } 48 49 func (v *view) setDisplaySyncEnabled(enabled bool) { 50 if !v.vsyncDisabled == enabled { 51 return 52 } 53 v.forceSetDisplaySyncEnabled(enabled) 54 } 55 56 func (v *view) forceSetDisplaySyncEnabled(enabled bool) { 57 v.ml.SetDisplaySyncEnabled(enabled) 58 v.vsyncDisabled = !enabled 59 60 // setting presentsWithTransaction true makes the FPS stable (#1196). We're not sure why... 61 v.updatePresentsWithTransaction() 62 } 63 64 func (v *view) setFullscreen(fullscreen bool) { 65 if v.fullscreen == fullscreen { 66 return 67 } 68 v.fullscreen = fullscreen 69 v.updatePresentsWithTransaction() 70 } 71 72 func (v *view) updatePresentsWithTransaction() { 73 v.ml.SetPresentsWithTransaction(v.usePresentsWithTransaction()) 74 v.ml.SetMaximumDrawableCount(v.maximumDrawableCount()) 75 } 76 77 func (v *view) colorPixelFormat() mtl.PixelFormat { 78 return v.ml.PixelFormat() 79 } 80 81 func (v *view) reset() error { 82 var err error 83 v.device, err = mtl.CreateSystemDefaultDevice() 84 if err != nil { 85 return err 86 } 87 88 v.ml = ca.MakeMetalLayer() 89 v.ml.SetDevice(v.device) 90 // https://developer.apple.com/documentation/quartzcore/cametallayer/1478155-pixelformat 91 // 92 // The pixel format for a Metal layer must be MTLPixelFormatBGRA8Unorm, 93 // MTLPixelFormatBGRA8Unorm_sRGB, MTLPixelFormatRGBA16Float, MTLPixelFormatBGRA10_XR, or 94 // MTLPixelFormatBGRA10_XR_sRGB. 95 v.ml.SetPixelFormat(mtl.PixelFormatBGRA8UNorm) 96 97 // The vsync state might be reset. Set the state again (#1364). 98 v.forceSetDisplaySyncEnabled(!v.vsyncDisabled) 99 v.ml.SetFramebufferOnly(true) 100 101 return nil 102 } 103 104 func (v *view) nextDrawable() ca.MetalDrawable { 105 d, err := v.ml.NextDrawable() 106 if err != nil { 107 // Drawable is nil. This can happen at the initial state. Let's wait and see. 108 return ca.MetalDrawable{} 109 } 110 return d 111 } 112 113 func (v *view) presentsWithTransaction() bool { 114 return v.ml.PresentsWithTransaction() 115 }