aboutsummaryrefslogtreecommitdiffhomepage
path: root/src/gpu
diff options
context:
space:
mode:
authorGravatar Brian Salomon <bsalomon@google.com>2017-05-23 16:53:47 -0400
committerGravatar Skia Commit-Bot <skia-commit-bot@chromium.org>2017-05-23 21:38:38 +0000
commitd17b4a678b4b1df49a8eb84fb8c3c954d292a12c (patch)
tree82d59ef35abe6666d01723c62e4f22570b563801 /src/gpu
parent0610a462ad2e17057849784cdab73d634bab5fb9 (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.cpp8
-rw-r--r--src/gpu/GrResourceProvider.cpp5
-rw-r--r--src/gpu/GrSurfaceProxy.cpp4
-rw-r--r--src/gpu/gl/GrGLAssembleInterface.cpp8
-rw-r--r--src/gpu/gl/GrGLCaps.cpp17
-rw-r--r--src/gpu/gl/GrGLCaps.h4
-rw-r--r--src/gpu/gl/GrGLGpu.cpp45
-rw-r--r--src/gpu/gl/GrGLGpu.h6
-rw-r--r--src/gpu/vk/GrVkGpu.cpp13
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;
}