aboutsummaryrefslogtreecommitdiffhomepage
diff options
context:
space:
mode:
-rw-r--r--gm/imagefromyuvtextures.cpp23
-rw-r--r--include/core/SkImage.h23
-rw-r--r--include/private/GrSurfaceProxy.h3
-rw-r--r--src/gpu/GrGpu.h14
-rw-r--r--src/gpu/GrSurfaceProxy.cpp2
-rw-r--r--src/gpu/gl/GrGLGpu.cpp72
-rw-r--r--src/gpu/gl/GrGLGpu.h6
-rw-r--r--src/gpu/mock/GrMockGpu.cpp15
-rw-r--r--src/gpu/mock/GrMockGpu.h4
-rw-r--r--src/gpu/mtl/GrMtlGpu.h7
-rw-r--r--src/gpu/vk/GrVkGpu.cpp347
-rw-r--r--src/gpu/vk/GrVkGpu.h6
-rw-r--r--src/image/SkImage.cpp8
-rw-r--r--src/image/SkImage_Gpu.cpp114
14 files changed, 126 insertions, 518 deletions
diff --git a/gm/imagefromyuvtextures.cpp b/gm/imagefromyuvtextures.cpp
index 7150669607..72100c2a56 100644
--- a/gm/imagefromyuvtextures.cpp
+++ b/gm/imagefromyuvtextures.cpp
@@ -93,7 +93,7 @@ protected:
fRGBImage = SkImage::MakeRasterCopy(SkPixmap(rgbBmp.info(), rgbColors, rgbBmp.rowBytes()));
}
- void createYUVTextures(GrContext* context, GrBackendObject yuvHandles[3]) {
+ void createYUVTextures(GrContext* context, GrBackendTexture yuvTextures[3]) {
GrGpu* gpu = context->getGpu();
if (!gpu) {
return;
@@ -101,15 +101,16 @@ protected:
for (int i = 0; i < 3; ++i) {
SkASSERT(fYUVBmps[i].width() == SkToInt(fYUVBmps[i].rowBytes()));
- yuvHandles[i] = gpu->createTestingOnlyBackendObject(fYUVBmps[i].getPixels(),
- fYUVBmps[i].width(),
- fYUVBmps[i].height(),
- kAlpha_8_GrPixelConfig);
+ yuvTextures[i] = gpu->createTestingOnlyBackendTexture(fYUVBmps[i].getPixels(),
+ fYUVBmps[i].width(),
+ fYUVBmps[i].height(),
+ kAlpha_8_GrPixelConfig,
+ false, GrMipMapped::kNo);
}
context->resetContext();
}
- void deleteYUVTextures(GrContext* context, const GrBackendObject yuvHandles[3]) {
+ void deleteYUVTextures(GrContext* context, GrBackendTexture yuvTextures[3]) {
GrGpu* gpu = context->getGpu();
if (!gpu) {
@@ -117,7 +118,7 @@ protected:
}
for (int i = 0; i < 3; ++i) {
- gpu->deleteTestingOnlyBackendObject(yuvHandles[i]);
+ gpu->deleteTestingOnlyBackendTexture(&yuvTextures[i]);
}
context->resetContext();
@@ -141,13 +142,13 @@ protected:
SkTArray<sk_sp<SkImage>> images;
images.push_back(fRGBImage);
for (int space = kJPEG_SkYUVColorSpace; space <= kLastEnum_SkYUVColorSpace; ++space) {
- GrBackendObject yuvHandles[3];
- this->createYUVTextures(context, yuvHandles);
+ GrBackendTexture yuvTextures[3];
+ this->createYUVTextures(context, yuvTextures);
images.push_back(SkImage::MakeFromYUVTexturesCopy(context,
static_cast<SkYUVColorSpace>(space),
- yuvHandles, sizes,
+ yuvTextures, sizes,
kTopLeft_GrSurfaceOrigin));
- this->deleteYUVTextures(context, yuvHandles);
+ this->deleteYUVTextures(context, yuvTextures);
}
for (int i = 0; i < images.count(); ++ i) {
SkScalar y = (i + 1) * kPad + i * fYUVBmps[0].height();
diff --git a/include/core/SkImage.h b/include/core/SkImage.h
index b2468e011e..454c5e4b7b 100644
--- a/include/core/SkImage.h
+++ b/include/core/SkImage.h
@@ -189,6 +189,29 @@ public:
GrSurfaceOrigin surfaceOrigin,
sk_sp<SkColorSpace> colorSpace = nullptr);
+ /**
+ * Create a new image by copying the pixels from the specified y, u, v textures. The data
+ * from the textures is immediately ingested into the image and the textures can be modified or
+ * deleted after the function returns. The image will have the dimensions of the y texture.
+ */
+ static sk_sp<SkImage> MakeFromYUVTexturesCopy(GrContext* context, SkYUVColorSpace yuvColorSpace,
+ const GrBackendTexture yuvTextureHandles[3],
+ const SkISize yuvSizes[3],
+ GrSurfaceOrigin surfaceOrigin,
+ sk_sp<SkColorSpace> colorSpace = nullptr);
+
+ /**
+ * Create a new image by copying the pixels from the specified y and uv textures. The data
+ * from the textures is immediately ingested into the image and the textures can be modified or
+ * deleted after the function returns. The image will have the dimensions of the y texture.
+ */
+ static sk_sp<SkImage> MakeFromNV12TexturesCopy(GrContext* context,
+ SkYUVColorSpace yuvColorSpace,
+ const GrBackendTexture nv12TextureHandles[2],
+ const SkISize nv12Sizes[2],
+ GrSurfaceOrigin surfaceOrigin,
+ sk_sp<SkColorSpace> colorSpace = nullptr);
+
enum class BitDepth {
kU8,
kF16,
diff --git a/include/private/GrSurfaceProxy.h b/include/private/GrSurfaceProxy.h
index 0e79a3f68b..493140b9dd 100644
--- a/include/private/GrSurfaceProxy.h
+++ b/include/private/GrSurfaceProxy.h
@@ -217,7 +217,8 @@ public:
const GrSurfaceDesc&, SkBudgeted,
const void* srcData, size_t rowBytes);
- static sk_sp<GrTextureProxy> MakeWrappedBackend(GrContext*, GrBackendTexture&, GrSurfaceOrigin);
+ static sk_sp<GrTextureProxy> MakeWrappedBackend(GrContext*, const GrBackendTexture&,
+ GrSurfaceOrigin);
using LazyInstantiateCallback = std::function<sk_sp<GrTexture>(GrResourceProvider*,
GrSurfaceOrigin* outOrigin)>;
diff --git a/src/gpu/GrGpu.h b/src/gpu/GrGpu.h
index c020158c9e..e68e683499 100644
--- a/src/gpu/GrGpu.h
+++ b/src/gpu/GrGpu.h
@@ -453,20 +453,6 @@ public:
/** Creates a texture directly in the backend API without wrapping it in a GrTexture. This is
only to be used for testing (particularly for testing the methods that import an externally
created texture into Skia. Must be matched with a call to deleteTestingOnlyTexture(). */
- virtual GrBackendObject createTestingOnlyBackendObject(
- void* pixels, int w, int h,
- GrPixelConfig config,
- bool isRenderTarget = false,
- GrMipMapped mipMapped = GrMipMapped::kNo) = 0;
- /** If ownership of the backend texture has been transferred pass true for abandonTexture. This
- will do any necessary cleanup of the handle without freeing the texture in the backend
- API. */
- virtual void deleteTestingOnlyBackendObject(GrBackendObject,
- bool abandonTexture = false) = 0;
-
- /** Creates a texture directly in the backend API without wrapping it in a GrTexture. This is
- only to be used for testing (particularly for testing the methods that import an externally
- created texture into Skia. Must be matched with a call to deleteTestingOnlyTexture(). */
virtual GrBackendTexture createTestingOnlyBackendTexture(
void* pixels, int w, int h,
GrPixelConfig config,
diff --git a/src/gpu/GrSurfaceProxy.cpp b/src/gpu/GrSurfaceProxy.cpp
index 2bcd923a62..8dd43deace 100644
--- a/src/gpu/GrSurfaceProxy.cpp
+++ b/src/gpu/GrSurfaceProxy.cpp
@@ -392,7 +392,7 @@ sk_sp<GrTextureProxy> GrSurfaceProxy::MakeDeferredMipMap(
}
sk_sp<GrTextureProxy> GrSurfaceProxy::MakeWrappedBackend(GrContext* context,
- GrBackendTexture& backendTex,
+ const GrBackendTexture& backendTex,
GrSurfaceOrigin origin) {
sk_sp<GrTexture> tex(context->resourceProvider()->wrapBackendTexture(backendTex));
return GrSurfaceProxy::MakeWrapped(std::move(tex), origin);
diff --git a/src/gpu/gl/GrGLGpu.cpp b/src/gpu/gl/GrGLGpu.cpp
index c114c6c2ed..95eb339db8 100644
--- a/src/gpu/gl/GrGLGpu.cpp
+++ b/src/gpu/gl/GrGLGpu.cpp
@@ -4387,78 +4387,6 @@ void GrGLGpu::xferBarrier(GrRenderTarget* rt, GrXferBarrierType type) {
}
}
-GrBackendObject GrGLGpu::createTestingOnlyBackendObject(void* pixels, int w, int h,
- GrPixelConfig config, bool /*isRT*/,
- GrMipMapped mipMapped) {
- if (!this->caps()->isConfigTexturable(config)) {
- return reinterpret_cast<GrBackendObject>(nullptr);
- }
-
- // Currently we don't support uploading pixel data when mipped.
- if (pixels && GrMipMapped::kYes == mipMapped) {
- return reinterpret_cast<GrBackendObject>(nullptr);
- }
-
- std::unique_ptr<GrGLTextureInfo> info = skstd::make_unique<GrGLTextureInfo>();
- info->fTarget = GR_GL_TEXTURE_2D;
- info->fID = 0;
- GL_CALL(GenTextures(1, &info->fID));
- GL_CALL(ActiveTexture(GR_GL_TEXTURE0));
- GL_CALL(PixelStorei(GR_GL_UNPACK_ALIGNMENT, 1));
- GL_CALL(BindTexture(info->fTarget, info->fID));
- fHWBoundTextureUniqueIDs[0].makeInvalid();
- GL_CALL(TexParameteri(info->fTarget, GR_GL_TEXTURE_MAG_FILTER, GR_GL_NEAREST));
- GL_CALL(TexParameteri(info->fTarget, GR_GL_TEXTURE_MIN_FILTER, GR_GL_NEAREST));
- GL_CALL(TexParameteri(info->fTarget, GR_GL_TEXTURE_WRAP_S, GR_GL_CLAMP_TO_EDGE));
- GL_CALL(TexParameteri(info->fTarget, GR_GL_TEXTURE_WRAP_T, GR_GL_CLAMP_TO_EDGE));
-
- GrGLenum internalFormat;
- GrGLenum externalFormat;
- GrGLenum externalType;
-
- if (!this->glCaps().getTexImageFormats(config, config, &internalFormat, &externalFormat,
- &externalType)) {
- return reinterpret_cast<GrBackendObject>(nullptr);
- }
-
- this->unbindCpuToGpuXferBuffer();
-
- // Figure out the number of mip levels.
- int mipLevels = 1;
- if (GrMipMapped::kYes == mipMapped) {
- mipLevels = SkMipMap::ComputeLevelCount(w, h) + 1;
- }
-
- size_t bpp = GrBytesPerPixel(config);
- size_t baseLayerSize = bpp * w * h;
- SkAutoMalloc defaultStorage(baseLayerSize);
- if (!pixels) {
- // Fill in the texture with all zeros so we don't have random garbage
- pixels = defaultStorage.get();
- memset(pixels, 0, baseLayerSize);
- }
-
- int width = w;
- int height = h;
- for (int i = 0; i < mipLevels; ++i) {
- GL_CALL(TexImage2D(info->fTarget, i, internalFormat, width, height, 0, externalFormat,
- externalType, pixels));
- width = SkTMax(1, width / 2);
- height = SkTMax(1, height / 2);
- }
-
- return reinterpret_cast<GrBackendObject>(info.release());
-}
-
-void GrGLGpu::deleteTestingOnlyBackendObject(GrBackendObject id, bool abandonTexture) {
- std::unique_ptr<const GrGLTextureInfo> info(reinterpret_cast<const GrGLTextureInfo*>(id));
- GrGLuint texID = info->fID;
-
- if (!abandonTexture) {
- GL_CALL(DeleteTextures(1, &texID));
- }
-}
-
GrBackendTexture GrGLGpu::createTestingOnlyBackendTexture(void* pixels, int w, int h,
GrPixelConfig config, bool /*isRT*/,
GrMipMapped mipMapped) {
diff --git a/src/gpu/gl/GrGLGpu.h b/src/gpu/gl/GrGLGpu.h
index 42897abc1c..5c059a0da1 100644
--- a/src/gpu/gl/GrGLGpu.h
+++ b/src/gpu/gl/GrGLGpu.h
@@ -161,12 +161,6 @@ public:
int width,
int height) override;
- GrBackendObject createTestingOnlyBackendObject(void* pixels, int w, int h,
- GrPixelConfig config,
- bool isRenderTarget,
- GrMipMapped mipMapped) override;
- void deleteTestingOnlyBackendObject(GrBackendObject, bool abandonTexture) override;
-
GrBackendTexture createTestingOnlyBackendTexture(void* pixels, int w, int h,
GrPixelConfig config,
bool isRenderTarget,
diff --git a/src/gpu/mock/GrMockGpu.cpp b/src/gpu/mock/GrMockGpu.cpp
index 40800198db..da6b21aea0 100644
--- a/src/gpu/mock/GrMockGpu.cpp
+++ b/src/gpu/mock/GrMockGpu.cpp
@@ -90,21 +90,6 @@ GrStencilAttachment* GrMockGpu::createStencilAttachmentForRenderTarget(const GrR
return new GrMockStencilAttachment(this, width, height, kBits, rt->numColorSamples());
}
-GrBackendObject GrMockGpu::createTestingOnlyBackendObject(void* pixels, int w, int h,
- GrPixelConfig config, bool isRT,
- GrMipMapped) {
- auto info = new GrMockTextureInfo;
- info->fID = NextExternalTextureID();
- fOutstandingTestingOnlyTextureIDs.add(info->fID);
- return reinterpret_cast<GrBackendObject>(info);
-}
-
-void GrMockGpu::deleteTestingOnlyBackendObject(GrBackendObject object, bool abandonTexture) {
- auto info = reinterpret_cast<const GrMockTextureInfo*>(object);
- fOutstandingTestingOnlyTextureIDs.remove(info->fID);
- delete info;
-}
-
GrBackendTexture GrMockGpu::createTestingOnlyBackendTexture(void* pixels, int w, int h,
GrPixelConfig config, bool isRT,
GrMipMapped) {
diff --git a/src/gpu/mock/GrMockGpu.h b/src/gpu/mock/GrMockGpu.h
index aaa465b9b6..4567505546 100644
--- a/src/gpu/mock/GrMockGpu.h
+++ b/src/gpu/mock/GrMockGpu.h
@@ -129,10 +129,6 @@ private:
int height) override;
void clearStencil(GrRenderTarget*, int clearValue) override {}
- GrBackendObject createTestingOnlyBackendObject(void* pixels, int w, int h, GrPixelConfig,
- bool isRT, GrMipMapped) override;
- void deleteTestingOnlyBackendObject(GrBackendObject, bool abandonTexture) override;
-
GrBackendTexture createTestingOnlyBackendTexture(void* pixels, int w, int h, GrPixelConfig,
bool isRT, GrMipMapped) override;
bool isTestingOnlyBackendTexture(const GrBackendTexture&) const override;
diff --git a/src/gpu/mtl/GrMtlGpu.h b/src/gpu/mtl/GrMtlGpu.h
index 6d30d1b2be..9c5ba8299a 100644
--- a/src/gpu/mtl/GrMtlGpu.h
+++ b/src/gpu/mtl/GrMtlGpu.h
@@ -141,13 +141,6 @@ private:
void clearStencil(GrRenderTarget* target, int clearValue) override {}
- GrBackendObject createTestingOnlyBackendObject(void* pixels, int w, int h,
- GrPixelConfig config, bool isRT,
- GrMipMapped) override {
- return 0;
- }
- void deleteTestingOnlyBackendObject(GrBackendObject, bool abandonTexture = false) override {}
-
GrBackendTexture createTestingOnlyBackendTexture(void* pixels, int w, int h,
GrPixelConfig config, bool isRT,
GrMipMapped) override {
diff --git a/src/gpu/vk/GrVkGpu.cpp b/src/gpu/vk/GrVkGpu.cpp
index 85ddd08f41..319e188ab3 100644
--- a/src/gpu/vk/GrVkGpu.cpp
+++ b/src/gpu/vk/GrVkGpu.cpp
@@ -1173,353 +1173,6 @@ bool copy_testing_data(GrVkGpu* gpu, void* srcData, const GrVkAlloc& alloc, size
return true;
}
-GrBackendObject GrVkGpu::createTestingOnlyBackendObject(void* srcData, int w, int h,
- GrPixelConfig config,
- bool isRenderTarget,
- GrMipMapped mipMapped) {
-
- VkFormat pixelFormat;
- if (!GrPixelConfigToVkFormat(config, &pixelFormat)) {
- return 0;
- }
-
- bool linearTiling = false;
- if (!fVkCaps->isConfigTexturable(config)) {
- return 0;
- }
-
- if (isRenderTarget && !fVkCaps->isConfigRenderable(config, false)) {
- return 0;
- }
-
- // Currently we don't support uploading pixel data when mipped.
- if (srcData && GrMipMapped::kYes == mipMapped) {
- return 0;
- }
-
- if (fVkCaps->isConfigTexturableLinearly(config) &&
- (!isRenderTarget || fVkCaps->isConfigRenderableLinearly(config, false)) &&
- GrMipMapped::kNo == mipMapped) {
- linearTiling = true;
- }
-
- VkImageUsageFlags usageFlags = VK_IMAGE_USAGE_SAMPLED_BIT;
- usageFlags |= VK_IMAGE_USAGE_TRANSFER_SRC_BIT;
- usageFlags |= VK_IMAGE_USAGE_TRANSFER_DST_BIT;
- if (isRenderTarget) {
- usageFlags |= VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT;
- }
-
- VkImage image = VK_NULL_HANDLE;
- GrVkAlloc alloc = { VK_NULL_HANDLE, 0, 0, 0 };
-
- VkImageTiling imageTiling = linearTiling ? VK_IMAGE_TILING_LINEAR : VK_IMAGE_TILING_OPTIMAL;
- VkImageLayout initialLayout = (VK_IMAGE_TILING_LINEAR == imageTiling)
- ? VK_IMAGE_LAYOUT_PREINITIALIZED
- : VK_IMAGE_LAYOUT_UNDEFINED;
-
- // Create Image
- VkSampleCountFlagBits vkSamples;
- if (!GrSampleCountToVkSampleCount(1, &vkSamples)) {
- return 0;
- }
-
- // Figure out the number of mip levels.
- uint32_t mipLevels = 1;
- if (GrMipMapped::kYes == mipMapped) {
- mipLevels = SkMipMap::ComputeLevelCount(w, h) + 1;
- }
-
- const VkImageCreateInfo imageCreateInfo = {
- VK_STRUCTURE_TYPE_IMAGE_CREATE_INFO, // sType
- nullptr, // pNext
- 0, // VkImageCreateFlags
- VK_IMAGE_TYPE_2D, // VkImageType
- pixelFormat, // VkFormat
- { (uint32_t) w, (uint32_t) h, 1 }, // VkExtent3D
- mipLevels, // mipLevels
- 1, // arrayLayers
- vkSamples, // samples
- imageTiling, // VkImageTiling
- usageFlags, // VkImageUsageFlags
- VK_SHARING_MODE_EXCLUSIVE, // VkSharingMode
- 0, // queueFamilyCount
- 0, // pQueueFamilyIndices
- initialLayout // initialLayout
- };
-
- GR_VK_CALL_ERRCHECK(this->vkInterface(), CreateImage(this->device(), &imageCreateInfo, nullptr, &image));
-
- if (!GrVkMemory::AllocAndBindImageMemory(this, image, linearTiling, &alloc)) {
- VK_CALL(DestroyImage(this->device(), image, nullptr));
- return 0;
- }
-
- // We need to declare these early so that we can delete them at the end outside of the if block.
- GrVkAlloc bufferAlloc = { VK_NULL_HANDLE, 0, 0, 0 };
- VkBuffer buffer = VK_NULL_HANDLE;
-
- VkResult err;
- const VkCommandBufferAllocateInfo cmdInfo = {
- VK_STRUCTURE_TYPE_COMMAND_BUFFER_ALLOCATE_INFO, // sType
- nullptr, // pNext
- fCmdPool, // commandPool
- VK_COMMAND_BUFFER_LEVEL_PRIMARY, // level
- 1 // bufferCount
- };
-
- VkCommandBuffer cmdBuffer;
- err = VK_CALL(AllocateCommandBuffers(fDevice, &cmdInfo, &cmdBuffer));
- if (err) {
- GrVkMemory::FreeImageMemory(this, false, alloc);
- VK_CALL(DestroyImage(fDevice, image, nullptr));
- return 0;
- }
-
- VkCommandBufferBeginInfo cmdBufferBeginInfo;
- memset(&cmdBufferBeginInfo, 0, sizeof(VkCommandBufferBeginInfo));
- cmdBufferBeginInfo.sType = VK_STRUCTURE_TYPE_COMMAND_BUFFER_BEGIN_INFO;
- cmdBufferBeginInfo.pNext = nullptr;
- cmdBufferBeginInfo.flags = VK_COMMAND_BUFFER_USAGE_ONE_TIME_SUBMIT_BIT;
- cmdBufferBeginInfo.pInheritanceInfo = nullptr;
-
- err = VK_CALL(BeginCommandBuffer(cmdBuffer, &cmdBufferBeginInfo));
- SkASSERT(!err);
-
- size_t bpp = GrBytesPerPixel(config);
- size_t rowCopyBytes = bpp * w;
- if (linearTiling) {
- const VkImageSubresource subres = {
- VK_IMAGE_ASPECT_COLOR_BIT,
- 0, // mipLevel
- 0, // arraySlice
- };
- VkSubresourceLayout layout;
-
- VK_CALL(GetImageSubresourceLayout(fDevice, image, &subres, &layout));
-
- if (!copy_testing_data(this, srcData, alloc, 0, rowCopyBytes,
- static_cast<size_t>(layout.rowPitch), h)) {
- GrVkMemory::FreeImageMemory(this, true, alloc);
- VK_CALL(DestroyImage(fDevice, image, nullptr));
- VK_CALL(EndCommandBuffer(cmdBuffer));
- VK_CALL(FreeCommandBuffers(fDevice, fCmdPool, 1, &cmdBuffer));
- return 0;
- }
- } else {
- SkASSERT(w && h);
-
- SkTArray<size_t> individualMipOffsets(mipLevels);
- individualMipOffsets.push_back(0);
- size_t combinedBufferSize = w * bpp * h;
- int currentWidth = w;
- int currentHeight = h;
- // The alignment must be at least 4 bytes and a multiple of the bytes per pixel of the image
- // config. This works with the assumption that the bytes in pixel config is always a power
- // of 2.
- SkASSERT((bpp & (bpp - 1)) == 0);
- const size_t alignmentMask = 0x3 | (bpp - 1);
- for (uint32_t currentMipLevel = 1; currentMipLevel < mipLevels; currentMipLevel++) {
- currentWidth = SkTMax(1, currentWidth/2);
- currentHeight = SkTMax(1, currentHeight/2);
-
- const size_t trimmedSize = currentWidth * bpp * currentHeight;
- const size_t alignmentDiff = combinedBufferSize & alignmentMask;
- if (alignmentDiff != 0) {
- combinedBufferSize += alignmentMask - alignmentDiff + 1;
- }
- individualMipOffsets.push_back(combinedBufferSize);
- combinedBufferSize += trimmedSize;
- }
-
- VkBufferCreateInfo bufInfo;
- memset(&bufInfo, 0, sizeof(VkBufferCreateInfo));
- bufInfo.sType = VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO;
- bufInfo.flags = 0;
- bufInfo.size = combinedBufferSize;
- bufInfo.usage = VK_BUFFER_USAGE_TRANSFER_SRC_BIT;
- bufInfo.sharingMode = VK_SHARING_MODE_EXCLUSIVE;
- bufInfo.queueFamilyIndexCount = 0;
- bufInfo.pQueueFamilyIndices = nullptr;
- err = VK_CALL(CreateBuffer(fDevice, &bufInfo, nullptr, &buffer));
-
- if (err) {
- GrVkMemory::FreeImageMemory(this, false, alloc);
- VK_CALL(DestroyImage(fDevice, image, nullptr));
- VK_CALL(EndCommandBuffer(cmdBuffer));
- VK_CALL(FreeCommandBuffers(fDevice, fCmdPool, 1, &cmdBuffer));
- return 0;
- }
-
- if (!GrVkMemory::AllocAndBindBufferMemory(this, buffer, GrVkBuffer::kCopyRead_Type,
- true, &bufferAlloc)) {
- GrVkMemory::FreeImageMemory(this, false, alloc);
- VK_CALL(DestroyImage(fDevice, image, nullptr));
- VK_CALL(DestroyBuffer(fDevice, buffer, nullptr));
- VK_CALL(EndCommandBuffer(cmdBuffer));
- VK_CALL(FreeCommandBuffers(fDevice, fCmdPool, 1, &cmdBuffer));
- return 0;
- }
-
- currentWidth = w;
- currentHeight = h;
- for (uint32_t currentMipLevel = 0; currentMipLevel < mipLevels; currentMipLevel++) {
- SkASSERT(0 == currentMipLevel || !srcData);
- size_t currentRowBytes = bpp * currentWidth;
- size_t bufferOffset = individualMipOffsets[currentMipLevel];
- if (!copy_testing_data(this, srcData, bufferAlloc, bufferOffset,
- currentRowBytes, currentRowBytes, currentHeight)) {
- GrVkMemory::FreeImageMemory(this, false, alloc);
- VK_CALL(DestroyImage(fDevice, image, nullptr));
- GrVkMemory::FreeBufferMemory(this, GrVkBuffer::kCopyRead_Type, bufferAlloc);
- VK_CALL(DestroyBuffer(fDevice, buffer, nullptr));
- VK_CALL(EndCommandBuffer(cmdBuffer));
- VK_CALL(FreeCommandBuffers(fDevice, fCmdPool, 1, &cmdBuffer));
- return 0;
- }
- currentWidth = SkTMax(1, currentWidth/2);
- currentHeight = SkTMax(1, currentHeight/2);
- }
-
- // Set image layout and add barrier
- VkImageMemoryBarrier barrier;
- memset(&barrier, 0, sizeof(VkImageMemoryBarrier));
- barrier.sType = VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER;
- barrier.pNext = nullptr;
- barrier.srcAccessMask = GrVkMemory::LayoutToSrcAccessMask(initialLayout);
- barrier.dstAccessMask = VK_ACCESS_TRANSFER_WRITE_BIT;
- barrier.oldLayout = initialLayout;
- barrier.newLayout = VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL;
- barrier.srcQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED;
- barrier.dstQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED;
- barrier.image = image;
- barrier.subresourceRange = { VK_IMAGE_ASPECT_COLOR_BIT, 0, mipLevels, 0 , 1};
-
- VK_CALL(CmdPipelineBarrier(cmdBuffer,
- GrVkMemory::LayoutToPipelineStageFlags(initialLayout),
- VK_PIPELINE_STAGE_TRANSFER_BIT,
- 0,
- 0, nullptr,
- 0, nullptr,
- 1, &barrier));
- initialLayout = VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL;
-
- SkTArray<VkBufferImageCopy> regions(mipLevels);
-
- currentWidth = w;
- currentHeight = h;
- for (uint32_t currentMipLevel = 0; currentMipLevel < mipLevels; currentMipLevel++) {
- // Submit copy command
- VkBufferImageCopy& region = regions.push_back();
- memset(&region, 0, sizeof(VkBufferImageCopy));
- region.bufferOffset = individualMipOffsets[currentMipLevel];
- region.bufferRowLength = currentWidth;
- region.bufferImageHeight = currentHeight;
- region.imageSubresource = { VK_IMAGE_ASPECT_COLOR_BIT, 0, 0, 1 };
- region.imageOffset = { 0, 0, 0 };
- region.imageExtent = { (uint32_t)currentWidth, (uint32_t)currentHeight, 1 };
- currentWidth = SkTMax(1, currentWidth/2);
- currentHeight = SkTMax(1, currentHeight/2);
- }
-
- VK_CALL(CmdCopyBufferToImage(cmdBuffer, buffer, image, initialLayout, regions.count(),
- regions.begin()));
- }
- // Change Image layout to shader read since if we use this texture as a borrowed textures within
- // Ganesh we require that its layout be set to that
- VkImageMemoryBarrier barrier;
- memset(&barrier, 0, sizeof(VkImageMemoryBarrier));
- barrier.sType = VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER;
- barrier.pNext = nullptr;
- barrier.srcAccessMask = GrVkMemory::LayoutToSrcAccessMask(initialLayout);
- barrier.dstAccessMask = VK_ACCESS_SHADER_READ_BIT;
- barrier.oldLayout = initialLayout;
- barrier.newLayout = VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL;
- barrier.srcQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED;
- barrier.dstQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED;
- barrier.image = image;
- barrier.subresourceRange = { VK_IMAGE_ASPECT_COLOR_BIT, 0, mipLevels, 0 , 1};
-
- VK_CALL(CmdPipelineBarrier(cmdBuffer,
- GrVkMemory::LayoutToPipelineStageFlags(initialLayout),
- VK_PIPELINE_STAGE_ALL_GRAPHICS_BIT,
- 0,
- 0, nullptr,
- 0, nullptr,
- 1, &barrier));
-
- // End CommandBuffer
- err = VK_CALL(EndCommandBuffer(cmdBuffer));
- SkASSERT(!err);
-
- // Create Fence for queue
- VkFence fence;
- VkFenceCreateInfo fenceInfo;
- memset(&fenceInfo, 0, sizeof(VkFenceCreateInfo));
- fenceInfo.sType = VK_STRUCTURE_TYPE_FENCE_CREATE_INFO;
-
- err = VK_CALL(CreateFence(fDevice, &fenceInfo, nullptr, &fence));
- SkASSERT(!err);
-
- VkSubmitInfo submitInfo;
- memset(&submitInfo, 0, sizeof(VkSubmitInfo));
- submitInfo.sType = VK_STRUCTURE_TYPE_SUBMIT_INFO;
- submitInfo.pNext = nullptr;
- submitInfo.waitSemaphoreCount = 0;
- submitInfo.pWaitSemaphores = nullptr;
- submitInfo.pWaitDstStageMask = 0;
- submitInfo.commandBufferCount = 1;
- submitInfo.pCommandBuffers = &cmdBuffer;
- submitInfo.signalSemaphoreCount = 0;
- submitInfo.pSignalSemaphores = nullptr;
- err = VK_CALL(QueueSubmit(this->queue(), 1, &submitInfo, fence));
- SkASSERT(!err);
-
- err = VK_CALL(WaitForFences(fDevice, 1, &fence, true, UINT64_MAX));
- if (VK_TIMEOUT == err) {
- GrVkMemory::FreeImageMemory(this, false, alloc);
- VK_CALL(DestroyImage(fDevice, image, nullptr));
- GrVkMemory::FreeBufferMemory(this, GrVkBuffer::kCopyRead_Type, bufferAlloc);
- VK_CALL(DestroyBuffer(fDevice, buffer, nullptr));
- VK_CALL(FreeCommandBuffers(fDevice, fCmdPool, 1, &cmdBuffer));
- VK_CALL(DestroyFence(fDevice, fence, nullptr));
- SkDebugf("Fence failed to signal: %d\n", err);
- SK_ABORT("failing");
- }
- SkASSERT(!err);
-
- // Clean up transfer resources
- if (buffer != VK_NULL_HANDLE) { // workaround for an older NVidia driver crash
- GrVkMemory::FreeBufferMemory(this, GrVkBuffer::kCopyRead_Type, bufferAlloc);
- VK_CALL(DestroyBuffer(fDevice, buffer, nullptr));
- }
- VK_CALL(FreeCommandBuffers(fDevice, fCmdPool, 1, &cmdBuffer));
- VK_CALL(DestroyFence(fDevice, fence, nullptr));
-
-
- GrVkImageInfo* info = new GrVkImageInfo;
- info->fImage = image;
- info->fAlloc = alloc;
- info->fImageTiling = imageTiling;
- info->fImageLayout = VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL;
- info->fFormat = pixelFormat;
- info->fLevelCount = mipLevels;
-
- return (GrBackendObject)info;
-}
-
-void GrVkGpu::deleteTestingOnlyBackendObject(GrBackendObject id, bool abandon) {
- GrVkImageInfo* backend = reinterpret_cast<GrVkImageInfo*>(id);
- if (backend) {
- if (!abandon) {
- // something in the command buffer may still be using this, so force submit
- this->submitCommandBuffer(kForce_SyncQueue);
- GrVkImage::DestroyImageInfo(this, backend);
- }
- delete backend;
- }
-}
-
GrBackendTexture GrVkGpu::createTestingOnlyBackendTexture(void* srcData, int w, int h,
GrPixelConfig config,
bool isRenderTarget,
diff --git a/src/gpu/vk/GrVkGpu.h b/src/gpu/vk/GrVkGpu.h
index dd45ed1de1..1fa22ca20d 100644
--- a/src/gpu/vk/GrVkGpu.h
+++ b/src/gpu/vk/GrVkGpu.h
@@ -85,12 +85,6 @@ public:
void xferBarrier(GrRenderTarget*, GrXferBarrierType) override {}
- GrBackendObject createTestingOnlyBackendObject(void* pixels, int w, int h,
- GrPixelConfig config,
- bool isRenderTarget,
- GrMipMapped) override;
- void deleteTestingOnlyBackendObject(GrBackendObject id, bool abandonTexture) override;
-
GrBackendTexture createTestingOnlyBackendTexture(void* pixels, int w, int h,
GrPixelConfig config,
bool isRenderTarget,
diff --git a/src/image/SkImage.cpp b/src/image/SkImage.cpp
index b9dc2e6cc5..01aceab773 100644
--- a/src/image/SkImage.cpp
+++ b/src/image/SkImage.cpp
@@ -379,6 +379,14 @@ sk_sp<SkImage> SkImage::MakeFromYUVTexturesCopy(GrContext* ctx, SkYUVColorSpace
return nullptr;
}
+sk_sp<SkImage> SkImage::MakeFromYUVTexturesCopy(GrContext* ctx, SkYUVColorSpace space,
+ const GrBackendTexture yuvTextureHandles[3],
+ const SkISize yuvSizes[3],
+ GrSurfaceOrigin origin,
+ sk_sp<SkColorSpace> imageColorSpace) {
+ return nullptr;
+}
+
sk_sp<SkImage> SkImage::makeTextureImage(GrContext*, SkColorSpace* dstColorSpace) const {
return nullptr;
}
diff --git a/src/image/SkImage_Gpu.cpp b/src/image/SkImage_Gpu.cpp
index 9249d47506..05c2670ca4 100644
--- a/src/image/SkImage_Gpu.cpp
+++ b/src/image/SkImage_Gpu.cpp
@@ -332,49 +332,38 @@ static GrBackendTexture make_backend_texture_from_handle(GrBackend backend,
}
}
+static bool are_yuv_sizes_valid(const SkISize yuvSizes[], bool nv12) {
+ if (yuvSizes[0].fWidth <= 0 || yuvSizes[0].fHeight <= 0 ||
+ yuvSizes[1].fWidth <= 0 || yuvSizes[1].fHeight <= 0) {
+ return false;
+ }
+ if (!nv12 && (yuvSizes[2].fWidth <= 0 || yuvSizes[2].fHeight <= 0)) {
+ return false;
+ }
+
+ return true;
+}
+
static sk_sp<SkImage> make_from_yuv_textures_copy(GrContext* ctx, SkYUVColorSpace colorSpace,
bool nv12,
- const GrBackendObject yuvTextureHandles[],
+ const GrBackendTexture yuvBackendTextures[],
const SkISize yuvSizes[],
GrSurfaceOrigin origin,
sk_sp<SkColorSpace> imageColorSpace) {
- const SkBudgeted budgeted = SkBudgeted::kYes;
-
- if (yuvSizes[0].fWidth <= 0 || yuvSizes[0].fHeight <= 0 || yuvSizes[1].fWidth <= 0 ||
- yuvSizes[1].fHeight <= 0) {
- return nullptr;
- }
- if (!nv12 && (yuvSizes[2].fWidth <= 0 || yuvSizes[2].fHeight <= 0)) {
+ if (!are_yuv_sizes_valid(yuvSizes, nv12)) {
return nullptr;
}
- const GrPixelConfig kConfig = nv12 ? kRGBA_8888_GrPixelConfig : kAlpha_8_GrPixelConfig;
-
- GrBackend backend = ctx->contextPriv().getBackend();
- GrBackendTexture yTex = make_backend_texture_from_handle(backend,
- yuvSizes[0].fWidth,
- yuvSizes[0].fHeight,
- kConfig,
- yuvTextureHandles[0]);
- GrBackendTexture uTex = make_backend_texture_from_handle(backend,
- yuvSizes[1].fWidth,
- yuvSizes[1].fHeight,
- kConfig,
- yuvTextureHandles[1]);
-
- sk_sp<GrTextureProxy> yProxy = GrSurfaceProxy::MakeWrappedBackend(ctx, yTex, origin);
- sk_sp<GrTextureProxy> uProxy = GrSurfaceProxy::MakeWrappedBackend(ctx, uTex, origin);
+ sk_sp<GrTextureProxy> yProxy = GrSurfaceProxy::MakeWrappedBackend(ctx, yuvBackendTextures[0],
+ origin);
+ sk_sp<GrTextureProxy> uProxy = GrSurfaceProxy::MakeWrappedBackend(ctx, yuvBackendTextures[1],
+ origin);
sk_sp<GrTextureProxy> vProxy;
if (nv12) {
vProxy = uProxy;
} else {
- GrBackendTexture vTex = make_backend_texture_from_handle(backend,
- yuvSizes[2].fWidth,
- yuvSizes[2].fHeight,
- kConfig,
- yuvTextureHandles[2]);
- vProxy = GrSurfaceProxy::MakeWrappedBackend(ctx, vTex, origin);
+ vProxy = GrSurfaceProxy::MakeWrappedBackend(ctx, yuvBackendTextures[2], origin);
}
if (!yProxy || !uProxy || !vProxy) {
return nullptr;
@@ -413,15 +402,55 @@ static sk_sp<SkImage> make_from_yuv_textures_copy(GrContext* ctx, SkYUVColorSpac
// MDB: this call is okay bc we know 'renderTargetContext' was exact
return sk_make_sp<SkImage_Gpu>(ctx, kNeedNewImageUniqueID, kOpaque_SkAlphaType,
renderTargetContext->asTextureProxyRef(),
- renderTargetContext->colorSpaceInfo().refColorSpace(), budgeted);
+ renderTargetContext->colorSpaceInfo().refColorSpace(),
+ SkBudgeted::kYes);
+}
+
+static sk_sp<SkImage> make_from_yuv_objects_copy(GrContext* ctx, SkYUVColorSpace colorSpace,
+ bool nv12,
+ const GrBackendObject yuvTextureHandles[],
+ const SkISize yuvSizes[],
+ GrSurfaceOrigin origin,
+ sk_sp<SkColorSpace> imageColorSpace) {
+ if (!are_yuv_sizes_valid(yuvSizes, nv12)) {
+ return nullptr;
+ }
+
+ GrBackendTexture backendTextures[3];
+
+ const GrPixelConfig kConfig = nv12 ? kRGBA_8888_GrPixelConfig : kAlpha_8_GrPixelConfig;
+
+ GrBackend backend = ctx->contextPriv().getBackend();
+ backendTextures[0] = make_backend_texture_from_handle(backend,
+ yuvSizes[0].fWidth,
+ yuvSizes[0].fHeight,
+ kConfig,
+ yuvTextureHandles[0]);
+ backendTextures[1] = make_backend_texture_from_handle(backend,
+ yuvSizes[1].fWidth,
+ yuvSizes[1].fHeight,
+ kConfig,
+ yuvTextureHandles[1]);
+
+ if (!nv12) {
+ backendTextures[2] = make_backend_texture_from_handle(backend,
+ yuvSizes[2].fWidth,
+ yuvSizes[2].fHeight,
+ kConfig,
+ yuvTextureHandles[2]);
+ }
+
+ return make_from_yuv_textures_copy(ctx, colorSpace, nv12,
+ backendTextures, yuvSizes, origin,
+ std::move(imageColorSpace));
}
sk_sp<SkImage> SkImage::MakeFromYUVTexturesCopy(GrContext* ctx, SkYUVColorSpace colorSpace,
const GrBackendObject yuvTextureHandles[3],
const SkISize yuvSizes[3], GrSurfaceOrigin origin,
sk_sp<SkColorSpace> imageColorSpace) {
- return make_from_yuv_textures_copy(ctx, colorSpace, false, yuvTextureHandles, yuvSizes, origin,
- std::move(imageColorSpace));
+ return make_from_yuv_objects_copy(ctx, colorSpace, false, yuvTextureHandles, yuvSizes, origin,
+ std::move(imageColorSpace));
}
sk_sp<SkImage> SkImage::MakeFromNV12TexturesCopy(GrContext* ctx, SkYUVColorSpace colorSpace,
@@ -429,7 +458,24 @@ sk_sp<SkImage> SkImage::MakeFromNV12TexturesCopy(GrContext* ctx, SkYUVColorSpace
const SkISize yuvSizes[2],
GrSurfaceOrigin origin,
sk_sp<SkColorSpace> imageColorSpace) {
- return make_from_yuv_textures_copy(ctx, colorSpace, true, yuvTextureHandles, yuvSizes, origin,
+ return make_from_yuv_objects_copy(ctx, colorSpace, true, yuvTextureHandles, yuvSizes, origin,
+ std::move(imageColorSpace));
+}
+
+sk_sp<SkImage> SkImage::MakeFromYUVTexturesCopy(GrContext* ctx, SkYUVColorSpace colorSpace,
+ const GrBackendTexture yuvBackendTextures[3],
+ const SkISize yuvSizes[3], GrSurfaceOrigin origin,
+ sk_sp<SkColorSpace> imageColorSpace) {
+ return make_from_yuv_textures_copy(ctx, colorSpace, false, yuvBackendTextures, yuvSizes, origin,
+ std::move(imageColorSpace));
+}
+
+sk_sp<SkImage> SkImage::MakeFromNV12TexturesCopy(GrContext* ctx, SkYUVColorSpace colorSpace,
+ const GrBackendTexture yuvBackendTextures[2],
+ const SkISize yuvSizes[2],
+ GrSurfaceOrigin origin,
+ sk_sp<SkColorSpace> imageColorSpace) {
+ return make_from_yuv_textures_copy(ctx, colorSpace, true, yuvBackendTextures, yuvSizes, origin,
std::move(imageColorSpace));
}