diff options
author | Brian Salomon <bsalomon@google.com> | 2017-05-31 09:55:04 -0400 |
---|---|---|
committer | Skia Commit-Bot <skia-commit-bot@chromium.org> | 2017-05-31 14:38:43 +0000 |
commit | 0cc507d22566bb7e28e5fe21e4b3fc7b682d86a2 (patch) | |
tree | 460ac21731d404377053dbe4755530b49f170d64 /src/gpu | |
parent | 59a8b9c12e4b6152f9a5807bd3fd45664de35048 (diff) |
Expand partial render target write pixels workaround.
The workaround is extended in the following ways:
1) It now applies to any texture whose base level has *ever* been attached to a FBO.
2) It applies to Adreno 5xx in addition to Adreno 4xx
3) It applies in the atlas upload code path.
This workaround (and a similar one) are narrowed to GLCaps rather than Caps.
Bug: skia:
Change-Id: Id600e9739bb97bf6766075ea2a987fd2039e53e5
Reviewed-on: https://skia-review.googlesource.com/18150
Reviewed-by: Robert Phillips <robertphillips@google.com>
Commit-Queue: Brian Salomon <bsalomon@google.com>
Diffstat (limited to 'src/gpu')
-rw-r--r-- | src/gpu/GrCaps.cpp | 4 | ||||
-rw-r--r-- | src/gpu/GrGpu.cpp | 9 | ||||
-rw-r--r-- | src/gpu/GrOpFlushState.cpp | 32 | ||||
-rw-r--r-- | src/gpu/GrOpFlushState.h | 11 | ||||
-rw-r--r-- | src/gpu/gl/GrGLCaps.cpp | 13 | ||||
-rw-r--r-- | src/gpu/gl/GrGLCaps.h | 14 | ||||
-rw-r--r-- | src/gpu/gl/GrGLGpu.cpp | 36 | ||||
-rw-r--r-- | src/gpu/gl/GrGLTexture.h | 5 |
8 files changed, 89 insertions, 35 deletions
diff --git a/src/gpu/GrCaps.cpp b/src/gpu/GrCaps.cpp index 5c04d190c5..b30af0f134 100644 --- a/src/gpu/GrCaps.cpp +++ b/src/gpu/GrCaps.cpp @@ -72,8 +72,6 @@ GrCaps::GrCaps(const GrContextOptions& options) { fImmediateFlush = options.fImmediateMode; fWireframeMode = options.fWireframeMode; fBufferMapThreshold = options.fBufferMapThreshold; - fUseDrawInsteadOfPartialRenderTargetWrite = options.fUseDrawInsteadOfPartialRenderTargetWrite; - fUseDrawInsteadOfAllRenderTargetWrites = false; fAvoidInstancedDrawsToFPTargets = false; fAvoidStencilBuffers = false; @@ -141,8 +139,6 @@ SkString GrCaps::dump() const { r.appendf("Cross context texture support : %s\n", gNY[fCrossContextTextureSupport]); r.appendf("Draw Instead of Clear [workaround] : %s\n", gNY[fUseDrawInsteadOfClear]); - r.appendf("Draw Instead of TexSubImage [workaround] : %s\n", - gNY[fUseDrawInsteadOfPartialRenderTargetWrite]); r.appendf("Prefer VRAM Use over flushes [workaround] : %s\n", gNY[fPreferVRAMUseOverFlushes]); if (this->advancedBlendEquationSupport()) { diff --git a/src/gpu/GrGpu.cpp b/src/gpu/GrGpu.cpp index 12a2d92281..bbf2a0b51b 100644 --- a/src/gpu/GrGpu.cpp +++ b/src/gpu/GrGpu.cpp @@ -291,15 +291,6 @@ bool GrGpu::getWritePixelsInfo(GrSurface* dstSurface, int width, int height, SkASSERT(dstSurface); SkASSERT(kGpuPrefersDraw_DrawPreference != *drawPreference); - if (SkToBool(dstSurface->asRenderTarget())) { - if (this->caps()->useDrawInsteadOfAllRenderTargetWrites()) { - ElevateDrawPreference(drawPreference, kRequireDraw_DrawPreference); - } else if (this->caps()->useDrawInsteadOfPartialRenderTargetWrite() && - (width < dstSurface->width() || height < dstSurface->height())) { - ElevateDrawPreference(drawPreference, kRequireDraw_DrawPreference); - } - } - if (!this->onGetWritePixelsInfo(dstSurface, width, height, srcConfig, drawPreference, tempDrawInfo)) { return false; diff --git a/src/gpu/GrOpFlushState.cpp b/src/gpu/GrOpFlushState.cpp index c6f5d38383..72deabe197 100644 --- a/src/gpu/GrOpFlushState.cpp +++ b/src/gpu/GrOpFlushState.cpp @@ -8,7 +8,7 @@ #include "GrOpFlushState.h" #include "GrDrawOpAtlas.h" -#include "GrPipeline.h" +#include "GrResourceProvider.h" GrOpFlushState::GrOpFlushState(GrGpu* gpu, GrResourceProvider* resourceProvider) : fGpu(gpu) @@ -29,3 +29,33 @@ uint16_t* GrOpFlushState::makeIndexSpace(int indexCount, const GrBuffer** buffer, int* startIndex) { return reinterpret_cast<uint16_t*>(fIndexPool.makeSpace(indexCount, buffer, startIndex)); } + +void GrOpFlushState::doUpload(GrDrawOp::DeferredUploadFn& upload) { + GrDrawOp::WritePixelsFn wp = [this](GrSurface* surface, int left, int top, int width, + int height, GrPixelConfig config, const void* buffer, + size_t rowBytes) { + GrGpu::DrawPreference drawPreference = GrGpu::kNoDraw_DrawPreference; + GrGpu::WritePixelTempDrawInfo tempInfo; + fGpu->getWritePixelsInfo(surface, width, height, surface->config(), &drawPreference, + &tempInfo); + if (GrGpu::kNoDraw_DrawPreference == drawPreference) { + return this->fGpu->writePixels(surface, left, top, width, height, config, buffer, + rowBytes); + } + GrSurfaceDesc desc; + desc.fConfig = surface->config(); + desc.fWidth = width; + desc.fHeight = height; + desc.fOrigin = surface->origin(); + sk_sp<GrTexture> temp(this->fResourceProvider->createApproxTexture( + desc, GrResourceProvider::kNoPendingIO_Flag)); + if (!temp) { + return false; + } + if (!fGpu->writePixels(temp.get(), 0, 0, width, height, desc.fConfig, buffer, rowBytes)) { + return false; + } + return fGpu->copySurface(surface, temp.get(), SkIRect::MakeWH(width, height), {left, top}); + }; + upload(wp); +} diff --git a/src/gpu/GrOpFlushState.h b/src/gpu/GrOpFlushState.h index 85a356e44f..402bac5325 100644 --- a/src/gpu/GrOpFlushState.h +++ b/src/gpu/GrOpFlushState.h @@ -72,16 +72,7 @@ public: fAsapUploads.reset(); } - void doUpload(GrDrawOp::DeferredUploadFn& upload) { - GrDrawOp::WritePixelsFn wp = [this] (GrSurface* surface, - int left, int top, int width, int height, - GrPixelConfig config, const void* buffer, - size_t rowBytes) -> bool { - return this->fGpu->writePixels(surface, left, top, width, height, config, buffer, - rowBytes); - }; - upload(wp); - } + void doUpload(GrDrawOp::DeferredUploadFn&); void putBackIndices(size_t indices) { fIndexPool.putBack(indices * sizeof(uint16_t)); } diff --git a/src/gpu/gl/GrGLCaps.cpp b/src/gpu/gl/GrGLCaps.cpp index df905a4f0f..3eab060f89 100644 --- a/src/gpu/gl/GrGLCaps.cpp +++ b/src/gpu/gl/GrGLCaps.cpp @@ -56,6 +56,8 @@ GrGLCaps::GrGLCaps(const GrContextOptions& contextOptions, fClearToBoundaryValuesIsBroken = false; fClearTextureSupport = false; fDrawArraysBaseVertexIsBroken = false; + fDisallowTexSubImageForTexturesEverBoundToFBO = false; + fUseDrawInsteadOfAllRenderTargetWrites = false; fBlitFramebufferFlags = kNoSupport_BlitFramebufferFlag; @@ -497,12 +499,12 @@ void GrGLCaps::init(const GrContextOptions& contextOptions, } if (kAdreno4xx_GrGLRenderer == ctxInfo.renderer()) { - fUseDrawInsteadOfPartialRenderTargetWrite = true; + fDisallowTexSubImageForTexturesEverBoundToFBO = true; } // Texture uploads sometimes seem to be ignored to textures bound to FBOS on Tegra3. if (kTegra3_GrGLRenderer == ctxInfo.renderer()) { - fUseDrawInsteadOfPartialRenderTargetWrite = true; + fDisallowTexSubImageForTexturesEverBoundToFBO = true; fUseDrawInsteadOfAllRenderTargetWrites = true; } @@ -1253,6 +1255,10 @@ SkString GrGLCaps::dump() const { r.appendf("Texture swizzle support: %s\n", (fTextureSwizzleSupport ? "YES" : "NO")); r.appendf("BGRA to RGBA readback conversions are slow: %s\n", (fRGBAToBGRAReadbackConversionsAreSlow ? "YES" : "NO")); + r.appendf("Intermediate texture for partial updates of textures ever bound to FBOs: %s\n", + fDisallowTexSubImageForTexturesEverBoundToFBO ? "YES" : "NO"); + r.appendf("Intermediate texture for all updates of textures bound to FBOs: %s\n", + fUseDrawInsteadOfAllRenderTargetWrites ? "YES" : "NO"); r.append("Configs\n-------\n"); for (int i = 0; i < kGrPixelConfigCnt; ++i) { @@ -2147,4 +2153,7 @@ void GrGLCaps::onApplyOptionsOverrides(const GrContextOptions& options) { fAvoidInstancedDrawsToFPTargets = true; #endif } + if (options.fUseDrawInsteadOfPartialRenderTargetWrite) { + fUseDrawInsteadOfAllRenderTargetWrites = true; + } } diff --git a/src/gpu/gl/GrGLCaps.h b/src/gpu/gl/GrGLCaps.h index b7273a08b1..75a12d7762 100644 --- a/src/gpu/gl/GrGLCaps.h +++ b/src/gpu/gl/GrGLCaps.h @@ -368,6 +368,18 @@ public: // https://bugs.chromium.org/p/skia/issues/detail?id=6650 bool drawArraysBaseVertexIsBroken() const { return fDrawArraysBaseVertexIsBroken; } + // If true then we must use an intermediate surface to perform partial updates to a texture that + // has ever been bound to a FBO. + bool disallowTexSubImageForTexturesEverBoundToFBO() const { + return fDisallowTexSubImageForTexturesEverBoundToFBO; + } + + // Use an intermediate surface to write pixels (full or partial overwrite) to into a texture + // that is bound to an FBO. + bool useDrawInsteadOfAllRenderTargetWrites() const { + return fUseDrawInsteadOfAllRenderTargetWrites; + } + bool initDescForDstCopy(const GrRenderTargetProxy* src, GrSurfaceDesc* desc, bool* rectsMustMatch, bool* disallowSubrect) const override; @@ -442,6 +454,8 @@ private: bool fClearToBoundaryValuesIsBroken : 1; bool fClearTextureSupport : 1; bool fDrawArraysBaseVertexIsBroken : 1; + bool fDisallowTexSubImageForTexturesEverBoundToFBO : 1; + bool fUseDrawInsteadOfAllRenderTargetWrites : 1; uint32_t fBlitFramebufferFlags; diff --git a/src/gpu/gl/GrGLGpu.cpp b/src/gpu/gl/GrGLGpu.cpp index 045804c668..f3aac8afc1 100644 --- a/src/gpu/gl/GrGLGpu.cpp +++ b/src/gpu/gl/GrGLGpu.cpp @@ -582,7 +582,10 @@ sk_sp<GrTexture> GrGLGpu::onWrapBackendTexture(const GrBackendTexture& backendTe if (!this->createRenderTargetObjects(surfDesc, idDesc.fInfo, &rtIDDesc)) { return nullptr; } - return GrGLTextureRenderTarget::MakeWrapped(this, surfDesc, idDesc, rtIDDesc); + sk_sp<GrGLTextureRenderTarget> texRT( + GrGLTextureRenderTarget::MakeWrapped(this, surfDesc, idDesc, rtIDDesc)); + texRT->baseLevelWasBoundToFBO(); + return texRT; } return GrGLTexture::MakeWrapped(this, surfDesc, idDesc); @@ -662,16 +665,28 @@ bool GrGLGpu::onGetWritePixelsInfo(GrSurface* dstSurface, int width, int height, GrPixelConfig srcConfig, DrawPreference* drawPreference, WritePixelTempDrawInfo* tempDrawInfo) { - // This subclass only allows writes to textures. If the dst is not a texture we have to draw - // into it. We could use glDrawPixels on GLs that have it, but we don't today. - if (!dstSurface->asTexture()) { - ElevateDrawPreference(drawPreference, kRequireDraw_DrawPreference); - } else { - GrGLTexture* texture = static_cast<GrGLTexture*>(dstSurface->asTexture()); + if (SkToBool(dstSurface->asRenderTarget())) { + if (this->glCaps().useDrawInsteadOfAllRenderTargetWrites()) { + ElevateDrawPreference(drawPreference, kRequireDraw_DrawPreference); + } + } + + GrGLTexture* texture = static_cast<GrGLTexture*>(dstSurface->asTexture()); + + if (texture) { if (GR_GL_TEXTURE_EXTERNAL == texture->target()) { // We don't currently support writing pixels to EXTERNAL textures. return false; } + if (texture->hasBaseLevelBeenBoundToFBO() && + this->glCaps().disallowTexSubImageForTexturesEverBoundToFBO() && + (width < dstSurface->width() || height < dstSurface->height())) { + ElevateDrawPreference(drawPreference, kRequireDraw_DrawPreference); + } + } else { + // This subclass only allows writes to textures. If the dst is not a texture we have to draw + // into it. We could use glDrawPixels on GLs that have it, but we don't today. + ElevateDrawPreference(drawPreference, kRequireDraw_DrawPreference); } // If the dst is MSAA, we have to draw, or we'll just be writing to the resolve target. @@ -1373,6 +1388,7 @@ GrTexture* GrGLGpu::onCreateTexture(const GrSurfaceDesc& desc, } tex = new GrGLTextureRenderTarget(this, budgeted, desc, idDesc, rtIDDesc, wasMipMapDataProvided); + tex->baseLevelWasBoundToFBO(); } else { tex = new GrGLTexture(this, budgeted, desc, idDesc, wasMipMapDataProvided); } @@ -3217,8 +3233,9 @@ void GrGLGpu::bindSurfaceFBOForPixelOps(GrSurface* surface, GrGLenum fboTarget, GrGLRenderTarget* rt = static_cast<GrGLRenderTarget*>(surface->asRenderTarget()); if (!rt) { SkASSERT(surface->asTexture()); - GrGLuint texID = static_cast<GrGLTexture*>(surface->asTexture())->textureID(); - GrGLenum target = static_cast<GrGLTexture*>(surface->asTexture())->target(); + GrGLTexture* texture = static_cast<GrGLTexture*>(surface->asTexture()); + GrGLuint texID = texture->textureID(); + GrGLenum target = texture->target(); GrGLuint* tempFBOID; tempFBOID = kSrc_TempFBOTarget == tempFBOTarget ? &fTempSrcFBOID : &fTempDstFBOID; @@ -3233,6 +3250,7 @@ void GrGLGpu::bindSurfaceFBOForPixelOps(GrSurface* surface, GrGLenum fboTarget, target, texID, 0)); + texture->baseLevelWasBoundToFBO(); viewport->fLeft = 0; viewport->fBottom = 0; viewport->fWidth = surface->width(); diff --git a/src/gpu/gl/GrGLTexture.h b/src/gpu/gl/GrGLTexture.h index 74358914ec..85ada01c87 100644 --- a/src/gpu/gl/GrGLTexture.h +++ b/src/gpu/gl/GrGLTexture.h @@ -66,7 +66,11 @@ public: GrGLenum target() const { return fInfo.fTarget; } + bool hasBaseLevelBeenBoundToFBO() const { return fBaseLevelHasBeenBoundToFBO; } + void baseLevelWasBoundToFBO() { fBaseLevelHasBeenBoundToFBO = true; } + static sk_sp<GrGLTexture> MakeWrapped(GrGLGpu*, const GrSurfaceDesc&, const IDDesc&); + protected: // Constructor for subclasses. GrGLTexture(GrGLGpu*, const GrSurfaceDesc&, const IDDesc&, bool wasMipMapDataProvided); @@ -96,6 +100,7 @@ private: // direct interaction with the GL object. GrGLTextureInfo fInfo; GrBackendObjectOwnership fTextureIDOwnership; + bool fBaseLevelHasBeenBoundToFBO = false; ReleaseProc fReleaseProc = nullptr; ReleaseCtx fReleaseCtx = nullptr; |