1cb93a386Sopenharmony_ci 2cb93a386Sopenharmony_ci/* 3cb93a386Sopenharmony_ci * Copyright 2019 Google Inc. 4cb93a386Sopenharmony_ci * 5cb93a386Sopenharmony_ci * Use of this source code is governed by a BSD-style license that can be 6cb93a386Sopenharmony_ci * found in the LICENSE file. 7cb93a386Sopenharmony_ci */ 8cb93a386Sopenharmony_ci 9cb93a386Sopenharmony_ci#include "include/core/SkCanvas.h" 10cb93a386Sopenharmony_ci#include "include/core/SkColorFilter.h" 11cb93a386Sopenharmony_ci#include "include/gpu/gl/GrGLInterface.h" 12cb93a386Sopenharmony_ci#include "tools/ToolUtils.h" 13cb93a386Sopenharmony_ci#include "tools/sk_app/GLWindowContext.h" 14cb93a386Sopenharmony_ci#include "tools/sk_app/ios/WindowContextFactory_ios.h" 15cb93a386Sopenharmony_ci 16cb93a386Sopenharmony_ci#import <OpenGLES/ES3/gl.h> 17cb93a386Sopenharmony_ci#import <UIKit/UIKit.h> 18cb93a386Sopenharmony_ci 19cb93a386Sopenharmony_ciusing sk_app::DisplayParams; 20cb93a386Sopenharmony_ciusing sk_app::window_context_factory::IOSWindowInfo; 21cb93a386Sopenharmony_ciusing sk_app::GLWindowContext; 22cb93a386Sopenharmony_ci 23cb93a386Sopenharmony_ci@interface RasterView : MainView 24cb93a386Sopenharmony_ci@end 25cb93a386Sopenharmony_ci 26cb93a386Sopenharmony_ci@implementation RasterView 27cb93a386Sopenharmony_ci+ (Class) layerClass { 28cb93a386Sopenharmony_ci return [CAEAGLLayer class]; 29cb93a386Sopenharmony_ci} 30cb93a386Sopenharmony_ci@end 31cb93a386Sopenharmony_ci 32cb93a386Sopenharmony_cinamespace { 33cb93a386Sopenharmony_ci 34cb93a386Sopenharmony_ci// TODO: This still uses GL to handle the update rather than using a purely raster backend, 35cb93a386Sopenharmony_ci// for historical reasons. Writing a pure raster backend would be better in the long run. 36cb93a386Sopenharmony_ci 37cb93a386Sopenharmony_ciclass RasterWindowContext_ios : public GLWindowContext { 38cb93a386Sopenharmony_cipublic: 39cb93a386Sopenharmony_ci RasterWindowContext_ios(const IOSWindowInfo&, const DisplayParams&); 40cb93a386Sopenharmony_ci 41cb93a386Sopenharmony_ci ~RasterWindowContext_ios() override; 42cb93a386Sopenharmony_ci 43cb93a386Sopenharmony_ci sk_sp<SkSurface> getBackbufferSurface() override; 44cb93a386Sopenharmony_ci 45cb93a386Sopenharmony_ci void onSwapBuffers() override; 46cb93a386Sopenharmony_ci 47cb93a386Sopenharmony_ci sk_sp<const GrGLInterface> onInitializeContext() override; 48cb93a386Sopenharmony_ci void onDestroyContext() override; 49cb93a386Sopenharmony_ci 50cb93a386Sopenharmony_ci void resize(int w, int h) override; 51cb93a386Sopenharmony_ci 52cb93a386Sopenharmony_ciprivate: 53cb93a386Sopenharmony_ci sk_app::Window_ios* fWindow; 54cb93a386Sopenharmony_ci UIViewController* fViewController; 55cb93a386Sopenharmony_ci RasterView* fRasterView; 56cb93a386Sopenharmony_ci EAGLContext* fGLContext; 57cb93a386Sopenharmony_ci GLuint fFramebuffer; 58cb93a386Sopenharmony_ci GLuint fRenderbuffer; 59cb93a386Sopenharmony_ci sk_sp<SkSurface> fBackbufferSurface; 60cb93a386Sopenharmony_ci 61cb93a386Sopenharmony_ci using INHERITED = GLWindowContext; 62cb93a386Sopenharmony_ci}; 63cb93a386Sopenharmony_ci 64cb93a386Sopenharmony_ciRasterWindowContext_ios::RasterWindowContext_ios(const IOSWindowInfo& info, 65cb93a386Sopenharmony_ci const DisplayParams& params) 66cb93a386Sopenharmony_ci : INHERITED(params) 67cb93a386Sopenharmony_ci , fWindow(info.fWindow) 68cb93a386Sopenharmony_ci , fViewController(info.fViewController) 69cb93a386Sopenharmony_ci , fGLContext(nil) { 70cb93a386Sopenharmony_ci 71cb93a386Sopenharmony_ci // any config code here (particularly for msaa)? 72cb93a386Sopenharmony_ci 73cb93a386Sopenharmony_ci this->initializeContext(); 74cb93a386Sopenharmony_ci} 75cb93a386Sopenharmony_ci 76cb93a386Sopenharmony_ciRasterWindowContext_ios::~RasterWindowContext_ios() { 77cb93a386Sopenharmony_ci this->destroyContext(); 78cb93a386Sopenharmony_ci [fRasterView removeFromSuperview]; 79cb93a386Sopenharmony_ci [fRasterView release]; 80cb93a386Sopenharmony_ci} 81cb93a386Sopenharmony_ci 82cb93a386Sopenharmony_cisk_sp<const GrGLInterface> RasterWindowContext_ios::onInitializeContext() { 83cb93a386Sopenharmony_ci SkASSERT(nil != fViewController); 84cb93a386Sopenharmony_ci SkASSERT(!fGLContext); 85cb93a386Sopenharmony_ci 86cb93a386Sopenharmony_ci CGRect frameRect = [fViewController.view frame]; 87cb93a386Sopenharmony_ci fRasterView = [[[RasterView alloc] initWithFrame:frameRect] initWithWindow:fWindow]; 88cb93a386Sopenharmony_ci [fViewController.view addSubview:fRasterView]; 89cb93a386Sopenharmony_ci 90cb93a386Sopenharmony_ci fGLContext = [[EAGLContext alloc] initWithAPI:kEAGLRenderingAPIOpenGLES3]; 91cb93a386Sopenharmony_ci 92cb93a386Sopenharmony_ci if (!fGLContext) 93cb93a386Sopenharmony_ci { 94cb93a386Sopenharmony_ci SkDebugf("Could Not Create OpenGL ES Context\n"); 95cb93a386Sopenharmony_ci return nullptr; 96cb93a386Sopenharmony_ci } 97cb93a386Sopenharmony_ci 98cb93a386Sopenharmony_ci if (![EAGLContext setCurrentContext:fGLContext]) { 99cb93a386Sopenharmony_ci SkDebugf("Could Not Set OpenGL ES Context As Current\n"); 100cb93a386Sopenharmony_ci this->onDestroyContext(); 101cb93a386Sopenharmony_ci return nullptr; 102cb93a386Sopenharmony_ci } 103cb93a386Sopenharmony_ci 104cb93a386Sopenharmony_ci // Set up EAGLLayer 105cb93a386Sopenharmony_ci CAEAGLLayer* eaglLayer = (CAEAGLLayer*)fRasterView.layer; 106cb93a386Sopenharmony_ci eaglLayer.drawableProperties = @{kEAGLDrawablePropertyRetainedBacking : @NO, 107cb93a386Sopenharmony_ci kEAGLDrawablePropertyColorFormat : kEAGLColorFormatRGBA8 }; 108cb93a386Sopenharmony_ci eaglLayer.opaque = YES; 109cb93a386Sopenharmony_ci eaglLayer.frame = frameRect; 110cb93a386Sopenharmony_ci eaglLayer.contentsGravity = kCAGravityTopLeft; 111cb93a386Sopenharmony_ci 112cb93a386Sopenharmony_ci // Set up framebuffer 113cb93a386Sopenharmony_ci glGenFramebuffers(1, &fFramebuffer); 114cb93a386Sopenharmony_ci glBindFramebuffer(GL_FRAMEBUFFER, fFramebuffer); 115cb93a386Sopenharmony_ci 116cb93a386Sopenharmony_ci glGenRenderbuffers(1, &fRenderbuffer); 117cb93a386Sopenharmony_ci glBindRenderbuffer(GL_RENDERBUFFER, fRenderbuffer); 118cb93a386Sopenharmony_ci glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_RENDERBUFFER, fRenderbuffer); 119cb93a386Sopenharmony_ci 120cb93a386Sopenharmony_ci [fGLContext renderbufferStorage:GL_RENDERBUFFER fromDrawable:eaglLayer]; 121cb93a386Sopenharmony_ci 122cb93a386Sopenharmony_ci GLenum status = glCheckFramebufferStatus(GL_FRAMEBUFFER); 123cb93a386Sopenharmony_ci if (status != GL_FRAMEBUFFER_COMPLETE) { 124cb93a386Sopenharmony_ci SkDebugf("Invalid Framebuffer\n"); 125cb93a386Sopenharmony_ci this->onDestroyContext(); 126cb93a386Sopenharmony_ci return nullptr; 127cb93a386Sopenharmony_ci } 128cb93a386Sopenharmony_ci 129cb93a386Sopenharmony_ci glClearStencil(0); 130cb93a386Sopenharmony_ci glClearColor(0, 0, 0, 255); 131cb93a386Sopenharmony_ci glStencilMask(0xffffffff); 132cb93a386Sopenharmony_ci glClear(GL_STENCIL_BUFFER_BIT | GL_COLOR_BUFFER_BIT); 133cb93a386Sopenharmony_ci 134cb93a386Sopenharmony_ci fStencilBits = 8; 135cb93a386Sopenharmony_ci fSampleCount = 1; // TODO: handle multisampling 136cb93a386Sopenharmony_ci 137cb93a386Sopenharmony_ci fWidth = fViewController.view.frame.size.width; 138cb93a386Sopenharmony_ci fHeight = fViewController.view.frame.size.height; 139cb93a386Sopenharmony_ci 140cb93a386Sopenharmony_ci glViewport(0, 0, fWidth, fHeight); 141cb93a386Sopenharmony_ci 142cb93a386Sopenharmony_ci // make the offscreen image 143cb93a386Sopenharmony_ci SkImageInfo info = SkImageInfo::Make(fWidth, fHeight, fDisplayParams.fColorType, 144cb93a386Sopenharmony_ci kPremul_SkAlphaType, fDisplayParams.fColorSpace); 145cb93a386Sopenharmony_ci fBackbufferSurface = SkSurface::MakeRaster(info); 146cb93a386Sopenharmony_ci return GrGLMakeNativeInterface(); 147cb93a386Sopenharmony_ci} 148cb93a386Sopenharmony_ci 149cb93a386Sopenharmony_civoid RasterWindowContext_ios::onDestroyContext() { 150cb93a386Sopenharmony_ci glDeleteFramebuffers(1, &fFramebuffer); 151cb93a386Sopenharmony_ci glDeleteRenderbuffers(1, &fRenderbuffer); 152cb93a386Sopenharmony_ci [EAGLContext setCurrentContext:nil]; 153cb93a386Sopenharmony_ci [fGLContext release]; 154cb93a386Sopenharmony_ci fGLContext = nil; 155cb93a386Sopenharmony_ci} 156cb93a386Sopenharmony_ci 157cb93a386Sopenharmony_cisk_sp<SkSurface> RasterWindowContext_ios::getBackbufferSurface() { 158cb93a386Sopenharmony_ci return fBackbufferSurface; 159cb93a386Sopenharmony_ci} 160cb93a386Sopenharmony_ci 161cb93a386Sopenharmony_civoid RasterWindowContext_ios::onSwapBuffers() { 162cb93a386Sopenharmony_ci if (fBackbufferSurface) { 163cb93a386Sopenharmony_ci // We made/have an off-screen surface. Get the contents as an SkImage: 164cb93a386Sopenharmony_ci sk_sp<SkImage> snapshot = fBackbufferSurface->makeImageSnapshot(); 165cb93a386Sopenharmony_ci 166cb93a386Sopenharmony_ci sk_sp<SkSurface> gpuSurface = INHERITED::getBackbufferSurface(); 167cb93a386Sopenharmony_ci SkCanvas* gpuCanvas = gpuSurface->getCanvas(); 168cb93a386Sopenharmony_ci gpuCanvas->drawImage(snapshot, 0, 0); 169cb93a386Sopenharmony_ci gpuCanvas->flush(); 170cb93a386Sopenharmony_ci glBindRenderbuffer(GL_RENDERBUFFER, fRenderbuffer); 171cb93a386Sopenharmony_ci [fGLContext presentRenderbuffer:GL_RENDERBUFFER]; 172cb93a386Sopenharmony_ci } 173cb93a386Sopenharmony_ci} 174cb93a386Sopenharmony_ci 175cb93a386Sopenharmony_civoid RasterWindowContext_ios::resize(int w, int h) { 176cb93a386Sopenharmony_ci // TODO: handle rotation 177cb93a386Sopenharmony_ci // [fGLContext update]; 178cb93a386Sopenharmony_ci INHERITED::resize(w, h); 179cb93a386Sopenharmony_ci} 180cb93a386Sopenharmony_ci 181cb93a386Sopenharmony_ci} // anonymous namespace 182cb93a386Sopenharmony_ci 183cb93a386Sopenharmony_cinamespace sk_app { 184cb93a386Sopenharmony_cinamespace window_context_factory { 185cb93a386Sopenharmony_ci 186cb93a386Sopenharmony_cistd::unique_ptr<WindowContext> MakeRasterForIOS(const IOSWindowInfo& info, 187cb93a386Sopenharmony_ci const DisplayParams& params) { 188cb93a386Sopenharmony_ci std::unique_ptr<WindowContext> ctx(new RasterWindowContext_ios(info, params)); 189cb93a386Sopenharmony_ci if (!ctx->isValid()) { 190cb93a386Sopenharmony_ci return nullptr; 191cb93a386Sopenharmony_ci } 192cb93a386Sopenharmony_ci return ctx; 193cb93a386Sopenharmony_ci} 194cb93a386Sopenharmony_ci 195cb93a386Sopenharmony_ci} // namespace window_context_factory 196cb93a386Sopenharmony_ci} // namespace sk_app 197