1*c8dee2aaSAndroid Build Coastguard Worker/* 2*c8dee2aaSAndroid Build Coastguard Worker * Copyright 2021 Google Inc. 3*c8dee2aaSAndroid Build Coastguard Worker * 4*c8dee2aaSAndroid Build Coastguard Worker * Use of this source code is governed by a BSD-style license that can be 5*c8dee2aaSAndroid Build Coastguard Worker * found in the LICENSE file. 6*c8dee2aaSAndroid Build Coastguard Worker */ 7*c8dee2aaSAndroid Build Coastguard Worker 8*c8dee2aaSAndroid Build Coastguard Worker#include "tools/window/GraphiteNativeMetalWindowContext.h" 9*c8dee2aaSAndroid Build Coastguard Worker 10*c8dee2aaSAndroid Build Coastguard Worker#include "include/core/SkSurface.h" 11*c8dee2aaSAndroid Build Coastguard Worker#include "include/gpu/graphite/BackendTexture.h" 12*c8dee2aaSAndroid Build Coastguard Worker#include "include/gpu/graphite/Context.h" 13*c8dee2aaSAndroid Build Coastguard Worker#include "include/gpu/graphite/ContextOptions.h" 14*c8dee2aaSAndroid Build Coastguard Worker#include "include/gpu/graphite/Recorder.h" 15*c8dee2aaSAndroid Build Coastguard Worker#include "include/gpu/graphite/Recording.h" 16*c8dee2aaSAndroid Build Coastguard Worker#include "include/gpu/graphite/Surface.h" 17*c8dee2aaSAndroid Build Coastguard Worker#include "include/gpu/graphite/mtl/MtlBackendContext.h" 18*c8dee2aaSAndroid Build Coastguard Worker#include "include/gpu/graphite/mtl/MtlGraphiteTypes.h" 19*c8dee2aaSAndroid Build Coastguard Worker#include "include/gpu/graphite/mtl/MtlGraphiteUtils.h" 20*c8dee2aaSAndroid Build Coastguard Worker#include "src/base/SkMathPriv.h" 21*c8dee2aaSAndroid Build Coastguard Worker#include "src/gpu/graphite/ContextOptionsPriv.h" 22*c8dee2aaSAndroid Build Coastguard Worker#include "tools/graphite/GraphiteToolUtils.h" 23*c8dee2aaSAndroid Build Coastguard Worker#include "tools/graphite/TestOptions.h" 24*c8dee2aaSAndroid Build Coastguard Worker#include "tools/window/GraphiteDisplayParams.h" 25*c8dee2aaSAndroid Build Coastguard Worker 26*c8dee2aaSAndroid Build Coastguard Workerusing skwindow::DisplayParams; 27*c8dee2aaSAndroid Build Coastguard Workerusing skwindow::internal::GraphiteMetalWindowContext; 28*c8dee2aaSAndroid Build Coastguard Worker 29*c8dee2aaSAndroid Build Coastguard Workernamespace skwindow::internal { 30*c8dee2aaSAndroid Build Coastguard Worker 31*c8dee2aaSAndroid Build Coastguard WorkerGraphiteMetalWindowContext::GraphiteMetalWindowContext(std::unique_ptr<const DisplayParams> params) 32*c8dee2aaSAndroid Build Coastguard Worker : WindowContext(DisplayParamsBuilder(params.get()).roundUpMSAA().build()) 33*c8dee2aaSAndroid Build Coastguard Worker , fValid(false) 34*c8dee2aaSAndroid Build Coastguard Worker , fDrawableHandle(nil) {} 35*c8dee2aaSAndroid Build Coastguard Worker 36*c8dee2aaSAndroid Build Coastguard Workervoid GraphiteMetalWindowContext::initializeContext() { 37*c8dee2aaSAndroid Build Coastguard Worker SkASSERT(!fContext); 38*c8dee2aaSAndroid Build Coastguard Worker SkASSERT(!fGraphiteContext); 39*c8dee2aaSAndroid Build Coastguard Worker 40*c8dee2aaSAndroid Build Coastguard Worker fDevice.reset(MTLCreateSystemDefaultDevice()); 41*c8dee2aaSAndroid Build Coastguard Worker fQueue.reset([*fDevice newCommandQueue]); 42*c8dee2aaSAndroid Build Coastguard Worker 43*c8dee2aaSAndroid Build Coastguard Worker if (fDisplayParams->msaaSampleCount() > 1) { 44*c8dee2aaSAndroid Build Coastguard Worker if (@available(macOS 10.11, iOS 9.0, tvOS 9.0, *)) { 45*c8dee2aaSAndroid Build Coastguard Worker if (![*fDevice supportsTextureSampleCount:fDisplayParams->msaaSampleCount()]) { 46*c8dee2aaSAndroid Build Coastguard Worker return; 47*c8dee2aaSAndroid Build Coastguard Worker } 48*c8dee2aaSAndroid Build Coastguard Worker } else { 49*c8dee2aaSAndroid Build Coastguard Worker return; 50*c8dee2aaSAndroid Build Coastguard Worker } 51*c8dee2aaSAndroid Build Coastguard Worker } 52*c8dee2aaSAndroid Build Coastguard Worker fSampleCount = fDisplayParams->msaaSampleCount(); 53*c8dee2aaSAndroid Build Coastguard Worker fStencilBits = 8; 54*c8dee2aaSAndroid Build Coastguard Worker 55*c8dee2aaSAndroid Build Coastguard Worker fValid = this->onInitializeContext(); 56*c8dee2aaSAndroid Build Coastguard Worker 57*c8dee2aaSAndroid Build Coastguard Worker skgpu::graphite::MtlBackendContext backendContext = {}; 58*c8dee2aaSAndroid Build Coastguard Worker backendContext.fDevice.retain((CFTypeRef)fDevice.get()); 59*c8dee2aaSAndroid Build Coastguard Worker backendContext.fQueue.retain((CFTypeRef)fQueue.get()); 60*c8dee2aaSAndroid Build Coastguard Worker 61*c8dee2aaSAndroid Build Coastguard Worker SkASSERT(fDisplayParams->graphiteTestOptions()); 62*c8dee2aaSAndroid Build Coastguard Worker skwindow::GraphiteTestOptions opts = *fDisplayParams->graphiteTestOptions(); 63*c8dee2aaSAndroid Build Coastguard Worker 64*c8dee2aaSAndroid Build Coastguard Worker opts.fTestOptions.fContextOptions.fDisableCachedGlyphUploads = true; 65*c8dee2aaSAndroid Build Coastguard Worker // Needed to make synchronous readPixels work: 66*c8dee2aaSAndroid Build Coastguard Worker opts.fPriv.fStoreContextRefInRecorder = true; 67*c8dee2aaSAndroid Build Coastguard Worker fDisplayParams = 68*c8dee2aaSAndroid Build Coastguard Worker GraphiteDisplayParamsBuilder(fDisplayParams.get()).graphiteTestOptions(opts).build(); 69*c8dee2aaSAndroid Build Coastguard Worker fGraphiteContext = skgpu::graphite::ContextFactory::MakeMetal( 70*c8dee2aaSAndroid Build Coastguard Worker backendContext, fDisplayParams->graphiteTestOptions()->fTestOptions.fContextOptions); 71*c8dee2aaSAndroid Build Coastguard Worker fGraphiteRecorder = fGraphiteContext->makeRecorder(ToolUtils::CreateTestingRecorderOptions()); 72*c8dee2aaSAndroid Build Coastguard Worker // TODO 73*c8dee2aaSAndroid Build Coastguard Worker // if (!fGraphiteContext && fDisplayParams->msaaSampleCount() > 1) { 74*c8dee2aaSAndroid Build Coastguard Worker // fDisplayParams->msaaSampleCount() /= 2; 75*c8dee2aaSAndroid Build Coastguard Worker // this->initializeContext(); 76*c8dee2aaSAndroid Build Coastguard Worker // return; 77*c8dee2aaSAndroid Build Coastguard Worker // } 78*c8dee2aaSAndroid Build Coastguard Worker} 79*c8dee2aaSAndroid Build Coastguard Worker 80*c8dee2aaSAndroid Build Coastguard Workervoid GraphiteMetalWindowContext::destroyContext() { 81*c8dee2aaSAndroid Build Coastguard Worker if (fGraphiteContext) { 82*c8dee2aaSAndroid Build Coastguard Worker fGraphiteRecorder.reset(); 83*c8dee2aaSAndroid Build Coastguard Worker fGraphiteContext.reset(); 84*c8dee2aaSAndroid Build Coastguard Worker } 85*c8dee2aaSAndroid Build Coastguard Worker 86*c8dee2aaSAndroid Build Coastguard Worker this->onDestroyContext(); 87*c8dee2aaSAndroid Build Coastguard Worker 88*c8dee2aaSAndroid Build Coastguard Worker fMetalLayer = nil; 89*c8dee2aaSAndroid Build Coastguard Worker fValid = false; 90*c8dee2aaSAndroid Build Coastguard Worker 91*c8dee2aaSAndroid Build Coastguard Worker fQueue.reset(); 92*c8dee2aaSAndroid Build Coastguard Worker fDevice.reset(); 93*c8dee2aaSAndroid Build Coastguard Worker} 94*c8dee2aaSAndroid Build Coastguard Worker 95*c8dee2aaSAndroid Build Coastguard Workersk_sp<SkSurface> GraphiteMetalWindowContext::getBackbufferSurface() { 96*c8dee2aaSAndroid Build Coastguard Worker sk_sp<SkSurface> surface; 97*c8dee2aaSAndroid Build Coastguard Worker id<CAMetalDrawable> currentDrawable = [fMetalLayer nextDrawable]; 98*c8dee2aaSAndroid Build Coastguard Worker if (currentDrawable == nil) { 99*c8dee2aaSAndroid Build Coastguard Worker return nullptr; 100*c8dee2aaSAndroid Build Coastguard Worker } 101*c8dee2aaSAndroid Build Coastguard Worker 102*c8dee2aaSAndroid Build Coastguard Worker auto backendTex = skgpu::graphite::BackendTextures::MakeMetal( 103*c8dee2aaSAndroid Build Coastguard Worker this->dimensions(), (CFTypeRef)currentDrawable.texture); 104*c8dee2aaSAndroid Build Coastguard Worker 105*c8dee2aaSAndroid Build Coastguard Worker surface = SkSurfaces::WrapBackendTexture(this->graphiteRecorder(), 106*c8dee2aaSAndroid Build Coastguard Worker backendTex, 107*c8dee2aaSAndroid Build Coastguard Worker kBGRA_8888_SkColorType, 108*c8dee2aaSAndroid Build Coastguard Worker fDisplayParams->colorSpace(), 109*c8dee2aaSAndroid Build Coastguard Worker &fDisplayParams->surfaceProps()); 110*c8dee2aaSAndroid Build Coastguard Worker fDrawableHandle = CFRetain((CFTypeRef)currentDrawable); 111*c8dee2aaSAndroid Build Coastguard Worker 112*c8dee2aaSAndroid Build Coastguard Worker return surface; 113*c8dee2aaSAndroid Build Coastguard Worker} 114*c8dee2aaSAndroid Build Coastguard Worker 115*c8dee2aaSAndroid Build Coastguard Workervoid GraphiteMetalWindowContext::onSwapBuffers() { 116*c8dee2aaSAndroid Build Coastguard Worker this->submitToGpu(); 117*c8dee2aaSAndroid Build Coastguard Worker 118*c8dee2aaSAndroid Build Coastguard Worker id<CAMetalDrawable> currentDrawable = (id<CAMetalDrawable>)fDrawableHandle; 119*c8dee2aaSAndroid Build Coastguard Worker 120*c8dee2aaSAndroid Build Coastguard Worker id<MTLCommandBuffer> commandBuffer([*fQueue commandBuffer]); 121*c8dee2aaSAndroid Build Coastguard Worker commandBuffer.label = @"Present"; 122*c8dee2aaSAndroid Build Coastguard Worker 123*c8dee2aaSAndroid Build Coastguard Worker [commandBuffer presentDrawable:currentDrawable]; 124*c8dee2aaSAndroid Build Coastguard Worker [commandBuffer commit]; 125*c8dee2aaSAndroid Build Coastguard Worker // ARC is off in sk_app, so we need to release the CF ref manually 126*c8dee2aaSAndroid Build Coastguard Worker CFRelease(fDrawableHandle); 127*c8dee2aaSAndroid Build Coastguard Worker fDrawableHandle = nil; 128*c8dee2aaSAndroid Build Coastguard Worker} 129*c8dee2aaSAndroid Build Coastguard Worker 130*c8dee2aaSAndroid Build Coastguard Workervoid GraphiteMetalWindowContext::setDisplayParams(std::unique_ptr<const DisplayParams> params) { 131*c8dee2aaSAndroid Build Coastguard Worker this->destroyContext(); 132*c8dee2aaSAndroid Build Coastguard Worker fDisplayParams = std::move(params); 133*c8dee2aaSAndroid Build Coastguard Worker this->initializeContext(); 134*c8dee2aaSAndroid Build Coastguard Worker} 135*c8dee2aaSAndroid Build Coastguard Worker 136*c8dee2aaSAndroid Build Coastguard Workervoid GraphiteMetalWindowContext::activate(bool isActive) {} 137*c8dee2aaSAndroid Build Coastguard Worker 138*c8dee2aaSAndroid Build Coastguard Worker} // namespace skwindow::internal 139