Index: src/gpu/gl/GrGpuGL.cpp |
diff --git a/src/gpu/gl/GrGpuGL.cpp b/src/gpu/gl/GrGpuGL.cpp |
index 12938f16a596e25b43ce969740c111182041d434..f1b6da8261351908a2222cf3df695bfc8bf20c32 100644 |
--- a/src/gpu/gl/GrGpuGL.cpp |
+++ b/src/gpu/gl/GrGpuGL.cpp |
@@ -201,8 +201,7 @@ GrPixelConfig GrGpuGL::preferredWritePixelsConfig(GrPixelConfig writeConfig, |
} |
bool GrGpuGL::canWriteTexturePixels(const GrTexture* texture, GrPixelConfig srcConfig) const { |
- if (kIndex_8_GrPixelConfig == srcConfig || kIndex_8_GrPixelConfig == texture->config() || |
- GrPixelConfigIsCompressed(srcConfig) || GrPixelConfigIsCompressed(texture->config())) { |
+ if (kIndex_8_GrPixelConfig == srcConfig || kIndex_8_GrPixelConfig == texture->config()) { |
return false; |
} |
if (srcConfig != texture->config() && kGLES_GrGLStandard == this->glStandard()) { |
@@ -478,14 +477,24 @@ bool GrGpuGL::onWriteTexturePixels(GrTexture* texture, |
desc.fTextureID = glTex->textureID(); |
desc.fOrigin = glTex->origin(); |
- if (this->uploadTexData(desc, false, |
- left, top, width, height, |
- config, buffer, rowBytes)) { |
+ bool success = false; |
+ if (GrPixelConfigIsCompressed(desc.fConfig)) { |
+ // We check that config == desc.fConfig in GrGpuGL::canWriteTexturePixels() |
+ SkASSERT(config == desc.fConfig); |
+ success = this->uploadCompressedTexData(desc, buffer, false, |
+ left, top, width, height); |
+ } else { |
+ success = this->uploadTexData(desc, false, |
+ left, top, width, height, |
+ config, buffer, rowBytes); |
+ } |
+ |
+ if (success) { |
texture->impl()->dirtyMipMaps(true); |
return true; |
- } else { |
- return false; |
} |
+ |
+ return false; |
} |
namespace { |
@@ -703,16 +712,41 @@ bool GrGpuGL::uploadTexData(const GrGLTexture::Desc& desc, |
return succeeded; |
} |
+// TODO: This function is using a lot of wonky semantics like, if width == -1 |
+// then set width = desc.fWdith ... blah. A better way to do it might be to |
+// create a CompressedTexData struct that takes a desc/ptr and figures out |
+// the proper upload semantics. Then users can construct this function how they |
+// see fit if they want to go against the "standard" way to do it. |
bool GrGpuGL::uploadCompressedTexData(const GrGLTexture::Desc& desc, |
- const void* data) { |
- SkASSERT(NULL != data); |
+ const void* data, |
+ bool isNewTexture, |
+ int left, int top, int width, int height) { |
+ SkASSERT(NULL != data || isNewTexture); |
// No support for software flip y, yet... |
SkASSERT(kBottomLeft_GrSurfaceOrigin != desc.fOrigin); |
+ if (-1 == width) { |
+ width = desc.fWidth; |
+ } |
+#ifdef SK_DEBUG |
+ else { |
+ SkASSERT(width <= desc.fWidth); |
+ } |
+#endif |
+ |
+ if (-1 == height) { |
+ height = desc.fHeight; |
+ } |
+#ifdef SK_DEBUG |
+ else { |
+ SkASSERT(height <= desc.fHeight); |
+ } |
+#endif |
+ |
// Make sure that the width and height that we pass to OpenGL |
// is a multiple of the block size. |
- int dataSize = GrCompressedFormatDataSize(desc.fConfig, desc.fWidth, desc.fHeight); |
+ int dataSize = GrCompressedFormatDataSize(desc.fConfig, width, height); |
// We only need the internal format for compressed 2D textures. |
GrGLenum internalFormat = 0; |
@@ -722,14 +756,26 @@ bool GrGpuGL::uploadCompressedTexData(const GrGLTexture::Desc& desc, |
bool succeeded = true; |
CLEAR_ERROR_BEFORE_ALLOC(this->glInterface()); |
- GL_ALLOC_CALL(this->glInterface(), |
- CompressedTexImage2D(GR_GL_TEXTURE_2D, |
- 0, // level |
- internalFormat, |
- desc.fWidth, desc.fHeight, |
- 0, // border |
- dataSize, |
- data)); |
+ |
+ if (isNewTexture) { |
+ GL_ALLOC_CALL(this->glInterface(), |
+ CompressedTexImage2D(GR_GL_TEXTURE_2D, |
+ 0, // level |
+ internalFormat, |
+ width, height, |
+ 0, // border |
+ dataSize, |
+ data)); |
+ } else { |
+ GL_ALLOC_CALL(this->glInterface(), |
+ CompressedTexSubImage2D(GR_GL_TEXTURE_2D, |
+ 0, // level |
+ left, top, |
+ width, height, |
+ internalFormat, |
+ dataSize, |
+ data)); |
+ } |
GrGLenum error = check_alloc_error(desc, this->glInterface()); |
if (error != GR_GL_NO_ERROR) { |