aboutsummaryrefslogtreecommitdiffhomepage
path: root/src/gpu/gl
diff options
context:
space:
mode:
authorGravatar Brian Salomon <bsalomon@google.com>2018-06-20 16:25:26 -0400
committerGravatar Skia Commit-Bot <skia-commit-bot@chromium.org>2018-06-20 21:13:27 +0000
commit930f939c48af1be6005af12bb6f709ca5da9d118 (patch)
tree21dbb8b105aa1190237c148358b7993565158335 /src/gpu/gl
parent2a284de7a51c198096a6f34ec1cbfe9118db554c (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.cpp88
-rw-r--r--src/gpu/gl/GrGLGpu.h9
-rw-r--r--src/gpu/gl/GrGLProgram.cpp22
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()));
+ }
}
}