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