Swap front and back stencil sides when rendering bottom-left
This makes sure the front face is always clockwise in device space,
and the back face is always counterclockwise, regardless of origin.
Bug: skia:
Change-Id: If4b9be6197e0fb9ac22a58f9198afd37a49a8187
Reviewed-on: https://skia-review.googlesource.com/c/skia/+/208991
Reviewed-by: Brian Salomon <bsalomon@google.com>
Commit-Queue: Chris Dalton <csmartdalton@google.com>
diff --git a/src/gpu/GrStencilSettings.h b/src/gpu/GrStencilSettings.h
index 1fed6b8..a730b32 100644
--- a/src/gpu/GrStencilSettings.h
+++ b/src/gpu/GrStencilSettings.h
@@ -78,8 +78,19 @@
void setDisabled();
};
- const Face& front() const { SkASSERT(!this->isDisabled()); return fFront; }
- const Face& back() const { SkASSERT(this->isTwoSided()); return fBack; }
+ const Face& frontAndBack() const {
+ SkASSERT(!this->isDisabled());
+ SkASSERT(!this->isTwoSided());
+ return fFront;
+ }
+ const Face& front(GrSurfaceOrigin origin) const {
+ SkASSERT(this->isTwoSided());
+ return (kTopLeft_GrSurfaceOrigin == origin) ? fFront : fBack;
+ }
+ const Face& back(GrSurfaceOrigin origin) const {
+ SkASSERT(this->isTwoSided());
+ return (kTopLeft_GrSurfaceOrigin == origin) ? fBack : fFront;
+ }
/**
* Given a thing to draw into the stencil clip, a fill type, and a set op
diff --git a/src/gpu/gl/GrGLGpu.cpp b/src/gpu/gl/GrGLGpu.cpp
index d34abce..d1283e2 100644
--- a/src/gpu/gl/GrGLGpu.cpp
+++ b/src/gpu/gl/GrGLGpu.cpp
@@ -2047,7 +2047,7 @@
stencil.reset(*pipeline.getUserStencil(), pipeline.hasStencilClip(),
glRT->renderTargetPriv().numStencilBits());
}
- this->flushStencil(stencil);
+ this->flushStencil(stencil, origin);
if (pipeline.isScissorEnabled()) {
static constexpr SkIRect kBogusScissor{0, 0, 1, 1};
GrScissorState state(fixedDynamicState ? fixedDynamicState->fScissorRect : kBogusScissor);
@@ -2835,28 +2835,25 @@
}
}
-void GrGLGpu::flushStencil(const GrStencilSettings& stencilSettings) {
+void GrGLGpu::flushStencil(const GrStencilSettings& stencilSettings, GrSurfaceOrigin origin) {
if (stencilSettings.isDisabled()) {
this->disableStencil();
- } else if (fHWStencilSettings != stencilSettings) {
+ } else if (fHWStencilSettings != stencilSettings ||
+ (stencilSettings.isTwoSided() && fHWStencilOrigin != origin)) {
if (kYes_TriState != fHWStencilTestEnabled) {
GL_CALL(Enable(GR_GL_STENCIL_TEST));
fHWStencilTestEnabled = kYes_TriState;
}
if (stencilSettings.isTwoSided()) {
- set_gl_stencil(this->glInterface(),
- stencilSettings.front(),
- GR_GL_FRONT);
- set_gl_stencil(this->glInterface(),
- stencilSettings.back(),
- GR_GL_BACK);
+ set_gl_stencil(this->glInterface(), stencilSettings.front(origin), GR_GL_FRONT);
+ set_gl_stencil(this->glInterface(), stencilSettings.back(origin), GR_GL_BACK);
} else {
- set_gl_stencil(this->glInterface(),
- stencilSettings.front(),
- GR_GL_FRONT_AND_BACK);
+ set_gl_stencil(
+ this->glInterface(), stencilSettings.frontAndBack(), GR_GL_FRONT_AND_BACK);
}
fHWStencilSettings = stencilSettings;
+ fHWStencilOrigin = origin;
}
}
diff --git a/src/gpu/gl/GrGLGpu.h b/src/gpu/gl/GrGLGpu.h
index cddcf06..1b8e875 100644
--- a/src/gpu/gl/GrGLGpu.h
+++ b/src/gpu/gl/GrGLGpu.h
@@ -380,7 +380,7 @@
// Need not be called if flushRenderTarget is used.
void flushViewport(const GrGLIRect&);
- void flushStencil(const GrStencilSettings&);
+ void flushStencil(const GrStencilSettings&, GrSurfaceOrigin);
void disableStencil();
// rt is used only if useHWAA is true.
@@ -599,6 +599,7 @@
TriState fMSAAEnabled;
GrStencilSettings fHWStencilSettings;
+ GrSurfaceOrigin fHWStencilOrigin;
TriState fHWStencilTestEnabled;
diff --git a/src/gpu/gl/GrGLPathRendering.cpp b/src/gpu/gl/GrGLPathRendering.cpp
index 19e8bba..cc41975 100644
--- a/src/gpu/gl/GrGLPathRendering.cpp
+++ b/src/gpu/gl/GrGLPathRendering.cpp
@@ -98,11 +98,10 @@
const GrGLPath* glPath = static_cast<const GrGLPath*>(path);
this->flushPathStencilSettings(*args.fStencil);
- SkASSERT(!fHWPathStencilSettings.isTwoSided());
GrGLenum fillMode =
- gr_stencil_op_to_gl_path_rendering_fill_mode(fHWPathStencilSettings.front().fPassOp);
- GrGLint writeMask = fHWPathStencilSettings.front().fWriteMask;
+ gr_stencil_op_to_gl_path_rendering_fill_mode(fHWPathStencilSettings.frontAndBack().fPassOp);
+ GrGLint writeMask = fHWPathStencilSettings.frontAndBack().fWriteMask;
if (glPath->shouldFill()) {
GL_CALL(StencilFillPath(glPath->pathID(), fillMode, writeMask));
@@ -125,11 +124,10 @@
const GrGLPath* glPath = static_cast<const GrGLPath*>(path);
this->flushPathStencilSettings(stencilPassSettings);
- SkASSERT(!fHWPathStencilSettings.isTwoSided());
GrGLenum fillMode =
- gr_stencil_op_to_gl_path_rendering_fill_mode(fHWPathStencilSettings.front().fPassOp);
- GrGLint writeMask = fHWPathStencilSettings.front().fWriteMask;
+ gr_stencil_op_to_gl_path_rendering_fill_mode(fHWPathStencilSettings.frontAndBack().fPassOp);
+ GrGLint writeMask = fHWPathStencilSettings.frontAndBack().fWriteMask;
if (glPath->shouldStroke()) {
if (glPath->shouldFill()) {
@@ -246,18 +244,19 @@
}
void GrGLPathRendering::flushPathStencilSettings(const GrStencilSettings& stencilSettings) {
+ SkASSERT(!stencilSettings.isTwoSided());
if (fHWPathStencilSettings != stencilSettings) {
SkASSERT(stencilSettings.isValid());
// Just the func, ref, and mask is set here. The op and write mask are params to the call
// that draws the path to the SB (glStencilFillPath)
- uint16_t ref = stencilSettings.front().fRef;
- GrStencilTest test = stencilSettings.front().fTest;
- uint16_t testMask = stencilSettings.front().fTestMask;
+ uint16_t ref = stencilSettings.frontAndBack().fRef;
+ GrStencilTest test = stencilSettings.frontAndBack().fTest;
+ uint16_t testMask = stencilSettings.frontAndBack().fTestMask;
if (!fHWPathStencilSettings.isValid() ||
- ref != fHWPathStencilSettings.front().fRef ||
- test != fHWPathStencilSettings.front().fTest ||
- testMask != fHWPathStencilSettings.front().fTestMask) {
+ ref != fHWPathStencilSettings.frontAndBack().fRef ||
+ test != fHWPathStencilSettings.frontAndBack().fTest ||
+ testMask != fHWPathStencilSettings.frontAndBack().fTestMask) {
GL_CALL(PathStencilFunc(GrToGLStencilFunc(test), ref, testMask));
}
fHWPathStencilSettings = stencilSettings;
diff --git a/src/gpu/mtl/GrMtlPipelineState.mm b/src/gpu/mtl/GrMtlPipelineState.mm
index 0416159..d93337e 100644
--- a/src/gpu/mtl/GrMtlPipelineState.mm
+++ b/src/gpu/mtl/GrMtlPipelineState.mm
@@ -266,15 +266,17 @@
}
else {
MTLDepthStencilDescriptor* desc = [[MTLDepthStencilDescriptor alloc] init];
- desc.frontFaceStencil = skia_stencil_to_mtl(fStencil.front());
+ GrSurfaceOrigin origin = fRenderTargetState.fRenderTargetOrigin;
if (fStencil.isTwoSided()) {
- desc.backFaceStencil = skia_stencil_to_mtl(fStencil.back());
- [renderCmdEncoder setStencilFrontReferenceValue:fStencil.front().fRef
- backReferenceValue:fStencil.back().fRef];
+ desc.frontFaceStencil = skia_stencil_to_mtl(fStencil.front(origin));
+ desc.backFaceStencil = skia_stencil_to_mtl(fStencil.back(origin));
+ [renderCmdEncoder setStencilFrontReferenceValue:fStencil.front(origin).fRef
+ backReferenceValue:fStencil.back(origin).fRef];
}
else {
+ desc.frontFaceStencil = skia_stencil_to_mtl(fStencil.frontAndBack());
desc.backFaceStencil = desc.frontFaceStencil;
- [renderCmdEncoder setStencilReferenceValue:fStencil.front().fRef];
+ [renderCmdEncoder setStencilReferenceValue:fStencil.frontAndBack().fRef];
}
id<MTLDepthStencilState> state = [fGpu->device() newDepthStencilStateWithDescriptor:desc];
[renderCmdEncoder setDepthStencilState:state];
diff --git a/src/gpu/vk/GrVkPipeline.cpp b/src/gpu/vk/GrVkPipeline.cpp
index cfacc3a..05a23e0 100644
--- a/src/gpu/vk/GrVkPipeline.cpp
+++ b/src/gpu/vk/GrVkPipeline.cpp
@@ -224,8 +224,20 @@
return gTable[(int)test];
}
-static void setup_depth_stencil_state(const GrStencilSettings& stencilSettings,
- VkPipelineDepthStencilStateCreateInfo* stencilInfo) {
+static void setup_stencil_op_state(
+ VkStencilOpState* opState, const GrStencilSettings::Face& stencilFace) {
+ opState->failOp = stencil_op_to_vk_stencil_op(stencilFace.fFailOp);
+ opState->passOp = stencil_op_to_vk_stencil_op(stencilFace.fPassOp);
+ opState->depthFailOp = opState->failOp;
+ opState->compareOp = stencil_func_to_vk_compare_op(stencilFace.fTest);
+ opState->compareMask = stencilFace.fTestMask;
+ opState->writeMask = stencilFace.fWriteMask;
+ opState->reference = stencilFace.fRef;
+}
+
+static void setup_depth_stencil_state(
+ const GrStencilSettings& stencilSettings, GrSurfaceOrigin origin,
+ VkPipelineDepthStencilStateCreateInfo* stencilInfo) {
memset(stencilInfo, 0, sizeof(VkPipelineDepthStencilStateCreateInfo));
stencilInfo->sType = VK_STRUCTURE_TYPE_PIPELINE_DEPTH_STENCIL_STATE_CREATE_INFO;
stencilInfo->pNext = nullptr;
@@ -237,28 +249,12 @@
stencilInfo->depthBoundsTestEnable = VK_FALSE;
stencilInfo->stencilTestEnable = !stencilSettings.isDisabled();
if (!stencilSettings.isDisabled()) {
- // Set front face
- const GrStencilSettings::Face& front = stencilSettings.front();
- stencilInfo->front.failOp = stencil_op_to_vk_stencil_op(front.fFailOp);
- stencilInfo->front.passOp = stencil_op_to_vk_stencil_op(front.fPassOp);
- stencilInfo->front.depthFailOp = stencilInfo->front.failOp;
- stencilInfo->front.compareOp = stencil_func_to_vk_compare_op(front.fTest);
- stencilInfo->front.compareMask = front.fTestMask;
- stencilInfo->front.writeMask = front.fWriteMask;
- stencilInfo->front.reference = front.fRef;
-
- // Set back face
if (!stencilSettings.isTwoSided()) {
+ setup_stencil_op_state(&stencilInfo->front, stencilSettings.frontAndBack());
stencilInfo->back = stencilInfo->front;
} else {
- const GrStencilSettings::Face& back = stencilSettings.back();
- stencilInfo->back.failOp = stencil_op_to_vk_stencil_op(back.fFailOp);
- stencilInfo->back.passOp = stencil_op_to_vk_stencil_op(back.fPassOp);
- stencilInfo->back.depthFailOp = stencilInfo->front.failOp;
- stencilInfo->back.compareOp = stencil_func_to_vk_compare_op(back.fTest);
- stencilInfo->back.compareMask = back.fTestMask;
- stencilInfo->back.writeMask = back.fWriteMask;
- stencilInfo->back.reference = back.fRef;
+ setup_stencil_op_state(&stencilInfo->front, stencilSettings.front(origin));
+ setup_stencil_op_state(&stencilInfo->back, stencilSettings.back(origin));
}
}
stencilInfo->minDepthBounds = 0.0f;
@@ -500,13 +496,12 @@
dynamicInfo->pDynamicStates = dynamicStates;
}
-GrVkPipeline* GrVkPipeline::Create(GrVkGpu* gpu, int numColorSamples,
- const GrPrimitiveProcessor& primProc,
- const GrPipeline& pipeline, const GrStencilSettings& stencil,
- VkPipelineShaderStageCreateInfo* shaderStageInfo,
- int shaderStageCount, GrPrimitiveType primitiveType,
- VkRenderPass compatibleRenderPass, VkPipelineLayout layout,
- VkPipelineCache cache) {
+GrVkPipeline* GrVkPipeline::Create(
+ GrVkGpu* gpu, int numColorSamples, const GrPrimitiveProcessor& primProc,
+ const GrPipeline& pipeline, const GrStencilSettings& stencil, GrSurfaceOrigin origin,
+ VkPipelineShaderStageCreateInfo* shaderStageInfo, int shaderStageCount,
+ GrPrimitiveType primitiveType, VkRenderPass compatibleRenderPass, VkPipelineLayout layout,
+ VkPipelineCache cache) {
VkPipelineVertexInputStateCreateInfo vertexInputInfo;
SkSTArray<2, VkVertexInputBindingDescription, true> bindingDescs;
SkSTArray<16, VkVertexInputAttributeDescription> attributeDesc;
@@ -519,7 +514,7 @@
setup_input_assembly_state(primitiveType, &inputAssemblyInfo);
VkPipelineDepthStencilStateCreateInfo depthStencilInfo;
- setup_depth_stencil_state(stencil, &depthStencilInfo);
+ setup_depth_stencil_state(stencil, origin, &depthStencilInfo);
VkPipelineViewportStateCreateInfo viewportInfo;
setup_viewport_scissor_state(&viewportInfo);
diff --git a/src/gpu/vk/GrVkPipeline.h b/src/gpu/vk/GrVkPipeline.h
index b00dd4b..25d3dce 100644
--- a/src/gpu/vk/GrVkPipeline.h
+++ b/src/gpu/vk/GrVkPipeline.h
@@ -29,6 +29,7 @@
const GrPrimitiveProcessor&,
const GrPipeline& pipeline,
const GrStencilSettings&,
+ GrSurfaceOrigin,
VkPipelineShaderStageCreateInfo* shaderStageInfo,
int shaderStageCount,
GrPrimitiveType primitiveType,
diff --git a/src/gpu/vk/GrVkPipelineStateBuilder.cpp b/src/gpu/vk/GrVkPipelineStateBuilder.cpp
index d4e5a97..164091a 100644
--- a/src/gpu/vk/GrVkPipelineStateBuilder.cpp
+++ b/src/gpu/vk/GrVkPipelineStateBuilder.cpp
@@ -247,8 +247,8 @@
}
}
GrVkPipeline* pipeline = resourceProvider.createPipeline(
- this->renderTarget()->numColorSamples(), fPrimProc, fPipeline, stencil, shaderStageInfo,
- numShaderStages, primitiveType, compatibleRenderPass, pipelineLayout);
+ this->renderTarget()->numColorSamples(), fPrimProc, fPipeline, stencil, this->origin(),
+ shaderStageInfo, numShaderStages, primitiveType, compatibleRenderPass, pipelineLayout);
GR_VK_CALL(fGpu->vkInterface(), DestroyShaderModule(fGpu->device(), vertShaderModule,
nullptr));
GR_VK_CALL(fGpu->vkInterface(), DestroyShaderModule(fGpu->device(), fragShaderModule,
diff --git a/src/gpu/vk/GrVkResourceProvider.cpp b/src/gpu/vk/GrVkResourceProvider.cpp
index c875c71..bb1fe91 100644
--- a/src/gpu/vk/GrVkResourceProvider.cpp
+++ b/src/gpu/vk/GrVkResourceProvider.cpp
@@ -96,14 +96,15 @@
const GrPrimitiveProcessor& primProc,
const GrPipeline& pipeline,
const GrStencilSettings& stencil,
+ GrSurfaceOrigin origin,
VkPipelineShaderStageCreateInfo* shaderStageInfo,
int shaderStageCount,
GrPrimitiveType primitiveType,
VkRenderPass compatibleRenderPass,
VkPipelineLayout layout) {
- return GrVkPipeline::Create(fGpu, numColorSamples, primProc, pipeline, stencil, shaderStageInfo,
- shaderStageCount, primitiveType, compatibleRenderPass, layout,
- this->pipelineCache());
+ return GrVkPipeline::Create(
+ fGpu, numColorSamples, primProc, pipeline, stencil, origin, shaderStageInfo,
+ shaderStageCount, primitiveType, compatibleRenderPass, layout, this->pipelineCache());
}
GrVkCopyPipeline* GrVkResourceProvider::findOrCreateCopyPipeline(
diff --git a/src/gpu/vk/GrVkResourceProvider.h b/src/gpu/vk/GrVkResourceProvider.h
index 3cc35f0..29170c1 100644
--- a/src/gpu/vk/GrVkResourceProvider.h
+++ b/src/gpu/vk/GrVkResourceProvider.h
@@ -48,6 +48,7 @@
const GrPrimitiveProcessor& primProc,
const GrPipeline& pipeline,
const GrStencilSettings& stencil,
+ GrSurfaceOrigin,
VkPipelineShaderStageCreateInfo* shaderStageInfo,
int shaderStageCount,
GrPrimitiveType primitiveType,