aboutsummaryrefslogtreecommitdiffhomepage
path: root/src
diff options
context:
space:
mode:
authorGravatar Brian Salomon <bsalomon@google.com>2017-06-06 07:50:59 -0400
committerGravatar Skia Commit-Bot <skia-commit-bot@chromium.org>2017-06-06 19:36:31 +0000
commit4e8c581f2aa911bf49f97a246cc26134da292a8c (patch)
tree8562ef8f588a954e35650934efb2e366fada2d34 /src
parentba83233e68d44366ff7e9ef3131d5e8cb8c93bff (diff)
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>
Diffstat (limited to 'src')
-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
8 files changed, 86 insertions, 121 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,