mirror of
https://github.com/hajimehoshi/ebiten.git
synced 2024-12-24 18:58:54 +01:00
graphicsdriver/metal: Rename Driver -> Graphics
This commit is contained in:
parent
6cbf37e855
commit
01d1afa25c
@ -283,7 +283,7 @@ type rpsKey struct {
|
|||||||
screen bool
|
screen bool
|
||||||
}
|
}
|
||||||
|
|
||||||
type Driver struct {
|
type Graphics struct {
|
||||||
view view
|
view view
|
||||||
|
|
||||||
screenRPS mtl.RenderPipelineState
|
screenRPS mtl.RenderPipelineState
|
||||||
@ -307,91 +307,91 @@ type Driver struct {
|
|||||||
pool unsafe.Pointer
|
pool unsafe.Pointer
|
||||||
}
|
}
|
||||||
|
|
||||||
var theDriver Driver
|
var theGraphics Graphics
|
||||||
|
|
||||||
func Get() *Driver {
|
func Get() *Graphics {
|
||||||
return &theDriver
|
return &theGraphics
|
||||||
}
|
}
|
||||||
|
|
||||||
func (d *Driver) SetThread(thread *thread.Thread) {
|
func (g *Graphics) SetThread(thread *thread.Thread) {
|
||||||
d.t = thread
|
g.t = thread
|
||||||
}
|
}
|
||||||
|
|
||||||
func (d *Driver) Begin() {
|
func (g *Graphics) Begin() {
|
||||||
d.t.Call(func() error {
|
g.t.Call(func() error {
|
||||||
// NSAutoreleasePool is required to release drawable correctly (#847).
|
// NSAutoreleasePool is required to release drawable correctly (#847).
|
||||||
// https://developer.apple.com/library/archive/documentation/3DDrawing/Conceptual/MTLBestPracticesGuide/Drawables.html
|
// https://developer.apple.com/library/archive/documentation/3DDrawing/Conceptual/MTLBestPracticesGuide/Drawables.html
|
||||||
d.pool = C.allocAutoreleasePool()
|
g.pool = C.allocAutoreleasePool()
|
||||||
return nil
|
return nil
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
func (d *Driver) End() {
|
func (g *Graphics) End() {
|
||||||
d.flush(false, true)
|
g.flush(false, true)
|
||||||
d.t.Call(func() error {
|
g.t.Call(func() error {
|
||||||
d.screenDrawable = ca.MetalDrawable{}
|
g.screenDrawable = ca.MetalDrawable{}
|
||||||
C.releaseAutoreleasePool(d.pool)
|
C.releaseAutoreleasePool(g.pool)
|
||||||
d.pool = nil
|
g.pool = nil
|
||||||
return nil
|
return nil
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
func (d *Driver) SetWindow(window unsafe.Pointer) {
|
func (g *Graphics) SetWindow(window unsafe.Pointer) {
|
||||||
d.t.Call(func() error {
|
g.t.Call(func() error {
|
||||||
// Note that [NSApp mainWindow] returns nil when the window is borderless.
|
// Note that [NSApp mainWindow] returns nil when the window is borderless.
|
||||||
// Then the window is needed to be given explicitly.
|
// Then the window is needed to be given explicitly.
|
||||||
d.view.setWindow(window)
|
g.view.setWindow(window)
|
||||||
return nil
|
return nil
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
func (d *Driver) SetUIView(uiview uintptr) {
|
func (g *Graphics) SetUIView(uiview uintptr) {
|
||||||
// TODO: Should this be called on the main thread?
|
// TODO: Should this be called on the main thread?
|
||||||
d.view.setUIView(uiview)
|
g.view.setUIView(uiview)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (d *Driver) SetVertices(vertices []float32, indices []uint16) {
|
func (g *Graphics) SetVertices(vertices []float32, indices []uint16) {
|
||||||
d.t.Call(func() error {
|
g.t.Call(func() error {
|
||||||
if d.vb != (mtl.Buffer{}) {
|
if g.vb != (mtl.Buffer{}) {
|
||||||
d.vb.Release()
|
g.vb.Release()
|
||||||
}
|
}
|
||||||
if d.ib != (mtl.Buffer{}) {
|
if g.ib != (mtl.Buffer{}) {
|
||||||
d.ib.Release()
|
g.ib.Release()
|
||||||
}
|
}
|
||||||
d.vb = d.view.getMTLDevice().MakeBufferWithBytes(unsafe.Pointer(&vertices[0]), unsafe.Sizeof(vertices[0])*uintptr(len(vertices)), resourceStorageMode)
|
g.vb = g.view.getMTLDevice().MakeBufferWithBytes(unsafe.Pointer(&vertices[0]), unsafe.Sizeof(vertices[0])*uintptr(len(vertices)), resourceStorageMode)
|
||||||
d.ib = d.view.getMTLDevice().MakeBufferWithBytes(unsafe.Pointer(&indices[0]), unsafe.Sizeof(indices[0])*uintptr(len(indices)), resourceStorageMode)
|
g.ib = g.view.getMTLDevice().MakeBufferWithBytes(unsafe.Pointer(&indices[0]), unsafe.Sizeof(indices[0])*uintptr(len(indices)), resourceStorageMode)
|
||||||
return nil
|
return nil
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
func (d *Driver) flush(wait bool, present bool) {
|
func (g *Graphics) flush(wait bool, present bool) {
|
||||||
d.t.Call(func() error {
|
g.t.Call(func() error {
|
||||||
if d.cb == (mtl.CommandBuffer{}) {
|
if g.cb == (mtl.CommandBuffer{}) {
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
if present && d.screenDrawable != (ca.MetalDrawable{}) {
|
if present && g.screenDrawable != (ca.MetalDrawable{}) {
|
||||||
d.cb.PresentDrawable(d.screenDrawable)
|
g.cb.PresentDrawable(g.screenDrawable)
|
||||||
}
|
}
|
||||||
d.cb.Commit()
|
g.cb.Commit()
|
||||||
if wait {
|
if wait {
|
||||||
d.cb.WaitUntilCompleted()
|
g.cb.WaitUntilCompleted()
|
||||||
}
|
}
|
||||||
|
|
||||||
d.cb = mtl.CommandBuffer{}
|
g.cb = mtl.CommandBuffer{}
|
||||||
|
|
||||||
return nil
|
return nil
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
func (d *Driver) checkSize(width, height int) {
|
func (g *Graphics) checkSize(width, height int) {
|
||||||
if width < 1 {
|
if width < 1 {
|
||||||
panic(fmt.Sprintf("metal: width (%d) must be equal or more than %d", width, 1))
|
panic(fmt.Sprintf("metal: width (%d) must be equal or more than %d", width, 1))
|
||||||
}
|
}
|
||||||
if height < 1 {
|
if height < 1 {
|
||||||
panic(fmt.Sprintf("metal: height (%d) must be equal or more than %d", height, 1))
|
panic(fmt.Sprintf("metal: height (%d) must be equal or more than %d", height, 1))
|
||||||
}
|
}
|
||||||
m := d.MaxImageSize()
|
m := g.MaxImageSize()
|
||||||
if width > m {
|
if width > m {
|
||||||
panic(fmt.Sprintf("metal: width (%d) must be less than or equal to %d", width, m))
|
panic(fmt.Sprintf("metal: width (%d) must be less than or equal to %d", width, m))
|
||||||
}
|
}
|
||||||
@ -400,8 +400,8 @@ func (d *Driver) checkSize(width, height int) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func (d *Driver) NewImage(width, height int) (driver.Image, error) {
|
func (g *Graphics) NewImage(width, height int) (driver.Image, error) {
|
||||||
d.checkSize(width, height)
|
g.checkSize(width, height)
|
||||||
td := mtl.TextureDescriptor{
|
td := mtl.TextureDescriptor{
|
||||||
PixelFormat: mtl.PixelFormatRGBA8UNorm,
|
PixelFormat: mtl.PixelFormatRGBA8UNorm,
|
||||||
Width: graphics.InternalImageSize(width),
|
Width: graphics.InternalImageSize(width),
|
||||||
@ -410,52 +410,52 @@ func (d *Driver) NewImage(width, height int) (driver.Image, error) {
|
|||||||
Usage: textureUsage,
|
Usage: textureUsage,
|
||||||
}
|
}
|
||||||
var t mtl.Texture
|
var t mtl.Texture
|
||||||
d.t.Call(func() error {
|
g.t.Call(func() error {
|
||||||
t = d.view.getMTLDevice().MakeTexture(td)
|
t = g.view.getMTLDevice().MakeTexture(td)
|
||||||
return nil
|
return nil
|
||||||
})
|
})
|
||||||
return &Image{
|
return &Image{
|
||||||
driver: d,
|
graphics: g,
|
||||||
width: width,
|
width: width,
|
||||||
height: height,
|
height: height,
|
||||||
texture: t,
|
texture: t,
|
||||||
}, nil
|
}, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (d *Driver) NewScreenFramebufferImage(width, height int) (driver.Image, error) {
|
func (g *Graphics) NewScreenFramebufferImage(width, height int) (driver.Image, error) {
|
||||||
d.t.Call(func() error {
|
g.t.Call(func() error {
|
||||||
d.view.setDrawableSize(width, height)
|
g.view.setDrawableSize(width, height)
|
||||||
return nil
|
return nil
|
||||||
})
|
})
|
||||||
return &Image{
|
return &Image{
|
||||||
driver: d,
|
graphics: g,
|
||||||
width: width,
|
width: width,
|
||||||
height: height,
|
height: height,
|
||||||
screen: true,
|
screen: true,
|
||||||
}, nil
|
}, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (d *Driver) SetTransparent(transparent bool) {
|
func (g *Graphics) SetTransparent(transparent bool) {
|
||||||
d.transparent = transparent
|
g.transparent = transparent
|
||||||
}
|
}
|
||||||
|
|
||||||
func (d *Driver) Reset() error {
|
func (g *Graphics) Reset() error {
|
||||||
if err := d.t.Call(func() error {
|
if err := g.t.Call(func() error {
|
||||||
if d.cq != (mtl.CommandQueue{}) {
|
if g.cq != (mtl.CommandQueue{}) {
|
||||||
d.cq.Release()
|
g.cq.Release()
|
||||||
d.cq = mtl.CommandQueue{}
|
g.cq = mtl.CommandQueue{}
|
||||||
}
|
}
|
||||||
|
|
||||||
// TODO: Release existing rpss
|
// TODO: Release existing rpss
|
||||||
if d.rpss == nil {
|
if g.rpss == nil {
|
||||||
d.rpss = map[rpsKey]mtl.RenderPipelineState{}
|
g.rpss = map[rpsKey]mtl.RenderPipelineState{}
|
||||||
}
|
}
|
||||||
|
|
||||||
if err := d.view.reset(); err != nil {
|
if err := g.view.reset(); err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
if d.transparent {
|
if g.transparent {
|
||||||
d.view.ml.SetOpaque(false)
|
g.view.ml.SetOpaque(false)
|
||||||
}
|
}
|
||||||
|
|
||||||
replaces := map[string]string{
|
replaces := map[string]string{
|
||||||
@ -470,7 +470,7 @@ func (d *Driver) Reset() error {
|
|||||||
src = strings.Replace(src, k, v, -1)
|
src = strings.Replace(src, k, v, -1)
|
||||||
}
|
}
|
||||||
|
|
||||||
lib, err := d.view.getMTLDevice().MakeLibrary(src, mtl.CompileOptions{})
|
lib, err := g.view.getMTLDevice().MakeLibrary(src, mtl.CompileOptions{})
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
@ -487,17 +487,17 @@ func (d *Driver) Reset() error {
|
|||||||
VertexFunction: vs,
|
VertexFunction: vs,
|
||||||
FragmentFunction: fs,
|
FragmentFunction: fs,
|
||||||
}
|
}
|
||||||
rpld.ColorAttachments[0].PixelFormat = d.view.colorPixelFormat()
|
rpld.ColorAttachments[0].PixelFormat = g.view.colorPixelFormat()
|
||||||
rpld.ColorAttachments[0].BlendingEnabled = true
|
rpld.ColorAttachments[0].BlendingEnabled = true
|
||||||
rpld.ColorAttachments[0].DestinationAlphaBlendFactor = mtl.BlendFactorZero
|
rpld.ColorAttachments[0].DestinationAlphaBlendFactor = mtl.BlendFactorZero
|
||||||
rpld.ColorAttachments[0].DestinationRGBBlendFactor = mtl.BlendFactorZero
|
rpld.ColorAttachments[0].DestinationRGBBlendFactor = mtl.BlendFactorZero
|
||||||
rpld.ColorAttachments[0].SourceAlphaBlendFactor = mtl.BlendFactorOne
|
rpld.ColorAttachments[0].SourceAlphaBlendFactor = mtl.BlendFactorOne
|
||||||
rpld.ColorAttachments[0].SourceRGBBlendFactor = mtl.BlendFactorOne
|
rpld.ColorAttachments[0].SourceRGBBlendFactor = mtl.BlendFactorOne
|
||||||
rps, err := d.view.getMTLDevice().MakeRenderPipelineState(rpld)
|
rps, err := g.view.getMTLDevice().MakeRenderPipelineState(rpld)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
d.screenRPS = rps
|
g.screenRPS = rps
|
||||||
|
|
||||||
conv := func(c driver.Operation) mtl.BlendFactor {
|
conv := func(c driver.Operation) mtl.BlendFactor {
|
||||||
switch c {
|
switch c {
|
||||||
@ -544,7 +544,7 @@ func (d *Driver) Reset() error {
|
|||||||
|
|
||||||
pix := mtl.PixelFormatRGBA8UNorm
|
pix := mtl.PixelFormatRGBA8UNorm
|
||||||
if screen {
|
if screen {
|
||||||
pix = d.view.colorPixelFormat()
|
pix = g.view.colorPixelFormat()
|
||||||
}
|
}
|
||||||
rpld.ColorAttachments[0].PixelFormat = pix
|
rpld.ColorAttachments[0].PixelFormat = pix
|
||||||
rpld.ColorAttachments[0].BlendingEnabled = true
|
rpld.ColorAttachments[0].BlendingEnabled = true
|
||||||
@ -554,11 +554,11 @@ func (d *Driver) Reset() error {
|
|||||||
rpld.ColorAttachments[0].DestinationRGBBlendFactor = conv(dst)
|
rpld.ColorAttachments[0].DestinationRGBBlendFactor = conv(dst)
|
||||||
rpld.ColorAttachments[0].SourceAlphaBlendFactor = conv(src)
|
rpld.ColorAttachments[0].SourceAlphaBlendFactor = conv(src)
|
||||||
rpld.ColorAttachments[0].SourceRGBBlendFactor = conv(src)
|
rpld.ColorAttachments[0].SourceRGBBlendFactor = conv(src)
|
||||||
rps, err := d.view.getMTLDevice().MakeRenderPipelineState(rpld)
|
rps, err := g.view.getMTLDevice().MakeRenderPipelineState(rpld)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
d.rpss[rpsKey{
|
g.rpss[rpsKey{
|
||||||
screen: screen,
|
screen: screen,
|
||||||
useColorM: cm,
|
useColorM: cm,
|
||||||
filter: f,
|
filter: f,
|
||||||
@ -571,7 +571,7 @@ func (d *Driver) Reset() error {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
d.cq = d.view.getMTLDevice().MakeCommandQueue()
|
g.cq = g.view.getMTLDevice().MakeCommandQueue()
|
||||||
return nil
|
return nil
|
||||||
}); err != nil {
|
}); err != nil {
|
||||||
return err
|
return err
|
||||||
@ -580,11 +580,11 @@ func (d *Driver) Reset() error {
|
|||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (d *Driver) Draw(indexLen int, indexOffset int, mode driver.CompositeMode, colorM *affine.ColorM, filter driver.Filter, address driver.Address) error {
|
func (g *Graphics) Draw(indexLen int, indexOffset int, mode driver.CompositeMode, colorM *affine.ColorM, filter driver.Filter, address driver.Address) error {
|
||||||
d.drawCalled = true
|
g.drawCalled = true
|
||||||
|
|
||||||
if err := d.t.Call(func() error {
|
if err := g.t.Call(func() error {
|
||||||
d.view.update()
|
g.view.update()
|
||||||
|
|
||||||
rpd := mtl.RenderPassDescriptor{}
|
rpd := mtl.RenderPassDescriptor{}
|
||||||
// Even though the destination pixels are not used, mtl.LoadActionDontCare might cause glitches
|
// Even though the destination pixels are not used, mtl.LoadActionDontCare might cause glitches
|
||||||
@ -593,33 +593,33 @@ func (d *Driver) Draw(indexLen int, indexOffset int, mode driver.CompositeMode,
|
|||||||
rpd.ColorAttachments[0].StoreAction = mtl.StoreActionStore
|
rpd.ColorAttachments[0].StoreAction = mtl.StoreActionStore
|
||||||
|
|
||||||
var t mtl.Texture
|
var t mtl.Texture
|
||||||
if d.dst.screen {
|
if g.dst.screen {
|
||||||
if d.screenDrawable == (ca.MetalDrawable{}) {
|
if g.screenDrawable == (ca.MetalDrawable{}) {
|
||||||
drawable := d.view.drawable()
|
drawable := g.view.drawable()
|
||||||
if drawable == (ca.MetalDrawable{}) {
|
if drawable == (ca.MetalDrawable{}) {
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
d.screenDrawable = drawable
|
g.screenDrawable = drawable
|
||||||
}
|
}
|
||||||
t = d.screenDrawable.Texture()
|
t = g.screenDrawable.Texture()
|
||||||
} else {
|
} else {
|
||||||
t = d.dst.texture
|
t = g.dst.texture
|
||||||
}
|
}
|
||||||
rpd.ColorAttachments[0].Texture = t
|
rpd.ColorAttachments[0].Texture = t
|
||||||
rpd.ColorAttachments[0].ClearColor = mtl.ClearColor{}
|
rpd.ColorAttachments[0].ClearColor = mtl.ClearColor{}
|
||||||
|
|
||||||
w, h := d.dst.viewportSize()
|
w, h := g.dst.viewportSize()
|
||||||
|
|
||||||
if d.cb == (mtl.CommandBuffer{}) {
|
if g.cb == (mtl.CommandBuffer{}) {
|
||||||
d.cb = d.cq.MakeCommandBuffer()
|
g.cb = g.cq.MakeCommandBuffer()
|
||||||
}
|
}
|
||||||
rce := d.cb.MakeRenderCommandEncoder(rpd)
|
rce := g.cb.MakeRenderCommandEncoder(rpd)
|
||||||
|
|
||||||
if d.dst.screen && filter == driver.FilterScreen {
|
if g.dst.screen && filter == driver.FilterScreen {
|
||||||
rce.SetRenderPipelineState(d.screenRPS)
|
rce.SetRenderPipelineState(g.screenRPS)
|
||||||
} else {
|
} else {
|
||||||
rce.SetRenderPipelineState(d.rpss[rpsKey{
|
rce.SetRenderPipelineState(g.rpss[rpsKey{
|
||||||
screen: d.dst.screen,
|
screen: g.dst.screen,
|
||||||
useColorM: colorM != nil,
|
useColorM: colorM != nil,
|
||||||
filter: filter,
|
filter: filter,
|
||||||
address: address,
|
address: address,
|
||||||
@ -634,14 +634,14 @@ func (d *Driver) Draw(indexLen int, indexOffset int, mode driver.CompositeMode,
|
|||||||
ZNear: -1,
|
ZNear: -1,
|
||||||
ZFar: 1,
|
ZFar: 1,
|
||||||
})
|
})
|
||||||
rce.SetVertexBuffer(d.vb, 0, 0)
|
rce.SetVertexBuffer(g.vb, 0, 0)
|
||||||
|
|
||||||
viewportSize := [...]float32{float32(w), float32(h)}
|
viewportSize := [...]float32{float32(w), float32(h)}
|
||||||
rce.SetVertexBytes(unsafe.Pointer(&viewportSize[0]), unsafe.Sizeof(viewportSize), 1)
|
rce.SetVertexBytes(unsafe.Pointer(&viewportSize[0]), unsafe.Sizeof(viewportSize), 1)
|
||||||
|
|
||||||
sourceSize := [...]float32{
|
sourceSize := [...]float32{
|
||||||
float32(graphics.InternalImageSize(d.src.width)),
|
float32(graphics.InternalImageSize(g.src.width)),
|
||||||
float32(graphics.InternalImageSize(d.src.height)),
|
float32(graphics.InternalImageSize(g.src.height)),
|
||||||
}
|
}
|
||||||
rce.SetFragmentBytes(unsafe.Pointer(&sourceSize[0]), unsafe.Sizeof(sourceSize), 2)
|
rce.SetFragmentBytes(unsafe.Pointer(&sourceSize[0]), unsafe.Sizeof(sourceSize), 2)
|
||||||
|
|
||||||
@ -649,15 +649,15 @@ func (d *Driver) Draw(indexLen int, indexOffset int, mode driver.CompositeMode,
|
|||||||
rce.SetFragmentBytes(unsafe.Pointer(&esBody[0]), unsafe.Sizeof(esBody[0])*uintptr(len(esBody)), 3)
|
rce.SetFragmentBytes(unsafe.Pointer(&esBody[0]), unsafe.Sizeof(esBody[0])*uintptr(len(esBody)), 3)
|
||||||
rce.SetFragmentBytes(unsafe.Pointer(&esTranslate[0]), unsafe.Sizeof(esTranslate[0])*uintptr(len(esTranslate)), 4)
|
rce.SetFragmentBytes(unsafe.Pointer(&esTranslate[0]), unsafe.Sizeof(esTranslate[0])*uintptr(len(esTranslate)), 4)
|
||||||
|
|
||||||
scale := float32(d.dst.width) / float32(d.src.width)
|
scale := float32(g.dst.width) / float32(g.src.width)
|
||||||
rce.SetFragmentBytes(unsafe.Pointer(&scale), unsafe.Sizeof(scale), 5)
|
rce.SetFragmentBytes(unsafe.Pointer(&scale), unsafe.Sizeof(scale), 5)
|
||||||
|
|
||||||
if d.src != nil {
|
if g.src != nil {
|
||||||
rce.SetFragmentTexture(d.src.texture, 0)
|
rce.SetFragmentTexture(g.src.texture, 0)
|
||||||
} else {
|
} else {
|
||||||
rce.SetFragmentTexture(mtl.Texture{}, 0)
|
rce.SetFragmentTexture(mtl.Texture{}, 0)
|
||||||
}
|
}
|
||||||
rce.DrawIndexedPrimitives(mtl.PrimitiveTypeTriangle, indexLen, mtl.IndexTypeUInt16, d.ib, indexOffset*2)
|
rce.DrawIndexedPrimitives(mtl.PrimitiveTypeTriangle, indexLen, mtl.IndexTypeUInt16, g.ib, indexOffset*2)
|
||||||
rce.EndEncoding()
|
rce.EndEncoding()
|
||||||
|
|
||||||
return nil
|
return nil
|
||||||
@ -668,76 +668,76 @@ func (d *Driver) Draw(indexLen int, indexOffset int, mode driver.CompositeMode,
|
|||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (d *Driver) ResetSource() {
|
func (g *Graphics) ResetSource() {
|
||||||
d.t.Call(func() error {
|
g.t.Call(func() error {
|
||||||
d.src = nil
|
g.src = nil
|
||||||
return nil
|
return nil
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
func (d *Driver) SetVsyncEnabled(enabled bool) {
|
func (g *Graphics) SetVsyncEnabled(enabled bool) {
|
||||||
d.view.setDisplaySyncEnabled(enabled)
|
g.view.setDisplaySyncEnabled(enabled)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (d *Driver) VDirection() driver.VDirection {
|
func (g *Graphics) VDirection() driver.VDirection {
|
||||||
return driver.VUpward
|
return driver.VUpward
|
||||||
}
|
}
|
||||||
|
|
||||||
func (d *Driver) NeedsRestoring() bool {
|
func (g *Graphics) NeedsRestoring() bool {
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
|
|
||||||
func (d *Driver) IsGL() bool {
|
func (g *Graphics) IsGL() bool {
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
|
|
||||||
func (d *Driver) HasHighPrecisionFloat() bool {
|
func (g *Graphics) HasHighPrecisionFloat() bool {
|
||||||
return true
|
return true
|
||||||
}
|
}
|
||||||
|
|
||||||
func (d *Driver) MaxImageSize() int {
|
func (g *Graphics) MaxImageSize() int {
|
||||||
m := 0
|
m := 0
|
||||||
d.t.Call(func() error {
|
g.t.Call(func() error {
|
||||||
if d.maxImageSize == 0 {
|
if g.maxImageSize == 0 {
|
||||||
d.maxImageSize = 4096
|
g.maxImageSize = 4096
|
||||||
// https://developer.apple.com/metal/Metal-Feature-Set-Tables.pdf
|
// https://developer.apple.com/metal/Metal-Feature-Set-Tables.pdf
|
||||||
switch {
|
switch {
|
||||||
case d.view.getMTLDevice().SupportsFeatureSet(mtl.FeatureSet_iOS_GPUFamily5_v1):
|
case g.view.getMTLDevice().SupportsFeatureSet(mtl.FeatureSet_iOS_GPUFamily5_v1):
|
||||||
d.maxImageSize = 16384
|
g.maxImageSize = 16384
|
||||||
case d.view.getMTLDevice().SupportsFeatureSet(mtl.FeatureSet_iOS_GPUFamily4_v1):
|
case g.view.getMTLDevice().SupportsFeatureSet(mtl.FeatureSet_iOS_GPUFamily4_v1):
|
||||||
d.maxImageSize = 16384
|
g.maxImageSize = 16384
|
||||||
case d.view.getMTLDevice().SupportsFeatureSet(mtl.FeatureSet_iOS_GPUFamily3_v1):
|
case g.view.getMTLDevice().SupportsFeatureSet(mtl.FeatureSet_iOS_GPUFamily3_v1):
|
||||||
d.maxImageSize = 16384
|
g.maxImageSize = 16384
|
||||||
case d.view.getMTLDevice().SupportsFeatureSet(mtl.FeatureSet_iOS_GPUFamily2_v2):
|
case g.view.getMTLDevice().SupportsFeatureSet(mtl.FeatureSet_iOS_GPUFamily2_v2):
|
||||||
d.maxImageSize = 8192
|
g.maxImageSize = 8192
|
||||||
case d.view.getMTLDevice().SupportsFeatureSet(mtl.FeatureSet_iOS_GPUFamily2_v1):
|
case g.view.getMTLDevice().SupportsFeatureSet(mtl.FeatureSet_iOS_GPUFamily2_v1):
|
||||||
d.maxImageSize = 4096
|
g.maxImageSize = 4096
|
||||||
case d.view.getMTLDevice().SupportsFeatureSet(mtl.FeatureSet_iOS_GPUFamily1_v2):
|
case g.view.getMTLDevice().SupportsFeatureSet(mtl.FeatureSet_iOS_GPUFamily1_v2):
|
||||||
d.maxImageSize = 8192
|
g.maxImageSize = 8192
|
||||||
case d.view.getMTLDevice().SupportsFeatureSet(mtl.FeatureSet_iOS_GPUFamily1_v1):
|
case g.view.getMTLDevice().SupportsFeatureSet(mtl.FeatureSet_iOS_GPUFamily1_v1):
|
||||||
d.maxImageSize = 4096
|
g.maxImageSize = 4096
|
||||||
case d.view.getMTLDevice().SupportsFeatureSet(mtl.FeatureSet_tvOS_GPUFamily2_v1):
|
case g.view.getMTLDevice().SupportsFeatureSet(mtl.FeatureSet_tvOS_GPUFamily2_v1):
|
||||||
d.maxImageSize = 16384
|
g.maxImageSize = 16384
|
||||||
case d.view.getMTLDevice().SupportsFeatureSet(mtl.FeatureSet_tvOS_GPUFamily1_v1):
|
case g.view.getMTLDevice().SupportsFeatureSet(mtl.FeatureSet_tvOS_GPUFamily1_v1):
|
||||||
d.maxImageSize = 8192
|
g.maxImageSize = 8192
|
||||||
case d.view.getMTLDevice().SupportsFeatureSet(mtl.FeatureSet_macOS_GPUFamily1_v1):
|
case g.view.getMTLDevice().SupportsFeatureSet(mtl.FeatureSet_macOS_GPUFamily1_v1):
|
||||||
d.maxImageSize = 16384
|
g.maxImageSize = 16384
|
||||||
default:
|
default:
|
||||||
panic("metal: there is no supported feature set")
|
panic("metal: there is no supported feature set")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
m = d.maxImageSize
|
m = g.maxImageSize
|
||||||
return nil
|
return nil
|
||||||
})
|
})
|
||||||
return m
|
return m
|
||||||
}
|
}
|
||||||
|
|
||||||
type Image struct {
|
type Image struct {
|
||||||
driver *Driver
|
graphics *Graphics
|
||||||
width int
|
width int
|
||||||
height int
|
height int
|
||||||
screen bool
|
screen bool
|
||||||
texture mtl.Texture
|
texture mtl.Texture
|
||||||
}
|
}
|
||||||
|
|
||||||
// viewportSize must be called from the main thread.
|
// viewportSize must be called from the main thread.
|
||||||
@ -749,7 +749,7 @@ func (i *Image) viewportSize() (int, int) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (i *Image) Dispose() {
|
func (i *Image) Dispose() {
|
||||||
i.driver.t.Call(func() error {
|
i.graphics.t.Call(func() error {
|
||||||
if i.texture != (mtl.Texture{}) {
|
if i.texture != (mtl.Texture{}) {
|
||||||
i.texture.Release()
|
i.texture.Release()
|
||||||
i.texture = mtl.Texture{}
|
i.texture = mtl.Texture{}
|
||||||
@ -766,12 +766,12 @@ func (i *Image) IsInvalidated() bool {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (i *Image) syncTexture() {
|
func (i *Image) syncTexture() {
|
||||||
i.driver.t.Call(func() error {
|
i.graphics.t.Call(func() error {
|
||||||
if i.driver.cb != (mtl.CommandBuffer{}) {
|
if i.graphics.cb != (mtl.CommandBuffer{}) {
|
||||||
panic("metal: command buffer must be empty at syncTexture: flush is not called yet?")
|
panic("metal: command buffer must be empty at syncTexture: flush is not called yet?")
|
||||||
}
|
}
|
||||||
|
|
||||||
cb := i.driver.cq.MakeCommandBuffer()
|
cb := i.graphics.cq.MakeCommandBuffer()
|
||||||
bce := cb.MakeBlitCommandEncoder()
|
bce := cb.MakeBlitCommandEncoder()
|
||||||
bce.SynchronizeTexture(i.texture, 0, 0)
|
bce.SynchronizeTexture(i.texture, 0, 0)
|
||||||
bce.EndEncoding()
|
bce.EndEncoding()
|
||||||
@ -782,11 +782,11 @@ func (i *Image) syncTexture() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (i *Image) Pixels() ([]byte, error) {
|
func (i *Image) Pixels() ([]byte, error) {
|
||||||
i.driver.flush(true, false)
|
i.graphics.flush(true, false)
|
||||||
i.syncTexture()
|
i.syncTexture()
|
||||||
|
|
||||||
b := make([]byte, 4*i.width*i.height)
|
b := make([]byte, 4*i.width*i.height)
|
||||||
i.driver.t.Call(func() error {
|
i.graphics.t.Call(func() error {
|
||||||
i.texture.GetBytes(&b[0], uintptr(4*i.width), mtl.Region{
|
i.texture.GetBytes(&b[0], uintptr(4*i.width), mtl.Region{
|
||||||
Size: mtl.Size{Width: i.width, Height: i.height, Depth: 1},
|
Size: mtl.Size{Width: i.width, Height: i.height, Depth: 1},
|
||||||
}, 0)
|
}, 0)
|
||||||
@ -796,27 +796,27 @@ func (i *Image) Pixels() ([]byte, error) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (i *Image) SetAsDestination() {
|
func (i *Image) SetAsDestination() {
|
||||||
i.driver.t.Call(func() error {
|
i.graphics.t.Call(func() error {
|
||||||
i.driver.dst = i
|
i.graphics.dst = i
|
||||||
return nil
|
return nil
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
func (i *Image) SetAsSource() {
|
func (i *Image) SetAsSource() {
|
||||||
i.driver.t.Call(func() error {
|
i.graphics.t.Call(func() error {
|
||||||
i.driver.src = i
|
i.graphics.src = i
|
||||||
return nil
|
return nil
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
func (i *Image) ReplacePixels(args []*driver.ReplacePixelsArgs) {
|
func (i *Image) ReplacePixels(args []*driver.ReplacePixelsArgs) {
|
||||||
d := i.driver
|
g := i.graphics
|
||||||
if d.drawCalled {
|
if g.drawCalled {
|
||||||
d.flush(true, false)
|
g.flush(true, false)
|
||||||
d.drawCalled = false
|
g.drawCalled = false
|
||||||
}
|
}
|
||||||
|
|
||||||
d.t.Call(func() error {
|
g.t.Call(func() error {
|
||||||
for _, a := range args {
|
for _, a := range args {
|
||||||
i.texture.ReplaceRegion(mtl.Region{
|
i.texture.ReplaceRegion(mtl.Region{
|
||||||
Origin: mtl.Origin{X: a.X, Y: a.Y, Z: 0},
|
Origin: mtl.Origin{X: a.X, Y: a.Y, Z: 0},
|
Loading…
Reference in New Issue
Block a user