1/* 2 * Copyright 2019 Google Inc. 3 * 4 * Use of this source code is governed by a BSD-style license that can be 5 * found in the LICENSE file. 6 */ 7 8#include "tools/sk_app/MetalWindowContext.h" 9#include "tools/sk_app/ios/WindowContextFactory_ios.h" 10 11#import <Metal/Metal.h> 12#import <UIKit/UIKit.h> 13 14using sk_app::DisplayParams; 15using sk_app::window_context_factory::IOSWindowInfo; 16using sk_app::MetalWindowContext; 17 18@interface MetalView : MainView 19@end 20 21@implementation MetalView 22+ (Class) layerClass { 23 return [CAMetalLayer class]; 24} 25@end 26 27namespace { 28 29class MetalWindowContext_ios : public MetalWindowContext { 30public: 31 MetalWindowContext_ios(const IOSWindowInfo&, const DisplayParams&); 32 33 ~MetalWindowContext_ios() override; 34 35 bool onInitializeContext() override; 36 void onDestroyContext() override; 37 38 void resize(int w, int h) override; 39 40private: 41 sk_app::Window_ios* fWindow; 42 UIViewController* fViewController; 43 MetalView* fMetalView; 44 45 using INHERITED = MetalWindowContext; 46}; 47 48MetalWindowContext_ios::MetalWindowContext_ios(const IOSWindowInfo& info, 49 const DisplayParams& params) 50 : INHERITED(params) 51 , fWindow(info.fWindow) 52 , fViewController(info.fViewController) { 53 54 // any config code here (particularly for msaa)? 55 56 this->initializeContext(); 57} 58 59MetalWindowContext_ios::~MetalWindowContext_ios() { 60 this->destroyContext(); 61 [fMetalView removeFromSuperview]; 62 [fMetalView release]; 63} 64 65bool MetalWindowContext_ios::onInitializeContext() { 66 SkASSERT(nil != fWindow); 67 SkASSERT(nil != fViewController); 68 69 CGRect frameRect = [fViewController.view frame]; 70 fMetalView = [[[MetalView alloc] initWithFrame:frameRect] initWithWindow:fWindow]; 71 [fViewController.view addSubview:fMetalView]; 72 73 fMetalLayer = (CAMetalLayer*)fMetalView.layer; 74 fMetalLayer.device = fDevice.get(); 75 fMetalLayer.pixelFormat = MTLPixelFormatBGRA8Unorm; 76 fMetalLayer.drawableSize = frameRect.size; 77 fMetalLayer.frame = frameRect; 78 79 // TODO: need solution for iOS 80 // BOOL useVsync = fDisplayParams.fDisableVsync ? NO : YES; 81 // fMetalLayer.displaySyncEnabled = useVsync; 82 fMetalLayer.contentsGravity = kCAGravityTopLeft; 83 84 fWidth = frameRect.size.width; 85 fHeight = frameRect.size.height; 86 87 return true; 88} 89 90void MetalWindowContext_ios::onDestroyContext() {} 91 92void MetalWindowContext_ios::resize(int w, int h) { 93 // TODO: handle rotation 94 fMetalLayer.drawableSize = fMetalView.frame.size; 95 fMetalLayer.frame = fMetalView.frame; 96 fWidth = w; 97 fHeight = h; 98} 99 100} // anonymous namespace 101 102namespace sk_app { 103namespace window_context_factory { 104 105std::unique_ptr<WindowContext> MakeMetalForIOS(const IOSWindowInfo& info, 106 const DisplayParams& params) { 107 std::unique_ptr<WindowContext> ctx(new MetalWindowContext_ios(info, params)); 108 if (!ctx->isValid()) { 109 return nullptr; 110 } 111 return ctx; 112} 113 114} // namespace window_context_factory 115} // namespace sk_app 116