aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMike Klein <mtklein@google.com>2017-06-06 23:29:53 +0000
committerMike Klein <mtklein@google.com>2017-06-06 23:32:28 +0000
commit31550dbc9804dafb18a71c968deb513cc8857cf3 (patch)
tree8dbcebc00f08a0378a4daac30e907ffe0a3e7de5
parent8b06ed7c9f76760563ed3c46716e8e8f27ec2311 (diff)
downloadskia-31550dbc9804dafb18a71c968deb513cc8857cf3.tar.gz
Revert "Revert "Workaround Adreno driver issue with stencil clears.""
This reverts commit 8b06ed7c9f76760563ed3c46716e8e8f27ec2311. Reason for revert: try again. Original change's description: > Revert "Workaround Adreno driver issue with stencil clears." > > This reverts commit 4e8c581f2aa911bf49f97a246cc26134da292a8c. > > Reason for revert: breaks Google3 roll > > Original change's description: > > Workaround Adreno driver issue with stencil clears. > > > > This also removes the "debug wire rect" which was not used and not implemented for Vulkan. > > > > Also some declared but not implemented methods are removed from GrGLGpu. > > > > Bug: skia:5587 > > > > Change-Id: I750051e90e6cfbfad6a6fe20792226182f698bcf > > Reviewed-on: https://skia-review.googlesource.com/18639 > > Reviewed-by: Chris Dalton <csmartdalton@google.com> > > Commit-Queue: Brian Salomon <bsalomon@google.com> > > TBR=bsalomon@google.com,csmartdalton@google.com > No-Presubmit: true > No-Tree-Checks: true > No-Try: true > Bug: skia:5587 > > Change-Id: I65aa16b3f8c70cdef56ff16e16304ba09604c475 > Reviewed-on: https://skia-review.googlesource.com/18924 > Reviewed-by: Mike Klein <mtklein@google.com> > Commit-Queue: Mike Klein <mtklein@google.com> TBR=mtklein@google.com,bsalomon@google.com,reviews@skia.org,csmartdalton@google.com No-Presubmit: true No-Tree-Checks: true No-Try: true Bug: skia:5587 Change-Id: Ice49027bda1c1ff7e0362d0680341ac862159850 Reviewed-on: https://skia-review.googlesource.com/18928 Reviewed-by: Mike Klein <mtklein@google.com>
-rw-r--r--src/gpu/GrGpu.h3
-rw-r--r--src/gpu/GrStencilSettings.cpp14
-rw-r--r--src/gpu/GrStencilSettings.h3
-rw-r--r--src/gpu/gl/GrGLCaps.cpp2
-rw-r--r--src/gpu/gl/GrGLCaps.h6
-rw-r--r--src/gpu/gl/GrGLGpu.cpp159
-rw-r--r--src/gpu/gl/GrGLGpu.h18
-rw-r--r--src/gpu/vk/GrVkGpu.h2
-rw-r--r--tools/gpu/GrTest.cpp2
9 files changed, 86 insertions, 123 deletions
diff --git a/src/gpu/GrGpu.h b/src/gpu/GrGpu.h
index dd63839db5..8b8c7b3809 100644
--- a/src/gpu/GrGpu.h
+++ b/src/gpu/GrGpu.h
@@ -479,9 +479,6 @@ public:
// clears target's entire stencil buffer to 0
virtual void clearStencil(GrRenderTarget* target) = 0;
- // draws an outline rectangle for debugging/visualization purposes.
- virtual void drawDebugWireRect(GrRenderTarget*, const SkIRect&, GrColor) = 0;
-
// Determines whether a texture will need to be rescaled in order to be used with the
// GrSamplerParams. This variation is called when the caller will create a new texture using the
// resource provider from a non-texture src (cpu-backed image, ...).
diff --git a/src/gpu/GrStencilSettings.cpp b/src/gpu/GrStencilSettings.cpp
index 7790c5506b..689557eaf4 100644
--- a/src/gpu/GrStencilSettings.cpp
+++ b/src/gpu/GrStencilSettings.cpp
@@ -455,6 +455,20 @@ GrUserStencilSettings const* const* GrStencilSettings::GetClipPasses(SkRegion::O
return gUserToClipTable[invertedFill][op];
}
+static constexpr GrUserStencilSettings gZeroStencilClipBit(
+ GrUserStencilSettings::StaticInit<
+ 0x0000,
+ GrUserStencilTest::kAlways,
+ 0xffff,
+ GrUserStencilOp::kZeroClipBit,
+ GrUserStencilOp::kZeroClipBit,
+ 0x0000>()
+);
+
+const GrUserStencilSettings* GrStencilSettings::SetClipBitSettings(bool setToInside) {
+ return setToInside ? &gReplaceClip : &gZeroStencilClipBit;
+}
+
void GrStencilSettings::genKey(GrProcessorKeyBuilder* b) const {
b->add32(fFlags);
if (this->isDisabled()) {
diff --git a/src/gpu/GrStencilSettings.h b/src/gpu/GrStencilSettings.h
index 15a8cac12f..1fed6b8e63 100644
--- a/src/gpu/GrStencilSettings.h
+++ b/src/gpu/GrStencilSettings.h
@@ -109,6 +109,9 @@ public:
bool invertedFill,
bool* drawDirectToClip);
+ /** Gets the user stencil settings to directly set the clip bit. */
+ static const GrUserStencilSettings* SetClipBitSettings(bool setToInside);
+
private:
// Internal flag for backends to optionally mark their tracked stencil state as invalid.
enum { kInvalid_PrivateFlag = (kLast_StencilFlag << 1) };
diff --git a/src/gpu/gl/GrGLCaps.cpp b/src/gpu/gl/GrGLCaps.cpp
index c672cb9a59..44d25299ae 100644
--- a/src/gpu/gl/GrGLCaps.cpp
+++ b/src/gpu/gl/GrGLCaps.cpp
@@ -55,6 +55,7 @@ GrGLCaps::GrGLCaps(const GrContextOptions& contextOptions,
fClearToBoundaryValuesIsBroken = false;
fClearTextureSupport = false;
fDrawArraysBaseVertexIsBroken = false;
+ fUseDrawToClearStencilClip = false;
fBlitFramebufferFlags = kNoSupport_BlitFramebufferFlag;
@@ -511,6 +512,7 @@ void GrGLCaps::init(const GrContextOptions& contextOptions,
if (kAdreno4xx_GrGLRenderer == ctxInfo.renderer()) {
fUseDrawInsteadOfPartialRenderTargetWrite = true;
+ fUseDrawToClearStencilClip = true;
}
// Texture uploads sometimes seem to be ignored to textures bound to FBOS on Tegra3.
diff --git a/src/gpu/gl/GrGLCaps.h b/src/gpu/gl/GrGLCaps.h
index b7273a08b1..efb324b064 100644
--- a/src/gpu/gl/GrGLCaps.h
+++ b/src/gpu/gl/GrGLCaps.h
@@ -368,6 +368,11 @@ public:
// https://bugs.chromium.org/p/skia/issues/detail?id=6650
bool drawArraysBaseVertexIsBroken() const { return fDrawArraysBaseVertexIsBroken; }
+ /// Adreno 4xx devices experience an issue when there are a large number of stencil clip bit
+ /// clears. The minimal repro steps are not precisely known but drawing a rect with a stencil
+ /// op instead of using glClear seems to resolve the issue.
+ bool useDrawToClearStencilClip() const { return fUseDrawToClearStencilClip; }
+
bool initDescForDstCopy(const GrRenderTargetProxy* src, GrSurfaceDesc* desc,
bool* rectsMustMatch, bool* disallowSubrect) const override;
@@ -442,6 +447,7 @@ private:
bool fClearToBoundaryValuesIsBroken : 1;
bool fClearTextureSupport : 1;
bool fDrawArraysBaseVertexIsBroken : 1;
+ bool fUseDrawToClearStencilClip : 1;
uint32_t fBlitFramebufferFlags;
diff --git a/src/gpu/gl/GrGLGpu.cpp b/src/gpu/gl/GrGLGpu.cpp
index fc629d60d0..3160ecaed5 100644
--- a/src/gpu/gl/GrGLGpu.cpp
+++ b/src/gpu/gl/GrGLGpu.cpp
@@ -220,7 +220,7 @@ GrGLGpu::GrGLGpu(GrGLContext* ctx, GrContext* context)
for (size_t i = 0; i < SK_ARRAY_COUNT(fMipmapPrograms); ++i) {
fMipmapPrograms[i].fProgram = 0;
}
- fWireRectProgram.fProgram = 0;
+ fStencilClipClearProgram = 0;
SkASSERT(ctx);
fCaps.reset(SkRef(ctx->caps()));
@@ -277,7 +277,7 @@ GrGLGpu::~GrGLGpu() {
fPathRendering.reset();
fCopyProgramArrayBuffer.reset();
fMipmapProgramArrayBuffer.reset();
- fWireRectArrayBuffer.reset();
+ fStencilClipClearArrayBuffer.reset();
if (0 != fHWProgramID) {
// detach the current program so there is no confusion on OpenGL's part
@@ -307,8 +307,8 @@ GrGLGpu::~GrGLGpu() {
}
}
- if (0 != fWireRectProgram.fProgram) {
- GL_CALL(DeleteProgram(fWireRectProgram.fProgram));
+ if (0 != fStencilClipClearProgram) {
+ GL_CALL(DeleteProgram(fStencilClipClearProgram));
}
delete fProgramCache;
@@ -339,8 +339,8 @@ void GrGLGpu::disconnect(DisconnectType type) {
GL_CALL(DeleteProgram(fMipmapPrograms[i].fProgram));
}
}
- if (fWireRectProgram.fProgram) {
- GL_CALL(DeleteProgram(fWireRectProgram.fProgram));
+ if (fStencilClipClearProgram) {
+ GL_CALL(DeleteProgram(fStencilClipClearProgram));
}
} else {
if (fProgramCache) {
@@ -363,8 +363,8 @@ void GrGLGpu::disconnect(DisconnectType type) {
for (size_t i = 0; i < SK_ARRAY_COUNT(fMipmapPrograms); ++i) {
fMipmapPrograms[i].fProgram = 0;
}
- fWireRectProgram.fProgram = 0;
- fWireRectArrayBuffer.reset();
+ fStencilClipClearProgram = 0;
+ fStencilClipClearArrayBuffer.reset();
if (this->glCaps().shaderCaps()->pathRenderingSupport()) {
this->glPathRendering()->disconnect(type);
}
@@ -1943,6 +1943,11 @@ void GrGLGpu::clearStencilClip(const GrFixedClip& clip,
SkASSERT(target);
this->handleDirtyContext();
+ if (this->glCaps().useDrawToClearStencilClip()) {
+ this->clearStencilClipAsDraw(clip, insideStencilMask, target);
+ return;
+ }
+
GrStencilAttachment* sb = target->renderTargetPriv().getStencilAttachment();
// this should only be called internally when we know we have a
// stencil buffer.
@@ -3611,64 +3616,43 @@ bool GrGLGpu::createMipmapProgram(int progIdx) {
return true;
}
-bool GrGLGpu::createWireRectProgram() {
- if (!fWireRectArrayBuffer) {
- static const GrGLfloat vdata[] = {
- 0, 0,
- 0, 1,
- 1, 1,
- 1, 0
- };
- fWireRectArrayBuffer.reset(GrGLBuffer::Create(this, sizeof(vdata), kVertex_GrBufferType,
- kStatic_GrAccessPattern, vdata));
- if (!fWireRectArrayBuffer) {
+bool GrGLGpu::createStencilClipClearProgram() {
+ if (!fStencilClipClearArrayBuffer) {
+ static const GrGLfloat vdata[] = {-1, -1, 1, -1, -1, 1, 1, 1};
+ fStencilClipClearArrayBuffer.reset(GrGLBuffer::Create(
+ this, sizeof(vdata), kVertex_GrBufferType, kStatic_GrAccessPattern, vdata));
+ if (!fStencilClipClearArrayBuffer) {
return false;
}
}
- SkASSERT(!fWireRectProgram.fProgram);
- GL_CALL_RET(fWireRectProgram.fProgram, CreateProgram());
- if (!fWireRectProgram.fProgram) {
+ SkASSERT(!fStencilClipClearProgram);
+ GL_CALL_RET(fStencilClipClearProgram, CreateProgram());
+ if (!fStencilClipClearProgram) {
return false;
}
- GrShaderVar uColor("u_color", kVec4f_GrSLType, GrShaderVar::kUniform_TypeModifier);
- GrShaderVar uRect("u_rect", kVec4f_GrSLType, GrShaderVar::kUniform_TypeModifier);
GrShaderVar aVertex("a_vertex", kVec2f_GrSLType, GrShaderVar::kIn_TypeModifier);
const char* version = this->caps()->shaderCaps()->versionDeclString();
- // The rect uniform specifies the rectangle in NDC space as a vec4 (left,top,right,bottom). The
- // program is used with a vbo containing the unit square. Vertices are computed from the rect
- // uniform using the 4 vbo vertices.
SkString vshaderTxt(version);
aVertex.appendDecl(this->caps()->shaderCaps(), &vshaderTxt);
vshaderTxt.append(";");
- uRect.appendDecl(this->caps()->shaderCaps(), &vshaderTxt);
- vshaderTxt.append(";");
vshaderTxt.append(
- "// Wire Rect Program VS\n"
- "void main() {"
- " gl_Position.x = u_rect.x + a_vertex.x * (u_rect.z - u_rect.x);"
- " gl_Position.y = u_rect.y + a_vertex.y * (u_rect.w - u_rect.y);"
- " gl_Position.zw = vec2(0, 1);"
- "}"
- );
-
- GrShaderVar oFragColor("o_FragColor", kVec4f_GrSLType, GrShaderVar::kOut_TypeModifier);
+ "// Stencil Clip Clear Program VS\n"
+ "void main() {"
+ " gl_Position = vec4(a_vertex.x, a_vertex.y, 0, 1);"
+ "}");
SkString fshaderTxt(version);
GrGLSLAppendDefaultFloatPrecisionDeclaration(kMedium_GrSLPrecision,
*this->caps()->shaderCaps(),
&fshaderTxt);
- uColor.appendDecl(this->caps()->shaderCaps(), &fshaderTxt);
- fshaderTxt.append(";");
fshaderTxt.appendf(
- "// Write Rect Program FS\n"
- "void main() {"
- " sk_FragColor = %s;"
- "}",
- uColor.c_str()
- );
+ "// Stencil Clip Clear Program FS\n"
+ "void main() {"
+ " sk_FragColor = vec4(0);"
+ "}");
const char* str;
GrGLint length;
@@ -3678,25 +3662,21 @@ bool GrGLGpu::createWireRectProgram() {
SkSL::Program::Settings settings;
settings.fCaps = this->caps()->shaderCaps();
SkSL::Program::Inputs inputs;
- GrGLuint vshader = GrGLCompileAndAttachShader(*fGLContext, fWireRectProgram.fProgram,
- GR_GL_VERTEX_SHADER, &str, &length, 1,
- &fStats, settings, &inputs);
+ GrGLuint vshader =
+ GrGLCompileAndAttachShader(*fGLContext, fStencilClipClearProgram, GR_GL_VERTEX_SHADER,
+ &str, &length, 1, &fStats, settings, &inputs);
SkASSERT(inputs.isEmpty());
str = fshaderTxt.c_str();
length = SkToInt(fshaderTxt.size());
- GrGLuint fshader = GrGLCompileAndAttachShader(*fGLContext, fWireRectProgram.fProgram,
- GR_GL_FRAGMENT_SHADER, &str, &length, 1,
- &fStats, settings, &inputs);
+ GrGLuint fshader =
+ GrGLCompileAndAttachShader(*fGLContext, fStencilClipClearProgram, GR_GL_FRAGMENT_SHADER,
+ &str, &length, 1, &fStats, settings, &inputs);
SkASSERT(inputs.isEmpty());
- GL_CALL(LinkProgram(fWireRectProgram.fProgram));
+ GL_CALL(LinkProgram(fStencilClipClearProgram));
- GL_CALL_RET(fWireRectProgram.fColorUniform,
- GetUniformLocation(fWireRectProgram.fProgram, "u_color"));
- GL_CALL_RET(fWireRectProgram.fRectUniform,
- GetUniformLocation(fWireRectProgram.fProgram, "u_rect"));
- GL_CALL(BindAttribLocation(fWireRectProgram.fProgram, 0, "a_vertex"));
+ GL_CALL(BindAttribLocation(fStencilClipClearProgram, 0, "a_vertex"));
GL_CALL(DeleteShader(vshader));
GL_CALL(DeleteShader(fshader));
@@ -3704,71 +3684,46 @@ bool GrGLGpu::createWireRectProgram() {
return true;
}
-void GrGLGpu::drawDebugWireRect(GrRenderTarget* rt, const SkIRect& rect, GrColor color) {
+void GrGLGpu::clearStencilClipAsDraw(const GrFixedClip& clip, bool insideStencilMask,
+ GrRenderTarget* rt) {
// TODO: This should swizzle the output to match dst's config, though it is a debugging
// visualization.
this->handleDirtyContext();
- if (!fWireRectProgram.fProgram) {
- if (!this->createWireRectProgram()) {
- SkDebugf("Failed to create wire rect program.\n");
+ if (!fStencilClipClearProgram) {
+ if (!this->createStencilClipClearProgram()) {
+ SkDebugf("Failed to create stencil clip clear program.\n");
return;
}
}
- int w = rt->width();
- int h = rt->height();
-
- // Compute the edges of the rectangle (top,left,right,bottom) in NDC space. Must consider
- // whether the render target is flipped or not.
- GrGLfloat edges[4];
- edges[0] = SkIntToScalar(rect.fLeft) + 0.5f;
- edges[2] = SkIntToScalar(rect.fRight) - 0.5f;
- if (kBottomLeft_GrSurfaceOrigin == rt->origin()) {
- edges[1] = h - (SkIntToScalar(rect.fTop) + 0.5f);
- edges[3] = h - (SkIntToScalar(rect.fBottom) - 0.5f);
- } else {
- edges[1] = SkIntToScalar(rect.fTop) + 0.5f;
- edges[3] = SkIntToScalar(rect.fBottom) - 0.5f;
- }
- edges[0] = 2 * edges[0] / w - 1.0f;
- edges[1] = 2 * edges[1] / h - 1.0f;
- edges[2] = 2 * edges[2] / w - 1.0f;
- edges[3] = 2 * edges[3] / h - 1.0f;
-
- GrGLfloat channels[4];
- static const GrGLfloat scale255 = 1.f / 255.f;
- channels[0] = GrColorUnpackR(color) * scale255;
- channels[1] = GrColorUnpackG(color) * scale255;
- channels[2] = GrColorUnpackB(color) * scale255;
- channels[3] = GrColorUnpackA(color) * scale255;
-
GrGLRenderTarget* glRT = static_cast<GrGLRenderTarget*>(rt->asRenderTarget());
- this->flushRenderTarget(glRT, &rect);
+ this->flushRenderTarget(glRT, nullptr);
- GL_CALL(UseProgram(fWireRectProgram.fProgram));
- fHWProgramID = fWireRectProgram.fProgram;
+ GL_CALL(UseProgram(fStencilClipClearProgram));
+ fHWProgramID = fStencilClipClearProgram;
fHWVertexArrayState.setVertexArrayID(this, 0);
GrGLAttribArrayState* attribs = fHWVertexArrayState.bindInternalVertexArray(this);
attribs->enableVertexArrays(this, 1);
- attribs->set(this, 0, fWireRectArrayBuffer.get(), kVec2f_GrVertexAttribType,
+ attribs->set(this, 0, fStencilClipClearArrayBuffer.get(), kVec2f_GrVertexAttribType,
2 * sizeof(GrGLfloat), 0);
- GL_CALL(Uniform4fv(fWireRectProgram.fRectUniform, 1, edges));
- GL_CALL(Uniform4fv(fWireRectProgram.fColorUniform, 1, channels));
-
GrXferProcessor::BlendInfo blendInfo;
blendInfo.reset();
this->flushBlend(blendInfo, GrSwizzle::RGBA());
- this->flushColorWrite(true);
+ this->flushColorWrite(false);
this->flushHWAAState(glRT, false, false);
- this->disableScissor();
- this->disableWindowRectangles();
- this->disableStencil();
-
- GL_CALL(DrawArrays(GR_GL_LINE_LOOP, 0, 4));
+ this->flushScissor(clip.scissorState(), glRT->getViewport(), glRT->origin());
+ this->flushWindowRectangles(clip.windowRectsState(), glRT);
+ GrStencilAttachment* sb = rt->renderTargetPriv().getStencilAttachment();
+ // This should only be called internally when we know we have a stencil buffer.
+ SkASSERT(sb);
+ GrStencilSettings settings = GrStencilSettings(
+ *GrStencilSettings::SetClipBitSettings(insideStencilMask), false, sb->bits());
+ this->flushStencil(settings);
+ GL_CALL(DrawArrays(GR_GL_TRIANGLE_STRIP, 0, 4));
}
diff --git a/src/gpu/gl/GrGLGpu.h b/src/gpu/gl/GrGLGpu.h
index 770c357c5f..1785eae143 100644
--- a/src/gpu/gl/GrGLGpu.h
+++ b/src/gpu/gl/GrGLGpu.h
@@ -162,8 +162,6 @@ public:
void resetShaderCacheForTesting() const override;
- void drawDebugWireRect(GrRenderTarget*, const SkIRect&, GrColor) override;
-
GrFence SK_WARN_UNUSED_RESULT insertFence() override;
bool waitFence(GrFence, uint64_t timeout) override;
void deleteFence(GrFence) const override;
@@ -296,6 +294,7 @@ private:
const SkIRect& srcRect,
const SkIPoint& dstPoint);
bool generateMipmap(GrGLTexture* texture, bool gammaCorrect);
+ void clearStencilClipAsDraw(const GrFixedClip&, bool insideStencilMask, GrRenderTarget*);
static bool BlendCoeffReferencesConstant(GrBlendCoeff coeff);
@@ -349,11 +348,6 @@ private:
void flushWindowRectangles(const GrWindowRectsState&, const GrGLRenderTarget*);
void disableWindowRectangles();
- void initFSAASupport();
-
- // determines valid stencil formats
- void initStencilFormats();
-
// sets a texture unit to use for texture operations other than binding a texture to a program.
// ensures that such operations don't negatively interact with tracking bound textures.
void setScratchTextureUnit();
@@ -407,7 +401,7 @@ private:
bool createCopyProgram(GrTexture* srcTexture);
bool createMipmapProgram(int progIdx);
- bool createWireRectProgram();
+ bool createStencilClipClearProgram();
// GL program-related state
ProgramCache* fProgramCache;
@@ -620,12 +614,8 @@ private:
} fMipmapPrograms[4];
sk_sp<GrGLBuffer> fMipmapProgramArrayBuffer;
- struct {
- GrGLuint fProgram;
- GrGLint fColorUniform;
- GrGLint fRectUniform;
- } fWireRectProgram;
- sk_sp<GrGLBuffer> fWireRectArrayBuffer;
+ GrGLuint fStencilClipClearProgram;
+ sk_sp<GrGLBuffer> fStencilClipClearArrayBuffer;
static int TextureToCopyProgramIdx(GrTexture* texture) {
switch (texture->texturePriv().samplerType()) {
diff --git a/src/gpu/vk/GrVkGpu.h b/src/gpu/vk/GrVkGpu.h
index cce6883f8d..f81daea336 100644
--- a/src/gpu/vk/GrVkGpu.h
+++ b/src/gpu/vk/GrVkGpu.h
@@ -98,8 +98,6 @@ public:
const GrGpuCommandBuffer::LoadAndStoreInfo& colorInfo,
const GrGpuCommandBuffer::LoadAndStoreInfo& stencilInfo) override;
- void drawDebugWireRect(GrRenderTarget*, const SkIRect&, GrColor) override {}
-
void addMemoryBarrier(VkPipelineStageFlags srcStageMask,
VkPipelineStageFlags dstStageMask,
bool byRegion,
diff --git a/tools/gpu/GrTest.cpp b/tools/gpu/GrTest.cpp
index bd85cff7ec..32f2d765f8 100644
--- a/tools/gpu/GrTest.cpp
+++ b/tools/gpu/GrTest.cpp
@@ -339,8 +339,6 @@ public:
return nullptr;
}
- void drawDebugWireRect(GrRenderTarget*, const SkIRect&, GrColor) override {}
-
GrFence SK_WARN_UNUSED_RESULT insertFence() override { return 0; }
bool waitFence(GrFence, uint64_t) override { return true; }
void deleteFence(GrFence) const override {}