1*c8dee2aaSAndroid Build Coastguard Worker/* 2*c8dee2aaSAndroid Build Coastguard Worker * Copyright 2018 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 "src/gpu/ganesh/GrStencilSettings.h" 9*c8dee2aaSAndroid Build Coastguard Worker#include "src/gpu/ganesh/mtl/GrMtlDepthStencil.h" 10*c8dee2aaSAndroid Build Coastguard Worker#include "src/gpu/ganesh/mtl/GrMtlGpu.h" 11*c8dee2aaSAndroid Build Coastguard Worker 12*c8dee2aaSAndroid Build Coastguard Worker#if !__has_feature(objc_arc) 13*c8dee2aaSAndroid Build Coastguard Worker#error This file must be compiled with Arc. Use -fobjc-arc flag 14*c8dee2aaSAndroid Build Coastguard Worker#endif 15*c8dee2aaSAndroid Build Coastguard Worker 16*c8dee2aaSAndroid Build Coastguard WorkerGR_NORETAIN_BEGIN 17*c8dee2aaSAndroid Build Coastguard Worker 18*c8dee2aaSAndroid Build Coastguard WorkerMTLStencilOperation skia_stencil_op_to_mtl(GrStencilOp op) { 19*c8dee2aaSAndroid Build Coastguard Worker switch (op) { 20*c8dee2aaSAndroid Build Coastguard Worker case GrStencilOp::kKeep: 21*c8dee2aaSAndroid Build Coastguard Worker return MTLStencilOperationKeep; 22*c8dee2aaSAndroid Build Coastguard Worker case GrStencilOp::kZero: 23*c8dee2aaSAndroid Build Coastguard Worker return MTLStencilOperationZero; 24*c8dee2aaSAndroid Build Coastguard Worker case GrStencilOp::kReplace: 25*c8dee2aaSAndroid Build Coastguard Worker return MTLStencilOperationReplace; 26*c8dee2aaSAndroid Build Coastguard Worker case GrStencilOp::kInvert: 27*c8dee2aaSAndroid Build Coastguard Worker return MTLStencilOperationInvert; 28*c8dee2aaSAndroid Build Coastguard Worker case GrStencilOp::kIncWrap: 29*c8dee2aaSAndroid Build Coastguard Worker return MTLStencilOperationIncrementWrap; 30*c8dee2aaSAndroid Build Coastguard Worker case GrStencilOp::kDecWrap: 31*c8dee2aaSAndroid Build Coastguard Worker return MTLStencilOperationDecrementWrap; 32*c8dee2aaSAndroid Build Coastguard Worker case GrStencilOp::kIncClamp: 33*c8dee2aaSAndroid Build Coastguard Worker return MTLStencilOperationIncrementClamp; 34*c8dee2aaSAndroid Build Coastguard Worker case GrStencilOp::kDecClamp: 35*c8dee2aaSAndroid Build Coastguard Worker return MTLStencilOperationDecrementClamp; 36*c8dee2aaSAndroid Build Coastguard Worker } 37*c8dee2aaSAndroid Build Coastguard Worker} 38*c8dee2aaSAndroid Build Coastguard Worker 39*c8dee2aaSAndroid Build Coastguard WorkerMTLStencilDescriptor* skia_stencil_to_mtl(GrStencilSettings::Face face) { 40*c8dee2aaSAndroid Build Coastguard Worker MTLStencilDescriptor* result = [[MTLStencilDescriptor alloc] init]; 41*c8dee2aaSAndroid Build Coastguard Worker switch (face.fTest) { 42*c8dee2aaSAndroid Build Coastguard Worker case GrStencilTest::kAlways: 43*c8dee2aaSAndroid Build Coastguard Worker result.stencilCompareFunction = MTLCompareFunctionAlways; 44*c8dee2aaSAndroid Build Coastguard Worker break; 45*c8dee2aaSAndroid Build Coastguard Worker case GrStencilTest::kNever: 46*c8dee2aaSAndroid Build Coastguard Worker result.stencilCompareFunction = MTLCompareFunctionNever; 47*c8dee2aaSAndroid Build Coastguard Worker break; 48*c8dee2aaSAndroid Build Coastguard Worker case GrStencilTest::kGreater: 49*c8dee2aaSAndroid Build Coastguard Worker result.stencilCompareFunction = MTLCompareFunctionGreater; 50*c8dee2aaSAndroid Build Coastguard Worker break; 51*c8dee2aaSAndroid Build Coastguard Worker case GrStencilTest::kGEqual: 52*c8dee2aaSAndroid Build Coastguard Worker result.stencilCompareFunction = MTLCompareFunctionGreaterEqual; 53*c8dee2aaSAndroid Build Coastguard Worker break; 54*c8dee2aaSAndroid Build Coastguard Worker case GrStencilTest::kLess: 55*c8dee2aaSAndroid Build Coastguard Worker result.stencilCompareFunction = MTLCompareFunctionLess; 56*c8dee2aaSAndroid Build Coastguard Worker break; 57*c8dee2aaSAndroid Build Coastguard Worker case GrStencilTest::kLEqual: 58*c8dee2aaSAndroid Build Coastguard Worker result.stencilCompareFunction = MTLCompareFunctionLessEqual; 59*c8dee2aaSAndroid Build Coastguard Worker break; 60*c8dee2aaSAndroid Build Coastguard Worker case GrStencilTest::kEqual: 61*c8dee2aaSAndroid Build Coastguard Worker result.stencilCompareFunction = MTLCompareFunctionEqual; 62*c8dee2aaSAndroid Build Coastguard Worker break; 63*c8dee2aaSAndroid Build Coastguard Worker case GrStencilTest::kNotEqual: 64*c8dee2aaSAndroid Build Coastguard Worker result.stencilCompareFunction = MTLCompareFunctionNotEqual; 65*c8dee2aaSAndroid Build Coastguard Worker break; 66*c8dee2aaSAndroid Build Coastguard Worker } 67*c8dee2aaSAndroid Build Coastguard Worker result.readMask = face.fTestMask; 68*c8dee2aaSAndroid Build Coastguard Worker result.writeMask = face.fWriteMask; 69*c8dee2aaSAndroid Build Coastguard Worker result.depthStencilPassOperation = skia_stencil_op_to_mtl(face.fPassOp); 70*c8dee2aaSAndroid Build Coastguard Worker result.stencilFailureOperation = skia_stencil_op_to_mtl(face.fFailOp); 71*c8dee2aaSAndroid Build Coastguard Worker return result; 72*c8dee2aaSAndroid Build Coastguard Worker} 73*c8dee2aaSAndroid Build Coastguard Worker 74*c8dee2aaSAndroid Build Coastguard WorkerGrMtlDepthStencil* GrMtlDepthStencil::Create(const GrMtlGpu* gpu, 75*c8dee2aaSAndroid Build Coastguard Worker const GrStencilSettings& stencil, 76*c8dee2aaSAndroid Build Coastguard Worker GrSurfaceOrigin origin) { 77*c8dee2aaSAndroid Build Coastguard Worker MTLDepthStencilDescriptor* desc = [[MTLDepthStencilDescriptor alloc] init]; 78*c8dee2aaSAndroid Build Coastguard Worker if (!stencil.isDisabled()) { 79*c8dee2aaSAndroid Build Coastguard Worker if (stencil.isTwoSided()) { 80*c8dee2aaSAndroid Build Coastguard Worker desc.frontFaceStencil = skia_stencil_to_mtl(stencil.postOriginCCWFace(origin)); 81*c8dee2aaSAndroid Build Coastguard Worker desc.backFaceStencil = skia_stencil_to_mtl(stencil.postOriginCWFace(origin)); 82*c8dee2aaSAndroid Build Coastguard Worker } 83*c8dee2aaSAndroid Build Coastguard Worker else { 84*c8dee2aaSAndroid Build Coastguard Worker desc.frontFaceStencil = skia_stencil_to_mtl(stencil.singleSidedFace()); 85*c8dee2aaSAndroid Build Coastguard Worker desc.backFaceStencil = desc.frontFaceStencil; 86*c8dee2aaSAndroid Build Coastguard Worker } 87*c8dee2aaSAndroid Build Coastguard Worker } 88*c8dee2aaSAndroid Build Coastguard Worker 89*c8dee2aaSAndroid Build Coastguard Worker return new GrMtlDepthStencil([gpu->device() newDepthStencilStateWithDescriptor: desc], 90*c8dee2aaSAndroid Build Coastguard Worker GenerateKey(stencil, origin)); 91*c8dee2aaSAndroid Build Coastguard Worker} 92*c8dee2aaSAndroid Build Coastguard Worker 93*c8dee2aaSAndroid Build Coastguard Workervoid skia_stencil_to_key(GrStencilSettings::Face face, GrMtlDepthStencil::Key::Face* faceKey) { 94*c8dee2aaSAndroid Build Coastguard Worker const int kPassOpShift = 3; 95*c8dee2aaSAndroid Build Coastguard Worker const int kFailOpShift = 6; 96*c8dee2aaSAndroid Build Coastguard Worker 97*c8dee2aaSAndroid Build Coastguard Worker faceKey->fReadMask = face.fTestMask; 98*c8dee2aaSAndroid Build Coastguard Worker faceKey->fWriteMask = face.fWriteMask; 99*c8dee2aaSAndroid Build Coastguard Worker 100*c8dee2aaSAndroid Build Coastguard Worker SkASSERT(static_cast<int>(face.fTest) <= 7); 101*c8dee2aaSAndroid Build Coastguard Worker faceKey->fOps = static_cast<uint32_t>(face.fTest); 102*c8dee2aaSAndroid Build Coastguard Worker 103*c8dee2aaSAndroid Build Coastguard Worker SkASSERT(static_cast<int>(face.fPassOp) <= 7); 104*c8dee2aaSAndroid Build Coastguard Worker faceKey->fOps |= (static_cast<uint32_t>(face.fPassOp) << kPassOpShift); 105*c8dee2aaSAndroid Build Coastguard Worker 106*c8dee2aaSAndroid Build Coastguard Worker SkASSERT(static_cast<int>(face.fFailOp) <= 7); 107*c8dee2aaSAndroid Build Coastguard Worker faceKey->fOps |= (static_cast<uint32_t>(face.fFailOp) << kFailOpShift); 108*c8dee2aaSAndroid Build Coastguard Worker} 109*c8dee2aaSAndroid Build Coastguard Worker 110*c8dee2aaSAndroid Build Coastguard WorkerGrMtlDepthStencil::Key GrMtlDepthStencil::GenerateKey(const GrStencilSettings& stencil, 111*c8dee2aaSAndroid Build Coastguard Worker GrSurfaceOrigin origin) { 112*c8dee2aaSAndroid Build Coastguard Worker Key depthStencilKey; 113*c8dee2aaSAndroid Build Coastguard Worker 114*c8dee2aaSAndroid Build Coastguard Worker if (stencil.isDisabled()) { 115*c8dee2aaSAndroid Build Coastguard Worker memset(&depthStencilKey, 0, sizeof(Key)); 116*c8dee2aaSAndroid Build Coastguard Worker } else { 117*c8dee2aaSAndroid Build Coastguard Worker if (stencil.isTwoSided()) { 118*c8dee2aaSAndroid Build Coastguard Worker skia_stencil_to_key(stencil.postOriginCCWFace(origin), &depthStencilKey.fFront); 119*c8dee2aaSAndroid Build Coastguard Worker skia_stencil_to_key(stencil.postOriginCWFace(origin), &depthStencilKey.fBack); 120*c8dee2aaSAndroid Build Coastguard Worker } 121*c8dee2aaSAndroid Build Coastguard Worker else { 122*c8dee2aaSAndroid Build Coastguard Worker skia_stencil_to_key(stencil.singleSidedFace(), &depthStencilKey.fFront); 123*c8dee2aaSAndroid Build Coastguard Worker memcpy(&depthStencilKey.fBack, &depthStencilKey.fFront, sizeof(Key::Face)); 124*c8dee2aaSAndroid Build Coastguard Worker } 125*c8dee2aaSAndroid Build Coastguard Worker } 126*c8dee2aaSAndroid Build Coastguard Worker 127*c8dee2aaSAndroid Build Coastguard Worker return depthStencilKey; 128*c8dee2aaSAndroid Build Coastguard Worker} 129*c8dee2aaSAndroid Build Coastguard Worker 130*c8dee2aaSAndroid Build Coastguard WorkerGR_NORETAIN_END 131