blob: 59d4bd6320ecec879758de7de5585c1f1297dc91 [file] [log] [blame]
/*
* Copyright 2021 Google LLC
*
* Use of this source code is governed by a BSD-style license that can be
* found in the LICENSE file.
*/
#include "src/gpu/graphite/TextureProxy.h"
#include "include/gpu/graphite/Recorder.h"
#include "src/core/SkMipmap.h"
#include "src/gpu/graphite/Caps.h"
#include "src/gpu/graphite/RecorderPriv.h"
#include "src/gpu/graphite/ResourceProvider.h"
#include "src/gpu/graphite/ScratchResourceManager.h"
#include "src/gpu/graphite/Texture.h"
#include "src/gpu/graphite/TextureUtils.h"
namespace skgpu::graphite {
TextureProxy::TextureProxy(SkISize dimensions,
const TextureInfo& info,
std::string_view label,
skgpu::Budgeted budgeted)
: fDimensions(dimensions)
, fInfo(info)
, fLabel(label)
, fBudgeted(budgeted)
, fVolatile(Volatile::kNo) {
SkASSERT(fInfo.isValid());
}
TextureProxy::TextureProxy(sk_sp<Texture> texture)
: fDimensions(texture->dimensions())
, fInfo(texture->textureInfo())
, fLabel(texture->getLabel())
, fBudgeted(texture->budgeted())
, fVolatile(Volatile::kNo)
, fTexture(std::move(texture)) {
SkASSERT(fInfo.isValid());
}
TextureProxy::TextureProxy(SkISize dimensions,
const TextureInfo& textureInfo,
skgpu::Budgeted budgeted,
Volatile isVolatile,
LazyInstantiateCallback&& callback)
: fDimensions(dimensions)
, fInfo(textureInfo)
, fBudgeted(budgeted)
, fVolatile(isVolatile)
, fLazyInstantiateCallback(std::move(callback)) {
SkASSERT(fInfo.isValid());
SkASSERT(fLazyInstantiateCallback);
}
TextureProxy::~TextureProxy() {}
SkISize TextureProxy::dimensions() const {
SkASSERT(!this->isFullyLazy() || this->isInstantiated());
return this->isInstantiated() ? fTexture->dimensions() : fDimensions;
}
bool TextureProxy::isLazy() const {
return SkToBool(fLazyInstantiateCallback);
}
bool TextureProxy::isFullyLazy() const {
bool result = fDimensions.width() < 0;
SkASSERT(result == (fDimensions.height() < 0));
SkASSERT(!result || this->isLazy());
return result;
}
bool TextureProxy::isVolatile() const {
SkASSERT(fVolatile == Volatile::kNo || SkToBool(fLazyInstantiateCallback));
return fVolatile == Volatile::kYes;
}
bool TextureProxy::isProtected() const {
return fInfo.isProtected() == Protected::kYes;
}
size_t TextureProxy::uninstantiatedGpuMemorySize() const {
return ComputeSize(fDimensions, fInfo);
}
bool TextureProxy::instantiate(ResourceProvider* resourceProvider) {
SkASSERT(!this->isLazy());
if (fTexture) {
return true;
}
fTexture = resourceProvider->findOrCreateScratchTexture(fDimensions, fInfo, fLabel, fBudgeted);
if (!fTexture) {
return false;
}
SkDEBUGCODE(this->validateTexture(fTexture.get()));
return true;
}
bool TextureProxy::lazyInstantiate(ResourceProvider* resourceProvider) {
SkASSERT(this->isLazy());
if (fTexture) {
return true;
}
fTexture = fLazyInstantiateCallback(resourceProvider);
if (!fTexture) {
return false;
}
SkDEBUGCODE(this->validateTexture(fTexture.get()));
return true;
}
bool TextureProxy::InstantiateIfNotLazy(ResourceProvider* resourceProvider,
TextureProxy* textureProxy) {
if (textureProxy->isLazy()) {
return true;
}
return textureProxy->instantiate(resourceProvider);
}
bool TextureProxy::InstantiateIfNotLazy(ScratchResourceManager* scratchManager,
TextureProxy* textureProxy) {
if (textureProxy->isLazy() || textureProxy->isInstantiated()) {
return true;
}
textureProxy->fTexture = scratchManager->getScratchTexture(textureProxy->dimensions(),
textureProxy->textureInfo(),
textureProxy->fLabel);
if (!textureProxy->fTexture) {
return false;
}
SkDEBUGCODE(textureProxy->validateTexture(textureProxy->fTexture.get()));
return true;
}
void TextureProxy::deinstantiate() {
SkASSERT(fVolatile == Volatile::kYes && SkToBool(fLazyInstantiateCallback));
fTexture.reset();
}
sk_sp<Texture> TextureProxy::refTexture() const {
return fTexture;
}
const Texture* TextureProxy::texture() const {
return fTexture.get();
}
sk_sp<TextureProxy> TextureProxy::Make(const Caps* caps,
ResourceProvider* resourceProvider,
SkISize dimensions,
const TextureInfo& textureInfo,
std::string_view label,
skgpu::Budgeted budgeted) {
if (dimensions.width() < 1 || dimensions.height() < 1 ||
dimensions.width() > caps->maxTextureSize() ||
dimensions.height() > caps->maxTextureSize() ||
!textureInfo.isValid()) {
return nullptr;
}
sk_sp<TextureProxy> proxy{new TextureProxy(dimensions,
textureInfo,
std::move(label),
budgeted)};
if (budgeted == Budgeted::kNo) {
// Instantiate immediately to avoid races later on if the client starts to use the wrapping
// object on multiple threads.
if (!proxy->instantiate(resourceProvider)) {
return nullptr;
}
}
return proxy;
}
sk_sp<TextureProxy> TextureProxy::MakeLazy(const Caps* caps,
SkISize dimensions,
const TextureInfo& textureInfo,
skgpu::Budgeted budgeted,
Volatile isVolatile,
LazyInstantiateCallback&& callback) {
SkASSERT(textureInfo.isValid());
if (dimensions.width() < 1 || dimensions.height() < 1 ||
dimensions.width() > caps->maxTextureSize() ||
dimensions.height() > caps->maxTextureSize()) {
return nullptr;
}
return sk_sp<TextureProxy>(new TextureProxy(dimensions,
textureInfo,
budgeted,
isVolatile,
std::move(callback)));
}
sk_sp<TextureProxy> TextureProxy::MakeFullyLazy(const TextureInfo& textureInfo,
skgpu::Budgeted budgeted,
Volatile isVolatile,
LazyInstantiateCallback&& callback) {
SkASSERT(textureInfo.isValid());
return sk_sp<TextureProxy>(new TextureProxy(SkISize::Make(-1, -1),
textureInfo,
budgeted,
isVolatile,
std::move(callback)));
}
sk_sp<TextureProxy> TextureProxy::Wrap(sk_sp<Texture> texture) {
return sk_sp<TextureProxy>(new TextureProxy(std::move(texture)));
}
#ifdef SK_DEBUG
void TextureProxy::validateTexture(const Texture* texture) {
SkASSERT(this->isFullyLazy() || fDimensions == texture->dimensions());
SkASSERTF(fInfo.isCompatible(texture->textureInfo()),
"proxy->fInfo[%s] incompatible with texture->fInfo[%s]",
fInfo.toString().c_str(),
texture->textureInfo().toString().c_str());
}
#endif
} // namespace skgpu::graphite