aboutsummaryrefslogtreecommitdiffhomepage
path: root/src/gpu/gl
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/gpu/gl
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/gpu/gl')
-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
4 files changed, 69 insertions, 116 deletions
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()) {