GrMtlDepthStencil.mm 4.7 KB

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