Index: src/gpu/gl/GrGLGpu.cpp |
diff --git a/src/gpu/gl/GrGLGpu.cpp b/src/gpu/gl/GrGLGpu.cpp |
index 071b11383d1691cf134207da8efeaaaefec8fb41..29841331c01d308d45b7c1948db0dfe54547a4a6 100644 |
--- a/src/gpu/gl/GrGLGpu.cpp |
+++ b/src/gpu/gl/GrGLGpu.cpp |
@@ -916,7 +916,7 @@ static inline GrGLenum check_alloc_error(const GrSurfaceDesc& desc, |
* |
* @param desc The surface descriptor for the texture being created. |
* @param interface The GL interface in use. |
- * @param target The GL target to which the texture is bound |
+ * @param caps The capabilities of the GL device. |
* @param internalFormat The data format used for the internal storage of the texture. |
* @param externalFormat The data format used for the external storage of the texture. |
* @param externalType The type of the data used for the external storage of the texture. |
@@ -928,6 +928,7 @@ static inline GrGLenum check_alloc_error(const GrSurfaceDesc& desc, |
*/ |
static void allocate_and_populate_uncompressed_texture(const GrSurfaceDesc& desc, |
const GrGLInterface& interface, |
+ const GrGLCaps& caps, |
GrGLenum target, |
GrGLenum internalFormat, |
GrGLenum externalFormat, |
@@ -936,27 +937,70 @@ static void allocate_and_populate_uncompressed_texture(const GrSurfaceDesc& desc |
int baseWidth, int baseHeight, |
bool* succeeded) { |
CLEAR_ERROR_BEFORE_ALLOC(&interface); |
- *succeeded = true; |
- for (int currentMipLevel = 0; currentMipLevel < texels.count(); currentMipLevel++) { |
- int twoToTheMipLevel = 1 << currentMipLevel; |
- int currentWidth = SkTMax(1, baseWidth / twoToTheMipLevel); |
- int currentHeight = SkTMax(1, baseHeight / twoToTheMipLevel); |
- const void* currentMipData = texels[currentMipLevel].fPixels; |
- // Even if curremtMipData is nullptr, continue to call TexImage2D. |
- // This will allocate texture memory which we can later populate. |
+ |
+ bool useTexStorage = caps.isConfigTexSupportEnabled(desc.fConfig); |
+ // We can only use TexStorage if we know we will not later change the storage requirements. |
+ // This means if we may later want to add mipmaps, we cannot use TexStorage. |
+ // Right now, we cannot know if we will later add mipmaps or not. |
+ // The only time we can use TexStorage is when we already have the |
+ // mipmaps. |
+ useTexStorage &= texels.count() > 1; |
+ |
+ if (useTexStorage) { |
+ // We never resize or change formats of textures. |
GL_ALLOC_CALL(&interface, |
- TexImage2D(target, |
- currentMipLevel, |
- internalFormat, |
- currentWidth, |
- currentHeight, |
- 0, // border |
- externalFormat, externalType, |
- currentMipData)); |
+ TexStorage2D(target, |
+ texels.count(), |
+ internalFormat, |
+ desc.fWidth, desc.fHeight)); |
GrGLenum error = check_alloc_error(desc, &interface); |
if (error != GR_GL_NO_ERROR) { |
*succeeded = false; |
- break; |
+ } else { |
+ for (int currentMipLevel = 0; currentMipLevel < texels.count(); currentMipLevel++) { |
+ const void* currentMipData = texels[currentMipLevel].fPixels; |
+ if (currentMipData == nullptr) { |
+ continue; |
+ } |
+ int twoToTheMipLevel = 1 << currentMipLevel; |
+ int currentWidth = SkTMax(1, desc.fWidth / twoToTheMipLevel); |
+ int currentHeight = SkTMax(1, desc.fHeight / twoToTheMipLevel); |
+ |
+ GR_GL_CALL(&interface, |
+ TexSubImage2D(target, |
+ currentMipLevel, |
+ 0, // left |
+ 0, // top |
+ currentWidth, |
+ currentHeight, |
+ externalFormat, externalType, |
+ currentMipData)); |
+ } |
+ *succeeded = true; |
+ } |
+ } else { |
+ *succeeded = true; |
+ for (int currentMipLevel = 0; currentMipLevel < texels.count(); currentMipLevel++) { |
+ int twoToTheMipLevel = 1 << currentMipLevel; |
+ int currentWidth = SkTMax(1, baseWidth / twoToTheMipLevel); |
+ int currentHeight = SkTMax(1, baseHeight / twoToTheMipLevel); |
+ const void* currentMipData = texels[currentMipLevel].fPixels; |
+ // Even if curremtMipData is nullptr, continue to call TexImage2D. |
+ // This will allocate texture memory which we can later populate. |
+ GL_ALLOC_CALL(&interface, |
+ TexImage2D(target, |
+ currentMipLevel, |
+ internalFormat, |
+ currentWidth, |
+ currentHeight, |
+ 0, // border |
+ externalFormat, externalType, |
+ currentMipData)); |
+ GrGLenum error = check_alloc_error(desc, &interface); |
+ if (error != GR_GL_NO_ERROR) { |
+ *succeeded = false; |
+ break; |
+ } |
} |
} |
} |
@@ -966,40 +1010,86 @@ static void allocate_and_populate_uncompressed_texture(const GrSurfaceDesc& desc |
* |
* @param desc The surface descriptor for the texture being created. |
* @param interface The GL interface in use. |
- * @param target The GL target to which the texture is bound |
+ * @param caps The capabilities of the GL device. |
* @param internalFormat The data format used for the internal storage of the texture. |
* @param texels The texel data of the texture being created. |
- * @param baseWidth The width of the texture's base mipmap level |
- * @param baseHeight The height of the texture's base mipmap level |
*/ |
static bool allocate_and_populate_compressed_texture(const GrSurfaceDesc& desc, |
const GrGLInterface& interface, |
+ const GrGLCaps& caps, |
GrGLenum target, GrGLenum internalFormat, |
const SkTArray<GrMipLevel>& texels, |
int baseWidth, int baseHeight) { |
CLEAR_ERROR_BEFORE_ALLOC(&interface); |
- for (int currentMipLevel = 0; currentMipLevel < texels.count(); currentMipLevel++) { |
- int twoToTheMipLevel = 1 << currentMipLevel; |
- int currentWidth = SkTMax(1, baseWidth / twoToTheMipLevel); |
- int currentHeight = SkTMax(1, baseHeight / twoToTheMipLevel); |
- // Make sure that the width and height that we pass to OpenGL |
- // is a multiple of the block size. |
- size_t dataSize = GrCompressedFormatDataSize(desc.fConfig, baseWidth, baseHeight); |
+ bool useTexStorage = caps.isConfigTexSupportEnabled(desc.fConfig); |
+ // We can only use TexStorage if we know we will not later change the storage requirements. |
+ // This means if we may later want to add mipmaps, we cannot use TexStorage. |
+ // Right now, we cannot know if we will later add mipmaps or not. |
+ // The only time we can use TexStorage is when we already have the |
+ // mipmaps. |
+ useTexStorage &= texels.count() > 1; |
+ if (useTexStorage) { |
+ // We never resize or change formats of textures. |
GL_ALLOC_CALL(&interface, |
- CompressedTexImage2D(target, |
- currentMipLevel, |
- internalFormat, |
- currentWidth, |
- currentHeight, |
- 0, // border |
- SkToInt(dataSize), |
- texels[currentMipLevel].fPixels)); |
- |
+ TexStorage2D(target, |
+ texels.count(), |
+ internalFormat, |
+ baseWidth, baseHeight)); |
GrGLenum error = check_alloc_error(desc, &interface); |
if (error != GR_GL_NO_ERROR) { |
return false; |
+ } else { |
+ for (int currentMipLevel = 0; currentMipLevel < texels.count(); currentMipLevel++) { |
+ const void* currentMipData = texels[currentMipLevel].fPixels; |
+ if (currentMipData == nullptr) { |
+ continue; |
+ } |
+ |
+ int twoToTheMipLevel = 1 << currentMipLevel; |
+ int currentWidth = SkTMax(1, baseWidth / twoToTheMipLevel); |
+ int currentHeight = SkTMax(1, baseHeight / twoToTheMipLevel); |
+ |
+ // Make sure that the width and height that we pass to OpenGL |
+ // is a multiple of the block size. |
+ size_t dataSize = GrCompressedFormatDataSize(desc.fConfig, currentWidth, |
+ currentHeight); |
+ GR_GL_CALL(&interface, CompressedTexSubImage2D(target, |
+ currentMipLevel, |
+ 0, // left |
+ 0, // top |
+ currentWidth, |
+ currentHeight, |
+ internalFormat, |
+ SkToInt(dataSize), |
+ currentMipData)); |
+ } |
+ } |
+ } else { |
+ for (int currentMipLevel = 0; currentMipLevel < texels.count(); currentMipLevel++) { |
+ int twoToTheMipLevel = 1 << currentMipLevel; |
+ int currentWidth = SkTMax(1, baseWidth / twoToTheMipLevel); |
+ int currentHeight = SkTMax(1, baseHeight / twoToTheMipLevel); |
+ |
+ // Make sure that the width and height that we pass to OpenGL |
+ // is a multiple of the block size. |
+ size_t dataSize = GrCompressedFormatDataSize(desc.fConfig, baseWidth, baseHeight); |
+ |
+ GL_ALLOC_CALL(&interface, |
+ CompressedTexImage2D(target, |
+ currentMipLevel, |
+ internalFormat, |
+ currentWidth, |
+ currentHeight, |
+ 0, // border |
+ SkToInt(dataSize), |
+ texels[currentMipLevel].fPixels)); |
+ |
+ GrGLenum error = check_alloc_error(desc, &interface); |
+ if (error != GR_GL_NO_ERROR) { |
+ return false; |
+ } |
} |
} |
@@ -1191,7 +1281,7 @@ bool GrGLGpu::uploadTexData(const GrSurfaceDesc& desc, |
0 == left && 0 == top && |
desc.fWidth == width && desc.fHeight == height && |
!desc.fTextureStorageAllocator.fAllocateTextureStorage) { |
- allocate_and_populate_uncompressed_texture(desc, *interface, target, |
+ allocate_and_populate_uncompressed_texture(desc, *interface, caps, target, |
internalFormat, externalFormat, |
externalType, texelsShallowCopy, |
width, height, &succeeded); |
@@ -1268,8 +1358,8 @@ bool GrGLGpu::uploadCompressedTexData(const GrSurfaceDesc& desc, |
} |
if (kNewTexture_UploadType == uploadType) { |
- return allocate_and_populate_compressed_texture(desc, *interface, target, internalFormat, |
- texels, width, height); |
+ return allocate_and_populate_compressed_texture(desc, *interface, caps, target, |
+ internalFormat, texels, width, height); |
} else { |
// Paletted textures can't be updated. |
if (GR_GL_PALETTE8_RGBA8 == internalFormat) { |