/* * Copyright 2015 Google Inc. * * Use of this source code is governed by a BSD-style license that can be * found in the LICENSE file. */ #include "GrVkTexture.h" #include "GrTexturePriv.h" #include "GrVkGpu.h" #include "GrVkImageView.h" #include "GrVkTextureRenderTarget.h" #include "GrVkUtil.h" #include "vk/GrVkTypes.h" #define VK_CALL(GPU, X) GR_VK_CALL(GPU->vkInterface(), X) // This method parallels GrTextureProxy::highestFilterMode static inline GrSamplerState::Filter highest_filter_mode(GrPixelConfig config) { return GrSamplerState::Filter::kMipMap; } // Because this class is virtually derived from GrSurface we must explicitly call its constructor. GrVkTexture::GrVkTexture(GrVkGpu* gpu, SkBudgeted budgeted, const GrSurfaceDesc& desc, const GrVkImageInfo& info, sk_sp layout, const GrVkImageView* view, GrMipMapsStatus mipMapsStatus) : GrSurface(gpu, desc) , GrVkImage(info, std::move(layout), GrBackendObjectOwnership::kOwned) , INHERITED(gpu, desc, GrTextureType::k2D, highest_filter_mode(desc.fConfig), mipMapsStatus) , fTextureView(view) { SkASSERT((GrMipMapsStatus::kNotAllocated == mipMapsStatus) == (1 == info.fLevelCount)); this->registerWithCache(budgeted); } GrVkTexture::GrVkTexture(GrVkGpu* gpu, Wrapped, const GrSurfaceDesc& desc, const GrVkImageInfo& info, sk_sp layout, const GrVkImageView* view, GrMipMapsStatus mipMapsStatus, GrBackendObjectOwnership ownership) : GrSurface(gpu, desc) , GrVkImage(info, std::move(layout), ownership) , INHERITED(gpu, desc, GrTextureType::k2D, highest_filter_mode(desc.fConfig), mipMapsStatus) , fTextureView(view) { SkASSERT((GrMipMapsStatus::kNotAllocated == mipMapsStatus) == (1 == info.fLevelCount)); this->registerWithCacheWrapped(); } // Because this class is virtually derived from GrSurface we must explicitly call its constructor. GrVkTexture::GrVkTexture(GrVkGpu* gpu, const GrSurfaceDesc& desc, const GrVkImageInfo& info, sk_sp layout, const GrVkImageView* view, GrMipMapsStatus mipMapsStatus, GrBackendObjectOwnership ownership) : GrSurface(gpu, desc) , GrVkImage(info, layout, ownership) , INHERITED(gpu, desc, GrTextureType::k2D, highest_filter_mode(desc.fConfig), mipMapsStatus) , fTextureView(view) { SkASSERT((GrMipMapsStatus::kNotAllocated == mipMapsStatus) == (1 == info.fLevelCount)); } sk_sp GrVkTexture::CreateNewTexture(GrVkGpu* gpu, SkBudgeted budgeted, const GrSurfaceDesc& desc, const GrVkImage::ImageDesc& imageDesc, GrMipMapsStatus mipMapsStatus) { SkASSERT(imageDesc.fUsageFlags & VK_IMAGE_USAGE_SAMPLED_BIT); GrVkImageInfo info; if (!GrVkImage::InitImageInfo(gpu, imageDesc, &info)) { return nullptr; } const GrVkImageView* imageView = GrVkImageView::Create(gpu, info.fImage, info.fFormat, GrVkImageView::kColor_Type, info.fLevelCount); if (!imageView) { GrVkImage::DestroyImageInfo(gpu, &info); return nullptr; } sk_sp layout(new GrVkImageLayout(info.fImageLayout)); return sk_sp(new GrVkTexture(gpu, budgeted, desc, info, std::move(layout), imageView, mipMapsStatus)); } sk_sp GrVkTexture::MakeWrappedTexture(GrVkGpu* gpu, const GrSurfaceDesc& desc, GrWrapOwnership wrapOwnership, const GrVkImageInfo& info, sk_sp layout) { // Wrapped textures require both image and allocation (because they can be mapped) SkASSERT(VK_NULL_HANDLE != info.fImage && VK_NULL_HANDLE != info.fAlloc.fMemory); const GrVkImageView* imageView = GrVkImageView::Create(gpu, info.fImage, info.fFormat, GrVkImageView::kColor_Type, info.fLevelCount); if (!imageView) { return nullptr; } GrMipMapsStatus mipMapsStatus = info.fLevelCount > 1 ? GrMipMapsStatus::kValid : GrMipMapsStatus::kNotAllocated; GrBackendObjectOwnership ownership = kBorrow_GrWrapOwnership == wrapOwnership ? GrBackendObjectOwnership::kBorrowed : GrBackendObjectOwnership::kOwned; return sk_sp(new GrVkTexture(gpu, kWrapped, desc, info, std::move(layout), imageView, mipMapsStatus, ownership)); } GrVkTexture::~GrVkTexture() { // either release or abandon should have been called by the owner of this object. SkASSERT(!fTextureView); } void GrVkTexture::onRelease() { // we create this and don't hand it off, so we should always destroy it if (fTextureView) { fTextureView->unref(this->getVkGpu()); fTextureView = nullptr; } this->releaseImage(this->getVkGpu()); INHERITED::onRelease(); } void GrVkTexture::onAbandon() { if (fTextureView) { fTextureView->unrefAndAbandon(); fTextureView = nullptr; } this->abandonImage(); INHERITED::onAbandon(); } GrBackendTexture GrVkTexture::getBackendTexture() const { return GrBackendTexture(this->width(), this->height(), fInfo, this->grVkImageLayout()); } GrVkGpu* GrVkTexture::getVkGpu() const { SkASSERT(!this->wasDestroyed()); return static_cast(this->getGpu()); } const GrVkImageView* GrVkTexture::textureView() { return fTextureView; }