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