mirror of
https://github.com/hajimehoshi/ebiten.git
synced 2024-12-25 11:18:54 +01:00
cmd/ebitenmobile: Use Metal on iOS
The emulators still use OpenGL. Fixes #737
This commit is contained in:
parent
17d7a33676
commit
3c976eae02
@ -133,21 +133,39 @@ const objcM = `// Code generated by ebitenmobile. DO NOT EDIT.
|
|||||||
|
|
||||||
// +build ios
|
// +build ios
|
||||||
|
|
||||||
|
#import <TargetConditionals.h>
|
||||||
|
|
||||||
|
#if TARGET_IPHONE_SIMULATOR
|
||||||
|
#define EBITEN_METAL 0
|
||||||
|
#else
|
||||||
|
#define EBITEN_METAL 1
|
||||||
|
#endif
|
||||||
|
|
||||||
#import <stdint.h>
|
#import <stdint.h>
|
||||||
#import <UIKit/UIKit.h>
|
#import <UIKit/UIKit.h>
|
||||||
#import <GLKit/GLkit.h>
|
#import <GLKit/GLkit.h>
|
||||||
|
|
||||||
#import "Ebitenmobileview.objc.h"
|
#import "Ebitenmobileview.objc.h"
|
||||||
|
|
||||||
@interface {{.PrefixUpper}}EbitenViewController : UIViewController
|
@interface {{.PrefixUpper}}EbitenViewController : UIViewController
|
||||||
@end
|
@end
|
||||||
|
|
||||||
@implementation {{.PrefixUpper}}EbitenViewController {
|
@implementation {{.PrefixUpper}}EbitenViewController {
|
||||||
|
UIView* metalView_;
|
||||||
GLKView* glkView_;
|
GLKView* glkView_;
|
||||||
bool started_;
|
bool started_;
|
||||||
bool active_;
|
bool active_;
|
||||||
bool error_;
|
bool error_;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
- (UIView*)metalView {
|
||||||
|
if (!metalView_) {
|
||||||
|
metalView_ = [[UIView alloc] init];
|
||||||
|
metalView_.multipleTouchEnabled = YES;
|
||||||
|
}
|
||||||
|
return metalView_;
|
||||||
|
}
|
||||||
|
|
||||||
- (GLKView*)glkView {
|
- (GLKView*)glkView {
|
||||||
if (!glkView_) {
|
if (!glkView_) {
|
||||||
glkView_ = [[GLKView alloc] init];
|
glkView_ = [[GLKView alloc] init];
|
||||||
@ -166,6 +184,10 @@ const objcM = `// Code generated by ebitenmobile. DO NOT EDIT.
|
|||||||
started_ = true;
|
started_ = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#if EBITEN_METAL
|
||||||
|
[self.view addSubview: self.metalView];
|
||||||
|
EbitenmobileviewSetUIView((uintptr_t)(self.metalView));
|
||||||
|
#else
|
||||||
self.glkView.delegate = (id<GLKViewDelegate>)(self);
|
self.glkView.delegate = (id<GLKViewDelegate>)(self);
|
||||||
[self.view addSubview: self.glkView];
|
[self.view addSubview: self.glkView];
|
||||||
|
|
||||||
@ -173,6 +195,7 @@ const objcM = `// Code generated by ebitenmobile. DO NOT EDIT.
|
|||||||
[self glkView].context = context;
|
[self glkView].context = context;
|
||||||
|
|
||||||
[EAGLContext setCurrentContext:context];
|
[EAGLContext setCurrentContext:context];
|
||||||
|
#endif
|
||||||
|
|
||||||
CADisplayLink *displayLink = [CADisplayLink displayLinkWithTarget:self selector:@selector(drawFrame)];
|
CADisplayLink *displayLink = [CADisplayLink displayLinkWithTarget:self selector:@selector(drawFrame)];
|
||||||
[displayLink addToRunLoop:[NSRunLoop currentRunLoop] forMode:NSDefaultRunLoopMode];
|
[displayLink addToRunLoop:[NSRunLoop currentRunLoop] forMode:NSDefaultRunLoopMode];
|
||||||
@ -186,8 +209,12 @@ const objcM = `// Code generated by ebitenmobile. DO NOT EDIT.
|
|||||||
}
|
}
|
||||||
|
|
||||||
- (void)setViewRect:(long)x y:(long)y width:(long)width height:(long)height {
|
- (void)setViewRect:(long)x y:(long)y width:(long)width height:(long)height {
|
||||||
CGRect glkViewRect = CGRectMake(x, y, width, height);
|
CGRect viewRect = CGRectMake(x, y, width, height);
|
||||||
[[self glkView] setFrame:glkViewRect];
|
#if EBITEN_METAL
|
||||||
|
[[self metalView] setFrame:viewRect];
|
||||||
|
#else
|
||||||
|
[[self glkView] setFrame:viewRect];
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
- (void)didReceiveMemoryWarning {
|
- (void)didReceiveMemoryWarning {
|
||||||
@ -202,12 +229,21 @@ const objcM = `// Code generated by ebitenmobile. DO NOT EDIT.
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#if EBITEN_METAL
|
||||||
|
[self updateEbiten];
|
||||||
|
#else
|
||||||
[[self glkView] setNeedsDisplay];
|
[[self glkView] setNeedsDisplay];
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
- (void)glkView:(GLKView*)view drawInRect:(CGRect)rect {
|
- (void)glkView:(GLKView*)view drawInRect:(CGRect)rect {
|
||||||
@synchronized(self) {
|
@synchronized(self) {
|
||||||
|
[self updateEbiten];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
- (void)updateEbiten {
|
||||||
if (error_) {
|
if (error_) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@ -220,7 +256,6 @@ const objcM = `// Code generated by ebitenmobile. DO NOT EDIT.
|
|||||||
error_ = true;
|
error_ = true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
- (void)onErrorOnGameUpdate:(NSError*)err {
|
- (void)onErrorOnGameUpdate:(NSError*)err {
|
||||||
NSLog(@"Error: %@", err);
|
NSLog(@"Error: %@", err);
|
||||||
@ -228,9 +263,15 @@ const objcM = `// Code generated by ebitenmobile. DO NOT EDIT.
|
|||||||
|
|
||||||
- (void)updateTouches:(NSSet*)touches {
|
- (void)updateTouches:(NSSet*)touches {
|
||||||
for (UITouch* touch in touches) {
|
for (UITouch* touch in touches) {
|
||||||
|
#if EBITEN_METAL
|
||||||
|
if (touch.view != [self metalView]) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
#else
|
||||||
if (touch.view != [self glkView]) {
|
if (touch.view != [self glkView]) {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
#endif
|
||||||
CGPoint location = [touch locationInView:touch.view];
|
CGPoint location = [touch locationInView:touch.view];
|
||||||
EbitenmobileviewUpdateTouchesOnIOS(touch.phase, (uintptr_t)touch, location.x, location.y);
|
EbitenmobileviewUpdateTouchesOnIOS(touch.phase, (uintptr_t)touch, location.x, location.y);
|
||||||
}
|
}
|
||||||
@ -252,8 +293,7 @@ const objcM = `// Code generated by ebitenmobile. DO NOT EDIT.
|
|||||||
[self updateTouches:touches];
|
[self updateTouches:touches];
|
||||||
}
|
}
|
||||||
|
|
||||||
- (void)suspendGame
|
- (void)suspendGame {
|
||||||
{
|
|
||||||
NSAssert(started_, @"suspendGame msut not be called before viewDidLoad is called");
|
NSAssert(started_, @"suspendGame msut not be called before viewDidLoad is called");
|
||||||
|
|
||||||
@synchronized(self) {
|
@synchronized(self) {
|
||||||
@ -261,8 +301,7 @@ const objcM = `// Code generated by ebitenmobile. DO NOT EDIT.
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
- (void)resumeGame
|
- (void)resumeGame {
|
||||||
{
|
|
||||||
NSAssert(started_, @"resumeGame msut not be called before viewDidLoad is called");
|
NSAssert(started_, @"resumeGame msut not be called before viewDidLoad is called");
|
||||||
|
|
||||||
@synchronized(self) {
|
@synchronized(self) {
|
||||||
|
File diff suppressed because one or more lines are too long
32
graphicsdriver_ios.go
Normal file
32
graphicsdriver_ios.go
Normal file
@ -0,0 +1,32 @@
|
|||||||
|
// Copyright 2019 The Ebiten Authors
|
||||||
|
//
|
||||||
|
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
// you may not use this file except in compliance with the License.
|
||||||
|
// You may obtain a copy of the License at
|
||||||
|
//
|
||||||
|
// http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
//
|
||||||
|
// Unless required by applicable law or agreed to in writing, software
|
||||||
|
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
// See the License for the specific language governing permissions and
|
||||||
|
// limitations under the License.
|
||||||
|
|
||||||
|
// +build darwin,ios,arm darwin,ios,arm64
|
||||||
|
|
||||||
|
package ebiten
|
||||||
|
|
||||||
|
import (
|
||||||
|
"fmt"
|
||||||
|
|
||||||
|
"github.com/hajimehoshi/ebiten/internal/driver"
|
||||||
|
"github.com/hajimehoshi/ebiten/internal/graphicsdriver/metal"
|
||||||
|
"github.com/hajimehoshi/ebiten/internal/graphicsdriver/metal/mtl"
|
||||||
|
)
|
||||||
|
|
||||||
|
func graphicsDriver() driver.Graphics {
|
||||||
|
if _, err := mtl.CreateSystemDefaultDevice(); err != nil {
|
||||||
|
panic(fmt.Sprintf("ebiten: mtl.CreateSystemDefaultDevice failed on iOS: %v", err))
|
||||||
|
}
|
||||||
|
return metal.Get()
|
||||||
|
}
|
@ -12,7 +12,7 @@
|
|||||||
// See the License for the specific language governing permissions and
|
// See the License for the specific language governing permissions and
|
||||||
// limitations under the License.
|
// limitations under the License.
|
||||||
|
|
||||||
// +build android freebsd ios js linux windows
|
// +build android darwin,ios,386 darwin,ios,amd64 freebsd js linux windows
|
||||||
|
|
||||||
// As the Go playground tries to compile this with CGO_ENABLED=0 and GOOS=linux, check Cgo on build tags.
|
// As the Go playground tries to compile this with CGO_ENABLED=0 and GOOS=linux, check Cgo on build tags.
|
||||||
|
|
||||||
|
@ -344,6 +344,11 @@ func (d *Driver) SetWindow(window uintptr) {
|
|||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (d *Driver) SetUIView(uiview uintptr) {
|
||||||
|
// TODO: Should this be called on the main thread?
|
||||||
|
d.view.setUIView(uiview)
|
||||||
|
}
|
||||||
|
|
||||||
func (d *Driver) SetVertices(vertices []float32, indices []uint16) {
|
func (d *Driver) SetVertices(vertices []float32, indices []uint16) {
|
||||||
d.t.Call(func() error {
|
d.t.Call(func() error {
|
||||||
if d.vb != (mtl.Buffer{}) {
|
if d.vb != (mtl.Buffer{}) {
|
||||||
@ -352,8 +357,8 @@ func (d *Driver) SetVertices(vertices []float32, indices []uint16) {
|
|||||||
if d.ib != (mtl.Buffer{}) {
|
if d.ib != (mtl.Buffer{}) {
|
||||||
d.ib.Release()
|
d.ib.Release()
|
||||||
}
|
}
|
||||||
d.vb = d.view.getMTLDevice().MakeBufferWithBytes(unsafe.Pointer(&vertices[0]), unsafe.Sizeof(vertices[0])*uintptr(len(vertices)), mtl.ResourceStorageModeManaged)
|
d.vb = d.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)), mtl.ResourceStorageModeManaged)
|
d.ib = d.view.getMTLDevice().MakeBufferWithBytes(unsafe.Pointer(&indices[0]), unsafe.Sizeof(indices[0])*uintptr(len(indices)), resourceStorageMode)
|
||||||
return nil
|
return nil
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
@ -404,11 +409,8 @@ func (d *Driver) NewImage(width, height int) (driver.Image, error) {
|
|||||||
PixelFormat: mtl.PixelFormatRGBA8UNorm,
|
PixelFormat: mtl.PixelFormatRGBA8UNorm,
|
||||||
Width: graphics.InternalImageSize(width),
|
Width: graphics.InternalImageSize(width),
|
||||||
Height: graphics.InternalImageSize(height),
|
Height: graphics.InternalImageSize(height),
|
||||||
StorageMode: mtl.StorageModeManaged,
|
StorageMode: storageMode,
|
||||||
|
Usage: textureUsage,
|
||||||
// MTLTextureUsageRenderTarget might cause a problematic render result. Not sure the reason.
|
|
||||||
// Usage: mtl.TextureUsageShaderRead | mtl.TextureUsageRenderTarget
|
|
||||||
Usage: mtl.TextureUsageShaderRead,
|
|
||||||
}
|
}
|
||||||
var t mtl.Texture
|
var t mtl.Texture
|
||||||
d.t.Call(func() error {
|
d.t.Call(func() error {
|
||||||
|
81
internal/graphicsdriver/metal/view.go
Normal file
81
internal/graphicsdriver/metal/view.go
Normal file
@ -0,0 +1,81 @@
|
|||||||
|
// Copyright 2019 The Ebiten Authors
|
||||||
|
//
|
||||||
|
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
// you may not use this file except in compliance with the License.
|
||||||
|
// You may obtain a copy of the License at
|
||||||
|
//
|
||||||
|
// http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
//
|
||||||
|
// Unless required by applicable law or agreed to in writing, software
|
||||||
|
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
// See the License for the specific language governing permissions and
|
||||||
|
// limitations under the License.
|
||||||
|
|
||||||
|
// +build darwin
|
||||||
|
|
||||||
|
package metal
|
||||||
|
|
||||||
|
import (
|
||||||
|
"sync"
|
||||||
|
|
||||||
|
"github.com/hajimehoshi/ebiten/internal/graphicsdriver/metal/ca"
|
||||||
|
"github.com/hajimehoshi/ebiten/internal/graphicsdriver/metal/mtl"
|
||||||
|
)
|
||||||
|
|
||||||
|
type view struct {
|
||||||
|
window uintptr
|
||||||
|
uiview uintptr
|
||||||
|
|
||||||
|
device mtl.Device
|
||||||
|
ml ca.MetalLayer
|
||||||
|
|
||||||
|
once sync.Once
|
||||||
|
}
|
||||||
|
|
||||||
|
func (v *view) setDrawableSize(width, height int) {
|
||||||
|
v.ml.SetDrawableSize(width, height)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (v *view) getMTLDevice() mtl.Device {
|
||||||
|
return v.device
|
||||||
|
}
|
||||||
|
|
||||||
|
func (v *view) setDisplaySyncEnabled(enabled bool) {
|
||||||
|
// TODO: Now SetVsyncEnabled is called only from the main thread, and d.t.Run is not available since
|
||||||
|
// recursive function call via Run is forbidden.
|
||||||
|
// Fix this to use d.t.Run to avoid confusion.
|
||||||
|
v.ml.SetDisplaySyncEnabled(enabled)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (v *view) colorPixelFormat() mtl.PixelFormat {
|
||||||
|
return v.ml.PixelFormat()
|
||||||
|
}
|
||||||
|
|
||||||
|
func (v *view) reset() error {
|
||||||
|
var err error
|
||||||
|
v.device, err = mtl.CreateSystemDefaultDevice()
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
v.ml = ca.MakeMetalLayer()
|
||||||
|
v.ml.SetDevice(v.device)
|
||||||
|
// https://developer.apple.com/documentation/quartzcore/cametallayer/1478155-pixelformat
|
||||||
|
//
|
||||||
|
// The pixel format for a Metal layer must be MTLPixelFormatBGRA8Unorm,
|
||||||
|
// MTLPixelFormatBGRA8Unorm_sRGB, MTLPixelFormatRGBA16Float, MTLPixelFormatBGRA10_XR, or
|
||||||
|
// MTLPixelFormatBGRA10_XR_sRGB.
|
||||||
|
v.ml.SetPixelFormat(mtl.PixelFormatBGRA8UNorm)
|
||||||
|
v.ml.SetMaximumDrawableCount(3)
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (v *view) drawable() ca.MetalDrawable {
|
||||||
|
d, err := v.ml.NextDrawable()
|
||||||
|
if err != nil {
|
||||||
|
// Drawable is nil. This can happen at the initial state. Let's wait and see.
|
||||||
|
return ca.MetalDrawable{}
|
||||||
|
}
|
||||||
|
return d
|
||||||
|
}
|
@ -17,46 +17,49 @@
|
|||||||
|
|
||||||
package metal
|
package metal
|
||||||
|
|
||||||
|
// #cgo CFLAGS: -x objective-c
|
||||||
|
// #cgo LDFLAGS: -framework UIKit
|
||||||
|
//
|
||||||
|
// #import <UIKit/UIKit.h>
|
||||||
|
//
|
||||||
|
// static void addSublayer(void* view, void* sublayer) {
|
||||||
|
// CALayer* layer = ((UIView*)view).layer;
|
||||||
|
// [layer addSublayer:(CALayer*)sublayer];
|
||||||
|
// }
|
||||||
|
//
|
||||||
|
// static void setFrame(void* cametal, void* uiview) {
|
||||||
|
// CGSize size = ((UIView*)uiview).frame.size;
|
||||||
|
// ((CALayer*)cametal).frame = CGRectMake(0, 0, size.width, size.height);
|
||||||
|
// }
|
||||||
|
import "C"
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"github.com/hajimehoshi/ebiten/internal/graphicsdriver/metal/ca"
|
"unsafe"
|
||||||
|
|
||||||
"github.com/hajimehoshi/ebiten/internal/graphicsdriver/metal/mtl"
|
"github.com/hajimehoshi/ebiten/internal/graphicsdriver/metal/mtl"
|
||||||
)
|
)
|
||||||
|
|
||||||
type view struct {
|
|
||||||
}
|
|
||||||
|
|
||||||
func (v *view) setWindow(window uintptr) {
|
func (v *view) setWindow(window uintptr) {
|
||||||
panic("metal: setWindow cannot be called on iOS")
|
panic("metal: setWindow is not available on iOS")
|
||||||
}
|
}
|
||||||
|
|
||||||
func (v *view) setDrawableSize(width, height int) {
|
func (v *view) setUIView(uiview uintptr) {
|
||||||
// Do nothing
|
v.uiview = uiview
|
||||||
}
|
|
||||||
|
|
||||||
func (v *view) getMTLDevice() mtl.Device {
|
|
||||||
// TODO: Implement this
|
|
||||||
return mtl.Device{}
|
|
||||||
}
|
|
||||||
|
|
||||||
func (v *view) setDisplaySyncEnabled(enabled bool) {
|
|
||||||
// Do nothing
|
|
||||||
}
|
|
||||||
|
|
||||||
func (v *view) colorPixelFormat() mtl.PixelFormat {
|
|
||||||
// TODO: Implement this
|
|
||||||
return 0
|
|
||||||
}
|
|
||||||
|
|
||||||
func (v *view) reset() error {
|
|
||||||
// Do nothing
|
|
||||||
return nil
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func (v *view) update() {
|
func (v *view) update() {
|
||||||
// Do nothing
|
v.once.Do(func() {
|
||||||
|
if v.ml.Layer() == nil {
|
||||||
|
panic("metal: CAMetalLayer is not initialized yet")
|
||||||
|
}
|
||||||
|
C.addSublayer(unsafe.Pointer(v.uiview), v.ml.Layer())
|
||||||
|
})
|
||||||
|
C.setFrame(v.ml.Layer(), unsafe.Pointer(v.uiview))
|
||||||
}
|
}
|
||||||
|
|
||||||
func (v *view) drawable() ca.MetalDrawable {
|
const (
|
||||||
// TODO: Implemnt this
|
textureUsage = mtl.TextureUsageShaderRead | mtl.TextureUsageRenderTarget
|
||||||
return ca.MetalDrawable{}
|
|
||||||
}
|
storageMode = mtl.StorageModeShared
|
||||||
|
resourceStorageMode = mtl.ResourceStorageModeShared
|
||||||
|
)
|
||||||
|
@ -18,58 +18,16 @@
|
|||||||
package metal
|
package metal
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"github.com/hajimehoshi/ebiten/internal/graphicsdriver/metal/ca"
|
|
||||||
"github.com/hajimehoshi/ebiten/internal/graphicsdriver/metal/mtl"
|
"github.com/hajimehoshi/ebiten/internal/graphicsdriver/metal/mtl"
|
||||||
"github.com/hajimehoshi/ebiten/internal/graphicsdriver/metal/ns"
|
"github.com/hajimehoshi/ebiten/internal/graphicsdriver/metal/ns"
|
||||||
)
|
)
|
||||||
|
|
||||||
type view struct {
|
|
||||||
window uintptr
|
|
||||||
|
|
||||||
device mtl.Device
|
|
||||||
ml ca.MetalLayer
|
|
||||||
}
|
|
||||||
|
|
||||||
func (v *view) setWindow(window uintptr) {
|
func (v *view) setWindow(window uintptr) {
|
||||||
v.window = window
|
v.window = window
|
||||||
}
|
}
|
||||||
|
|
||||||
func (v *view) setDrawableSize(width, height int) {
|
func (v *view) setUIView(uiview uintptr) {
|
||||||
v.ml.SetDrawableSize(width, height)
|
panic("metal: setUIView is not available on macOS")
|
||||||
}
|
|
||||||
|
|
||||||
func (v *view) getMTLDevice() mtl.Device {
|
|
||||||
return v.device
|
|
||||||
}
|
|
||||||
|
|
||||||
func (v *view) setDisplaySyncEnabled(enabled bool) {
|
|
||||||
// TODO: Now SetVsyncEnabled is called only from the main thread, and d.t.Run is not available since
|
|
||||||
// recursive function call via Run is forbidden.
|
|
||||||
// Fix this to use d.t.Run to avoid confusion.
|
|
||||||
v.ml.SetDisplaySyncEnabled(enabled)
|
|
||||||
}
|
|
||||||
|
|
||||||
func (v *view) colorPixelFormat() mtl.PixelFormat {
|
|
||||||
return v.ml.PixelFormat()
|
|
||||||
}
|
|
||||||
|
|
||||||
func (v *view) reset() error {
|
|
||||||
var err error
|
|
||||||
v.device, err = mtl.CreateSystemDefaultDevice()
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
|
|
||||||
v.ml = ca.MakeMetalLayer()
|
|
||||||
v.ml.SetDevice(v.device)
|
|
||||||
// https://developer.apple.com/documentation/quartzcore/cametallayer/1478155-pixelformat
|
|
||||||
//
|
|
||||||
// The pixel format for a Metal layer must be MTLPixelFormatBGRA8Unorm,
|
|
||||||
// MTLPixelFormatBGRA8Unorm_sRGB, MTLPixelFormatRGBA16Float, MTLPixelFormatBGRA10_XR, or
|
|
||||||
// MTLPixelFormatBGRA10_XR_sRGB.
|
|
||||||
v.ml.SetPixelFormat(mtl.PixelFormatBGRA8UNorm)
|
|
||||||
v.ml.SetMaximumDrawableCount(3)
|
|
||||||
return nil
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func (v *view) update() {
|
func (v *view) update() {
|
||||||
@ -79,11 +37,10 @@ func (v *view) update() {
|
|||||||
cocoaWindow.ContentView().SetWantsLayer(true)
|
cocoaWindow.ContentView().SetWantsLayer(true)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (v *view) drawable() ca.MetalDrawable {
|
const (
|
||||||
d, err := v.ml.NextDrawable()
|
// MTLTextureUsageRenderTarget might cause a problematic render result. Not sure the reason.
|
||||||
if err != nil {
|
textureUsage = mtl.TextureUsageShaderRead
|
||||||
// Drawable is nil. This can happen at the initial state. Let's wait and see.
|
|
||||||
return ca.MetalDrawable{}
|
storageMode = mtl.StorageModeManaged
|
||||||
}
|
resourceStorageMode = mtl.ResourceStorageModeManaged
|
||||||
return d
|
)
|
||||||
}
|
|
||||||
|
@ -34,6 +34,7 @@ import (
|
|||||||
"github.com/hajimehoshi/ebiten/internal/devicescale"
|
"github.com/hajimehoshi/ebiten/internal/devicescale"
|
||||||
"github.com/hajimehoshi/ebiten/internal/driver"
|
"github.com/hajimehoshi/ebiten/internal/driver"
|
||||||
"github.com/hajimehoshi/ebiten/internal/graphicsdriver/opengl"
|
"github.com/hajimehoshi/ebiten/internal/graphicsdriver/opengl"
|
||||||
|
"github.com/hajimehoshi/ebiten/internal/thread"
|
||||||
)
|
)
|
||||||
|
|
||||||
var (
|
var (
|
||||||
@ -61,7 +62,14 @@ func (u *UserInterface) Render() {
|
|||||||
ctx, cancel := context.WithCancel(context.Background())
|
ctx, cancel := context.WithCancel(context.Background())
|
||||||
go func() {
|
go func() {
|
||||||
<-renderEndCh
|
<-renderEndCh
|
||||||
|
if u.t != nil {
|
||||||
|
u.t.Call(func() error {
|
||||||
cancel()
|
cancel()
|
||||||
|
return nil
|
||||||
|
})
|
||||||
|
} else {
|
||||||
|
cancel()
|
||||||
|
}
|
||||||
}()
|
}()
|
||||||
|
|
||||||
if u.graphics.IsGL() {
|
if u.graphics.IsGL() {
|
||||||
@ -79,9 +87,9 @@ func (u *UserInterface) Render() {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
return
|
return
|
||||||
|
} else {
|
||||||
|
u.t.Loop(ctx)
|
||||||
}
|
}
|
||||||
|
|
||||||
// TODO: Create and run the thread loop like the GLFW driver does.
|
|
||||||
}
|
}
|
||||||
|
|
||||||
type UserInterface struct {
|
type UserInterface struct {
|
||||||
@ -99,6 +107,7 @@ type UserInterface struct {
|
|||||||
|
|
||||||
input Input
|
input Input
|
||||||
|
|
||||||
|
t *thread.Thread
|
||||||
glWorker gl.Worker
|
glWorker gl.Worker
|
||||||
|
|
||||||
m sync.RWMutex
|
m sync.RWMutex
|
||||||
@ -211,6 +220,9 @@ func (u *UserInterface) run(width, height int, scale float64, title string, cont
|
|||||||
ctx, u.glWorker = gl.NewContext()
|
ctx, u.glWorker = gl.NewContext()
|
||||||
}
|
}
|
||||||
graphics.(*opengl.Driver).SetMobileGLContext(ctx)
|
graphics.(*opengl.Driver).SetMobileGLContext(ctx)
|
||||||
|
} else {
|
||||||
|
u.t = thread.New()
|
||||||
|
graphics.SetThread(u.t)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Force to set the screen size
|
// Force to set the screen size
|
||||||
|
@ -81,3 +81,7 @@ func UpdateTouchesOnAndroid(action int, id int, x, y int) {
|
|||||||
func UpdateTouchesOnIOS(phase int, ptr int64, x, y int) {
|
func UpdateTouchesOnIOS(phase int, ptr int64, x, y int) {
|
||||||
updateTouchesOnIOSImpl(phase, ptr, x, y)
|
updateTouchesOnIOSImpl(phase, ptr, x, y)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func SetUIView(uiview int64) {
|
||||||
|
setUIView(uintptr(uiview))
|
||||||
|
}
|
||||||
|
25
mobile/ebitenmobileview/impl_metal.go
Normal file
25
mobile/ebitenmobileview/impl_metal.go
Normal file
@ -0,0 +1,25 @@
|
|||||||
|
// Copyright 2019 The Ebiten Authors
|
||||||
|
//
|
||||||
|
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
// you may not use this file except in compliance with the License.
|
||||||
|
// You may obtain a copy of the License at
|
||||||
|
//
|
||||||
|
// http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
//
|
||||||
|
// Unless required by applicable law or agreed to in writing, software
|
||||||
|
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
// See the License for the specific language governing permissions and
|
||||||
|
// limitations under the License.
|
||||||
|
|
||||||
|
// +build darwin,ios,arm darwin,ios,arm64
|
||||||
|
|
||||||
|
package ebitenmobileview
|
||||||
|
|
||||||
|
import (
|
||||||
|
"github.com/hajimehoshi/ebiten/internal/graphicsdriver/metal"
|
||||||
|
)
|
||||||
|
|
||||||
|
func setUIView(uiview uintptr) {
|
||||||
|
metal.Get().SetUIView(uiview)
|
||||||
|
}
|
22
mobile/ebitenmobileview/impl_notmetal.go
Normal file
22
mobile/ebitenmobileview/impl_notmetal.go
Normal file
@ -0,0 +1,22 @@
|
|||||||
|
// Copyright 2019 The Ebiten Authors
|
||||||
|
//
|
||||||
|
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
// you may not use this file except in compliance with the License.
|
||||||
|
// You may obtain a copy of the License at
|
||||||
|
//
|
||||||
|
// http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
//
|
||||||
|
// Unless required by applicable law or agreed to in writing, software
|
||||||
|
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
// See the License for the specific language governing permissions and
|
||||||
|
// limitations under the License.
|
||||||
|
|
||||||
|
// +build darwin,ios,!arm
|
||||||
|
// +build darwin,ios,!arm64
|
||||||
|
|
||||||
|
package ebitenmobileview
|
||||||
|
|
||||||
|
func setUIView(uiview uintptr) {
|
||||||
|
panic("ebitenmobileview: setUIView is not available on this platform")
|
||||||
|
}
|
@ -36,3 +36,6 @@ func updateTouchesOnAndroid(action int, id int, x, y int) {
|
|||||||
|
|
||||||
func updateTouchesOnIOSImpl(phase int, ptr int64, x, y int) {
|
func updateTouchesOnIOSImpl(phase int, ptr int64, x, y int) {
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func setUIView(uiview uintptr) {
|
||||||
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user