Chromium Code Reviews| Index: src/gpu/gl/GrGpuGL.cpp |
| diff --git a/src/gpu/gl/GrGpuGL.cpp b/src/gpu/gl/GrGpuGL.cpp |
| index c4d1c27c004f5484f418fbff13a0d2bd5e562678..79585cca4d4c4d05a97d8c73b6400ff807095b64 100644 |
| --- a/src/gpu/gl/GrGpuGL.cpp |
| +++ b/src/gpu/gl/GrGpuGL.cpp |
| @@ -698,6 +698,62 @@ bool GrGpuGL::uploadTexData(const GrGLTexture::Desc& desc, |
| return succeeded; |
| } |
| +bool GrGpuGL::compressedFormatToGLFormats(GrCompressedFormat fmt, GrGLenum *internal) { |
| + switch(fmt) { |
| + case kETC1_GrCompressedFormat: |
| + *internal = GR_GL_COMPRESSED_RGB8_ETC1; |
| + return true; |
| + default: |
| + SkASSERT(!"Not a compressed format!"); |
| + break; |
| + } |
| + return false; |
| +} |
| + |
| +bool GrGpuGL::uploadCompressedTexData(const GrGLTexture::Desc& desc, |
| + GrCompressedFormat fmt, |
| + const void* data) { |
| + SkASSERT(NULL != data); |
| + |
| + // No support for software flip y, yet... |
| + SkASSERT(kBottomLeft_GrSurfaceOrigin != desc.fOrigin); |
| + |
| + // Make sure that the width and height that we pass to OpenGL |
| + // is a multiple of the block size. |
| + GrCompressedFormatDesc ctDesc = GrGetCompressedFormatDesc(fmt); |
| + SkASSERT((desc.fWidth % ctDesc.fBlockSizeX) == 0); |
| + SkASSERT((desc.fHeight % ctDesc.fBlockSizeY) == 0); |
| + |
| + int dataSize = |
| + (desc.fWidth / ctDesc.fBlockSizeX) * |
| + (desc.fHeight / ctDesc.fBlockSizeY) * |
| + ctDesc.fBytesPerBlock; |
| + |
|
robertphillips
2014/05/27 22:01:50
Remove this (tempStorage) ?
krajcevski
2014/05/27 22:19:29
Done.
|
| + SkAutoSMalloc<128 * 128> tempStorage; |
| + |
| + GrGLenum internalFormat; |
| + if (!this->compressedFormatToGLFormats(fmt, &internalFormat)) { |
| + return false; |
| + } |
| + |
| + 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)); |
| + |
| + GrGLenum error = check_alloc_error(desc, this->glInterface()); |
| + if (error != GR_GL_NO_ERROR) { |
| + succeeded = false; |
| + } |
| + return succeeded; |
| +} |
| + |
| static bool renderbuffer_storage_msaa(GrGLContext& ctx, |
| int sampleCount, |
| GrGLenum format, |
| @@ -977,6 +1033,89 @@ GrTexture* GrGpuGL::onCreateTexture(const GrTextureDesc& desc, |
| return tex; |
| } |
| +GrTexture* GrGpuGL::onCreateCompressedTexture(const GrTextureDesc& desc, |
| + const void* srcData, |
| + GrCompressedFormat format) { |
| + |
| + if(SkToBool(desc.fFlags & kRenderTarget_GrTextureFlagBit)) { |
| + return return_null_texture(); |
| + } |
| + |
| + // Make sure that we're not flipping Y. |
| + GrSurfaceOrigin texOrigin = resolve_origin(desc.fOrigin, false); |
| + if (kBottomLeft_GrSurfaceOrigin == texOrigin) { |
| + return return_null_texture(); |
| + } |
| + |
| + // Make sure that the width and height are multiples of the block |
| + // size for the associated format. |
| + GrCompressedFormatDesc ctDesc = GrGetCompressedFormatDesc(format); |
| + if ((desc.fWidth % ctDesc.fBlockSizeX) != 0 || |
| + (desc.fHeight % ctDesc.fBlockSizeY) != 0) { |
| + return return_null_texture(); |
| + } |
| + |
| + GrGLTexture::Desc glTexDesc; |
| + |
| + glTexDesc.fFlags = desc.fFlags; |
| + glTexDesc.fWidth = desc.fWidth; |
| + glTexDesc.fHeight = desc.fHeight; |
| + glTexDesc.fConfig = desc.fConfig; |
| + glTexDesc.fIsWrapped = false; |
| + glTexDesc.fOrigin = texOrigin; |
| + |
| + int maxSize = this->caps()->maxTextureSize(); |
| + if (glTexDesc.fWidth > maxSize || glTexDesc.fHeight > maxSize) { |
| + return return_null_texture(); |
| + } |
| + |
| + GL_CALL(GenTextures(1, &glTexDesc.fTextureID)); |
| + |
| + if (!glTexDesc.fTextureID) { |
| + return return_null_texture(); |
| + } |
| + |
| + this->setScratchTextureUnit(); |
| + GL_CALL(BindTexture(GR_GL_TEXTURE_2D, glTexDesc.fTextureID)); |
| + |
| + // Some drivers like to know filter/wrap before seeing glTexImage2D. Some |
| + // drivers have a bug where an FBO won't be complete if it includes a |
| + // texture that is not mipmap complete (considering the filter in use). |
| + GrGLTexture::TexParams initialTexParams; |
| + // we only set a subset here so invalidate first |
| + initialTexParams.invalidate(); |
| + initialTexParams.fMinFilter = GR_GL_NEAREST; |
| + initialTexParams.fMagFilter = GR_GL_NEAREST; |
| + initialTexParams.fWrapS = GR_GL_CLAMP_TO_EDGE; |
| + initialTexParams.fWrapT = GR_GL_CLAMP_TO_EDGE; |
| + GL_CALL(TexParameteri(GR_GL_TEXTURE_2D, |
| + GR_GL_TEXTURE_MAG_FILTER, |
| + initialTexParams.fMagFilter)); |
| + GL_CALL(TexParameteri(GR_GL_TEXTURE_2D, |
| + GR_GL_TEXTURE_MIN_FILTER, |
| + initialTexParams.fMinFilter)); |
| + GL_CALL(TexParameteri(GR_GL_TEXTURE_2D, |
| + GR_GL_TEXTURE_WRAP_S, |
| + initialTexParams.fWrapS)); |
| + GL_CALL(TexParameteri(GR_GL_TEXTURE_2D, |
| + GR_GL_TEXTURE_WRAP_T, |
| + initialTexParams.fWrapT)); |
| + |
| + if (!this->uploadCompressedTexData(glTexDesc, format, srcData)) { |
| + GL_CALL(DeleteTextures(1, &glTexDesc.fTextureID)); |
| + return return_null_texture(); |
| + } |
| + |
| + GrGLTexture* tex; |
| + tex = SkNEW_ARGS(GrGLTexture, (this, glTexDesc)); |
| + tex->setCachedTexParams(initialTexParams, this->getResetTimestamp()); |
| +#ifdef TRACE_TEXTURE_CREATION |
| + GrPrintf("--- new compressed texture [%d] format=%d size=(%d %d) config=%d\n", |
| + glTexDesc.fTextureID, format, desc.fWidth, desc.fHeight, desc.fConfig); |
| +#endif |
| + return tex; |
| +} |
| + |
| namespace { |
| const GrGLuint kUnknownBitCount = GrGLStencilBuffer::kUnknownBitCount; |