experimental/minimal_ios_mtl_skia_app: clean up
Motivation: make is easier to add multiple views sharing a GrContext.
- Split configure_mtk_view() from to_context()
- AppViewDelegate no longer owns GrContext
- Split out config_paint() and draw_example() fns
to delineate example code from useful code.
- AppViewDelegate no longer responsible for initializing
itself.
- AppViewController owns MTLDevice and GrContext.
No-Try: true
Change-Id: I608da76c7818b262c0bfbe52dd431f3007e86e2d
Reviewed-on: https://skia-review.googlesource.com/c/skia/+/240201
Reviewed-by: Jim Van Verth <jvanverth@google.com>
Commit-Queue: Hal Canary <halcanary@google.com>
diff --git a/experimental/minimal_ios_mtl_skia_app/main.mm b/experimental/minimal_ios_mtl_skia_app/main.mm
index a3ab3dc..273a949 100644
--- a/experimental/minimal_ios_mtl_skia_app/main.mm
+++ b/experimental/minimal_ios_mtl_skia_app/main.mm
@@ -22,13 +22,13 @@
////////////////////////////////////////////////////////////////////////////////
-static sk_sp<SkSurface> to_surface(MTKView* view, GrContext* grContext) {
- if (!grContext || view == nil) {
+static sk_sp<SkSurface> to_surface(MTKView* mtkView, GrContext* grContext) {
+ if (!grContext || mtkView == nil) {
return nullptr;
}
- id<CAMetalDrawable> drawable = view.currentDrawable;
- CGSize size = view.drawableSize;
- int sampleCount = (int)view.sampleCount;
+ id<CAMetalDrawable> drawable = mtkView.currentDrawable;
+ CGSize size = mtkView.drawableSize;
+ int sampleCount = (int)mtkView.sampleCount;
int width = (int)size.width;
int height = (int)size.height;
GrMtlTextureInfo fbInfo;
@@ -49,65 +49,68 @@
}
}
-static sk_sp<GrContext> to_context(MTKView* view) {
- // Configure view:
- view.depthStencilPixelFormat = MTLPixelFormatDepth32Float_Stencil8;
- view.colorPixelFormat = MTLPixelFormatBGRA8Unorm;
- view.sampleCount = 1;
-
- GrContextOptions defaultOpts; // set different options here.
- id<MTLCommandQueue> commandQueue = [view.device newCommandQueue];
- // Create long-lived GrContext:
- return GrContext::MakeMetal((__bridge void*)view.device,
- (__bridge void*)(commandQueue),
- defaultOpts);
+static sk_sp<GrContext> to_context(id<MTLDevice> device, const GrContextOptions& opts) {
+ if (device == nil) {
+ return nullptr;
+ }
+ id<MTLCommandQueue> queue = [device newCommandQueue];
+ return GrContext::MakeMetal((__bridge void*)device, (__bridge void*)queue, opts);
}
+
+static void configure_mtk_view(MTKView* mtkView) {
+ mtkView.depthStencilPixelFormat = MTLPixelFormatDepth32Float_Stencil8;
+ mtkView.colorPixelFormat = MTLPixelFormatBGRA8Unorm;
+ mtkView.sampleCount = 1;
+}
+
////////////////////////////////////////////////////////////////////////////////
-@interface AppViewDelegate : NSObject <MTKViewDelegate>
--(nonnull instancetype)initWithMetalKitView:(nonnull MTKView *)view;
-@end
+static void config_paint(SkPaint* paint) {
+ if (!paint->getShader()) {
+ // Perform as much work as possible before creating surface.
+ SkColor4f colors[2] = {SkColors::kBlack, SkColors::kWhite};
+ SkPoint points[2] = {{0, -1024}, {0, 1024}};
+ paint->setShader(SkGradientShader::MakeLinear(points, colors, nullptr, nullptr, 2,
+ SkTileMode::kClamp, 0, nullptr));
+ }
+}
-@implementation AppViewDelegate {
- sk_sp<GrContext> fGrContext;
+static void draw_example(SkSurface* surface, const SkPaint& paint, double rotation) {
+ SkCanvas* canvas = surface->getCanvas();
+ canvas->translate(surface->width() * 0.5f, surface->height() * 0.5f);
+ canvas->rotate(rotation);
+ canvas->drawPaint(paint);
+}
+
+////////////////////////////////////////////////////////////////////////////////
+
+@interface AppViewDelegate : NSObject <MTKViewDelegate> {
+@public
+ GrContext* fGrContext;
SkPaint fPaint;
}
+@end
--(nonnull instancetype)initWithMetalKitView:(nonnull MTKView *)view {
- self = [super init];
- if (view.device == nil) {
- view.device = MTLCreateSystemDefaultDevice();
- }
- fGrContext = to_context(view);
- view.delegate = self;
- return self;
-}
-
+@implementation AppViewDelegate
- (void)drawInMTKView:(nonnull MTKView *)view {
if (!fGrContext || view == nil) {
NSLog(@"error: no context");
return;
}
- if (!fPaint.getShader()) {
- // Perform as much work as possible before creating surface.
- SkColor4f colors[2] = {SkColors::kGreen, SkColors::kMagenta};
- SkPoint points[2] = {{0, -1024}, {0, 1024}};
- fPaint.setShader(SkGradientShader::MakeLinear(points, colors, nullptr, nullptr, 2,
- SkTileMode::kClamp, 0, nullptr));
- }
- float time = (float)(180 * 1e-9 * SkTime::GetNSecs());
+
+ // Do as much as possible before calling to_surface()
+ config_paint(&fPaint);
+ float rotation = (float)(180 * 1e-9 * SkTime::GetNSecs());
+
// Create surface:
- int width = (int)view.drawableSize.width;
- int height = (int)view.drawableSize.height;
- sk_sp<SkSurface> surface = to_surface(view, fGrContext.get());
+ sk_sp<SkSurface> surface = to_surface(view, fGrContext);
if (!surface) {
NSLog(@"error: no sksurface");
return;
}
- SkCanvas* c = surface->getCanvas();
- c->translate(width * 0.5f, height * 0.5f);
- c->rotate(time);
- c->drawPaint(fPaint);
+
+ draw_example(surface.get(), fPaint, rotation);
+
// Must flush *and* present for this to work!
surface->flush();
[view.currentDrawable present];
@@ -120,32 +123,40 @@
////////////////////////////////////////////////////////////////////////////////
-@interface AppViewController : UIViewController
+@interface AppViewController : UIViewController {
+ id<MTLDevice> fMtlDevice;
+ sk_sp<GrContext> fGrContext;
+}
+
@end
@implementation AppViewController
-
- (void)loadView {
self.view = [[MTKView alloc] initWithFrame:[[UIScreen mainScreen] bounds] device:nil];
}
- (void)viewDidLoad {
[super viewDidLoad];
- MTKView *mtkView = (MTKView *)self.view;
- mtkView.device = MTLCreateSystemDefaultDevice();
+ if (!fGrContext) {
+ fMtlDevice = MTLCreateSystemDefaultDevice();
+ GrContextOptions grContextOptions; // set different options here.
+ fGrContext = to_context(fMtlDevice, grContextOptions);
+ }
+ MTKView* mtkView = (MTKView*)self.view;
+ mtkView.device = fMtlDevice;
mtkView.backgroundColor = UIColor.blackColor;
- if(!mtkView.device)
- {
+ configure_mtk_view(mtkView);
+ if(!self.view || !mtkView.device) {
NSLog(@"Metal is not supported on this device");
self.view = [[UIView alloc] initWithFrame:self.view.frame];
return;
}
- AppViewDelegate * viewDelegate = [[AppViewDelegate alloc] initWithMetalKitView:mtkView];
+ AppViewDelegate* viewDelegate = [[AppViewDelegate alloc] init];
+ viewDelegate->fGrContext = fGrContext.get();
[viewDelegate mtkView:mtkView drawableSizeWillChange:mtkView.bounds.size];
mtkView.delegate = viewDelegate;
}
@end
-
////////////////////////////////////////////////////////////////////////////////
@interface AppDelegate : UIResponder <UIApplicationDelegate>