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