Revert "Reland "Separate compressed and uncompressed texture functions""
This reverts commit c0519233cdd2545a938848336c7d470bfe27fa96.
Reason for revert: breaking google3 cause of abort in constexpr
Original change's description:
> Reland "Separate compressed and uncompressed texture functions"
>
> This is a reland of 9acfb33ad8c6f5fc6097dff57c0de5e51ea590fd
>
> Original change's description:
> > Separate compressed and uncompressed texture functions
> >
> > Change-Id: Iccf31e1e4dbebde8aab4bb9b57cfb0341bb05912
> > Reviewed-on: https://skia-review.googlesource.com/c/skia/+/223802
> > Reviewed-by: Greg Daniel <egdaniel@google.com>
> > Commit-Queue: Brian Salomon <bsalomon@google.com>
>
> Change-Id: I9f212b7d34cf43216f7d2ec63b959b75fd6a71b3
> Reviewed-on: https://skia-review.googlesource.com/c/skia/+/223992
> Reviewed-by: Brian Salomon <bsalomon@google.com>
> Commit-Queue: Brian Salomon <bsalomon@google.com>
TBR=egdaniel@google.com,bsalomon@google.com,robertphillips@google.com
Change-Id: I9cee240b438a3682911a3c6cddadfe2062447b8c
No-Presubmit: true
No-Tree-Checks: true
No-Try: true
Reviewed-on: https://skia-review.googlesource.com/c/skia/+/223995
Reviewed-by: Greg Daniel <egdaniel@google.com>
Commit-Queue: Greg Daniel <egdaniel@google.com>
diff --git a/src/gpu/GrCaps.h b/src/gpu/GrCaps.h
index eba8ccd..c0c0561 100644
--- a/src/gpu/GrCaps.h
+++ b/src/gpu/GrCaps.h
@@ -367,8 +367,6 @@
GrSRGBEncoded srgbEncoded) const = 0;
GrBackendFormat getBackendFormatFromColorType(SkColorType ct) const;
- virtual GrBackendFormat getBackendFormatFromCompressionType(SkImage::CompressionType) const = 0;
-
/**
* The CLAMP_TO_BORDER wrap mode for texture coordinates was added to desktop GL in 1.3, and
* GLES 3.2, but is also available in extensions. Vulkan and Metal always have support.
diff --git a/src/gpu/GrDataUtils.cpp b/src/gpu/GrDataUtils.cpp
index 9dcc25b..c83a3cf 100644
--- a/src/gpu/GrDataUtils.cpp
+++ b/src/gpu/GrDataUtils.cpp
@@ -113,14 +113,10 @@
return w * h;
}
-size_t GrCompressedDataSize(SkImage::CompressionType type, int width, int height) {
- switch (type) {
- case SkImage::kETC1_CompressionType:
- int numBlocks = num_ETC1_blocks(width, height);
- return numBlocks * sizeof(ETC1Block);
- }
- SK_ABORT("Unexpected compression type");
- return 0;
+size_t GrETC1CompressedDataSize(int width, int height) {
+ int numBlocks = num_ETC1_blocks(width, height);
+
+ return numBlocks * sizeof(ETC1Block);
}
// Fill in 'dest' with ETC1 blocks derived from 'colorf'
@@ -304,14 +300,22 @@
return true;
}
-size_t GrComputeTightCombinedBufferSize(size_t bytesPerPixel, int baseWidth, int baseHeight,
- SkTArray<size_t>* individualMipOffsets, int mipLevelCount) {
+size_t GrComputeTightCombinedBufferSize(GrCompression compression, size_t bytesPerPixel,
+ int baseWidth, int baseHeight,
+ SkTArray<size_t>* individualMipOffsets,
+ int mipLevelCount) {
SkASSERT(individualMipOffsets && !individualMipOffsets->count());
SkASSERT(mipLevelCount >= 1);
individualMipOffsets->push_back(0);
size_t combinedBufferSize = baseWidth * bytesPerPixel * baseHeight;
+ if (GrCompression::kETC1 == compression) {
+ SkASSERT(0 == bytesPerPixel);
+ bytesPerPixel = 4; // munge Bpp to make the following code work (and not assert)
+ combinedBufferSize = GrETC1CompressedDataSize(baseWidth, baseHeight);
+ }
+
int currentWidth = baseWidth;
int currentHeight = baseHeight;
@@ -325,7 +329,12 @@
currentWidth = SkTMax(1, currentWidth / 2);
currentHeight = SkTMax(1, currentHeight / 2);
- size_t trimmedSize = currentWidth * bytesPerPixel * currentHeight;
+ size_t trimmedSize;
+ if (GrCompression::kETC1 == compression) {
+ trimmedSize = GrETC1CompressedDataSize(currentWidth, currentHeight);
+ } else {
+ trimmedSize = currentWidth * bytesPerPixel * currentHeight;
+ }
const size_t alignmentDiff = combinedBufferSize % desiredAlignment;
if (alignmentDiff != 0) {
combinedBufferSize += desiredAlignment - alignmentDiff;
@@ -340,11 +349,12 @@
return combinedBufferSize;
}
-void GrFillInData(GrPixelConfig config, int baseWidth, int baseHeight,
+void GrFillInData(GrCompression compression, GrPixelConfig config,
+ int baseWidth, int baseHeight,
const SkTArray<size_t>& individualMipOffsets, char* dstPixels,
const SkColor4f& colorf) {
TRACE_EVENT0("skia.gpu", TRACE_FUNC);
- SkASSERT(!GrPixelConfigIsCompressed(config));
+
int mipLevels = individualMipOffsets.count();
int currentWidth = baseWidth;
@@ -352,22 +362,19 @@
for (int currentMipLevel = 0; currentMipLevel < mipLevels; ++currentMipLevel) {
size_t offset = individualMipOffsets[currentMipLevel];
- fill_buffer_with_color(config, currentWidth, currentHeight, colorf, &(dstPixels[offset]));
+ if (GrCompression::kETC1 == compression) {
+ // TODO: compute the ETC1 block for 'colorf' just once
+ fillin_ETC1_with_color(currentWidth, currentHeight, colorf, &(dstPixels[offset]));
+ } else {
+ fill_buffer_with_color(config, currentWidth, currentHeight, colorf,
+ &(dstPixels[offset]));
+ }
+
currentWidth = SkTMax(1, currentWidth / 2);
currentHeight = SkTMax(1, currentHeight / 2);
}
}
-void GrFillInCompressedData(SkImage::CompressionType type, int baseWidth, int baseHeight,
- char* dstPixels, const SkColor4f& colorf) {
- TRACE_EVENT0("skia.gpu", TRACE_FUNC);
- int currentWidth = baseWidth;
- int currentHeight = baseHeight;
- if (SkImage::kETC1_CompressionType == type) {
- fillin_ETC1_with_color(currentWidth, currentHeight, colorf, dstPixels);
- }
-}
-
static GrSwizzle get_load_and_get_swizzle(GrColorType ct, SkRasterPipeline::StockStage* load,
bool* isNormalized) {
GrSwizzle swizzle("rgba");
@@ -410,6 +417,7 @@
break;
case GrColorType::kUnknown:
+ case GrColorType::kRGB_ETC1:
SK_ABORT("unexpected CT");
}
return swizzle;
@@ -457,6 +465,7 @@
case GrColorType::kGray_8: // not currently supported as output
case GrColorType::kUnknown:
+ case GrColorType::kRGB_ETC1:
SK_ABORT("unexpected CT");
}
return swizzle;
diff --git a/src/gpu/GrDataUtils.h b/src/gpu/GrDataUtils.h
index a55342f..fcf7a07 100644
--- a/src/gpu/GrDataUtils.h
+++ b/src/gpu/GrDataUtils.h
@@ -12,19 +12,27 @@
#include "include/private/GrTypesPriv.h"
#include "src/gpu/GrSwizzle.h"
-size_t GrCompressedDataSize(SkImage::CompressionType, int w, int h);
+// TODO: consolidate all the backend-specific flavors of this method to this
+size_t GrETC1CompressedDataSize(int w, int h);
+
+// TODO: should this be grown into a replacement for GrPixelConfig?
+enum class GrCompression {
+ kNone,
+ kETC1,
+};
// Compute the size of the buffer required to hold all the mipLevels of the specified type
// of data when all rowBytes are tight.
// Note there may still be padding between the mipLevels to meet alignment requirements.
-size_t GrComputeTightCombinedBufferSize(size_t bytesPerPixel, int baseWidth, int baseHeight,
- SkTArray<size_t>* individualMipOffsets, int mipLevelCount);
+size_t GrComputeTightCombinedBufferSize(GrCompression, size_t bytesPerPixel,
+ int baseWidth, int baseHeight,
+ SkTArray<size_t>* individualMipOffsets,
+ int mipLevelCount);
-void GrFillInData(GrPixelConfig, int baseWidth, int baseHeight,
- const SkTArray<size_t>& individualMipOffsets, char* dest, const SkColor4f& color);
-
-void GrFillInCompressedData(SkImage::CompressionType, int width, int height, char* dest,
- const SkColor4f& color);
+void GrFillInData(GrCompression, GrPixelConfig,
+ int baseWidth, int baseHeight,
+ const SkTArray<size_t>& individualMipOffsets,
+ char* dest, const SkColor4f& color);
struct GrColorInfo {
GrColorType fColorType = GrColorType::kUnknown;
diff --git a/src/gpu/GrGpu.cpp b/src/gpu/GrGpu.cpp
index 6c22e5c..52adb00 100644
--- a/src/gpu/GrGpu.cpp
+++ b/src/gpu/GrGpu.cpp
@@ -15,7 +15,6 @@
#include "src/gpu/GrAuditTrail.h"
#include "src/gpu/GrCaps.h"
#include "src/gpu/GrContextPriv.h"
-#include "src/gpu/GrDataUtils.h"
#include "src/gpu/GrGpuResourcePriv.h"
#include "src/gpu/GrMesh.h"
#include "src/gpu/GrPathRendering.h"
@@ -102,10 +101,6 @@
sk_sp<GrTexture> GrGpu::createTexture(const GrSurfaceDesc& origDesc, SkBudgeted budgeted,
const GrMipLevel texels[], int mipLevelCount) {
TRACE_EVENT0("skia.gpu", TRACE_FUNC);
- if (GrPixelConfigIsCompressed(origDesc.fConfig)) {
- // Call GrGpu::createCompressedTexture.
- return nullptr;
- }
GrSurfaceDesc desc = origDesc;
GrMipMapped mipMapped = mipLevelCount > 1 ? GrMipMapped::kYes : GrMipMapped::kNo;
@@ -124,6 +119,10 @@
return nullptr;
}
+ // We shouldn't be rendering into compressed textures
+ SkASSERT(!GrPixelConfigIsCompressed(desc.fConfig) || !isRT);
+ SkASSERT(!GrPixelConfigIsCompressed(desc.fConfig) || 1 == desc.fSampleCnt);
+
this->handleDirtyContext();
sk_sp<GrTexture> tex = this->onCreateTexture(desc, budgeted, texels, mipLevelCount);
if (tex) {
@@ -144,27 +143,6 @@
return this->createTexture(desc, budgeted, nullptr, 0);
}
-sk_sp<GrTexture> GrGpu::createCompressedTexture(int width, int height,
- SkImage::CompressionType compressionType,
- SkBudgeted budgeted, const void* data,
- size_t dataSize) {
- this->handleDirtyContext();
- if (width < 1 || width > this->caps()->maxTextureSize() ||
- height < 1 || height > this->caps()->maxTextureSize()) {
- return nullptr;
- }
- if (!data) {
- return nullptr;
- }
- if (!this->caps()->isConfigTexturable(GrCompressionTypePixelConfig(compressionType))) {
- return nullptr;
- }
- if (dataSize < GrCompressedDataSize(compressionType, width, height)) {
- return nullptr;
- }
- return this->onCreateCompressedTexture(width, height, compressionType, budgeted, data);
-}
-
sk_sp<GrTexture> GrGpu::wrapBackendTexture(const GrBackendTexture& backendTex,
GrWrapOwnership ownership, GrWrapCacheable cacheable,
GrIOType ioType) {
diff --git a/src/gpu/GrGpu.h b/src/gpu/GrGpu.h
index e52c476..3fb9862 100644
--- a/src/gpu/GrGpu.h
+++ b/src/gpu/GrGpu.h
@@ -103,9 +103,6 @@
*/
sk_sp<GrTexture> createTexture(const GrSurfaceDesc& desc, SkBudgeted);
- sk_sp<GrTexture> createCompressedTexture(int width, int height, SkImage::CompressionType,
- SkBudgeted, const void* data, size_t dataSize);
-
/**
* Implements GrResourceProvider::wrapBackendTexture
*/
@@ -495,9 +492,7 @@
// onCreateTexture is called.
virtual sk_sp<GrTexture> onCreateTexture(const GrSurfaceDesc&, SkBudgeted,
const GrMipLevel texels[], int mipLevelCount) = 0;
- virtual sk_sp<GrTexture> onCreateCompressedTexture(int width, int height,
- SkImage::CompressionType, SkBudgeted,
- const void* data) = 0;
+
virtual sk_sp<GrTexture> onWrapBackendTexture(const GrBackendTexture&, GrWrapOwnership,
GrWrapCacheable, GrIOType) = 0;
virtual sk_sp<GrTexture> onWrapRenderableBackendTexture(const GrBackendTexture&, int sampleCnt,
diff --git a/src/gpu/GrProxyProvider.cpp b/src/gpu/GrProxyProvider.cpp
index cb2cefa..aa52c00 100644
--- a/src/gpu/GrProxyProvider.cpp
+++ b/src/gpu/GrProxyProvider.cpp
@@ -411,10 +411,6 @@
if (kUnknown_GrPixelConfig == config) {
return false;
}
- if (GrPixelConfigIsCompressed(config)) {
- // We have no way to verify these at the moment.
- return true;
- }
SkColorType colorType = GrColorTypeToSkColorType(GrPixelConfigToColorType(config));
if (colorType == kUnknown_SkColorType) {
// We should add support for validating GrColorType with a GrBackendFormat. Currently we
@@ -435,10 +431,6 @@
SkBudgeted budgeted,
GrInternalSurfaceFlags surfaceFlags) {
SkASSERT(validate_backend_format_and_config(this->caps(), format, desc.fConfig));
- if (GrPixelConfigIsCompressed(desc.fConfig)) {
- // Deferred proxies for compressed textures are not supported.
- return nullptr;
- }
if (GrMipMapped::kYes == mipMapped) {
// SkMipMap doesn't include the base level in the level count so we have to add 1
int mipCount = SkMipMap::ComputeLevelCount(desc.fWidth, desc.fHeight) + 1;
@@ -473,27 +465,25 @@
fit, budgeted, surfaceFlags));
}
-sk_sp<GrTextureProxy> GrProxyProvider::createCompressedTextureProxy(
- int width, int height, SkBudgeted budgeted, SkImage::CompressionType compressionType,
- sk_sp<SkData> data) {
- GrBackendFormat format = this->caps()->getBackendFormatFromCompressionType(compressionType);
-
- GrSurfaceDesc desc;
- desc.fConfig = GrCompressionTypePixelConfig(compressionType);
- desc.fWidth = width;
- desc.fHeight = height;
-
+sk_sp<GrTextureProxy> GrProxyProvider::createProxy(sk_sp<SkData> data, const GrSurfaceDesc& desc) {
if (!this->caps()->isConfigTexturable(desc.fConfig)) {
return nullptr;
}
+ const GrColorType ct = GrPixelConfigToColorType(desc.fConfig);
+ const GrBackendFormat format =
+ this->caps()->getBackendFormatFromGrColorType(ct, GrSRGBEncoded::kNo);
+
sk_sp<GrTextureProxy> proxy = this->createLazyProxy(
- [width, height, compressionType, budgeted, data](GrResourceProvider* resourceProvider) {
- return LazyInstantiationResult(resourceProvider->createCompressedTexture(
- width, height, compressionType, budgeted, data.get()));
- },
- format, desc, kTopLeft_GrSurfaceOrigin, GrMipMapped::kNo, SkBackingFit::kExact,
- SkBudgeted::kYes);
+ [desc, data](GrResourceProvider* resourceProvider) {
+ GrMipLevel texels;
+ texels.fPixels = data->data();
+ texels.fRowBytes = GrBytesPerPixel(desc.fConfig)*desc.fWidth;
+ return LazyInstantiationResult(
+ resourceProvider->createTexture(desc, SkBudgeted::kYes, &texels, 1));
+ },
+ format, desc, kTopLeft_GrSurfaceOrigin, GrMipMapped::kNo, SkBackingFit::kExact,
+ SkBudgeted::kYes);
if (!proxy) {
return nullptr;
diff --git a/src/gpu/GrProxyProvider.h b/src/gpu/GrProxyProvider.h
index 435f973..bfa2243 100644
--- a/src/gpu/GrProxyProvider.h
+++ b/src/gpu/GrProxyProvider.h
@@ -96,11 +96,9 @@
}
/*
- * Create a texture proxy from compressed texture data.
+ * Create a texture proxy with data. It's assumed that the data is packed tightly.
*/
- sk_sp<GrTextureProxy> createCompressedTextureProxy(int width, int height, SkBudgeted budgeted,
- SkImage::CompressionType compressionType,
- sk_sp<SkData> data);
+ sk_sp<GrTextureProxy> createProxy(sk_sp<SkData>, const GrSurfaceDesc& desc);
// These match the definitions in SkImage & GrTexture.h, for whence they came
typedef void* ReleaseContext;
diff --git a/src/gpu/GrResourceProvider.cpp b/src/gpu/GrResourceProvider.cpp
index 023f86d..ae847e8 100644
--- a/src/gpu/GrResourceProvider.cpp
+++ b/src/gpu/GrResourceProvider.cpp
@@ -118,17 +118,6 @@
}
}
-sk_sp<GrTexture> GrResourceProvider::createCompressedTexture(int width, int height,
- SkImage::CompressionType compression,
- SkBudgeted budgeted, SkData* data) {
- ASSERT_SINGLE_OWNER
- if (this->isAbandoned()) {
- return nullptr;
- }
- return fGpu->createCompressedTexture(width, height, compression, budgeted, data->data(),
- data->size());
-}
-
sk_sp<GrTexture> GrResourceProvider::createTexture(const GrSurfaceDesc& desc, SkBudgeted budgeted,
Flags flags) {
ASSERT_SINGLE_OWNER
diff --git a/src/gpu/GrResourceProvider.h b/src/gpu/GrResourceProvider.h
index 00bf3d2..f382be8 100644
--- a/src/gpu/GrResourceProvider.h
+++ b/src/gpu/GrResourceProvider.h
@@ -88,11 +88,6 @@
sk_sp<GrTexture> createTexture(const GrSurfaceDesc&, SkBudgeted, SkBackingFit,
const GrMipLevel&, Flags);
- // Creates a compressed texture. The GrGpu must support the SkImageImage::Compression type.
- // This does not currently support MIP maps.
- sk_sp<GrTexture> createCompressedTexture(int width, int height, SkImage::CompressionType,
- SkBudgeted, SkData* data);
-
///////////////////////////////////////////////////////////////////////////
// Wrapped Backend Surfaces
diff --git a/src/gpu/GrSurfaceContext.cpp b/src/gpu/GrSurfaceContext.cpp
index 1a62316..afc1124 100644
--- a/src/gpu/GrSurfaceContext.cpp
+++ b/src/gpu/GrSurfaceContext.cpp
@@ -72,6 +72,7 @@
case GrColorType::kRGBA_F16_Clamped: return true;
case GrColorType::kRG_F32: return false;
case GrColorType::kRGBA_F32: return true;
+ case GrColorType::kRGB_ETC1: return false;
case GrColorType::kR_16: return false;
case GrColorType::kRG_1616: return false;
// Experimental (for Y416 and mutant P016/P010)
diff --git a/src/gpu/gl/GrGLCaps.cpp b/src/gpu/gl/GrGLCaps.cpp
index ecb3d3e..1a935b2 100644
--- a/src/gpu/gl/GrGLCaps.cpp
+++ b/src/gpu/gl/GrGLCaps.cpp
@@ -3333,16 +3333,6 @@
return GrBackendFormat::MakeGL(this->configSizedInternalFormat(config), GR_GL_TEXTURE_2D);
}
-GrBackendFormat GrGLCaps::getBackendFormatFromCompressionType(
- SkImage::CompressionType compressionType) const {
- switch (compressionType) {
- case SkImage::kETC1_CompressionType:
- return GrBackendFormat::MakeGL(GR_GL_COMPRESSED_ETC1_RGB8, GR_GL_TEXTURE_2D);
- }
- SK_ABORT("Invalid compression type");
- return {};
-}
-
#ifdef SK_DEBUG
static bool format_color_type_valid_pair(GrGLenum format, GrColorType colorType) {
switch (colorType) {
@@ -3357,10 +3347,7 @@
case GrColorType::kRGBA_8888:
return GR_GL_RGBA8 == format || GR_GL_SRGB8_ALPHA8 == format;
case GrColorType::kRGB_888x:
- GR_STATIC_ASSERT(GrCompressionTypeClosestColorType(SkImage::kETC1_CompressionType) ==
- GrColorType::kRGB_888x);
- return GR_GL_RGB8 == format || GR_GL_RGBA8 == format ||
- GR_GL_COMPRESSED_RGB8_ETC2 == format || GR_GL_COMPRESSED_ETC1_RGB8 == format;
+ return GR_GL_RGB8 == format || GR_GL_RGBA8 == format;
case GrColorType::kRG_88:
return GR_GL_RG8 == format;
case GrColorType::kBGRA_8888:
@@ -3379,6 +3366,8 @@
return GR_GL_RG32F == format;
case GrColorType::kRGBA_F32:
return GR_GL_RGBA32F == format;
+ case GrColorType::kRGB_ETC1:
+ return GR_GL_COMPRESSED_RGB8_ETC2 == format || GR_GL_COMPRESSED_ETC1_RGB8 == format;
case GrColorType::kR_16:
return GR_GL_R16 == format;
case GrColorType::kRG_1616:
diff --git a/src/gpu/gl/GrGLCaps.h b/src/gpu/gl/GrGLCaps.h
index 633df54..d963ae9 100644
--- a/src/gpu/gl/GrGLCaps.h
+++ b/src/gpu/gl/GrGLCaps.h
@@ -422,7 +422,6 @@
GrBackendFormat getBackendFormatFromGrColorType(GrColorType ct,
GrSRGBEncoded srgbEncoded) const override;
- GrBackendFormat getBackendFormatFromCompressionType(SkImage::CompressionType) const override;
GrSwizzle getTextureSwizzle(const GrBackendFormat&, GrColorType) const override;
GrSwizzle getOutputSwizzle(const GrBackendFormat&, GrColorType) const override;
diff --git a/src/gpu/gl/GrGLGpu.cpp b/src/gpu/gl/GrGLGpu.cpp
index f219f2b..84f28ad 100644
--- a/src/gpu/gl/GrGLGpu.cpp
+++ b/src/gpu/gl/GrGLGpu.cpp
@@ -1086,6 +1086,108 @@
}
/**
+ * Creates storage space for the texture and fills it with texels.
+ *
+ * @param config Compressed pixel config of the texture.
+ * @param interface The GL interface in use.
+ * @param caps The capabilities of the GL device.
+ * @param target Which bound texture to target (GR_GL_TEXTURE_2D, e.g.)
+ * @param internalFormat The data format used for the internal storage of the texture.
+ * @param texels The texel data of the texture being created.
+ * @param mipLevelCount Number of mipmap levels
+ * @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(GrPixelConfig config,
+ const GrGLInterface& interface,
+ const GrGLCaps& caps,
+ GrGLenum target, GrGLenum internalFormat,
+ const GrMipLevel texels[], int mipLevelCount,
+ int baseWidth, int baseHeight) {
+ CLEAR_ERROR_BEFORE_ALLOC(&interface);
+ SkASSERT(GrGLFormatIsCompressed(internalFormat));
+
+ bool useTexStorage = caps.isConfigTexSupportEnabled(config);
+ // 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 &= mipLevelCount > 1;
+
+ if (useTexStorage) {
+ // We never resize or change formats of textures.
+ GL_ALLOC_CALL(&interface,
+ TexStorage2D(target,
+ mipLevelCount,
+ internalFormat,
+ baseWidth, baseHeight));
+ GrGLenum error = CHECK_ALLOC_ERROR(&interface);
+ if (error != GR_GL_NO_ERROR) {
+ return false;
+ } else {
+ for (int currentMipLevel = 0; currentMipLevel < mipLevelCount; currentMipLevel++) {
+ const void* currentMipData = texels[currentMipLevel].fPixels;
+ if (currentMipData == nullptr) {
+ // Compressed textures require data for every level
+ return false;
+ }
+
+ 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 = GrGLFormatCompressedDataSize(internalFormat,
+ 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 < mipLevelCount; currentMipLevel++) {
+ const void* currentMipData = texels[currentMipLevel].fPixels;
+ if (currentMipData == nullptr) {
+ // Compressed textures require data for every level
+ return false;
+ }
+
+ 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 = GrGLFormatCompressedDataSize(internalFormat, baseWidth, baseHeight);
+
+ GL_ALLOC_CALL(&interface,
+ CompressedTexImage2D(target,
+ currentMipLevel,
+ internalFormat,
+ currentWidth,
+ currentHeight,
+ 0, // border
+ SkToInt(dataSize),
+ currentMipData));
+
+ GrGLenum error = CHECK_ALLOC_ERROR(&interface);
+ if (error != GR_GL_NO_ERROR) {
+ return false;
+ }
+ }
+ }
+
+ return true;
+}
+/**
* After a texture is created, any state which was altered during its creation
* needs to be restored.
*
@@ -1299,58 +1401,32 @@
return succeeded;
}
-GrGLenum GrGLGpu::uploadCompressedTexData(SkImage::CompressionType compressionType, int width,
- int height, GrGLenum target, const void* data) {
+bool GrGLGpu::uploadCompressedTexData(GrPixelConfig texConfig, int texWidth, int texHeight,
+ GrGLenum target,
+ const GrMipLevel texels[], int mipLevelCount,
+ GrMipMapsStatus* mipMapsStatus) {
+ SkASSERT(this->caps()->isConfigTexturable(texConfig));
+
+ const GrGLInterface* interface = this->glInterface();
const GrGLCaps& caps = this->glCaps();
- GrPixelConfig config = GrCompressionTypePixelConfig(compressionType);
// We only need the internal format for compressed 2D textures.
GrGLenum internalFormat;
- if (!caps.getCompressedTexImageFormats(config, &internalFormat)) {
- return 0;
+ if (!caps.getCompressedTexImageFormats(texConfig, &internalFormat)) {
+ return false;
}
- bool useTexStorage = caps.isConfigTexSupportEnabled(config);
-
- static constexpr int kMipLevelCount = 1;
-
- // Make sure that the width and height that we pass to OpenGL
- // is a multiple of the block size.
- size_t dataSize = GrCompressedDataSize(compressionType, width, height);
-
- if (useTexStorage) {
- // We never resize or change formats of textures.
- GL_ALLOC_CALL(this->glInterface(),
- TexStorage2D(target, kMipLevelCount, internalFormat, width, height));
- GrGLenum error = CHECK_ALLOC_ERROR(this->glInterface());
- if (error != GR_GL_NO_ERROR) {
- return 0;
- }
- GL_CALL(CompressedTexSubImage2D(target,
- 0, // level
- 0, // left
- 0, // top
- width,
- height,
- internalFormat,
- SkToInt(dataSize),
- data));
- } else {
- GL_ALLOC_CALL(this->glInterface(), CompressedTexImage2D(target,
- 0, // level
- internalFormat,
- width,
- height,
- 0, // border
- SkToInt(dataSize),
- data));
-
- GrGLenum error = CHECK_ALLOC_ERROR(this->glInterface());
- if (error != GR_GL_NO_ERROR) {
- return 0;
+ if (mipMapsStatus) {
+ if (mipLevelCount <= 1) {
+ *mipMapsStatus = GrMipMapsStatus::kNotAllocated;
+ } else {
+ *mipMapsStatus = GrMipMapsStatus::kValid;
}
}
- return internalFormat;
+
+ return allocate_and_populate_compressed_texture(texConfig, *interface, caps, target,
+ internalFormat, texels, mipLevelCount,
+ texWidth, texHeight);
}
static bool renderbuffer_storage_msaa(const GrGLContext& ctx,
@@ -1592,30 +1668,6 @@
return std::move(tex);
}
-sk_sp<GrTexture> GrGLGpu::onCreateCompressedTexture(int width, int height,
- SkImage::CompressionType compression,
- SkBudgeted budgeted, const void* data) {
- GrGLTexture::IDDesc idDesc;
- GrGLTextureParameters::SamplerOverriddenState initialState;
- if (!this->createCompressedTextureImpl(&idDesc.fInfo, width, height, compression, &initialState,
- data)) {
- return nullptr;
- }
- idDesc.fOwnership = GrBackendObjectOwnership::kOwned;
-
- GrSurfaceDesc desc;
- desc.fConfig = GrCompressionTypePixelConfig(compression);
- desc.fWidth = width;
- desc.fHeight = height;
- desc.fSampleCnt = 1;
- auto tex =
- sk_make_sp<GrGLTexture>(this, budgeted, desc, idDesc, GrMipMapsStatus::kNotAllocated);
- // The non-sampler params are still at their default values.
- tex->parameters()->set(&initialState, GrGLTextureParameters::NonsamplerState(),
- fResetTimestampForTextureParameters);
- return std::move(tex);
-}
-
namespace {
const GrGLuint kUnknownBitCount = GrGLStencilAttachment::kUnknownBitCount;
@@ -1759,7 +1811,6 @@
GrGLTextureParameters::SamplerOverriddenState* initialState,
const GrMipLevel texels[], int mipLevelCount,
GrMipMapsStatus* mipMapsStatus) {
- SkASSERT(!GrPixelConfigIsCompressed(desc.fConfig));
info->fID = 0;
info->fTarget = GR_GL_TEXTURE_2D;
GL_CALL(GenTextures(1, &(info->fID)));
@@ -1781,37 +1832,25 @@
*initialState = set_initial_texture_params(this->glInterface(), *info);
- if (!this->uploadTexData(desc.fConfig, desc.fWidth, desc.fHeight, info->fTarget,
- kNewTexture_UploadType, 0, 0, desc.fWidth, desc.fHeight, desc.fConfig,
- texels, mipLevelCount, mipMapsStatus)) {
+ bool success = false;
+ if (GrGLFormatIsCompressed(info->fFormat)) {
+ SkASSERT(GrRenderable::kNo == renderable);
+
+ success = this->uploadCompressedTexData(desc.fConfig, desc.fWidth, desc.fHeight,
+ info->fTarget,
+ texels, mipLevelCount, mipMapsStatus);
+ } else {
+ success = this->uploadTexData(desc.fConfig, desc.fWidth, desc.fHeight, info->fTarget,
+ kNewTexture_UploadType, 0, 0, desc.fWidth, desc.fHeight,
+ desc.fConfig, texels, mipLevelCount, mipMapsStatus);
+ }
+ if (!success) {
GL_CALL(DeleteTextures(1, &(info->fID)));
return false;
}
return true;
}
-bool GrGLGpu::createCompressedTextureImpl(
- GrGLTextureInfo* info, int width, int height, SkImage::CompressionType compression,
- GrGLTextureParameters::SamplerOverriddenState* initialState, const void* data) {
- info->fID = 0;
- GL_CALL(GenTextures(1, &info->fID));
- if (!info->fID) {
- return false;
- }
-
- info->fTarget = GR_GL_TEXTURE_2D;
- this->bindTextureToScratchUnit(info->fTarget, info->fID);
-
- *initialState = set_initial_texture_params(this->glInterface(), *info);
-
- info->fFormat = this->uploadCompressedTexData(compression, width, height, info->fTarget, data);
- if (!info->fFormat) {
- GL_CALL(DeleteTextures(1, &info->fID));
- return false;
- }
- return true;
-}
-
GrStencilAttachment* GrGLGpu::createStencilAttachmentForRenderTarget(const GrRenderTarget* rt,
int width, int height) {
SkASSERT(width >= rt->width());
@@ -3984,8 +4023,8 @@
return GrBackendTexture(); // invalid
}
- if (w < 1 || w > this->caps()->maxTextureSize() ||
- h < 1 || h > this->caps()->maxTextureSize()) {
+ if (w == 0 || w > this->caps()->maxTextureSize() ||
+ h == 0 || h > this->caps()->maxTextureSize()) {
return GrBackendTexture(); // invalid
}
@@ -3998,70 +4037,60 @@
return GrBackendTexture(); // invalid
}
- GrGLTextureInfo info;
- GrGLTextureParameters::SamplerOverriddenState initialState;
-
int mipLevelCount = 0;
SkAutoTMalloc<GrMipLevel> texels;
SkAutoMalloc pixelStorage;
- SkImage::CompressionType compressionType;
- if (GrGLFormatToCompressionType(*glFormat, &compressionType)) {
- // Compressed textures currently must be non-MIP mapped and have initial data.
- if (mipMapped == GrMipMapped::kYes) {
- return GrBackendTexture();
- }
- if (!srcPixels) {
- if (!color) {
- return GrBackendTexture();
- }
+
+ if (srcPixels) {
+ mipLevelCount = 1;
+
+ texels.reset(mipLevelCount);
+
+ if (GrGLFormatIsCompressed(*glFormat)) {
SkASSERT(0 == rowBytes);
- size_t size = GrCompressedDataSize(compressionType, w, h);
- srcPixels = pixelStorage.reset(size);
- GrFillInCompressedData(compressionType, w, h, (char*)srcPixels, *color);
}
- if (!this->createCompressedTextureImpl(&info, w, h, compressionType, &initialState,
- srcPixels)) {
- return GrBackendTexture();
+
+ texels.get()[0] = { srcPixels, rowBytes };
+ } else if (color) {
+ mipLevelCount = 1;
+ if (GrMipMapped::kYes == mipMapped) {
+ mipLevelCount = SkMipMap::ComputeLevelCount(w, h) + 1;
}
- } else {
- if (srcPixels) {
- mipLevelCount = 1;
- texels.reset(mipLevelCount);
- texels.get()[0] = {srcPixels, rowBytes};
- } else if (color) {
- mipLevelCount = 1;
- if (GrMipMapped::kYes == mipMapped) {
- mipLevelCount = SkMipMap::ComputeLevelCount(w, h) + 1;
- }
- texels.reset(mipLevelCount);
- SkTArray<size_t> individualMipOffsets(mipLevelCount);
+ texels.reset(mipLevelCount);
+ SkTArray<size_t> individualMipOffsets(mipLevelCount);
- size_t bytesPerPixel = GrBytesPerPixel(config);
+ GrCompression compression = GrGLFormat2Compression(*glFormat);
+ size_t bytesPerPixel = GrBytesPerPixel(config);
- size_t totalSize = GrComputeTightCombinedBufferSize(
- bytesPerPixel, w, h, &individualMipOffsets, mipLevelCount);
+ size_t totalSize = GrComputeTightCombinedBufferSize(compression, bytesPerPixel, w, h,
+ &individualMipOffsets, mipLevelCount);
- char* tmpPixels = (char*)pixelStorage.reset(totalSize);
+ char* tmpPixels = (char *) pixelStorage.reset(totalSize);
- GrFillInData(config, w, h, individualMipOffsets, tmpPixels, *color);
- for (int i = 0; i < mipLevelCount; ++i) {
- size_t offset = individualMipOffsets[i];
+ GrFillInData(compression, config, w, h, individualMipOffsets, tmpPixels, *color);
- int twoToTheMipLevel = 1 << i;
- int currentWidth = SkTMax(1, w / twoToTheMipLevel);
+ for (int i = 0; i < mipLevelCount; ++i) {
+ size_t offset = individualMipOffsets[i];
- texels.get()[i] = {&(tmpPixels[offset]), currentWidth * bytesPerPixel};
- }
+ int twoToTheMipLevel = 1 << i;
+ int currentWidth = SkTMax(1, w / twoToTheMipLevel);
+
+ texels.get()[i] = { &(tmpPixels[offset]), currentWidth*bytesPerPixel };
}
- GrSurfaceDesc desc;
- desc.fWidth = w;
- desc.fHeight = h;
- desc.fConfig = config;
- if (!this->createTextureImpl(desc, &info, renderable, &initialState, texels.get(),
- mipLevelCount, nullptr)) {
- return GrBackendTexture(); // invalid
- }
+ }
+
+ GrSurfaceDesc desc;
+ desc.fWidth = w;
+ desc.fHeight = h;
+ desc.fConfig = config;
+
+ GrGLTextureInfo info;
+ GrGLTextureParameters::SamplerOverriddenState initialState;
+
+ if (!this->createTextureImpl(desc, &info, renderable, &initialState, texels.get(),
+ mipLevelCount, nullptr)) {
+ return GrBackendTexture(); // invalid
}
// unbind the texture from the texture unit to avoid asserts
diff --git a/src/gpu/gl/GrGLGpu.h b/src/gpu/gl/GrGLGpu.h
index db6564e..47e75e6 100644
--- a/src/gpu/gl/GrGLGpu.h
+++ b/src/gpu/gl/GrGLGpu.h
@@ -194,9 +194,6 @@
sk_sp<GrTexture> onCreateTexture(const GrSurfaceDesc& desc, SkBudgeted budgeted,
const GrMipLevel texels[], int mipLevelCount) override;
- sk_sp<GrTexture> onCreateCompressedTexture(int width, int height,
- SkImage::CompressionType compression, SkBudgeted,
- const void* data) override;
sk_sp<GrGpuBuffer> onCreateBuffer(size_t size, GrGpuBufferType intendedType, GrAccessPattern,
const void* data) override;
@@ -224,11 +221,6 @@
const GrMipLevel texels[], int mipLevelCount,
GrMipMapsStatus* mipMapsStatus);
- bool createCompressedTextureImpl(GrGLTextureInfo* info, int width, int height,
- SkImage::CompressionType compression,
- GrGLTextureParameters::SamplerOverriddenState* initialState,
- const void* data);
-
// Checks whether glReadPixels can be called to get pixel values in readConfig from the
// render target.
bool readPixelsSupported(GrRenderTarget* target, GrPixelConfig readConfig);
@@ -406,11 +398,12 @@
GrPixelConfig dataConfig, const GrMipLevel texels[], int mipLevelCount,
GrMipMapsStatus* mipMapsStatus = nullptr);
- // Helper for onCreateCompressedTexture. Compressed textures are read-only so we
- // only use this to populate a new texture. Returns the internal format of the texture
- // or 0 on failure.
- GrGLenum uploadCompressedTexData(SkImage::CompressionType, int width, int height,
- GrGLenum target, const void* data);
+ // helper for onCreateCompressedTexture. Compressed textures are read-only so we
+ // only use this to populate a new texture.
+ bool uploadCompressedTexData(GrPixelConfig texConfig, int texWidth, int texHeight,
+ GrGLenum target,
+ const GrMipLevel texels[], int mipLevelCount,
+ GrMipMapsStatus* mipMapsStatus = nullptr);
bool createRenderTargetObjects(const GrSurfaceDesc&, const GrGLTextureInfo& texInfo,
GrGLRenderTarget::IDDesc*);
diff --git a/src/gpu/gl/GrGLUtil.cpp b/src/gpu/gl/GrGLUtil.cpp
index 0efeac6..d7ad1aa 100644
--- a/src/gpu/gl/GrGLUtil.cpp
+++ b/src/gpu/gl/GrGLUtil.cpp
@@ -602,17 +602,36 @@
default:
return false;
}
+ SK_ABORT("Invalid format");
+ return false;
}
-bool GrGLFormatToCompressionType(GrGLenum glFormat, SkImage::CompressionType* compressionType) {
+GrCompression GrGLFormat2Compression(GrGLenum glFormat) {
switch (glFormat) {
case GR_GL_COMPRESSED_RGB8_ETC2: // fall through
case GR_GL_COMPRESSED_ETC1_RGB8:
- *compressionType = SkImage::kETC1_CompressionType;
- return true;
+ return GrCompression::kETC1;
default:
- return false;
+ return GrCompression::kNone;
}
+ SK_ABORT("Invalid format");
+ return GrCompression::kNone;
+}
+
+size_t GrGLFormatCompressedDataSize(GrGLenum glFormat, int width, int height) {
+ SkASSERT(GrGLFormatIsCompressed(glFormat));
+
+ switch (glFormat) {
+ case GR_GL_COMPRESSED_RGB8_ETC2: // fall through
+ case GR_GL_COMPRESSED_ETC1_RGB8:
+ return GrETC1CompressedDataSize(width, height);
+ default:
+ SK_ABORT("Unknown compressed format");
+ return 4 * width * height;
+ }
+
+ SK_ABORT("Unknown compressed format");
+ return 4 * width * height;
}
size_t GrGLBytesPerFormat(GrGLenum glFormat) {
diff --git a/src/gpu/gl/GrGLUtil.h b/src/gpu/gl/GrGLUtil.h
index 9670776..4093816 100644
--- a/src/gpu/gl/GrGLUtil.h
+++ b/src/gpu/gl/GrGLUtil.h
@@ -282,9 +282,14 @@
bool GrGLFormatIsCompressed(GrGLenum glFormat);
/**
- * Maps a gl format into the CompressionType enum if appropriate.
+ * Maps a gl format into the GrCompressed enum.
*/
-bool GrGLFormatToCompressionType(GrGLenum glFormat, SkImage::CompressionType*);
+GrCompression GrGLFormat2Compression(GrGLenum glFormat);
+
+/**
+ * Returns the data size for the given compressed format
+ */
+size_t GrGLFormatCompressedDataSize(GrGLenum glFormat, int width, int height);
size_t GrGLBytesPerFormat(GrGLenum glFormat);
diff --git a/src/gpu/mock/GrMockCaps.h b/src/gpu/mock/GrMockCaps.h
index ff39757..678ce1c 100644
--- a/src/gpu/mock/GrMockCaps.h
+++ b/src/gpu/mock/GrMockCaps.h
@@ -150,16 +150,6 @@
return GrBackendFormat::MakeMock(config);
}
- GrBackendFormat getBackendFormatFromCompressionType(
- SkImage::CompressionType compressionType) const override {
- switch (compressionType) {
- case SkImage::kETC1_CompressionType:
- return GrBackendFormat::MakeMock(kRGB_ETC1_GrPixelConfig);
- }
- SK_ABORT("Invalid compression type");
- return {};
- }
-
GrSwizzle getTextureSwizzle(const GrBackendFormat&, GrColorType) const override {
return GrSwizzle();
}
diff --git a/src/gpu/mock/GrMockGpu.cpp b/src/gpu/mock/GrMockGpu.cpp
index e8c1899..f0355e5 100644
--- a/src/gpu/mock/GrMockGpu.cpp
+++ b/src/gpu/mock/GrMockGpu.cpp
@@ -106,25 +106,6 @@
return sk_sp<GrTexture>(new GrMockTexture(this, budgeted, desc, mipMapsStatus, texInfo));
}
-sk_sp<GrTexture> GrMockGpu::onCreateCompressedTexture(int width, int height,
- SkImage::CompressionType compressionType,
- SkBudgeted budgeted, const void* data) {
- if (fMockOptions.fFailTextureAllocations) {
- return nullptr;
- }
- GrBackendFormat format = this->caps()->getBackendFormatFromCompressionType(compressionType);
-
- GrMockTextureInfo texInfo;
- texInfo.fConfig = *format.getMockFormat();
- texInfo.fID = NextInternalTextureID();
- GrSurfaceDesc desc;
- desc.fConfig = texInfo.fConfig;
- desc.fWidth = width;
- desc.fHeight = height;
- return sk_sp<GrTexture>(
- new GrMockTexture(this, budgeted, desc, GrMipMapsStatus::kNotAllocated, texInfo));
-}
-
sk_sp<GrTexture> GrMockGpu::onWrapBackendTexture(const GrBackendTexture& tex,
GrWrapOwnership ownership,
GrWrapCacheable wrapType, GrIOType ioType) {
diff --git a/src/gpu/mock/GrMockGpu.h b/src/gpu/mock/GrMockGpu.h
index b26c4e1..b95f90b 100644
--- a/src/gpu/mock/GrMockGpu.h
+++ b/src/gpu/mock/GrMockGpu.h
@@ -66,9 +66,6 @@
sk_sp<GrTexture> onCreateTexture(const GrSurfaceDesc&, SkBudgeted, const GrMipLevel[],
int mipLevelCount) override;
- sk_sp<GrTexture> onCreateCompressedTexture(int width, int height, SkImage::CompressionType,
- SkBudgeted, const void* data) override;
-
sk_sp<GrTexture> onWrapBackendTexture(const GrBackendTexture&, GrWrapOwnership, GrWrapCacheable,
GrIOType) override;
diff --git a/src/gpu/mtl/GrMtlCaps.h b/src/gpu/mtl/GrMtlCaps.h
index adebbce..4134194 100644
--- a/src/gpu/mtl/GrMtlCaps.h
+++ b/src/gpu/mtl/GrMtlCaps.h
@@ -73,7 +73,6 @@
GrBackendFormat getBackendFormatFromGrColorType(GrColorType ct,
GrSRGBEncoded srgbEncoded) const override;
- GrBackendFormat getBackendFormatFromCompressionType(SkImage::CompressionType) const override;
GrSwizzle getTextureSwizzle(const GrBackendFormat&, GrColorType) const override;
GrSwizzle getOutputSwizzle(const GrBackendFormat&, GrColorType) const override;
diff --git a/src/gpu/mtl/GrMtlCaps.mm b/src/gpu/mtl/GrMtlCaps.mm
index dc3469a..e2dc706 100644
--- a/src/gpu/mtl/GrMtlCaps.mm
+++ b/src/gpu/mtl/GrMtlCaps.mm
@@ -637,20 +637,6 @@
return GrBackendFormat::MakeMtl(format);
}
-GrBackendFormat GrMtlCaps::getBackendFormatFromCompressionType(
- SkImage::CompressionType compressionType) const {
- switch (compressionType) {
- case SkImage::kETC1_CompressionType:
-#ifdef SK_BUILD_FOR_MAC
- return {};
-#else
- return GrBackendFormat::MakeMtl(MTLPixelFormatETC2_RGB8);
-#endif
- }
- SK_ABORT("Invalid compression type");
- return {};
-}
-
#ifdef SK_DEBUG
static bool format_color_type_valid_pair(MTLPixelFormat format, GrColorType colorType) {
switch (colorType) {
@@ -673,13 +659,7 @@
case GrColorType::kRGBA_8888:
return MTLPixelFormatRGBA8Unorm == format || MTLPixelFormatRGBA8Unorm_sRGB == format;
case GrColorType::kRGB_888x:
- GR_STATIC_ASSERT(GrCompressionTypeClosestColorType(SkImage::kETC1_CompressionType) ==
- GrColorType::kRGB_888x);
-#ifdef SK_BUILD_FOR_MAC
return MTLPixelFormatRGBA8Unorm == format;
-#else
- return MTLPixelFormatRGBA8Unorm == format || MTLPixelFormatETC2_RGB8 == format;
-#endif
case GrColorType::kRG_88:
return MTLPixelFormatRG8Unorm == format;
case GrColorType::kBGRA_8888:
@@ -698,6 +678,12 @@
return MTLPixelFormatRG32Float == format;
case GrColorType::kRGBA_F32:
return MTLPixelFormatRGBA32Float == format;
+ case GrColorType::kRGB_ETC1:
+#ifdef SK_BUILD_FOR_MAC
+ return false;
+#else
+ return MTLPixelFormatETC2_RGB8 == format;
+#endif
case GrColorType::kR_16:
return MTLPixelFormatR16Unorm == format;
case GrColorType::kRG_1616:
diff --git a/src/gpu/mtl/GrMtlGpu.h b/src/gpu/mtl/GrMtlGpu.h
index 8cd8288..6d5979a 100644
--- a/src/gpu/mtl/GrMtlGpu.h
+++ b/src/gpu/mtl/GrMtlGpu.h
@@ -131,10 +131,6 @@
sk_sp<GrTexture> onCreateTexture(const GrSurfaceDesc& desc, SkBudgeted budgeted,
const GrMipLevel texels[], int mipLevelCount) override;
- sk_sp<GrTexture> onCreateCompressedTexture(int width, int height, SkImage::CompressionType,
- SkBudgeted, const void* data) override {
- return nullptr;
- }
sk_sp<GrTexture> onWrapBackendTexture(const GrBackendTexture&, GrWrapOwnership, GrWrapCacheable,
GrIOType) override;
diff --git a/src/gpu/vk/GrVkCaps.cpp b/src/gpu/vk/GrVkCaps.cpp
index 28417e7..8b904d3 100644
--- a/src/gpu/vk/GrVkCaps.cpp
+++ b/src/gpu/vk/GrVkCaps.cpp
@@ -1086,16 +1086,6 @@
return GrBackendFormat::MakeVk(format);
}
-GrBackendFormat GrVkCaps::getBackendFormatFromCompressionType(
- SkImage::CompressionType compressionType) const {
- switch (compressionType) {
- case SkImage::kETC1_CompressionType:
- return GrBackendFormat::MakeVk(VK_FORMAT_ETC2_R8G8B8_UNORM_BLOCK);
- }
- SK_ABORT("Invalid compression type");
- return {};
-}
-
#ifdef SK_DEBUG
static bool format_color_type_valid_pair(VkFormat vkFormat, GrColorType colorType) {
switch (colorType) {
@@ -1111,10 +1101,7 @@
case GrColorType::kRGBA_8888:
return VK_FORMAT_R8G8B8A8_UNORM == vkFormat || VK_FORMAT_R8G8B8A8_SRGB == vkFormat;
case GrColorType::kRGB_888x:
- GR_STATIC_ASSERT(GrCompressionTypeClosestColorType(SkImage::kETC1_CompressionType) ==
- GrColorType::kRGB_888x);
- return VK_FORMAT_R8G8B8_UNORM == vkFormat || VK_FORMAT_R8G8B8A8_UNORM == vkFormat ||
- VK_FORMAT_ETC2_R8G8B8_UNORM_BLOCK == vkFormat;
+ return VK_FORMAT_R8G8B8_UNORM == vkFormat || VK_FORMAT_R8G8B8A8_UNORM == vkFormat;
case GrColorType::kRG_88:
return VK_FORMAT_R8G8_UNORM == vkFormat;
case GrColorType::kBGRA_8888:
@@ -1133,6 +1120,8 @@
return VK_FORMAT_R32G32_SFLOAT == vkFormat;
case GrColorType::kRGBA_F32:
return VK_FORMAT_R32G32B32A32_SFLOAT == vkFormat;
+ case GrColorType::kRGB_ETC1:
+ return VK_FORMAT_ETC2_R8G8B8_UNORM_BLOCK == vkFormat;
case GrColorType::kR_16:
return VK_FORMAT_R16_UNORM == vkFormat;
case GrColorType::kRG_1616:
diff --git a/src/gpu/vk/GrVkCaps.h b/src/gpu/vk/GrVkCaps.h
index c859121..9d1f04d 100644
--- a/src/gpu/vk/GrVkCaps.h
+++ b/src/gpu/vk/GrVkCaps.h
@@ -169,7 +169,6 @@
GrBackendFormat getBackendFormatFromGrColorType(GrColorType ct,
GrSRGBEncoded srgbEncoded) const override;
- GrBackendFormat getBackendFormatFromCompressionType(SkImage::CompressionType) const override;
GrSwizzle getTextureSwizzle(const GrBackendFormat&, GrColorType) const override;
GrSwizzle getOutputSwizzle(const GrBackendFormat&, GrColorType) const override;
diff --git a/src/gpu/vk/GrVkGpu.cpp b/src/gpu/vk/GrVkGpu.cpp
index 7b7bff5..7699ff4 100644
--- a/src/gpu/vk/GrVkGpu.cpp
+++ b/src/gpu/vk/GrVkGpu.cpp
@@ -896,30 +896,62 @@
// It's probably possible to roll this into uploadTexDataOptimal,
// but for now it's easier to maintain as a separate entity.
bool GrVkGpu::uploadTexDataCompressed(GrVkTexture* tex, int left, int top, int width, int height,
- SkImage::CompressionType compressionType, const void* data) {
- SkASSERT(data);
+ GrColorType dataColorType, const GrMipLevel texels[],
+ int mipLevelCount) {
SkASSERT(!tex->isLinearTiled());
// For now the assumption is that our rect is the entire texture.
// Compressed textures are read-only so this should be a reasonable assumption.
SkASSERT(0 == left && 0 == top && width == tex->width() && height == tex->height());
+ // We assume that if the texture has mip levels, we either upload to all the levels or just the
+ // first.
+ SkASSERT(1 == mipLevelCount || mipLevelCount == (tex->texturePriv().maxMipMapLevel() + 1));
+
+ SkASSERT(GrPixelConfigIsCompressed(GrColorTypeToPixelConfig(dataColorType,
+ GrSRGBEncoded::kNo)));
+
if (width == 0 || height == 0) {
return false;
}
- SkImage::CompressionType textureCompressionType;
- if (!GrVkFormatToCompressionType(tex->imageFormat(), &textureCompressionType) ||
- textureCompressionType != compressionType) {
+ if (GrPixelConfigToColorType(tex->config()) != dataColorType) {
return false;
}
SkASSERT(this->vkCaps().isFormatTexturable(tex->imageFormat()));
- size_t dataSize = GrCompressedDataSize(compressionType, width, height);
+ SkTArray<size_t> individualMipOffsets(mipLevelCount);
+ individualMipOffsets.push_back(0);
+ size_t combinedBufferSize = GrVkFormatCompressedDataSize(tex->imageFormat(), width, height);
+ int currentWidth = width;
+ int currentHeight = height;
+ if (!texels[0].fPixels) {
+ return false;
+ }
+
+ // We assume that the alignment for any compressed format is at least 4 bytes and so we don't
+ // need to worry about alignment issues. For example, each block in ETC1 is 8 bytes.
+ for (int currentMipLevel = 1; currentMipLevel < mipLevelCount; currentMipLevel++) {
+ currentWidth = SkTMax(1, currentWidth / 2);
+ currentHeight = SkTMax(1, currentHeight / 2);
+
+ if (texels[currentMipLevel].fPixels) {
+ const size_t dataSize = GrVkFormatCompressedDataSize(tex->imageFormat(), currentWidth,
+ currentHeight);
+ individualMipOffsets.push_back(combinedBufferSize);
+ combinedBufferSize += dataSize;
+ } else {
+ return false;
+ }
+ }
+ if (0 == combinedBufferSize) {
+ // We don't have any data to upload so fail (compressed textures are read-only).
+ return false;
+ }
// allocate buffer to hold our mip data
sk_sp<GrVkTransferBuffer> transferBuffer =
- GrVkTransferBuffer::Make(this, dataSize, GrVkBuffer::kCopyRead_Type);
+ GrVkTransferBuffer::Make(this, combinedBufferSize, GrVkBuffer::kCopyRead_Type);
if (!transferBuffer) {
return false;
}
@@ -929,17 +961,38 @@
GrVkTexture* uploadTexture = tex;
char* buffer = (char*)transferBuffer->map();
+ SkTArray<VkBufferImageCopy> regions(mipLevelCount);
- memcpy(buffer, data, dataSize);
+ currentWidth = width;
+ currentHeight = height;
+ int layerHeight = uploadTexture->height();
+ for (int currentMipLevel = 0; currentMipLevel < mipLevelCount; currentMipLevel++) {
+ if (texels[currentMipLevel].fPixels) {
+ // Again, we're assuming that our rect is the entire texture
+ SkASSERT(currentHeight == layerHeight);
+ SkASSERT(0 == uploadLeft && 0 == uploadTop);
- VkBufferImageCopy region;
- memset(®ion, 0, sizeof(VkBufferImageCopy));
- region.bufferOffset = transferBuffer->offset();
- region.bufferRowLength = width;
- region.bufferImageHeight = height;
- region.imageSubresource = { VK_IMAGE_ASPECT_COLOR_BIT, 0, 0, 1 };
- region.imageOffset = { uploadLeft, uploadTop, 0 };
- region.imageExtent = { SkToU32(width), SkToU32(height), 1 };
+ const size_t dataSize = GrVkFormatCompressedDataSize(tex->imageFormat(), currentWidth,
+ currentHeight);
+
+ // copy data into the buffer, skipping the trailing bytes
+ char* dst = buffer + individualMipOffsets[currentMipLevel];
+ const char* src = (const char*)texels[currentMipLevel].fPixels;
+ memcpy(dst, src, dataSize);
+
+ VkBufferImageCopy& region = regions.push_back();
+ memset(®ion, 0, sizeof(VkBufferImageCopy));
+ region.bufferOffset = transferBuffer->offset() + individualMipOffsets[currentMipLevel];
+ region.bufferRowLength = currentWidth;
+ region.bufferImageHeight = currentHeight;
+ region.imageSubresource = { VK_IMAGE_ASPECT_COLOR_BIT, SkToU32(currentMipLevel), 0, 1 };
+ region.imageOffset = { uploadLeft, uploadTop, 0 };
+ region.imageExtent = { (uint32_t)currentWidth, (uint32_t)currentHeight, 1 };
+ }
+ currentWidth = SkTMax(1, currentWidth / 2);
+ currentHeight = SkTMax(1, currentHeight / 2);
+ layerHeight = currentHeight;
+ }
// no need to flush non-coherent memory, unmap will do that for us
transferBuffer->unmap();
@@ -956,8 +1009,12 @@
transferBuffer.get(),
uploadTexture,
VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL,
- 1,
- ®ion);
+ regions.count(),
+ regions.begin());
+
+ if (1 == mipLevelCount) {
+ tex->texturePriv().markMipMapsDirty();
+ }
return true;
}
@@ -1022,16 +1079,24 @@
return nullptr;
}
+ bool isCompressed = GrVkFormatIsCompressed(tex->imageFormat());
auto colorType = GrPixelConfigToColorType(desc.fConfig);
if (mipLevelCount) {
- if (!this->uploadTexDataOptimal(tex.get(), 0, 0, desc.fWidth, desc.fHeight, colorType,
- texels, mipLevelCount)) {
+ bool success;
+ if (isCompressed) {
+ success = this->uploadTexDataCompressed(tex.get(), 0, 0, desc.fWidth, desc.fHeight,
+ colorType, texels, mipLevelCount);
+ } else {
+ success = this->uploadTexDataOptimal(tex.get(), 0, 0, desc.fWidth, desc.fHeight,
+ colorType, texels, mipLevelCount);
+ }
+ if (!success) {
tex->unref();
return nullptr;
}
}
- if (SkToBool(desc.fFlags & kPerformInitialClear_GrSurfaceFlag)) {
+ if (SkToBool(desc.fFlags & kPerformInitialClear_GrSurfaceFlag) && !isCompressed) {
VkClearColorValue zeroClearColor;
memset(&zeroClearColor, 0, sizeof(zeroClearColor));
VkImageSubresourceRange range;
@@ -1047,55 +1112,6 @@
return std::move(tex);
}
-sk_sp<GrTexture> GrVkGpu::onCreateCompressedTexture(int width, int height,
- SkImage::CompressionType compressionType,
- SkBudgeted budgeted, const void* data) {
- GrBackendFormat format = this->caps()->getBackendFormatFromCompressionType(compressionType);
- if (!format.getVkFormat()) {
- return nullptr;
- }
- VkFormat pixelFormat = *format.getVkFormat();
-
- VkImageUsageFlags usageFlags = VK_IMAGE_USAGE_SAMPLED_BIT;
-
- // For now we will set the VK_IMAGE_USAGE_TRANSFER_DESTINATION_BIT and
- // VK_IMAGE_USAGE_TRANSFER_SOURCE_BIT on every texture since we do not know whether or not we
- // will be using this texture in some copy or not. Also this assumes, as is the current case,
- // that all render targets in vulkan are also textures. If we change this practice of setting
- // both bits, we must make sure to set the destination bit if we are uploading srcData to the
- // texture.
- usageFlags |= VK_IMAGE_USAGE_TRANSFER_SRC_BIT | VK_IMAGE_USAGE_TRANSFER_DST_BIT;
-
- // Compressed textures with MIP levels or multiple samples are not supported as of now.
- GrVkImage::ImageDesc imageDesc;
- imageDesc.fImageType = VK_IMAGE_TYPE_2D;
- imageDesc.fFormat = pixelFormat;
- imageDesc.fWidth = width;
- imageDesc.fHeight = height;
- imageDesc.fLevels = 1;
- imageDesc.fSamples = 1;
- imageDesc.fImageTiling = VK_IMAGE_TILING_OPTIMAL;
- imageDesc.fUsageFlags = usageFlags;
- imageDesc.fIsProtected = GrProtected::kNo;
-
- GrSurfaceDesc desc;
- desc.fConfig = GrCompressionTypePixelConfig(compressionType);
- desc.fWidth = width;
- desc.fHeight = height;
- auto tex = GrVkTexture::MakeNewTexture(this, budgeted, desc, imageDesc,
- GrMipMapsStatus::kNotAllocated);
- if (!tex) {
- return nullptr;
- }
-
- if (!this->uploadTexDataCompressed(tex.get(), 0, 0, desc.fWidth, desc.fHeight, compressionType,
- data)) {
- return nullptr;
- }
-
- return std::move(tex);
-}
-
////////////////////////////////////////////////////////////////////////////////
void GrVkGpu::copyBuffer(GrVkBuffer* srcBuffer, GrVkBuffer* dstBuffer, VkDeviceSize srcOffset,
@@ -1464,30 +1480,6 @@
int width, int height,
const void* srcData, size_t srcRowBytes) {
SkASSERT(srcData);
- SkASSERT(!GrVkFormatIsCompressed(vkFormat));
-
- void* mapPtr = GrVkMemory::MapAlloc(gpu, alloc);
- if (!mapPtr) {
- return false;
- }
- size_t bytesPerPixel = GrVkBytesPerFormat(vkFormat);
- const size_t trimRowBytes = width * bytesPerPixel;
- if (!srcRowBytes) {
- srcRowBytes = trimRowBytes;
- }
- SkASSERT(trimRowBytes * height <= alloc.fSize);
-
- SkRectMemcpy(mapPtr, trimRowBytes, srcData, srcRowBytes, trimRowBytes, height);
-
- GrVkMemory::FlushMappedAlloc(gpu, alloc, 0, alloc.fSize);
- GrVkMemory::UnmapAlloc(gpu, alloc);
- return true;
-}
-
-bool copy_compressed_src_data(GrVkGpu* gpu, const GrVkAlloc& alloc,
- SkImage::CompressionType compressionType, int width, int height,
- const void* data) {
- SkASSERT(data);
void* mapPtr = GrVkMemory::MapAlloc(gpu, alloc);
if (!mapPtr) {
@@ -1495,30 +1487,43 @@
}
mapPtr = reinterpret_cast<char*>(mapPtr);
- size_t dataSize = GrCompressedDataSize(compressionType, width, height);
- SkASSERT(dataSize <= alloc.fSize);
- memcpy(mapPtr, data, dataSize);
+ if (GrVkFormatIsCompressed(vkFormat)) {
+ SkASSERT(0 == srcRowBytes);
+ size_t levelSize = GrVkFormatCompressedDataSize(vkFormat, width, height);
+
+ SkASSERT(levelSize <= alloc.fSize);
+ memcpy(mapPtr, srcData, levelSize);
+ } else {
+ size_t bytesPerPixel = GrVkBytesPerFormat(vkFormat);
+ const size_t trimRowBytes = width * bytesPerPixel;
+ if (!srcRowBytes) {
+ srcRowBytes = trimRowBytes;
+ }
+ SkASSERT(trimRowBytes * height <= alloc.fSize);
+
+ SkRectMemcpy(mapPtr, trimRowBytes, srcData, srcRowBytes, trimRowBytes, height);
+ }
+
GrVkMemory::FlushMappedAlloc(gpu, alloc, 0, alloc.fSize);
GrVkMemory::UnmapAlloc(gpu, alloc);
return true;
}
+
bool fill_in_with_color(GrVkGpu* gpu, const GrVkAlloc& alloc, VkFormat vkFormat,
int baseWidth, int baseHeight,
const SkTArray<size_t>& individualMipOffsets,
GrPixelConfig config, const SkColor4f& color) {
+ GrCompression compression = GrVkFormat2Compression(vkFormat);
+
void* mapPtr = GrVkMemory::MapAlloc(gpu, alloc);
if (!mapPtr) {
return false;
}
- SkImage::CompressionType compressionType;
- if (GrVkFormatToCompressionType(vkFormat, &compressionType)) {
- GrFillInCompressedData(compressionType, baseWidth, baseHeight, (char*)mapPtr, color);
- } else {
- // TODO: pass in alloc.fSize and assert we never write past it
- GrFillInData(config, baseWidth, baseHeight, individualMipOffsets, (char*)mapPtr, color);
- }
+ // TODO: pass in alloc.fSize and assert we never write past it
+ GrFillInData(compression, config, baseWidth, baseHeight,
+ individualMipOffsets, (char*) mapPtr, color);
GrVkMemory::FlushMappedAlloc(gpu, alloc, 0, alloc.fSize);
GrVkMemory::UnmapAlloc(gpu, alloc);
@@ -1661,24 +1666,10 @@
SkTArray<size_t> individualMipOffsets(mipLevels);
- SkImage::CompressionType compressionType;
- bool isCompressed = GrVkFormatToCompressionType(vkFormat, &compressionType);
+ GrCompression compression = GrVkFormat2Compression(vkFormat);
- size_t combinedBufferSize;
- if (isCompressed) {
- // Compressed textures currently must be non-MIP mapped and have initial data.
- if (mipMapped == GrMipMapped::kYes) {
- return false;
- }
- if (!srcData && !color) {
- return false;
- }
- combinedBufferSize = GrCompressedDataSize(compressionType, w, h);
- individualMipOffsets.push_back(0);
- } else {
- combinedBufferSize = GrComputeTightCombinedBufferSize(bytesPerPixel, w, h,
- &individualMipOffsets, mipLevels);
- }
+ size_t combinedBufferSize = GrComputeTightCombinedBufferSize(compression, bytesPerPixel, w, h,
+ &individualMipOffsets, mipLevels);
VkBufferCreateInfo bufInfo;
memset(&bufInfo, 0, sizeof(VkBufferCreateInfo));
@@ -1711,10 +1702,9 @@
if (!srcData) {
result = fill_in_with_color(this, bufferAlloc, vkFormat, w, h, individualMipOffsets,
config, *color);
- } else if (isCompressed) {
- result = copy_compressed_src_data(this, bufferAlloc, compressionType, w, h, srcData);
} else {
SkASSERT(1 == mipLevels);
+
result = copy_src_data(this, bufferAlloc, vkFormat, w, h, srcData, srcRowBytes);
}
diff --git a/src/gpu/vk/GrVkGpu.h b/src/gpu/vk/GrVkGpu.h
index 8392c48..5600eac 100644
--- a/src/gpu/vk/GrVkGpu.h
+++ b/src/gpu/vk/GrVkGpu.h
@@ -194,8 +194,6 @@
sk_sp<GrTexture> onCreateTexture(const GrSurfaceDesc&, SkBudgeted, const GrMipLevel[],
int mipLevelCount) override;
- sk_sp<GrTexture> onCreateCompressedTexture(int width, int height, SkImage::CompressionType,
- SkBudgeted, const void* data) override;
sk_sp<GrTexture> onWrapBackendTexture(const GrBackendTexture&, GrWrapOwnership, GrWrapCacheable,
GrIOType) override;
@@ -258,7 +256,8 @@
bool uploadTexDataOptimal(GrVkTexture* tex, int left, int top, int width, int height,
GrColorType colorType, const GrMipLevel texels[], int mipLevelCount);
bool uploadTexDataCompressed(GrVkTexture* tex, int left, int top, int width, int height,
- SkImage::CompressionType, const void* data);
+ GrColorType dataColorType, const GrMipLevel texels[],
+ int mipLevelCount);
void resolveImage(GrSurface* dst, GrVkRenderTarget* src, const SkIRect& srcRect,
const SkIPoint& dstPoint);
diff --git a/src/gpu/vk/GrVkUtil.cpp b/src/gpu/vk/GrVkUtil.cpp
index 39b6a0d..cf4bd64 100644
--- a/src/gpu/vk/GrVkUtil.cpp
+++ b/src/gpu/vk/GrVkUtil.cpp
@@ -337,14 +337,33 @@
default:
return false;
}
+ SK_ABORT("Invalid format");
+ return false;
}
-bool GrVkFormatToCompressionType(VkFormat vkFormat, SkImage::CompressionType* compressionType) {
+GrCompression GrVkFormat2Compression(VkFormat vkFormat) {
switch (vkFormat) {
case VK_FORMAT_ETC2_R8G8B8_UNORM_BLOCK:
- *compressionType = SkImage::kETC1_CompressionType;
- return true;
+ return GrCompression::kETC1;
default:
- return false;
+ return GrCompression::kNone;
}
+ SK_ABORT("Invalid format");
+ return GrCompression::kNone;
}
+
+size_t GrVkFormatCompressedDataSize(VkFormat vkFormat, int width, int height) {
+ SkASSERT(GrVkFormatIsCompressed(vkFormat));
+
+ switch (vkFormat) {
+ case VK_FORMAT_ETC2_R8G8B8_UNORM_BLOCK:
+ return GrETC1CompressedDataSize(width, height);
+ default:
+ SK_ABORT("Unknown compressed format");
+ return 4 * width * height;
+ }
+
+ SK_ABORT("Unknown compressed format");
+ return 4 * width * height;
+}
+
diff --git a/src/gpu/vk/GrVkUtil.h b/src/gpu/vk/GrVkUtil.h
index 6c77c74..7d2b241 100644
--- a/src/gpu/vk/GrVkUtil.h
+++ b/src/gpu/vk/GrVkUtil.h
@@ -68,8 +68,13 @@
bool GrVkFormatIsCompressed(VkFormat);
/**
- * Maps a vk format into the CompressionType enum if applicable.
+ * Returns the data size for the given compressed format
*/
-bool GrVkFormatToCompressionType(VkFormat vkFormat, SkImage::CompressionType* compressionType);
+size_t GrVkFormatCompressedDataSize(VkFormat, int width, int height);
+
+/**
+ * Maps a vk format into the GrCompressed enum.
+ */
+GrCompression GrVkFormat2Compression(VkFormat);
#endif
diff --git a/src/image/SkImage_Gpu.cpp b/src/image/SkImage_Gpu.cpp
index d4f9710..6fefd63 100644
--- a/src/image/SkImage_Gpu.cpp
+++ b/src/image/SkImage_Gpu.cpp
@@ -175,9 +175,23 @@
sk_sp<SkImage> SkImage::MakeFromCompressed(GrContext* context, sk_sp<SkData> data,
int width, int height, CompressionType type) {
+ // create the backing texture
+ GrSurfaceDesc desc;
+ desc.fFlags = kNone_GrSurfaceFlags;
+ desc.fWidth = width;
+ desc.fHeight = height;
+ switch (type) {
+ case kETC1_CompressionType:
+ desc.fConfig = kRGB_ETC1_GrPixelConfig;
+ break;
+ default:
+ desc.fConfig = kUnknown_GrPixelConfig;
+ break;
+ }
+ desc.fSampleCnt = 1;
+
GrProxyProvider* proxyProvider = context->priv().proxyProvider();
- sk_sp<GrTextureProxy> proxy = proxyProvider->createCompressedTextureProxy(
- width, height, SkBudgeted::kYes, type, std::move(data));
+ sk_sp<GrTextureProxy> proxy = proxyProvider->createProxy(std::move(data), desc);
if (!proxy) {
return nullptr;