1/* 2 * Copyright 2021 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 "include/core/SkSurface.h" 9#include "include/gpu/graphite/BackendTexture.h" 10#include "include/gpu/graphite/Context.h" 11#include "include/gpu/graphite/ContextOptions.h" 12#include "include/gpu/graphite/Recorder.h" 13#include "include/gpu/graphite/Recording.h" 14#include "include/gpu/graphite/Surface.h" 15#include "include/gpu/graphite/mtl/MtlBackendContext.h" 16#include "include/gpu/graphite/mtl/MtlGraphiteTypes.h" 17#include "include/gpu/graphite/mtl/MtlGraphiteUtils.h" 18#include "include/private/gpu/graphite/ContextOptionsPriv.h" 19#include "src/base/SkMathPriv.h" 20#include "tools/GpuToolUtils.h" 21#include "tools/window/GraphiteMetalWindowContext.h" 22 23using skwindow::DisplayParams; 24using skwindow::internal::GraphiteMetalWindowContext; 25 26namespace skwindow::internal { 27 28GraphiteMetalWindowContext::GraphiteMetalWindowContext(const DisplayParams& params) 29 : WindowContext(params) 30 , fValid(false) 31 , fDrawableHandle(nil) { 32 fDisplayParams.fMSAASampleCount = GrNextPow2(fDisplayParams.fMSAASampleCount); 33} 34 35void GraphiteMetalWindowContext::initializeContext() { 36 SkASSERT(!fContext); 37 SkASSERT(!fGraphiteContext); 38 39 fDevice.reset(MTLCreateSystemDefaultDevice()); 40 fQueue.reset([*fDevice newCommandQueue]); 41 42 if (fDisplayParams.fMSAASampleCount > 1) { 43 if (@available(macOS 10.11, iOS 9.0, tvOS 9.0, *)) { 44 if (![*fDevice supportsTextureSampleCount:fDisplayParams.fMSAASampleCount]) { 45 return; 46 } 47 } else { 48 return; 49 } 50 } 51 fSampleCount = fDisplayParams.fMSAASampleCount; 52 fStencilBits = 8; 53 54 fValid = this->onInitializeContext(); 55 56 skgpu::graphite::MtlBackendContext backendContext = {}; 57 backendContext.fDevice.retain((CFTypeRef)fDevice.get()); 58 backendContext.fQueue.retain((CFTypeRef)fQueue.get()); 59 60 fDisplayParams.fGraphiteContextOptions.fOptions.fDisableCachedGlyphUploads = true; 61 // Needed to make synchronous readPixels work: 62 fDisplayParams.fGraphiteContextOptions.fPriv.fStoreContextRefInRecorder = true; 63 fGraphiteContext = skgpu::graphite::ContextFactory::MakeMetal( 64 backendContext, fDisplayParams.fGraphiteContextOptions.fOptions); 65 fGraphiteRecorder = fGraphiteContext->makeRecorder(ToolUtils::CreateTestingRecorderOptions()); 66 // TODO 67// if (!fGraphiteContext && fDisplayParams.fMSAASampleCount > 1) { 68// fDisplayParams.fMSAASampleCount /= 2; 69// this->initializeContext(); 70// return; 71// } 72} 73 74void GraphiteMetalWindowContext::destroyContext() { 75 if (fGraphiteContext) { 76 fGraphiteRecorder.reset(); 77 fGraphiteContext.reset(); 78 } 79 80 this->onDestroyContext(); 81 82 fMetalLayer = nil; 83 fValid = false; 84 85 fQueue.reset(); 86 fDevice.reset(); 87} 88 89sk_sp<SkSurface> GraphiteMetalWindowContext::getBackbufferSurface() { 90 sk_sp<SkSurface> surface; 91 id<CAMetalDrawable> currentDrawable = [fMetalLayer nextDrawable]; 92 if (currentDrawable == nil) { 93 return nullptr; 94 } 95 96 skgpu::graphite::BackendTexture backendTex(this->dimensions(), 97 (CFTypeRef)currentDrawable.texture); 98 99 surface = SkSurfaces::WrapBackendTexture(this->graphiteRecorder(), 100 backendTex, 101 kBGRA_8888_SkColorType, 102 fDisplayParams.fColorSpace, 103 &fDisplayParams.fSurfaceProps); 104 fDrawableHandle = CFRetain((CFTypeRef) currentDrawable); 105 106 return surface; 107} 108 109void GraphiteMetalWindowContext::onSwapBuffers() { 110 this->snapRecordingAndSubmit(); 111 112 id<CAMetalDrawable> currentDrawable = (id<CAMetalDrawable>)fDrawableHandle; 113 114 id<MTLCommandBuffer> commandBuffer([*fQueue commandBuffer]); 115 commandBuffer.label = @"Present"; 116 117 [commandBuffer presentDrawable:currentDrawable]; 118 [commandBuffer commit]; 119 // ARC is off in sk_app, so we need to release the CF ref manually 120 CFRelease(fDrawableHandle); 121 fDrawableHandle = nil; 122} 123 124void GraphiteMetalWindowContext::setDisplayParams(const DisplayParams& params) { 125 this->destroyContext(); 126 fDisplayParams = params; 127 this->initializeContext(); 128} 129 130void GraphiteMetalWindowContext::activate(bool isActive) {} 131 132} //namespace skwindow::internal 133