diff options
author | 2017-05-23 16:53:47 -0400 | |
---|---|---|
committer | 2017-05-23 21:38:38 +0000 | |
commit | d17b4a678b4b1df49a8eb84fb8c3c954d292a12c (patch) | |
tree | 82d59ef35abe6666d01723c62e4f22570b563801 /src/gpu | |
parent | 0610a462ad2e17057849784cdab73d634bab5fb9 (diff) |
Revert "Revert "Add a flag to GrSurfaceFlags that requires the texture to be cleared upon creation. ""
This reverts commit a9e795eab5f59a52d96b8fdc39351452835f5eb9.
Bug: skia:
Change-Id: Ibfc51497ae99f332f8f72a799393a1b2996f7f3f
Reviewed-on: https://skia-review.googlesource.com/17767
Reviewed-by: Brian Osman <brianosman@google.com>
Commit-Queue: Brian Salomon <bsalomon@google.com>
Diffstat (limited to 'src/gpu')
-rw-r--r-- | src/gpu/GrGpu.cpp | 8 | ||||
-rw-r--r-- | src/gpu/GrResourceProvider.cpp | 5 | ||||
-rw-r--r-- | src/gpu/GrSurfaceProxy.cpp | 4 | ||||
-rw-r--r-- | src/gpu/gl/GrGLAssembleInterface.cpp | 8 | ||||
-rw-r--r-- | src/gpu/gl/GrGLCaps.cpp | 17 | ||||
-rw-r--r-- | src/gpu/gl/GrGLCaps.h | 4 | ||||
-rw-r--r-- | src/gpu/gl/GrGLGpu.cpp | 45 | ||||
-rw-r--r-- | src/gpu/gl/GrGLGpu.h | 6 | ||||
-rw-r--r-- | src/gpu/vk/GrVkGpu.cpp | 13 |
9 files changed, 101 insertions, 9 deletions
diff --git a/src/gpu/GrGpu.cpp b/src/gpu/GrGpu.cpp index 14ce050933..12a2d92281 100644 --- a/src/gpu/GrGpu.cpp +++ b/src/gpu/GrGpu.cpp @@ -138,11 +138,15 @@ GrTexture* GrGpu::createTexture(const GrSurfaceDesc& origDesc, SkBudgeted budget } desc.fSampleCnt = SkTMin(desc.fSampleCnt, caps->maxSampleCount()); - // Attempt to catch un- or wrongly intialized sample counts; + // Attempt to catch un- or wrongly initialized sample counts. SkASSERT(desc.fSampleCnt >= 0 && desc.fSampleCnt <= 64); desc.fOrigin = resolve_origin(desc.fOrigin, isRT); + if (texels.count() && (desc.fFlags & kPerformInitialClear_GrSurfaceFlag)) { + return nullptr; + } + this->handleDirtyContext(); GrTexture* tex = this->onCreateTexture(desc, budgeted, texels); if (tex) { @@ -262,7 +266,7 @@ bool GrGpu::getReadPixelsInfo(GrSurface* srcSurface, int width, int height, size return false; } - if (!this->onGetReadPixelsInfo(srcSurface, width, height, rowBytes, readConfig, drawPreference, + if (!this->onGetReadPixelsInfo(srcSurface, width, height, rowBytes, readConfig, drawPreference, tempDrawInfo)) { return false; } diff --git a/src/gpu/GrResourceProvider.cpp b/src/gpu/GrResourceProvider.cpp index 84e274eee2..128ef7598d 100644 --- a/src/gpu/GrResourceProvider.cpp +++ b/src/gpu/GrResourceProvider.cpp @@ -221,7 +221,10 @@ GrTexture* GrResourceProvider::refScratchTexture(const GrSurfaceDesc& inDesc, ui SkTCopyOnFirstWrite<GrSurfaceDesc> desc(inDesc); - if (fGpu->caps()->reuseScratchTextures() || (desc->fFlags & kRenderTarget_GrSurfaceFlag)) { + // We could make initial clears work with scratch textures but it is a rare case so we just opt + // to fall back to making a new texture. + if (!SkToBool(inDesc.fFlags & kPerformInitialClear_GrSurfaceFlag) && + (fGpu->caps()->reuseScratchTextures() || (desc->fFlags & kRenderTarget_GrSurfaceFlag))) { if (!(kExact_Flag & flags)) { // bin by pow2 with a reasonable min GrSurfaceDesc* wdesc = desc.writable(); diff --git a/src/gpu/GrSurfaceProxy.cpp b/src/gpu/GrSurfaceProxy.cpp index 3ced81b150..0d9198fd0d 100644 --- a/src/gpu/GrSurfaceProxy.cpp +++ b/src/gpu/GrSurfaceProxy.cpp @@ -30,6 +30,7 @@ GrSurfaceProxy::GrSurfaceProxy(sk_sp<GrSurface> surface, SkBackingFit fit) , fBudgeted(fTarget->resourcePriv().isBudgeted()) , fFlags(0) , fUniqueID(fTarget->uniqueID()) // Note: converting from unique resource ID to a proxy ID! + , fNeedsClear(false) , fGpuMemorySize(kInvalidGpuMemorySize) , fLastOpList(nullptr) {} @@ -53,6 +54,9 @@ GrSurface* GrSurfaceProxy::instantiateImpl(GrResourceProvider* resourceProvider, desc.fSampleCnt = sampleCnt; desc.fIsMipMapped = isMipMapped; desc.fFlags = flags; + if (fNeedsClear) { + desc.fFlags |= kPerformInitialClear_GrSurfaceFlag; + } if (SkBackingFit::kApprox == fFit) { fTarget = resourceProvider->createApproxTexture(desc, fFlags); diff --git a/src/gpu/gl/GrGLAssembleInterface.cpp b/src/gpu/gl/GrGLAssembleInterface.cpp index 7914934eac..7305696567 100644 --- a/src/gpu/gl/GrGLAssembleInterface.cpp +++ b/src/gpu/gl/GrGLAssembleInterface.cpp @@ -105,6 +105,10 @@ const GrGLInterface* GrGLAssembleGLInterface(void* ctx, GrGLGetProc get) { GET_PROC(Clear); GET_PROC(ClearColor); GET_PROC(ClearStencil); + if (glVer >= GR_GL_VER(4,4) || extensions.has("GL_ARB_clear_texture")) { + GET_PROC(ClearTexImage); + GET_PROC(ClearTexSubImage); + } GET_PROC(ColorMask); GET_PROC(CompileShader); GET_PROC(CompressedTexImage2D); @@ -584,6 +588,10 @@ const GrGLInterface* GrGLAssembleGLESInterface(void* ctx, GrGLGetProc get) { GET_PROC(Clear); GET_PROC(ClearColor); GET_PROC(ClearStencil); + if (extensions.has("GL_EXT_clear_texture")) { + GET_PROC_SUFFIX(ClearTexImage, EXT); + GET_PROC_SUFFIX(ClearTexSubImage, EXT); + } GET_PROC(ColorMask); GET_PROC(CompileShader); GET_PROC(CompressedTexImage2D); diff --git a/src/gpu/gl/GrGLCaps.cpp b/src/gpu/gl/GrGLCaps.cpp index b9eee088e0..8c4330312d 100644 --- a/src/gpu/gl/GrGLCaps.cpp +++ b/src/gpu/gl/GrGLCaps.cpp @@ -54,6 +54,7 @@ GrGLCaps::GrGLCaps(const GrContextOptions& contextOptions, fSRGBDecodeDisableSupport = false; fSRGBDecodeDisableAffectsMipmaps = false; fClearToBoundaryValuesIsBroken = false; + fClearTextureSupport = false; fDrawArraysBaseVertexIsBroken = false; fBlitFramebufferFlags = kNoSupport_BlitFramebufferFlag; @@ -252,6 +253,22 @@ void GrGLCaps::init(const GrContextOptions& contextOptions, // vis-versa. fRGBAToBGRAReadbackConversionsAreSlow = isMESA || isMAC; + if (kGL_GrGLStandard == standard) { + if (version >= GR_GL_VER(4,4) || ctxInfo.hasExtension("GL_ARB_clear_texture")) { + // glClearTexImage seems to have a bug in NVIDIA drivers that was fixed sometime between + // 340.96 and 367.57. + if (ctxInfo.driver() != kNVIDIA_GrGLDriver || + ctxInfo.driverVersion() >= GR_GL_DRIVER_VER(367, 57)) { + fClearTextureSupport = true; + } + } + } else if (ctxInfo.hasExtension("GL_EXT_clear_texture")) { + // Calling glClearTexImage crashes on the NexusPlayer. + if (kPowerVRRogue_GrGLRenderer != ctxInfo.renderer()) { + fClearTextureSupport = true; + } + } + /************************************************************************** * GrShaderCaps fields **************************************************************************/ diff --git a/src/gpu/gl/GrGLCaps.h b/src/gpu/gl/GrGLCaps.h index 3059ea7149..b7273a08b1 100644 --- a/src/gpu/gl/GrGLCaps.h +++ b/src/gpu/gl/GrGLCaps.h @@ -360,6 +360,9 @@ public: // Certain Intel GPUs on Mac fail to clear if the glClearColor is made up of only 1s and 0s. bool clearToBoundaryValuesIsBroken() const { return fClearToBoundaryValuesIsBroken; } + /// glClearTex(Sub)Image support + bool clearTextureSupport() const { return fClearTextureSupport; } + // Adreno/MSAA drops a draw on the imagefiltersbase GM if the base vertex param to // glDrawArrays is nonzero. // https://bugs.chromium.org/p/skia/issues/detail?id=6650 @@ -437,6 +440,7 @@ private: bool fSRGBDecodeDisableSupport : 1; bool fSRGBDecodeDisableAffectsMipmaps : 1; bool fClearToBoundaryValuesIsBroken : 1; + bool fClearTextureSupport : 1; bool fDrawArraysBaseVertexIsBroken : 1; uint32_t fBlitFramebufferFlags; diff --git a/src/gpu/gl/GrGLGpu.cpp b/src/gpu/gl/GrGLGpu.cpp index 565e60a220..81ee87c5e0 100644 --- a/src/gpu/gl/GrGLGpu.cpp +++ b/src/gpu/gl/GrGLGpu.cpp @@ -1320,24 +1320,44 @@ static void set_initial_texture_params(const GrGLInterface* interface, GrTexture* GrGLGpu::onCreateTexture(const GrSurfaceDesc& desc, SkBudgeted budgeted, - const SkTArray<GrMipLevel>& texels) { + const SkTArray<GrMipLevel>& origTexels) { // We fail if the MSAA was requested and is not available. if (GrGLCaps::kNone_MSFBOType == this->glCaps().msFBOType() && desc.fSampleCnt) { //SkDebugf("MSAA RT requested but not supported on this platform."); return return_null_texture(); } + bool performClear = (desc.fFlags & kPerformInitialClear_GrSurfaceFlag); + const SkTArray<GrMipLevel>* texels = &origTexels; + + SkTArray<GrMipLevel> zeroLevels; + std::unique_ptr<uint8_t[]> zeros; + // TODO: remove the GrPixelConfigIsSint test. This is here because we have yet to add support + // for glClearBuffer* which must be used instead of glClearColor/glClear for integer FBO + // attachments. + if (performClear && !this->glCaps().clearTextureSupport() && + (!this->glCaps().canConfigBeFBOColorAttachment(desc.fConfig) || + GrPixelConfigIsSint(desc.fConfig))) { + size_t rowSize = GrBytesPerPixel(desc.fConfig) * desc.fWidth; + size_t size = rowSize * desc.fHeight; + zeros.reset(new uint8_t[size]); + memset(zeros.get(), 0, size); + zeroLevels.push_back(GrMipLevel{zeros.get(), 0}); + texels = &zeroLevels; + performClear = false; + } + bool isRenderTarget = SkToBool(desc.fFlags & kRenderTarget_GrSurfaceFlag); GrGLTexture::IDDesc idDesc; idDesc.fOwnership = GrBackendObjectOwnership::kOwned; GrGLTexture::TexParams initialTexParams; - if (!this->createTextureImpl(desc, &idDesc.fInfo, isRenderTarget, &initialTexParams, texels)) { + if (!this->createTextureImpl(desc, &idDesc.fInfo, isRenderTarget, &initialTexParams, *texels)) { return return_null_texture(); } bool wasMipMapDataProvided = false; - if (texels.count() > 1) { + if (texels->count() > 1) { wasMipMapDataProvided = true; } @@ -1361,6 +1381,25 @@ GrTexture* GrGLGpu::onCreateTexture(const GrSurfaceDesc& desc, SkDebugf("--- new texture [%d] size=(%d %d) config=%d\n", idDesc.fInfo.fID, desc.fWidth, desc.fHeight, desc.fConfig); #endif + if (tex && performClear) { + if (this->glCaps().clearTextureSupport()) { + GrGLenum format = GrPixelConfigIsSint(tex->config()) ? GR_GL_RGBA_INTEGER : GR_GL_RGBA; + static constexpr uint32_t kZero = 0; + GL_CALL(ClearTexImage(tex->textureID(), 0, format, GR_GL_UNSIGNED_BYTE, &kZero)); + } else { + SkASSERT(!GrPixelConfigIsSint(desc.fConfig)); + GrGLIRect viewport; + this->bindSurfaceFBOForPixelOps(tex, GR_GL_FRAMEBUFFER, &viewport, kDst_TempFBOTarget); + this->disableScissor(); + this->disableWindowRectangles(); + GL_CALL(ColorMask(GR_GL_TRUE, GR_GL_TRUE, GR_GL_TRUE, GR_GL_TRUE)); + fHWWriteToColor = kYes_TriState; + GL_CALL(ClearColor(0, 0, 0, 0)); + GL_CALL(Clear(GR_GL_COLOR_BUFFER_BIT)); + this->unbindTextureFBOForPixelOps(GR_GL_FRAMEBUFFER, tex); + fHWBoundRenderTargetUniqueID.makeInvalid(); + } + } return tex; } diff --git a/src/gpu/gl/GrGLGpu.h b/src/gpu/gl/GrGLGpu.h index a4706c79ed..d19f2ef6ee 100644 --- a/src/gpu/gl/GrGLGpu.h +++ b/src/gpu/gl/GrGLGpu.h @@ -371,9 +371,9 @@ private: kDst_TempFBOTarget }; - // Binds a surface as a FBO for copying or reading. If the surface already owns an FBO ID then - // that ID is bound. If not the surface is temporarily bound to a FBO and that FBO is bound. - // This must be paired with a call to unbindSurfaceFBOForPixelOps(). + // Binds a surface as a FBO for copying, reading, or clearing. If the surface already owns an + // FBO ID then that ID is bound. If not the surface is temporarily bound to a FBO and that FBO + // is bound. This must be paired with a call to unbindSurfaceFBOForPixelOps(). void bindSurfaceFBOForPixelOps(GrSurface* surface, GrGLenum fboTarget, GrGLIRect* viewport, TempFBOTarget tempFBOTarget); diff --git a/src/gpu/vk/GrVkGpu.cpp b/src/gpu/vk/GrVkGpu.cpp index 7fbca9f9da..4d305acab5 100644 --- a/src/gpu/vk/GrVkGpu.cpp +++ b/src/gpu/vk/GrVkGpu.cpp @@ -745,6 +745,19 @@ GrTexture* GrVkGpu::onCreateTexture(const GrSurfaceDesc& desc, SkBudgeted budget } } + if (desc.fFlags & kPerformInitialClear_GrSurfaceFlag) { + VkClearColorValue zeroClearColor; + memset(&zeroClearColor, 0, sizeof(zeroClearColor)); + VkImageSubresourceRange range; + range.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT; + range.baseArrayLayer = 0; + range.baseMipLevel = 0; + range.layerCount = 1; + range.levelCount = 1; + tex->setImageLayout(this, VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, + VK_ACCESS_TRANSFER_WRITE_BIT, VK_PIPELINE_STAGE_TRANSFER_BIT, false); + this->currentCommandBuffer()->clearColorImage(this, tex, &zeroClearColor, 1, &range); + } return tex; } |