diff options
author | 2018-06-20 16:25:26 -0400 | |
---|---|---|
committer | 2018-06-20 21:13:27 +0000 | |
commit | 930f939c48af1be6005af12bb6f709ca5da9d118 (patch) | |
tree | 21dbb8b105aa1190237c148358b7993565158335 /src/gpu/gl | |
parent | 2a284de7a51c198096a6f34ec1cbfe9118db554c (diff) |
Ensure that textures exported via SkImage::MakeBackendTextureFromSkImage
have consistent content in their mip map levels.
Bug= chromium:850617
Change-Id: I3ad918aa453bd8e4e625eb145de6ba2a5dab7b0c
Reviewed-on: https://skia-review.googlesource.com/136230
Commit-Queue: Brian Salomon <bsalomon@google.com>
Reviewed-by: Greg Daniel <egdaniel@google.com>
Diffstat (limited to 'src/gpu/gl')
-rw-r--r-- | src/gpu/gl/GrGLGpu.cpp | 88 | ||||
-rw-r--r-- | src/gpu/gl/GrGLGpu.h | 9 | ||||
-rw-r--r-- | src/gpu/gl/GrGLProgram.cpp | 22 |
3 files changed, 37 insertions, 82 deletions
diff --git a/src/gpu/gl/GrGLGpu.cpp b/src/gpu/gl/GrGLGpu.cpp index 08bd168368..9e73259a55 100644 --- a/src/gpu/gl/GrGLGpu.cpp +++ b/src/gpu/gl/GrGLGpu.cpp @@ -2716,8 +2716,7 @@ static GrGLenum filter_to_gl_min_filter(GrSamplerState::Filter filter) { return 0; } -void GrGLGpu::bindTexture(int unitIdx, const GrSamplerState& samplerState, GrGLTexture* texture, - GrSurfaceOrigin textureOrigin) { +void GrGLGpu::bindTexture(int unitIdx, const GrSamplerState& samplerState, GrGLTexture* texture) { SkASSERT(texture); #ifdef SK_DEBUG @@ -2858,53 +2857,6 @@ void GrGLGpu::bindTexelBuffer(int unitIdx, GrPixelConfig texelConfig, GrGLBuffer } } -void GrGLGpu::generateMipmaps(const GrSamplerState& params, GrGLTexture* texture, - GrSurfaceOrigin textureOrigin) { - SkASSERT(texture); - - // First, figure out if we need mips for this texture at all: - GrSamplerState::Filter filterMode = params.filter(); - - if (GrSamplerState::Filter::kMipMap == filterMode) { - if (!this->caps()->mipMapSupport() || - texture->texturePriv().mipMapped() == GrMipMapped::kNo) { - filterMode = GrSamplerState::Filter::kBilerp; - } - } - - if (GrSamplerState::Filter::kMipMap != filterMode) { - return; - } - - SkASSERT(texture->texturePriv().mipMapped() == GrMipMapped::kYes); - - // If the mips aren't dirty, we're done: - if (!texture->texturePriv().mipMapsAreDirty()) { - return; - } - - // If we created a rt/tex and rendered to it without using a texture and now we're texturing - // from the rt it will still be the last bound texture, but it needs resolving. - GrGLRenderTarget* texRT = static_cast<GrGLRenderTarget*>(texture->asRenderTarget()); - if (texRT) { - this->onResolveRenderTarget(texRT); - } - - GrGLenum target = texture->target(); - this->setScratchTextureUnit(); - GL_CALL(BindTexture(target, texture->textureID())); - - // Either do manual mipmap generation or (if that fails), just rely on the driver: - if (!this->generateMipmap(texture, textureOrigin)) { - GL_CALL(GenerateMipmap(target)); - } - - texture->texturePriv().markMipMapsClean(); - - // We have potentially set lots of state on the texture. Easiest to dirty it all: - texture->textureParamsModified(); -} - void GrGLGpu::setTextureSwizzle(int unitIdx, GrGLenum target, const GrGLenum swizzle[]) { this->setTextureUnit(unitIdx); if (this->glStandard() == kGLES_GrGLStandard) { @@ -3664,7 +3616,7 @@ bool GrGLGpu::copySurfaceAsDraw(GrSurface* dst, GrSurfaceOrigin dstOrigin, int w = srcRect.width(); int h = srcRect.height(); - this->bindTexture(0, GrSamplerState::ClampNearest(), srcTex, srcOrigin); + this->bindTexture(0, GrSamplerState::ClampNearest(), srcTex); GrGLIRect dstVP; this->bindSurfaceFBOForPixelOps(dst, GR_GL_FRAMEBUFFER, &dstVP, kDst_TempFBOTarget); @@ -3820,23 +3772,25 @@ bool GrGLGpu::copySurfaceAsBlitFramebuffer(GrSurface* dst, GrSurfaceOrigin dstOr return true; } -// Manual implementation of mipmap generation, to work around driver bugs w/sRGB. -// Uses draw calls to do a series of downsample operations to successive mips. -// If this returns false, then the calling code falls back to using glGenerateMipmap. -bool GrGLGpu::generateMipmap(GrGLTexture* texture, GrSurfaceOrigin textureOrigin) { - // Our iterative downsample requires the ability to limit which level we're sampling: - if (!this->glCaps().doManualMipmapping()) { - return false; - } - +bool GrGLGpu::onRegenerateMipMapLevels(GrTexture* texture) { + auto glTex = static_cast<GrGLTexture*>(texture); // Mipmaps are only supported on 2D textures: - if (GR_GL_TEXTURE_2D != texture->target()) { + if (GR_GL_TEXTURE_2D != glTex->target()) { return false; } - // We need to be able to render to the texture for this to work: - if (!this->glCaps().canConfigBeFBOColorAttachment(texture->config())) { - return false; + // Manual implementation of mipmap generation, to work around driver bugs w/sRGB. + // Uses draw calls to do a series of downsample operations to successive mips. + + // The manual approach requires the ability to limit which level we're sampling and that the + // destination can be bound to a FBO: + if (!this->glCaps().doManualMipmapping() || + !this->glCaps().canConfigBeFBOColorAttachment(texture->config())) { + GrGLenum target = glTex->target(); + this->setScratchTextureUnit(); + GL_CALL(BindTexture(target, glTex->textureID())); + GL_CALL(GenerateMipmap(glTex->target())); + return true; } int width = texture->width(); @@ -3854,7 +3808,7 @@ bool GrGLGpu::generateMipmap(GrGLTexture* texture, GrSurfaceOrigin textureOrigin // Bind the texture, to get things configured for filtering. // We'll be changing our base level further below: this->setTextureUnit(0); - this->bindTexture(0, GrSamplerState::ClampBilerp(), texture, textureOrigin); + this->bindTexture(0, GrSamplerState::ClampBilerp(), glTex); // Vertex data: if (!fMipmapProgramArrayBuffer) { @@ -3916,8 +3870,8 @@ bool GrGLGpu::generateMipmap(GrGLTexture* texture, GrSurfaceOrigin textureOrigin // Only sample from previous mip GL_CALL(TexParameteri(GR_GL_TEXTURE_2D, GR_GL_TEXTURE_BASE_LEVEL, level - 1)); - GL_CALL(FramebufferTexture2D(GR_GL_FRAMEBUFFER, GR_GL_COLOR_ATTACHMENT0, - GR_GL_TEXTURE_2D, texture->textureID(), level)); + GL_CALL(FramebufferTexture2D(GR_GL_FRAMEBUFFER, GR_GL_COLOR_ATTACHMENT0, GR_GL_TEXTURE_2D, + glTex->textureID(), level)); width = SkTMax(1, width / 2); height = SkTMax(1, height / 2); @@ -3932,6 +3886,8 @@ bool GrGLGpu::generateMipmap(GrGLTexture* texture, GrSurfaceOrigin textureOrigin GL_CALL(FramebufferTexture2D(GR_GL_FRAMEBUFFER, GR_GL_COLOR_ATTACHMENT0, GR_GL_TEXTURE_2D, 0, 0)); + // We modified the base level param. + texture->textureParamsModified(); return true; } diff --git a/src/gpu/gl/GrGLGpu.h b/src/gpu/gl/GrGLGpu.h index 48cd21b426..d08974498a 100644 --- a/src/gpu/gl/GrGLGpu.h +++ b/src/gpu/gl/GrGLGpu.h @@ -54,14 +54,10 @@ public: } // Used by GrGLProgram to configure OpenGL state. - void bindTexture(int unitIdx, const GrSamplerState& samplerState, GrGLTexture* texture, - GrSurfaceOrigin textureOrigin); + void bindTexture(int unitIdx, const GrSamplerState& samplerState, GrGLTexture* texture); void bindTexelBuffer(int unitIdx, GrPixelConfig, GrGLBuffer*); - void generateMipmaps(const GrSamplerState& params, GrGLTexture* texture, - GrSurfaceOrigin textureOrigin); - // These functions should be used to bind GL objects. They track the GL state and skip redundant // bindings. Making the equivalent glBind calls directly will confuse the state tracking. void bindVertexArray(GrGLuint id) { @@ -244,6 +240,8 @@ private: void onResolveRenderTarget(GrRenderTarget* target) override; + bool onRegenerateMipMapLevels(GrTexture*) override; + bool onCopySurface(GrSurface* dst, GrSurfaceOrigin dstOrigin, GrSurface* src, GrSurfaceOrigin srcOrigin, const SkIRect& srcRect, const SkIPoint& dstPoint, @@ -286,7 +284,6 @@ private: bool copySurfaceAsBlitFramebuffer(GrSurface* dst, GrSurfaceOrigin dstOrigin, GrSurface* src, GrSurfaceOrigin srcOrigin, const SkIRect& srcRect, const SkIPoint& dstPoint); - bool generateMipmap(GrGLTexture* texture, GrSurfaceOrigin textureOrigin); void clearStencilClipAsDraw(const GrFixedClip&, bool insideStencilMask, GrRenderTarget*, GrSurfaceOrigin); diff --git a/src/gpu/gl/GrGLProgram.cpp b/src/gpu/gl/GrGLProgram.cpp index 3d4bd380fa..2a876d0851 100644 --- a/src/gpu/gl/GrGLProgram.cpp +++ b/src/gpu/gl/GrGLProgram.cpp @@ -6,15 +6,15 @@ */ #include "GrGLProgram.h" - #include "GrAllocator.h" -#include "GrProcessor.h" #include "GrCoordTransform.h" -#include "GrGLGpu.h" #include "GrGLBuffer.h" +#include "GrGLGpu.h" #include "GrGLPathRendering.h" #include "GrPathProcessor.h" #include "GrPipeline.h" +#include "GrProcessor.h" +#include "GrTexturePriv.h" #include "GrXferProcessor.h" #include "glsl/GrGLSLFragmentProcessor.h" #include "glsl/GrGLSLGeometryProcessor.h" @@ -99,8 +99,7 @@ void GrGLProgram::setData(const GrPrimitiveProcessor& primProc, const GrPipeline fXferProcessor->setData(fProgramDataManager, xp, dstTexture, offset); if (dstTexture) { fGpu->bindTexture(nextTexSamplerIdx++, GrSamplerState::ClampNearest(), - static_cast<GrGLTexture*>(dstTexture), - pipeline.dstTextureProxy()->origin()); + static_cast<GrGLTexture*>(dstTexture)); } SkASSERT(nextTexSamplerIdx == fNumTextureSamplers); SkASSERT(nextTexelBufferIdx == fNumTextureSamplers + fNumTexelBuffers); @@ -170,8 +169,7 @@ void GrGLProgram::bindTextures(const GrResourceIOProcessor& processor, for (int i = 0; i < processor.numTextureSamplers(); ++i) { const GrResourceIOProcessor::TextureSampler& sampler = processor.textureSampler(i); fGpu->bindTexture((*nextTexSamplerIdx)++, sampler.samplerState(), - static_cast<GrGLTexture*>(sampler.peekTexture()), - sampler.proxy()->origin()); + static_cast<GrGLTexture*>(sampler.peekTexture())); } for (int i = 0; i < processor.numBuffers(); ++i) { const GrResourceIOProcessor::BufferAccess& access = processor.bufferAccess(i); @@ -183,8 +181,12 @@ void GrGLProgram::bindTextures(const GrResourceIOProcessor& processor, void GrGLProgram::generateMipmaps(const GrResourceIOProcessor& processor) { for (int i = 0; i < processor.numTextureSamplers(); ++i) { const GrResourceIOProcessor::TextureSampler& sampler = processor.textureSampler(i); - fGpu->generateMipmaps(sampler.samplerState(), - static_cast<GrGLTexture*>(sampler.peekTexture()), - sampler.proxy()->origin()); + auto* tex = sampler.peekTexture(); + if (sampler.samplerState().filter() == GrSamplerState::Filter::kMipMap && + tex->texturePriv().mipMapped() == GrMipMapped::kYes && + tex->texturePriv().mipMapsAreDirty()) { + SkASSERT(fGpu->caps()->mipMapSupport()); + fGpu->regenerateMipMapLevels(static_cast<GrGLTexture*>(sampler.peekTexture())); + } } } |