Create a GrGpu::createBackendTexture choke point
This also makes createBackendTexture take SkPixmaps (instead of a raw pixels pointer)
Change-Id: I5d8a5a58fa7b15862fbf46a3c232cb6ea7f58976
Reviewed-on: https://skia-review.googlesource.com/c/skia/+/243158
Reviewed-by: Jim Van Verth <jvanverth@google.com>
Commit-Queue: Robert Phillips <robertphillips@google.com>
diff --git a/src/gpu/GrContextPriv.cpp b/src/gpu/GrContextPriv.cpp
index 511639a..db64798 100644
--- a/src/gpu/GrContextPriv.cpp
+++ b/src/gpu/GrContextPriv.cpp
@@ -393,6 +393,5 @@
// TODO: propagate the array of pixmaps interface to GrGpu
return gpu->createBackendTexture(baseWidth, baseHeight, backendFormat,
GrMipMapped::kNo, // TODO: use real mipmap setting here
- renderable, srcData[0].addr(), srcData[0].rowBytes(),
- nullptr, isProtected);
+ renderable, srcData, numLevels, nullptr, isProtected);
}
diff --git a/src/gpu/GrGpu.cpp b/src/gpu/GrGpu.cpp
index efc000f..0262554 100644
--- a/src/gpu/GrGpu.cpp
+++ b/src/gpu/GrGpu.cpp
@@ -12,6 +12,7 @@
#include "include/gpu/GrBackendSurface.h"
#include "include/gpu/GrContext.h"
#include "src/core/SkMathPriv.h"
+#include "src/core/SkMipMap.h"
#include "src/gpu/GrAuditTrail.h"
#include "src/gpu/GrCaps.h"
#include "src/gpu/GrContextPriv.h"
@@ -701,6 +702,73 @@
keys->push_back(SkString("shader_compilations")); values->push_back(fShaderCompilations);
}
-#endif
+#endif // GR_GPU_STATS
+#endif // GR_TEST_UTILS
-#endif
+
+bool GrGpu::MipMapsAreCorrect(int baseWidth, int baseHeight, GrMipMapped mipMapped,
+ const SkPixmap srcData[], int numMipLevels) {
+ if (!srcData) {
+ return true;
+ }
+
+ if (baseWidth != srcData[0].width() || baseHeight != srcData[0].height()) {
+ return false;
+ }
+
+ if (mipMapped == GrMipMapped::kYes) {
+ if (numMipLevels != SkMipMap::ComputeLevelCount(baseWidth, baseHeight) + 1) {
+ return false;
+ }
+
+ SkColorType colorType = srcData[0].colorType();
+
+ int currentWidth = baseWidth;
+ int currentHeight = baseHeight;
+ for (int i = 1; i < numMipLevels; ++i) {
+ currentWidth = SkTMax(1, currentWidth / 2);
+ currentHeight = SkTMax(1, currentHeight / 2);
+
+ if (srcData[i].colorType() != colorType) { // all levels must have same colorType
+ return false;
+ }
+
+ if (srcData[i].width() != currentWidth || srcData[i].height() != currentHeight) {
+ return false;
+ }
+ }
+ } else if (numMipLevels != 1) {
+ return false;
+ }
+
+ return true;
+}
+
+GrBackendTexture GrGpu::createBackendTexture(int w, int h, const GrBackendFormat& format,
+ GrMipMapped mipMapped, GrRenderable renderable,
+ const SkPixmap srcData[], int numMipLevels,
+ const SkColor4f* color, GrProtected isProtected) {
+ const GrCaps* caps = this->caps();
+
+ if (!format.isValid()) {
+ return {};
+ }
+
+ SkASSERT(!caps->isFormatCompressed(format) || !srcData); // There is no ETC1 SkColorType
+
+ if (w < 1 || w > caps->maxTextureSize() || h < 1 || h > caps->maxTextureSize()) {
+ return {};
+ }
+
+ // TODO: maybe just ignore the mipMapped parameter in this case
+ if (mipMapped == GrMipMapped::kYes && !this->caps()->mipMapSupport()) {
+ return {};
+ }
+
+ if (!MipMapsAreCorrect(w, h, mipMapped, srcData, numMipLevels)) {
+ return {};
+ }
+
+ return this->onCreateBackendTexture(w, h, format, mipMapped, renderable,
+ srcData, numMipLevels, color, isProtected);
+}
diff --git a/src/gpu/GrGpu.h b/src/gpu/GrGpu.h
index 3ef00d5..3a4732b 100644
--- a/src/gpu/GrGpu.h
+++ b/src/gpu/GrGpu.h
@@ -451,15 +451,24 @@
/**
* Creates a texture directly in the backend API without wrapping it in a GrTexture.
* Must be matched with a call to deleteBackendTexture().
- * Right now, the color is ignored if pixel data is provided.
- * In the future, if neither a color nor pixels are provided then the backend texture
- * will be uninitialized.
+ *
+ * If srcData is provided it will be used to initialize the texture. If srcData is
+ * not provided but a color is then it is used to initialize the texture. If neither
+ * srcData nor a color is provided then the texture is left uninitialized.
+ *
+ * If srcData is provided and mipMapped is kYes then data for all the miplevels must be
+ * provided (or the method will fail). If only a color is provided and mipMapped is kYes
+ * then all the mip levels will be allocated and initialized to the color. If neither
+ * srcData nor a color is provided but mipMapped is kYes then the mip levels will be allocated
+ * but left uninitialized.
+ *
+ * Note: if more than one pixmap is provided (i.e., for mipmap levels) they must all share
+ * the same SkColorType.
*/
- virtual GrBackendTexture createBackendTexture(int w, int h, const GrBackendFormat&,
- GrMipMapped, GrRenderable,
- const void* pixels, size_t rowBytes,
- const SkColor4f* color,
- GrProtected isProtected) = 0;
+ GrBackendTexture createBackendTexture(int w, int h, const GrBackendFormat&,
+ GrMipMapped, GrRenderable,
+ const SkPixmap srcData[], int numMipLevels,
+ const SkColor4f* color, GrProtected isProtected);
/**
* Frees a texture created by createBackendTexture(). If ownership of the backend
@@ -534,6 +543,9 @@
virtual void storeVkPipelineCacheData() {}
protected:
+ static bool MipMapsAreCorrect(int baseWidth, int baseHeight, GrMipMapped,
+ const SkPixmap srcData[], int numMipLevels);
+
// Handles cases where a surface will be updated without a call to flushRenderTarget.
void didWriteToSurface(GrSurface* surface, GrSurfaceOrigin origin, const SkIRect* bounds,
uint32_t mipLevels = 1) const;
@@ -544,6 +556,11 @@
sk_sp<const GrCaps> fCaps;
private:
+ virtual GrBackendTexture onCreateBackendTexture(int w, int h, const GrBackendFormat&,
+ GrMipMapped, GrRenderable,
+ const SkPixmap srcData[], int numMipLevels,
+ const SkColor4f* color, GrProtected) = 0;
+
// called when the 3D context state is unknown. Subclass should emit any
// assumed 3D context state and dirty any state cache.
virtual void onResetContext(uint32_t resetBits) = 0;
diff --git a/src/gpu/gl/GrGLGpu.cpp b/src/gpu/gl/GrGLGpu.cpp
index 89c1fca..8014d3b 100644
--- a/src/gpu/gl/GrGLGpu.cpp
+++ b/src/gpu/gl/GrGLGpu.cpp
@@ -3526,15 +3526,22 @@
SkUNREACHABLE;
}
-GrBackendTexture GrGLGpu::createBackendTexture(int w, int h,
- const GrBackendFormat& format,
- GrMipMapped mipMapped,
- GrRenderable renderable,
- const void* srcPixels, size_t rowBytes,
- const SkColor4f* color,
- GrProtected isProtected) {
+GrBackendTexture GrGLGpu::onCreateBackendTexture(int w, int h,
+ const GrBackendFormat& format,
+ GrMipMapped mipMapped,
+ GrRenderable renderable,
+ const SkPixmap srcData[], int numMipLevels,
+ const SkColor4f* color,
+ GrProtected isProtected) {
this->handleDirtyContext();
+ SkDEBUGCODE(const GrCaps* caps = this->caps();)
+
+ // GrGpu::createBackendTexture should've ensured these conditions
+ SkASSERT(w >= 1 && w <= caps->maxTextureSize() && h >= 1 && h <= caps->maxTextureSize());
+ SkASSERT(GrGpu::MipMapsAreCorrect(w, h, mipMapped, srcData, numMipLevels));
+ SkASSERT(mipMapped == GrMipMapped::kNo || caps->mipMapSupport());
+
GrGLFormat glFormat = format.asGLFormat();
if (glFormat == GrGLFormat::kUnknown) {
return GrBackendTexture(); // invalid
@@ -3548,21 +3555,13 @@
auto textureColorType = GrPixelConfigToColorType(config);
+ // TODO: move the texturability check up to GrGpu::createBackendTexture and just assert here
if (!this->caps()->isFormatTexturableAndUploadable(textureColorType, format)) {
return GrBackendTexture(); // invalid
}
- if (w < 1 || w > this->caps()->maxTextureSize() ||
- h < 1 || h > this->caps()->maxTextureSize()) {
- return GrBackendTexture(); // invalid
- }
-
// Currently we don't support uploading pixel data when mipped.
- if (srcPixels && GrMipMapped::kYes == mipMapped) {
- return GrBackendTexture(); // invalid
- }
-
- if (mipMapped == GrMipMapped::kYes && !this->caps()->mipMapSupport()) {
+ if (srcData && GrMipMapped::kYes == mipMapped) {
return GrBackendTexture(); // invalid
}
@@ -3573,19 +3572,19 @@
SkAutoMalloc pixelStorage;
SkImage::CompressionType compressionType;
if (GrGLFormatToCompressionType(glFormat, &compressionType)) {
- // Compressed textures currently must be non-MIP mapped and have initial data.
+ SkASSERT(!srcData); // there is no ETC1 SkColorType
+ if (!color) {
+ return GrBackendTexture();
+ }
+
+ // Compressed textures currently must be non-MIP mapped and have an initial color.
if (mipMapped == GrMipMapped::kYes) {
return GrBackendTexture();
}
- if (!srcPixels) {
- if (!color) {
- return GrBackendTexture();
- }
- SkASSERT(0 == rowBytes);
- size_t size = GrCompressedDataSize(compressionType, w, h);
- srcPixels = pixelStorage.reset(size);
- GrFillInCompressedData(compressionType, w, h, (char*)srcPixels, *color);
- }
+ size_t size = GrCompressedDataSize(compressionType, w, h);
+ const void* srcPixels = pixelStorage.reset(size);
+ GrFillInCompressedData(compressionType, w, h, (char*)srcPixels, *color);
+
info.fID = this->createCompressedTexture2D(
{w, h}, glFormat, compressionType, &initialState, srcPixels);
if (!info.fID) {
@@ -3594,9 +3593,9 @@
info.fFormat = GrGLFormatToEnum(glFormat);
info.fTarget = GR_GL_TEXTURE_2D;
} else {
- if (srcPixels) {
+ if (srcData) {
texels.append(1);
- texels[0] = {srcPixels, rowBytes};
+ texels[0] = { srcData->addr(), srcData->rowBytes() };
} else if (color) {
int mipLevelCount = 1;
if (GrMipMapped::kYes == mipMapped) {
diff --git a/src/gpu/gl/GrGLGpu.h b/src/gpu/gl/GrGLGpu.h
index 908ba5d..1510fdf 100644
--- a/src/gpu/gl/GrGLGpu.h
+++ b/src/gpu/gl/GrGLGpu.h
@@ -129,11 +129,6 @@
GrStencilAttachment* createStencilAttachmentForRenderTarget(
const GrRenderTarget* rt, int width, int height, int numStencilSamples) override;
- GrBackendTexture createBackendTexture(int w, int h, const GrBackendFormat&,
- GrMipMapped, GrRenderable,
- const void* pixels, size_t rowBytes,
- const SkColor4f* color,
- GrProtected isProtected) override;
void deleteBackendTexture(const GrBackendTexture&) override;
bool precompileShader(const SkData& key, const SkData& data) override {
@@ -181,6 +176,11 @@
GrGLGpu(std::unique_ptr<GrGLContext>, GrContext*);
// GrGpu overrides
+ GrBackendTexture onCreateBackendTexture(int w, int h, const GrBackendFormat&,
+ GrMipMapped, GrRenderable,
+ const SkPixmap srcData[], int numMipLevels,
+ const SkColor4f* color, GrProtected) override;
+
void onResetContext(uint32_t resetBits) override;
void onResetTextureBindings() override;
diff --git a/src/gpu/mock/GrMockGpu.cpp b/src/gpu/mock/GrMockGpu.cpp
index bc91c75..da36226 100644
--- a/src/gpu/mock/GrMockGpu.cpp
+++ b/src/gpu/mock/GrMockGpu.cpp
@@ -258,14 +258,14 @@
return new GrMockStencilAttachment(this, width, height, kBits, rt->numSamples());
}
-GrBackendTexture GrMockGpu::createBackendTexture(int w, int h,
- const GrBackendFormat& format,
- GrMipMapped mipMapped,
- GrRenderable /* renderable */,
- const void* /* pixels */,
- size_t /* rowBytes */,
- const SkColor4f* /* color */,
- GrProtected /* isProtected */) {
+GrBackendTexture GrMockGpu::onCreateBackendTexture(int w, int h,
+ const GrBackendFormat& format,
+ GrMipMapped mipMapped,
+ GrRenderable /* renderable */,
+ const SkPixmap /*srcData*/[],
+ int /*numMipLevels*/,
+ const SkColor4f* /* color */,
+ GrProtected /* isProtected */) {
auto colorType = format.asMockColorType();
if (!this->caps()->isFormatTexturable(format)) {
return GrBackendTexture(); // invalid
diff --git a/src/gpu/mock/GrMockGpu.h b/src/gpu/mock/GrMockGpu.h
index 7fec665..5731069 100644
--- a/src/gpu/mock/GrMockGpu.h
+++ b/src/gpu/mock/GrMockGpu.h
@@ -129,10 +129,10 @@
GrStencilAttachment* createStencilAttachmentForRenderTarget(
const GrRenderTarget*, int width, int height, int numStencilSamples) override;
- GrBackendTexture createBackendTexture(int w, int h, const GrBackendFormat&,
- GrMipMapped, GrRenderable,
- const void* pixels, size_t rowBytes,
- const SkColor4f* color, GrProtected isProtected) override;
+ GrBackendTexture onCreateBackendTexture(int w, int h, const GrBackendFormat&,
+ GrMipMapped, GrRenderable,
+ const SkPixmap srcData[], int numMipLevels,
+ const SkColor4f* color, GrProtected) override;
void deleteBackendTexture(const GrBackendTexture&) override;
#if GR_TEST_UTILS
diff --git a/src/gpu/mtl/GrMtlGpu.h b/src/gpu/mtl/GrMtlGpu.h
index c574d4d..48ac005 100644
--- a/src/gpu/mtl/GrMtlGpu.h
+++ b/src/gpu/mtl/GrMtlGpu.h
@@ -56,12 +56,6 @@
// command buffer to finish before creating a new buffer and returning.
void submitCommandBuffer(SyncQueue sync);
- GrBackendTexture createBackendTexture(int w, int h, const GrBackendFormat&,
- GrMipMapped, GrRenderable,
- const void* pixels, size_t rowBytes,
- const SkColor4f* color,
- GrProtected isProtected) override;
-
void deleteBackendTexture(const GrBackendTexture&) override;
#if GR_TEST_UTILS
@@ -133,6 +127,11 @@
void xferBarrier(GrRenderTarget*, GrXferBarrierType) override {}
+ GrBackendTexture onCreateBackendTexture(int w, int h, const GrBackendFormat&,
+ GrMipMapped, GrRenderable,
+ const SkPixmap srcData[], int numMipLevels,
+ const SkColor4f* color, GrProtected) override;
+
sk_sp<GrTexture> onCreateTexture(const GrSurfaceDesc& desc,
const GrBackendFormat& format,
GrRenderable,
@@ -224,9 +223,9 @@
bool createMtlTextureForBackendSurface(MTLPixelFormat,
int w, int h, bool texturable,
- bool renderable, GrMipMapped mipMapped,
- const void* srcData, size_t srcRowBytes,
- const SkColor4f* color, GrMtlTextureInfo* info);
+ bool renderable, GrMipMapped,
+ const SkPixmap srcData[], int numMipLevels,
+ const SkColor4f* color, GrMtlTextureInfo*);
sk_sp<GrMtlCaps> fMtlCaps;
diff --git a/src/gpu/mtl/GrMtlGpu.mm b/src/gpu/mtl/GrMtlGpu.mm
index 553f2f0..fe91d8c 100644
--- a/src/gpu/mtl/GrMtlGpu.mm
+++ b/src/gpu/mtl/GrMtlGpu.mm
@@ -715,12 +715,12 @@
bool GrMtlGpu::createMtlTextureForBackendSurface(MTLPixelFormat format,
int w, int h, bool texturable,
bool renderable, GrMipMapped mipMapped,
- const void* srcData, size_t srcRowBytes,
+ const SkPixmap srcData[], int numMipLevels,
const SkColor4f* color, GrMtlTextureInfo* info) {
SkASSERT(texturable || renderable);
if (!texturable) {
SkASSERT(GrMipMapped::kNo == mipMapped);
- SkASSERT(!srcData);
+ SkASSERT(!srcData && !numMipLevels);
}
if (texturable && !fMtlCaps->isFormatTexturable(format)) {
@@ -738,7 +738,10 @@
}
int mipLevelCount = 1;
- if (GrMipMapped::kYes == mipMapped) {
+ if (srcData) {
+ SkASSERT(numMipLevels > 0);
+ mipLevelCount = numMipLevels;
+ } else if (GrMipMapped::kYes == mipMapped) {
mipLevelCount = SkMipMap::ComputeLevelCount(w, h) + 1;
}
@@ -797,21 +800,16 @@
// Fill buffer with data
if (srcData) {
- if (isCompressed) {
- memcpy(buffer, srcData, combinedBufferSize);
- } else {
- const size_t trimRowBytes = w * bytesPerPixel;
+ SkASSERT(!isCompressed); // There is no ETC1 SkColorType
- // TODO: support mipmapping
- SkASSERT(1 == mipLevelCount);
- if (!srcRowBytes) {
- srcRowBytes = trimRowBytes;
- }
+ const size_t trimRowBytes = w * bytesPerPixel;
- // copy data into the buffer, skipping the trailing bytes
- const char* src = (const char*) srcData;
- SkRectMemcpy(buffer, trimRowBytes, src, srcRowBytes, trimRowBytes, h);
- }
+ // TODO: support mipmapping
+ SkASSERT(1 == mipLevelCount);
+
+ // copy data into the buffer, skipping the trailing bytes
+ const char* src = (const char*) srcData->addr();
+ SkRectMemcpy(buffer, trimRowBytes, src, srcData->rowBytes(), trimRowBytes, h);
} else if (color) {
if (isCompressed) {
GrFillInCompressedData(compressionType, w, h, buffer, *color);
@@ -869,22 +867,26 @@
return true;
}
-GrBackendTexture GrMtlGpu::createBackendTexture(int w, int h,
- const GrBackendFormat& format,
- GrMipMapped mipMapped,
- GrRenderable renderable,
- const void* pixels, size_t rowBytes,
- const SkColor4f* color, GrProtected isProtected) {
- if (w > this->caps()->maxTextureSize() || h > this->caps()->maxTextureSize()) {
- return GrBackendTexture();
- }
+GrBackendTexture GrMtlGpu::onCreateBackendTexture(int w, int h,
+ const GrBackendFormat& format,
+ GrMipMapped mipMapped,
+ GrRenderable renderable,
+ const SkPixmap srcData[], int numMipLevels,
+ const SkColor4f* color,
+ GrProtected isProtected) {
+ SkDEBUGCODE(const GrMtlCaps& caps = this->mtlCaps();)
+
+ // GrGpu::createBackendTexture should've ensured these conditions
+ SkASSERT(w >= 1 && w <= caps.maxTextureSize() && h >= 1 && h <= caps.maxTextureSize());
+ SkASSERT(GrGpu::MipMapsAreCorrect(w, h, mipMapped, srcData, numMipLevels));
+ SkASSERT(mipMapped == GrMipMapped::kNo || caps.mipMapSupport());
const MTLPixelFormat mtlFormat = GrBackendFormatAsMTLPixelFormat(format);
GrMtlTextureInfo info;
if (!this->createMtlTextureForBackendSurface(mtlFormat,
w, h, true,
GrRenderable::kYes == renderable, mipMapped,
- pixels, rowBytes, color, &info)) {
+ srcData, numMipLevels, color, &info)) {
return {};
}
diff --git a/src/gpu/vk/GrVkGpu.cpp b/src/gpu/vk/GrVkGpu.cpp
index 7b68e4d..1c1fa2f 100644
--- a/src/gpu/vk/GrVkGpu.cpp
+++ b/src/gpu/vk/GrVkGpu.cpp
@@ -1531,13 +1531,13 @@
bool GrVkGpu::createVkImageForBackendSurface(VkFormat vkFormat, int w, int h, bool texturable,
bool renderable, GrMipMapped mipMapped,
- const void* srcData, size_t srcRowBytes,
+ const SkPixmap srcData[], int numMipLevels,
const SkColor4f* color, GrVkImageInfo* info,
GrProtected isProtected) {
SkASSERT(texturable || renderable);
if (!texturable) {
SkASSERT(GrMipMapped::kNo == mipMapped);
- SkASSERT(!srcData);
+ SkASSERT(!srcData && !numMipLevels);
}
if (fProtectedContext != isProtected) {
@@ -1568,9 +1568,12 @@
}
// Figure out the number of mip levels.
- uint32_t mipLevels = 1;
- if (GrMipMapped::kYes == mipMapped) {
- mipLevels = SkMipMap::ComputeLevelCount(w, h) + 1;
+ uint32_t mipLevelCount = 1;
+ if (srcData) {
+ SkASSERT(numMipLevels > 0);
+ mipLevelCount = numMipLevels;
+ } else if (GrMipMapped::kYes == mipMapped) {
+ mipLevelCount = SkMipMap::ComputeLevelCount(w, h) + 1;
}
GrVkImage::ImageDesc imageDesc;
@@ -1578,7 +1581,7 @@
imageDesc.fFormat = vkFormat;
imageDesc.fWidth = w;
imageDesc.fHeight = h;
- imageDesc.fLevels = mipLevels;
+ imageDesc.fLevels = mipLevelCount;
imageDesc.fSamples = 1;
imageDesc.fImageTiling = VK_IMAGE_TILING_OPTIMAL;
imageDesc.fUsageFlags = usageFlags;
@@ -1627,25 +1630,32 @@
// Set image layout and add barrier
set_image_layout(this->vkInterface(), cmdBuffer, info, VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL,
- mipLevels, VK_ACCESS_TRANSFER_WRITE_BIT, VK_PIPELINE_STAGE_TRANSFER_BIT);
+ mipLevelCount, VK_ACCESS_TRANSFER_WRITE_BIT, VK_PIPELINE_STAGE_TRANSFER_BIT);
+
+ const void* srcPixels = nullptr;
+ size_t srcRowBytes = 0;
+ if (srcData) {
+ srcPixels = srcData->addr();
+ srcRowBytes = srcData->rowBytes();
+ }
// TODO: Lift this to GrContext level.
SkImage::CompressionType compressionType;
bool isCompressed = GrVkFormatToCompressionType(vkFormat, &compressionType);
std::unique_ptr<char[]> tempData;
- if (isCompressed && !srcData) {
- SkASSERT(color);
+ if (isCompressed) {
+ SkASSERT(!srcData && color);
size_t size = GrCompressedDataSize(compressionType, w, h);
tempData.reset(new char[size]);
GrFillInCompressedData(compressionType, w, h, tempData.get(), *color);
- srcData = tempData.get();
+ srcPixels = tempData.get();
}
- if (srcData) {
+ if (srcPixels) {
size_t bytesPerPixel = GrVkBytesPerFormat(vkFormat);
SkASSERT(w && h);
- SkTArray<size_t> individualMipOffsets(mipLevels);
+ SkTArray<size_t> individualMipOffsets(mipLevelCount);
SkImage::CompressionType compressionType;
bool isCompressed = GrVkFormatToCompressionType(vkFormat, &compressionType);
@@ -1660,7 +1670,8 @@
individualMipOffsets.push_back(0);
} else {
combinedBufferSize = GrComputeTightCombinedBufferSize(bytesPerPixel, w, h,
- &individualMipOffsets, mipLevels);
+ &individualMipOffsets,
+ mipLevelCount);
}
VkBufferCreateInfo bufInfo;
@@ -1692,10 +1703,10 @@
bool result;
if (isCompressed) {
- result = copy_compressed_src_data(this, bufferAlloc, compressionType, w, h, srcData);
+ result = copy_compressed_src_data(this, bufferAlloc, compressionType, w, h, srcPixels);
} else {
- SkASSERT(1 == mipLevels);
- result = copy_src_data(this, bufferAlloc, vkFormat, w, h, srcData, srcRowBytes);
+ SkASSERT(1 == mipLevelCount);
+ result = copy_src_data(this, bufferAlloc, vkFormat, w, h, srcPixels, srcRowBytes);
}
if (!result) {
GrVkImage::DestroyImageInfo(this, info);
@@ -1706,11 +1717,11 @@
return false;
}
- SkTArray<VkBufferImageCopy> regions(mipLevels);
+ SkTArray<VkBufferImageCopy> regions(mipLevelCount);
int currentWidth = w;
int currentHeight = h;
- for (uint32_t currentMipLevel = 0; currentMipLevel < mipLevels; currentMipLevel++) {
+ for (uint32_t currentMipLevel = 0; currentMipLevel < mipLevelCount; currentMipLevel++) {
// Submit copy command
VkBufferImageCopy& region = regions.push_back();
memset(®ion, 0, sizeof(VkBufferImageCopy));
@@ -1740,18 +1751,18 @@
range.baseArrayLayer = 0;
range.baseMipLevel = 0;
range.layerCount = 1;
- range.levelCount = mipLevels;
+ range.levelCount = mipLevelCount;
VK_CALL(CmdClearColorImage(cmdBuffer, info->fImage, VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL,
&vkColor, 1, &range));
}
- if (!srcData && renderable) {
+ if (!srcPixels && renderable) {
SkASSERT(color);
// Change image layout to color-attachment-optimal since if we use this texture as a
// borrowed texture within Ganesh we are probably going to render to it
set_image_layout(this->vkInterface(), cmdBuffer, info,
- VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL, mipLevels,
+ VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL, mipLevelCount,
VK_ACCESS_COLOR_ATTACHMENT_READ_BIT |
VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT,
VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT);
@@ -1759,7 +1770,7 @@
// Change image layout to shader read since if we use this texture as a borrowed
// texture within Ganesh we require that its layout be set to that
set_image_layout(this->vkInterface(), cmdBuffer, info,
- VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL, mipLevels,
+ VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL, mipLevelCount,
VK_ACCESS_SHADER_READ_BIT, VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT);
}
@@ -1825,20 +1836,22 @@
return true;
}
-GrBackendTexture GrVkGpu::createBackendTexture(int w, int h,
- const GrBackendFormat& format,
- GrMipMapped mipMapped,
- GrRenderable renderable,
- const void* srcData, size_t rowBytes,
- const SkColor4f* color, GrProtected isProtected) {
- const GrVkCaps& caps = this->vkCaps();
+GrBackendTexture GrVkGpu::onCreateBackendTexture(int w, int h,
+ const GrBackendFormat& format,
+ GrMipMapped mipMapped,
+ GrRenderable renderable,
+ const SkPixmap srcData[], int numMipLevels,
+ const SkColor4f* color, GrProtected isProtected) {
this->handleDirtyContext();
- if (fProtectedContext != isProtected) {
- return GrBackendTexture();
- }
+ const GrVkCaps& caps = this->vkCaps();
- if (w > caps.maxTextureSize() || h > caps.maxTextureSize()) {
+ // GrGpu::createBackendTexture should've ensured these conditions
+ SkASSERT(w >= 1 && w <= caps.maxTextureSize() && h >= 1 && h <= caps.maxTextureSize());
+ SkASSERT(GrGpu::MipMapsAreCorrect(w, h, mipMapped, srcData, numMipLevels));
+ SkASSERT(mipMapped == GrMipMapped::kNo || caps.mipMapSupport());
+
+ if (fProtectedContext != isProtected) {
return GrBackendTexture();
}
@@ -1848,6 +1861,7 @@
return GrBackendTexture();
}
+ // TODO: move the texturability check up to GrGpu::createBackendTexture and just assert here
if (!caps.isVkFormatTexturable(vkFormat)) {
SkDebugf("Config is not texturable\n");
return GrBackendTexture();
@@ -1860,8 +1874,8 @@
GrVkImageInfo info;
if (!this->createVkImageForBackendSurface(vkFormat, w, h, true,
- GrRenderable::kYes == renderable, mipMapped, srcData,
- rowBytes, color, &info, isProtected)) {
+ GrRenderable::kYes == renderable, mipMapped,
+ srcData, numMipLevels, color, &info, isProtected)) {
SkDebugf("Failed to create testing only image\n");
return GrBackendTexture();
}
diff --git a/src/gpu/vk/GrVkGpu.h b/src/gpu/vk/GrVkGpu.h
index 4863445..35d1a14 100644
--- a/src/gpu/vk/GrVkGpu.h
+++ b/src/gpu/vk/GrVkGpu.h
@@ -79,11 +79,6 @@
void xferBarrier(GrRenderTarget*, GrXferBarrierType) override {}
- GrBackendTexture createBackendTexture(int w, int h, const GrBackendFormat&,
- GrMipMapped, GrRenderable,
- const void* pixels, size_t rowBytes,
- const SkColor4f* color,
- GrProtected isProtected) override;
void deleteBackendTexture(const GrBackendTexture&) override;
#if GR_TEST_UTILS
bool isTestingOnlyBackendTexture(const GrBackendTexture&) const override;
@@ -190,6 +185,10 @@
void destroyResources();
+ GrBackendTexture onCreateBackendTexture(int w, int h, const GrBackendFormat&,
+ GrMipMapped, GrRenderable,
+ const SkPixmap srcData[], int numMipLevels,
+ const SkColor4f* color, GrProtected) override;
sk_sp<GrTexture> onCreateTexture(const GrSurfaceDesc&,
const GrBackendFormat& format,
GrRenderable,
@@ -275,9 +274,10 @@
const SkIPoint& dstPoint);
bool createVkImageForBackendSurface(VkFormat vkFormat, int w, int h, bool texturable,
- bool renderable, GrMipMapped mipMapped, const void* srcData,
- size_t srcRowBytes, const SkColor4f* color,
- GrVkImageInfo* info, GrProtected isProtected);
+ bool renderable, GrMipMapped mipMapped,
+ const SkPixmap srcData[], int numMipLevels,
+ const SkColor4f* color, GrVkImageInfo* info,
+ GrProtected isProtected);
sk_sp<const GrVkInterface> fInterface;
sk_sp<GrVkMemoryAllocator> fMemoryAllocator;