1cb93a386Sopenharmony_ci// Copyright 2019 Google LLC. 2cb93a386Sopenharmony_ci// Use of this source code is governed by a BSD-style license that can be found in the LICENSE file. 3cb93a386Sopenharmony_ci 4cb93a386Sopenharmony_ci// This is an example of a minimal iOS application that uses Skia to draw to 5cb93a386Sopenharmony_ci// a Metal drawable. 6cb93a386Sopenharmony_ci 7cb93a386Sopenharmony_ci// Much of this code is copied from the default application created by XCode. 8cb93a386Sopenharmony_ci 9cb93a386Sopenharmony_ci#include "tools/skottie_ios_app/SkMetalViewBridge.h" 10cb93a386Sopenharmony_ci 11cb93a386Sopenharmony_ci#include "include/core/SkCanvas.h" 12cb93a386Sopenharmony_ci#include "include/core/SkPaint.h" 13cb93a386Sopenharmony_ci#include "include/core/SkSurface.h" 14cb93a386Sopenharmony_ci#include "include/core/SkTime.h" 15cb93a386Sopenharmony_ci#include "include/effects/SkGradientShader.h" 16cb93a386Sopenharmony_ci#include "include/gpu/GrBackendSurface.h" 17cb93a386Sopenharmony_ci#include "include/gpu/GrDirectContext.h" 18cb93a386Sopenharmony_ci#include "include/gpu/mtl/GrMtlTypes.h" 19cb93a386Sopenharmony_ci 20cb93a386Sopenharmony_ci#import <Metal/Metal.h> 21cb93a386Sopenharmony_ci#import <MetalKit/MetalKit.h> 22cb93a386Sopenharmony_ci#import <UIKit/UIKit.h> 23cb93a386Sopenharmony_ci 24cb93a386Sopenharmony_ci//////////////////////////////////////////////////////////////////////////////// 25cb93a386Sopenharmony_ci 26cb93a386Sopenharmony_cistatic void config_paint(SkPaint* paint) { 27cb93a386Sopenharmony_ci if (!paint->getShader()) { 28cb93a386Sopenharmony_ci const SkColor4f colors[2] = {SkColors::kBlack, SkColors::kWhite}; 29cb93a386Sopenharmony_ci const SkPoint points[2] = {{0, -1024}, {0, 1024}}; 30cb93a386Sopenharmony_ci paint->setShader(SkGradientShader::MakeLinear(points, colors, nullptr, nullptr, 2, 31cb93a386Sopenharmony_ci SkTileMode::kClamp, 0, nullptr)); 32cb93a386Sopenharmony_ci } 33cb93a386Sopenharmony_ci} 34cb93a386Sopenharmony_ci 35cb93a386Sopenharmony_cistatic void draw_example(SkSurface* surface, const SkPaint& paint, double rotation) { 36cb93a386Sopenharmony_ci SkCanvas* canvas = surface->getCanvas(); 37cb93a386Sopenharmony_ci canvas->translate(surface->width() * 0.5f, surface->height() * 0.5f); 38cb93a386Sopenharmony_ci canvas->rotate(rotation); 39cb93a386Sopenharmony_ci canvas->drawPaint(paint); 40cb93a386Sopenharmony_ci} 41cb93a386Sopenharmony_ci 42cb93a386Sopenharmony_ci//////////////////////////////////////////////////////////////////////////////// 43cb93a386Sopenharmony_ci 44cb93a386Sopenharmony_ci@interface AppViewDelegate : NSObject <MTKViewDelegate> 45cb93a386Sopenharmony_ci@property (assign, nonatomic) GrDirectContext* grContext; // non-owning pointer. 46cb93a386Sopenharmony_ci@property (assign, nonatomic) id<MTLCommandQueue> metalQueue; 47cb93a386Sopenharmony_ci@end 48cb93a386Sopenharmony_ci 49cb93a386Sopenharmony_ci@implementation AppViewDelegate { 50cb93a386Sopenharmony_ci SkPaint fPaint; 51cb93a386Sopenharmony_ci} 52cb93a386Sopenharmony_ci 53cb93a386Sopenharmony_ci- (void)drawInMTKView:(nonnull MTKView *)view { 54cb93a386Sopenharmony_ci if (![self grContext] || !view) { 55cb93a386Sopenharmony_ci return; 56cb93a386Sopenharmony_ci } 57cb93a386Sopenharmony_ci // Do as much as possible before creating surface. 58cb93a386Sopenharmony_ci config_paint(&fPaint); 59cb93a386Sopenharmony_ci float rotation = (float)(180 * 1e-9 * SkTime::GetNSecs()); 60cb93a386Sopenharmony_ci 61cb93a386Sopenharmony_ci // Create surface: 62cb93a386Sopenharmony_ci sk_sp<SkSurface> surface = SkMtkViewToSurface(view, [self grContext]); 63cb93a386Sopenharmony_ci if (!surface) { 64cb93a386Sopenharmony_ci NSLog(@"error: no sksurface"); 65cb93a386Sopenharmony_ci return; 66cb93a386Sopenharmony_ci } 67cb93a386Sopenharmony_ci 68cb93a386Sopenharmony_ci draw_example(surface.get(), fPaint, rotation); 69cb93a386Sopenharmony_ci 70cb93a386Sopenharmony_ci // Must flush *and* present for this to work! 71cb93a386Sopenharmony_ci surface->flushAndSubmit(); 72cb93a386Sopenharmony_ci surface = nullptr; 73cb93a386Sopenharmony_ci 74cb93a386Sopenharmony_ci id<MTLCommandBuffer> commandBuffer = [[self metalQueue] commandBuffer]; 75cb93a386Sopenharmony_ci [commandBuffer presentDrawable:[view currentDrawable]]; 76cb93a386Sopenharmony_ci [commandBuffer commit]; 77cb93a386Sopenharmony_ci} 78cb93a386Sopenharmony_ci 79cb93a386Sopenharmony_ci- (void)mtkView:(nonnull MTKView *)view drawableSizeWillChange:(CGSize)size { 80cb93a386Sopenharmony_ci // change anything on size change? 81cb93a386Sopenharmony_ci} 82cb93a386Sopenharmony_ci@end 83cb93a386Sopenharmony_ci 84cb93a386Sopenharmony_ci//////////////////////////////////////////////////////////////////////////////// 85cb93a386Sopenharmony_ci 86cb93a386Sopenharmony_ci@interface AppViewController : UIViewController 87cb93a386Sopenharmony_ci@property (strong, nonatomic) id<MTLDevice> metalDevice; 88cb93a386Sopenharmony_ci@property (strong, nonatomic) id<MTLCommandQueue> metalQueue; 89cb93a386Sopenharmony_ci@end 90cb93a386Sopenharmony_ci 91cb93a386Sopenharmony_ci@implementation AppViewController { 92cb93a386Sopenharmony_ci GrContextHolder fGrContext; 93cb93a386Sopenharmony_ci} 94cb93a386Sopenharmony_ci 95cb93a386Sopenharmony_ci- (void)loadView { 96cb93a386Sopenharmony_ci [self setView:[[MTKView alloc] initWithFrame:[[UIScreen mainScreen] bounds] device:nil]]; 97cb93a386Sopenharmony_ci} 98cb93a386Sopenharmony_ci 99cb93a386Sopenharmony_ci- (void)viewDidLoad { 100cb93a386Sopenharmony_ci [super viewDidLoad]; 101cb93a386Sopenharmony_ci if (!fGrContext) { 102cb93a386Sopenharmony_ci [self setMetalDevice:MTLCreateSystemDefaultDevice()]; 103cb93a386Sopenharmony_ci [self setMetalQueue:[[self metalDevice] newCommandQueue]]; 104cb93a386Sopenharmony_ci fGrContext = SkMetalDeviceToGrContext([self metalDevice], [self metalQueue]); 105cb93a386Sopenharmony_ci } 106cb93a386Sopenharmony_ci if (![self view] || ![self metalDevice]) { 107cb93a386Sopenharmony_ci NSLog(@"Metal is not supported on this device"); 108cb93a386Sopenharmony_ci self.view = [[UIView alloc] initWithFrame:self.view.frame]; 109cb93a386Sopenharmony_ci return; 110cb93a386Sopenharmony_ci } 111cb93a386Sopenharmony_ci MTKView* mtkView = (MTKView*)[self view]; 112cb93a386Sopenharmony_ci [mtkView setDevice:[self metalDevice]]; 113cb93a386Sopenharmony_ci [mtkView setBackgroundColor:[UIColor blackColor]]; 114cb93a386Sopenharmony_ci SkMtkViewConfigForSkia(mtkView); 115cb93a386Sopenharmony_ci AppViewDelegate* viewDelegate = [[AppViewDelegate alloc] init]; 116cb93a386Sopenharmony_ci [viewDelegate setGrContext:fGrContext.get()]; 117cb93a386Sopenharmony_ci [viewDelegate setMetalQueue:[self metalQueue]]; 118cb93a386Sopenharmony_ci [viewDelegate mtkView:mtkView drawableSizeWillChange:[mtkView bounds].size]; 119cb93a386Sopenharmony_ci [mtkView setDelegate:viewDelegate]; 120cb93a386Sopenharmony_ci} 121cb93a386Sopenharmony_ci@end 122cb93a386Sopenharmony_ci 123cb93a386Sopenharmony_ci//////////////////////////////////////////////////////////////////////////////// 124cb93a386Sopenharmony_ci 125cb93a386Sopenharmony_ci@interface AppDelegate : UIResponder <UIApplicationDelegate> 126cb93a386Sopenharmony_ci@property (strong, nonatomic) UIWindow *window; 127cb93a386Sopenharmony_ci@end 128cb93a386Sopenharmony_ci 129cb93a386Sopenharmony_ci@implementation AppDelegate 130cb93a386Sopenharmony_ci- (BOOL)application:(UIApplication *)app didFinishLaunchingWithOptions:(NSDictionary*)opts { 131cb93a386Sopenharmony_ci // Override point for customization after application launch. 132cb93a386Sopenharmony_ci [self setWindow:[[UIWindow alloc] initWithFrame:[[UIScreen mainScreen] bounds]]]; 133cb93a386Sopenharmony_ci [[self window] setFrame:[[UIScreen mainScreen] bounds]]; 134cb93a386Sopenharmony_ci [[self window] setRootViewController:[[AppViewController alloc] init]]; 135cb93a386Sopenharmony_ci [[self window] makeKeyAndVisible]; 136cb93a386Sopenharmony_ci return YES; 137cb93a386Sopenharmony_ci} 138cb93a386Sopenharmony_ci@end 139cb93a386Sopenharmony_ci 140cb93a386Sopenharmony_ci//////////////////////////////////////////////////////////////////////////////// 141cb93a386Sopenharmony_ci 142cb93a386Sopenharmony_ciint main(int argc, char* argv[]) { 143cb93a386Sopenharmony_ci @autoreleasepool { 144cb93a386Sopenharmony_ci return UIApplicationMain(argc, argv, nil, NSStringFromClass([AppDelegate class])); 145cb93a386Sopenharmony_ci } 146cb93a386Sopenharmony_ci} 147