2 * Copyright 2018 Google Inc.
4 * Use of this source code is governed by a BSD-style license that can be
5 * found in the LICENSE file.
8 #include "src/gpu/ganesh/GrStencilSettings.h"
9 #include "src/gpu/ganesh/mtl/GrMtlDepthStencil.h"
10 #include "src/gpu/ganesh/mtl/GrMtlGpu.h"
12 #if !__has_feature(objc_arc)
13 #error This file must be compiled with Arc. Use -fobjc-arc flag
18 MTLStencilOperation skia_stencil_op_to_mtl(GrStencilOp 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;
39 MTLStencilDescriptor* skia_stencil_to_mtl(GrStencilSettings::Face face) {
40 MTLStencilDescriptor* result = [[MTLStencilDescriptor alloc] init];
42 case GrStencilTest::kAlways:
43 result.stencilCompareFunction = MTLCompareFunctionAlways;
45 case GrStencilTest::kNever:
46 result.stencilCompareFunction = MTLCompareFunctionNever;
48 case GrStencilTest::kGreater:
49 result.stencilCompareFunction = MTLCompareFunctionGreater;
51 case GrStencilTest::kGEqual:
52 result.stencilCompareFunction = MTLCompareFunctionGreaterEqual;
54 case GrStencilTest::kLess:
55 result.stencilCompareFunction = MTLCompareFunctionLess;
57 case GrStencilTest::kLEqual:
58 result.stencilCompareFunction = MTLCompareFunctionLessEqual;
60 case GrStencilTest::kEqual:
61 result.stencilCompareFunction = MTLCompareFunctionEqual;
63 case GrStencilTest::kNotEqual:
64 result.stencilCompareFunction = MTLCompareFunctionNotEqual;
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);
74 GrMtlDepthStencil* 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));
84 desc.frontFaceStencil = skia_stencil_to_mtl(stencil.singleSidedFace());
85 desc.backFaceStencil = desc.frontFaceStencil;
89 return new GrMtlDepthStencil([gpu->device() newDepthStencilStateWithDescriptor: desc],
90 GenerateKey(stencil, origin));
93 void skia_stencil_to_key(GrStencilSettings::Face face, GrMtlDepthStencil::Key::Face* faceKey) {
94 const int kPassOpShift = 3;
95 const int kFailOpShift = 6;
97 faceKey->fReadMask = face.fTestMask;
98 faceKey->fWriteMask = face.fWriteMask;
100 SkASSERT(static_cast<int>(face.fTest) <= 7);
101 faceKey->fOps = static_cast<uint32_t>(face.fTest);
103 SkASSERT(static_cast<int>(face.fPassOp) <= 7);
104 faceKey->fOps |= (static_cast<uint32_t>(face.fPassOp) << kPassOpShift);
106 SkASSERT(static_cast<int>(face.fFailOp) <= 7);
107 faceKey->fOps |= (static_cast<uint32_t>(face.fFailOp) << kFailOpShift);
110 GrMtlDepthStencil::Key GrMtlDepthStencil::GenerateKey(const GrStencilSettings& stencil,
111 GrSurfaceOrigin origin) {
114 if (stencil.isDisabled()) {
115 memset(&depthStencilKey, 0, sizeof(Key));
117 if (stencil.isTwoSided()) {
118 skia_stencil_to_key(stencil.postOriginCCWFace(origin), &depthStencilKey.fFront);
119 skia_stencil_to_key(stencil.postOriginCWFace(origin), &depthStencilKey.fBack);
122 skia_stencil_to_key(stencil.singleSidedFace(), &depthStencilKey.fFront);
123 memcpy(&depthStencilKey.fBack, &depthStencilKey.fFront, sizeof(Key::Face));
127 return depthStencilKey;