diff options
author | Mike Klein <mtklein@google.com> | 2017-06-06 21:47:32 +0000 |
---|---|---|
committer | Skia Commit-Bot <skia-commit-bot@chromium.org> | 2017-06-06 22:12:48 +0000 |
commit | 8b06ed7c9f76760563ed3c46716e8e8f27ec2311 (patch) | |
tree | 13d827f87401f9c7f3dd83d434b5447effe3345b /src | |
parent | a88da48436f4c013722b27064e02a0b33574d2f8 (diff) |
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>
Diffstat (limited to 'src')
-rw-r--r-- | src/gpu/GrGpu.h | 3 | ||||
-rw-r--r-- | src/gpu/GrStencilSettings.cpp | 14 | ||||
-rw-r--r-- | src/gpu/GrStencilSettings.h | 3 | ||||
-rw-r--r-- | src/gpu/gl/GrGLCaps.cpp | 2 | ||||
-rw-r--r-- | src/gpu/gl/GrGLCaps.h | 6 | ||||
-rw-r--r-- | src/gpu/gl/GrGLGpu.cpp | 159 | ||||
-rw-r--r-- | src/gpu/gl/GrGLGpu.h | 18 | ||||
-rw-r--r-- | src/gpu/vk/GrVkGpu.h | 2 |
8 files changed, 121 insertions, 86 deletions
diff --git a/src/gpu/GrGpu.h b/src/gpu/GrGpu.h index 8b8c7b3809..dd63839db5 100644 --- a/src/gpu/GrGpu.h +++ b/src/gpu/GrGpu.h @@ -479,6 +479,9 @@ 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 689557eaf4..7790c5506b 100644 --- a/src/gpu/GrStencilSettings.cpp +++ b/src/gpu/GrStencilSettings.cpp @@ -455,20 +455,6 @@ 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 1fed6b8e63..15a8cac12f 100644 --- a/src/gpu/GrStencilSettings.h +++ b/src/gpu/GrStencilSettings.h @@ -109,9 +109,6 @@ 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 44d25299ae..c672cb9a59 100644 --- a/src/gpu/gl/GrGLCaps.cpp +++ b/src/gpu/gl/GrGLCaps.cpp @@ -55,7 +55,6 @@ GrGLCaps::GrGLCaps(const GrContextOptions& contextOptions, fClearToBoundaryValuesIsBroken = false; fClearTextureSupport = false; fDrawArraysBaseVertexIsBroken = false; - fUseDrawToClearStencilClip = false; fBlitFramebufferFlags = kNoSupport_BlitFramebufferFlag; @@ -512,7 +511,6 @@ 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 efb324b064..b7273a08b1 100644 --- a/src/gpu/gl/GrGLCaps.h +++ b/src/gpu/gl/GrGLCaps.h @@ -368,11 +368,6 @@ 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; @@ -447,7 +442,6 @@ 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 3160ecaed5..fc629d60d0 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; } - fStencilClipClearProgram = 0; + fWireRectProgram.fProgram = 0; SkASSERT(ctx); fCaps.reset(SkRef(ctx->caps())); @@ -277,7 +277,7 @@ GrGLGpu::~GrGLGpu() { fPathRendering.reset(); fCopyProgramArrayBuffer.reset(); fMipmapProgramArrayBuffer.reset(); - fStencilClipClearArrayBuffer.reset(); + fWireRectArrayBuffer.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 != fStencilClipClearProgram) { - GL_CALL(DeleteProgram(fStencilClipClearProgram)); + if (0 != fWireRectProgram.fProgram) { + GL_CALL(DeleteProgram(fWireRectProgram.fProgram)); } delete fProgramCache; @@ -339,8 +339,8 @@ void GrGLGpu::disconnect(DisconnectType type) { GL_CALL(DeleteProgram(fMipmapPrograms[i].fProgram)); } } - if (fStencilClipClearProgram) { - GL_CALL(DeleteProgram(fStencilClipClearProgram)); + if (fWireRectProgram.fProgram) { + GL_CALL(DeleteProgram(fWireRectProgram.fProgram)); } } 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; } - fStencilClipClearProgram = 0; - fStencilClipClearArrayBuffer.reset(); + fWireRectProgram.fProgram = 0; + fWireRectArrayBuffer.reset(); if (this->glCaps().shaderCaps()->pathRenderingSupport()) { this->glPathRendering()->disconnect(type); } @@ -1943,11 +1943,6 @@ 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. @@ -3616,43 +3611,64 @@ bool GrGLGpu::createMipmapProgram(int progIdx) { return true; } -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) { +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) { return false; } } - SkASSERT(!fStencilClipClearProgram); - GL_CALL_RET(fStencilClipClearProgram, CreateProgram()); - if (!fStencilClipClearProgram) { + SkASSERT(!fWireRectProgram.fProgram); + GL_CALL_RET(fWireRectProgram.fProgram, CreateProgram()); + if (!fWireRectProgram.fProgram) { 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( - "// Stencil Clip Clear Program VS\n" - "void main() {" - " gl_Position = vec4(a_vertex.x, a_vertex.y, 0, 1);" - "}"); + "// 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); SkString fshaderTxt(version); GrGLSLAppendDefaultFloatPrecisionDeclaration(kMedium_GrSLPrecision, *this->caps()->shaderCaps(), &fshaderTxt); + uColor.appendDecl(this->caps()->shaderCaps(), &fshaderTxt); + fshaderTxt.append(";"); fshaderTxt.appendf( - "// Stencil Clip Clear Program FS\n" - "void main() {" - " sk_FragColor = vec4(0);" - "}"); + "// Write Rect Program FS\n" + "void main() {" + " sk_FragColor = %s;" + "}", + uColor.c_str() + ); const char* str; GrGLint length; @@ -3662,21 +3678,25 @@ bool GrGLGpu::createStencilClipClearProgram() { SkSL::Program::Settings settings; settings.fCaps = this->caps()->shaderCaps(); SkSL::Program::Inputs inputs; - GrGLuint vshader = - GrGLCompileAndAttachShader(*fGLContext, fStencilClipClearProgram, GR_GL_VERTEX_SHADER, - &str, &length, 1, &fStats, settings, &inputs); + GrGLuint vshader = GrGLCompileAndAttachShader(*fGLContext, fWireRectProgram.fProgram, + 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, fStencilClipClearProgram, GR_GL_FRAGMENT_SHADER, - &str, &length, 1, &fStats, settings, &inputs); + GrGLuint fshader = GrGLCompileAndAttachShader(*fGLContext, fWireRectProgram.fProgram, + GR_GL_FRAGMENT_SHADER, &str, &length, 1, + &fStats, settings, &inputs); SkASSERT(inputs.isEmpty()); - GL_CALL(LinkProgram(fStencilClipClearProgram)); + GL_CALL(LinkProgram(fWireRectProgram.fProgram)); - GL_CALL(BindAttribLocation(fStencilClipClearProgram, 0, "a_vertex")); + 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(DeleteShader(vshader)); GL_CALL(DeleteShader(fshader)); @@ -3684,46 +3704,71 @@ bool GrGLGpu::createStencilClipClearProgram() { return true; } -void GrGLGpu::clearStencilClipAsDraw(const GrFixedClip& clip, bool insideStencilMask, - GrRenderTarget* rt) { +void GrGLGpu::drawDebugWireRect(GrRenderTarget* rt, const SkIRect& rect, GrColor color) { // TODO: This should swizzle the output to match dst's config, though it is a debugging // visualization. this->handleDirtyContext(); - if (!fStencilClipClearProgram) { - if (!this->createStencilClipClearProgram()) { - SkDebugf("Failed to create stencil clip clear program.\n"); + if (!fWireRectProgram.fProgram) { + if (!this->createWireRectProgram()) { + SkDebugf("Failed to create wire rect 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, nullptr); + this->flushRenderTarget(glRT, &rect); - GL_CALL(UseProgram(fStencilClipClearProgram)); - fHWProgramID = fStencilClipClearProgram; + GL_CALL(UseProgram(fWireRectProgram.fProgram)); + fHWProgramID = fWireRectProgram.fProgram; fHWVertexArrayState.setVertexArrayID(this, 0); GrGLAttribArrayState* attribs = fHWVertexArrayState.bindInternalVertexArray(this); attribs->enableVertexArrays(this, 1); - attribs->set(this, 0, fStencilClipClearArrayBuffer.get(), kVec2f_GrVertexAttribType, + attribs->set(this, 0, fWireRectArrayBuffer.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(false); + this->flushColorWrite(true); this->flushHWAAState(glRT, false, false); - 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)); + this->disableScissor(); + this->disableWindowRectangles(); + this->disableStencil(); + + GL_CALL(DrawArrays(GR_GL_LINE_LOOP, 0, 4)); } diff --git a/src/gpu/gl/GrGLGpu.h b/src/gpu/gl/GrGLGpu.h index 1785eae143..770c357c5f 100644 --- a/src/gpu/gl/GrGLGpu.h +++ b/src/gpu/gl/GrGLGpu.h @@ -162,6 +162,8 @@ 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; @@ -294,7 +296,6 @@ 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); @@ -348,6 +349,11 @@ 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(); @@ -401,7 +407,7 @@ private: bool createCopyProgram(GrTexture* srcTexture); bool createMipmapProgram(int progIdx); - bool createStencilClipClearProgram(); + bool createWireRectProgram(); // GL program-related state ProgramCache* fProgramCache; @@ -614,8 +620,12 @@ private: } fMipmapPrograms[4]; sk_sp<GrGLBuffer> fMipmapProgramArrayBuffer; - GrGLuint fStencilClipClearProgram; - sk_sp<GrGLBuffer> fStencilClipClearArrayBuffer; + struct { + GrGLuint fProgram; + GrGLint fColorUniform; + GrGLint fRectUniform; + } fWireRectProgram; + sk_sp<GrGLBuffer> fWireRectArrayBuffer; static int TextureToCopyProgramIdx(GrTexture* texture) { switch (texture->texturePriv().samplerType()) { diff --git a/src/gpu/vk/GrVkGpu.h b/src/gpu/vk/GrVkGpu.h index f81daea336..cce6883f8d 100644 --- a/src/gpu/vk/GrVkGpu.h +++ b/src/gpu/vk/GrVkGpu.h @@ -98,6 +98,8 @@ 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, |