diff options
-rw-r--r-- | gm/imagefromyuvtextures.cpp | 23 | ||||
-rw-r--r-- | include/core/SkImage.h | 23 | ||||
-rw-r--r-- | include/private/GrSurfaceProxy.h | 3 | ||||
-rw-r--r-- | src/gpu/GrGpu.h | 14 | ||||
-rw-r--r-- | src/gpu/GrSurfaceProxy.cpp | 2 | ||||
-rw-r--r-- | src/gpu/gl/GrGLGpu.cpp | 72 | ||||
-rw-r--r-- | src/gpu/gl/GrGLGpu.h | 6 | ||||
-rw-r--r-- | src/gpu/mock/GrMockGpu.cpp | 15 | ||||
-rw-r--r-- | src/gpu/mock/GrMockGpu.h | 4 | ||||
-rw-r--r-- | src/gpu/mtl/GrMtlGpu.h | 7 | ||||
-rw-r--r-- | src/gpu/vk/GrVkGpu.cpp | 347 | ||||
-rw-r--r-- | src/gpu/vk/GrVkGpu.h | 6 | ||||
-rw-r--r-- | src/image/SkImage.cpp | 8 | ||||
-rw-r--r-- | src/image/SkImage_Gpu.cpp | 114 |
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(®ion, 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)); } |