Refactor to separate backend object lifecycle and GpuResource budget decision
Refactor GrGpuResource to contain two different pieces of state: a) instance is budgeted or not budgeted b) instance references wrapped backend objects or not The "object lifecycle" was also attached to backend object handles (ids), which made the code a bit unclear. Backend objects would be associated with GrGpuResource::LifeCycle, even though GrGpuResource::LifeCycle refers to the GpuResource, and individual backend objects in one GpuResource might be governed with different "lifecycle". Mark the budgeted/not budgeted with SkBudgeted::kYes, SkBudgeted::kNo. This was previously GrGpuResource::kCached_LifeCycle, GrGpuResource::kUncached_LifeCycle. Mark the "references wrapped object" with boolean. This was previously GrGpuResource::kBorrowed_LifeCycle, GrGpuResource::kAdopted_LifeCycle for GrGpuResource. Associate the backend object ownership status with GrBackendObjectOwnership for the backend object handles. The resource type leaf constuctors, such has GrGLTexture or GrGLTextureRenderTarget take "budgeted" parameter. This parameter is passed to GrGpuResource::registerWithCache(). The resource type intermediary constructors, such as GrGLTexture constructors for class GrGLTextureRenderTarget do not take "budgeted" parameters, intermediary construtors do not call registerWithCache. Removes the need for tagging GrGpuResource -derived subclass constructors with "Derived" parameter. Makes instances that wrap backend objects be registered with a new function GrGpuResource::registerWithCacheWrapped(). Removes "budgeted" parameter from classes such as StencilAttahment, as they are always cached and never wrap any external backend objects. Removes the use of concept "external" from the member function names. The API refers to the objects as "wrapped", so make all related functions use the term consistently. No change in functionality. Resources referencing wrapped objects are always inserted to the cache with budget decision kNo. BUG=594928 GOLD_TRYBOT_URL= https://gold.skia.org/search2?unt=true&query=source_type%3Dgm&master=false&issue=1862043002 Review URL: https://codereview.chromium.org/1862043002
This commit is contained in:
parent
cb61a6452f
commit
2e6055b3ea
@ -23,8 +23,8 @@ enum {
|
||||
class BenchResource : public GrGpuResource {
|
||||
public:
|
||||
BenchResource (GrGpu* gpu)
|
||||
: INHERITED(gpu, kCached_LifeCycle) {
|
||||
this->registerWithCache();
|
||||
: INHERITED(gpu) {
|
||||
this->registerWithCache(SkBudgeted::kYes);
|
||||
}
|
||||
|
||||
static void ComputeKey(int i, int keyData32Count, GrUniqueKey* key) {
|
||||
|
@ -110,22 +110,24 @@ public:
|
||||
protected:
|
||||
GrBuffer(GrGpu* gpu, size_t gpuMemorySize, GrBufferType intendedType,
|
||||
GrAccessPattern accessPattern, bool cpuBacked)
|
||||
: INHERITED(gpu, kCached_LifeCycle),
|
||||
: INHERITED(gpu),
|
||||
fMapPtr(nullptr),
|
||||
fGpuMemorySize(gpuMemorySize), // TODO: Zero for cpu backed buffers?
|
||||
fAccessPattern(accessPattern),
|
||||
fCPUBacked(cpuBacked) {
|
||||
fCPUBacked(cpuBacked),
|
||||
fIntendedType(intendedType) {
|
||||
}
|
||||
|
||||
void computeScratchKey(GrScratchKey* key) const override {
|
||||
if (!fCPUBacked && SkIsPow2(fGpuMemorySize) && kDynamic_GrAccessPattern == fAccessPattern) {
|
||||
GrScratchKey key;
|
||||
ComputeScratchKeyForDynamicBuffer(fGpuMemorySize, intendedType, &key);
|
||||
this->setScratchKey(key);
|
||||
ComputeScratchKeyForDynamicBuffer(fGpuMemorySize, fIntendedType, key);
|
||||
}
|
||||
}
|
||||
|
||||
void* fMapPtr;
|
||||
|
||||
private:
|
||||
virtual size_t onGpuMemorySize() const { return fGpuMemorySize; }
|
||||
size_t onGpuMemorySize() const override { return fGpuMemorySize; }
|
||||
|
||||
virtual void onMap() = 0;
|
||||
virtual void onUnmap() = 0;
|
||||
@ -134,7 +136,7 @@ private:
|
||||
size_t fGpuMemorySize;
|
||||
GrAccessPattern fAccessPattern;
|
||||
bool fCPUBacked;
|
||||
|
||||
GrBufferType fIntendedType;
|
||||
typedef GrGpuResource INHERITED;
|
||||
};
|
||||
|
||||
|
@ -140,34 +140,6 @@ private:
|
||||
class SK_API GrGpuResource : public GrIORef<GrGpuResource> {
|
||||
public:
|
||||
|
||||
|
||||
enum LifeCycle {
|
||||
/**
|
||||
* The resource is cached and owned by Skia. Resources with this status may be kept alive
|
||||
* by the cache as either scratch or unique resources even when there are no refs to them.
|
||||
* The cache may release them whenever there are no refs.
|
||||
*/
|
||||
kCached_LifeCycle,
|
||||
|
||||
/**
|
||||
* The resource is uncached. As soon as there are no more refs to it, it is released. Under
|
||||
* the hood the cache may opaquely recycle it as a cached resource.
|
||||
*/
|
||||
kUncached_LifeCycle,
|
||||
|
||||
/**
|
||||
* Similar to uncached, but Skia does not manage the lifetime of the underlying backend
|
||||
* 3D API object(s). The client is responsible for freeing those. Used to inject client-
|
||||
* created GPU resources into Skia (e.g. to render to a client-created texture).
|
||||
*/
|
||||
kBorrowed_LifeCycle,
|
||||
|
||||
/**
|
||||
* An external resource with ownership transfered into Skia. Skia will free the resource.
|
||||
*/
|
||||
kAdopted_LifeCycle,
|
||||
};
|
||||
|
||||
/**
|
||||
* Tests whether a object has been abandoned or released. All objects will
|
||||
* be in this state after their creating GrContext is destroyed or has
|
||||
@ -261,11 +233,16 @@ public:
|
||||
virtual void dumpMemoryStatistics(SkTraceMemoryDump* traceMemoryDump) const;
|
||||
|
||||
protected:
|
||||
// This must be called by every GrGpuObject. It should be called once the object is fully
|
||||
// initialized (i.e. not in a base class constructor).
|
||||
void registerWithCache();
|
||||
// This must be called by every non-wrapped GrGpuObject. It should be called once the object is
|
||||
// fully initialized (i.e. only from the constructors of the final class).
|
||||
void registerWithCache(SkBudgeted);
|
||||
|
||||
GrGpuResource(GrGpu*, LifeCycle);
|
||||
// This must be called by every GrGpuObject that references any wrapped backend objects. It
|
||||
// should be called once the object is fully initialized (i.e. only from the constructors of the
|
||||
// final class).
|
||||
void registerWithCacheWrapped();
|
||||
|
||||
GrGpuResource(GrGpu*);
|
||||
virtual ~GrGpuResource();
|
||||
|
||||
GrGpu* getGpu() const { return fGpu; }
|
||||
@ -277,25 +254,12 @@ protected:
|
||||
backend API calls should be made. */
|
||||
virtual void onAbandon() { }
|
||||
|
||||
bool shouldFreeResources() const { return fLifeCycle != kBorrowed_LifeCycle; }
|
||||
|
||||
bool isExternal() const {
|
||||
return GrGpuResource::kAdopted_LifeCycle == fLifeCycle ||
|
||||
GrGpuResource::kBorrowed_LifeCycle == fLifeCycle;
|
||||
}
|
||||
|
||||
/**
|
||||
* This entry point should be called whenever gpuMemorySize() should report a different size.
|
||||
* The cache will call gpuMemorySize() to update the current size of the resource.
|
||||
*/
|
||||
void didChangeGpuMemorySize() const;
|
||||
|
||||
/**
|
||||
* Optionally called by the GrGpuResource subclass if the resource can be used as scratch.
|
||||
* By default resources are not usable as scratch. This should only be called once.
|
||||
**/
|
||||
void setScratchKey(const GrScratchKey& scratchKey);
|
||||
|
||||
/**
|
||||
* Allows subclasses to add additional backing information to the SkTraceMemoryDump. Called by
|
||||
* onMemoryDump. The default implementation adds no backing information.
|
||||
@ -303,6 +267,14 @@ protected:
|
||||
virtual void setMemoryBacking(SkTraceMemoryDump*, const SkString&) const {}
|
||||
|
||||
private:
|
||||
/**
|
||||
* Called by the registerWithCache if the resource is available to be used as scratch.
|
||||
* Resource subclasses should override this if the instances should be recycled as scratch
|
||||
* resources and populate the scratchKey with the key.
|
||||
* By default resources are not recycled as scratch.
|
||||
**/
|
||||
virtual void computeScratchKey(GrScratchKey*) const { };
|
||||
|
||||
/**
|
||||
* Frees the object in the underlying 3D API. Called by CacheAccess.
|
||||
*/
|
||||
@ -341,7 +313,8 @@ private:
|
||||
GrGpu* fGpu;
|
||||
mutable size_t fGpuMemorySize;
|
||||
|
||||
LifeCycle fLifeCycle;
|
||||
SkBudgeted fBudgeted;
|
||||
bool fRefsWrappedObjects;
|
||||
const uint32_t fUniqueID;
|
||||
|
||||
SkAutoTUnref<const SkData> fData;
|
||||
|
@ -156,9 +156,9 @@ public:
|
||||
GrDrawTarget* getLastDrawTarget() { return fLastDrawTarget; }
|
||||
|
||||
protected:
|
||||
GrRenderTarget(GrGpu* gpu, LifeCycle lifeCycle, const GrSurfaceDesc& desc,
|
||||
GrRenderTarget(GrGpu* gpu, const GrSurfaceDesc& desc,
|
||||
SampleConfig sampleConfig, GrStencilAttachment* stencil = nullptr)
|
||||
: INHERITED(gpu, lifeCycle, desc)
|
||||
: INHERITED(gpu, desc)
|
||||
, fStencilAttachment(stencil)
|
||||
, fSampleConfig(sampleConfig)
|
||||
, fLastDrawTarget(nullptr) {
|
||||
|
@ -146,8 +146,8 @@ protected:
|
||||
// Provides access to methods that should be public within Skia code.
|
||||
friend class GrSurfacePriv;
|
||||
|
||||
GrSurface(GrGpu* gpu, LifeCycle lifeCycle, const GrSurfaceDesc& desc)
|
||||
: INHERITED(gpu, lifeCycle)
|
||||
GrSurface(GrGpu* gpu, const GrSurfaceDesc& desc)
|
||||
: INHERITED(gpu)
|
||||
, fDesc(desc)
|
||||
, fReleaseProc(NULL)
|
||||
, fReleaseCtx(NULL)
|
||||
|
@ -46,11 +46,12 @@ public:
|
||||
inline const GrTexturePriv texturePriv() const;
|
||||
|
||||
protected:
|
||||
GrTexture(GrGpu*, LifeCycle, const GrSurfaceDesc&, GrSLType, bool wasMipMapDataProvided);
|
||||
GrTexture(GrGpu*, const GrSurfaceDesc&, GrSLType, bool wasMipMapDataProvided);
|
||||
|
||||
void validateDesc() const;
|
||||
|
||||
private:
|
||||
void computeScratchKey(GrScratchKey*) const override;
|
||||
size_t onGpuMemorySize() const override;
|
||||
void dirtyMipMaps(bool mipMapsDirty);
|
||||
|
||||
|
@ -464,4 +464,14 @@ enum GrAccessPattern {
|
||||
#define GrCapsDebugf(caps, ...)
|
||||
#endif
|
||||
|
||||
/**
|
||||
* Specifies if the holder owns the backend, OpenGL or Vulkan, object.
|
||||
*/
|
||||
enum class GrBackendObjectOwnership : bool {
|
||||
/** Holder does not destroy the backend object. */
|
||||
kBorrowed = false,
|
||||
/** Holder destroys the backend object. */
|
||||
kOwned = true
|
||||
};
|
||||
|
||||
#endif
|
||||
|
@ -150,9 +150,6 @@ GrTexture* GrGpu::createTexture(const GrSurfaceDesc& origDesc, SkBudgeted budget
|
||||
desc.fOrigin = resolve_origin(desc.fOrigin, isRT);
|
||||
|
||||
GrTexture* tex = nullptr;
|
||||
GrGpuResource::LifeCycle lifeCycle = SkBudgeted::kYes == budgeted ?
|
||||
GrGpuResource::kCached_LifeCycle :
|
||||
GrGpuResource::kUncached_LifeCycle;
|
||||
|
||||
if (GrPixelConfigIsCompressed(desc.fConfig)) {
|
||||
// We shouldn't be rendering into this
|
||||
@ -165,10 +162,10 @@ GrTexture* GrGpu::createTexture(const GrSurfaceDesc& origDesc, SkBudgeted budget
|
||||
}
|
||||
|
||||
this->handleDirtyContext();
|
||||
tex = this->onCreateCompressedTexture(desc, lifeCycle, texels);
|
||||
tex = this->onCreateCompressedTexture(desc, budgeted, texels);
|
||||
} else {
|
||||
this->handleDirtyContext();
|
||||
tex = this->onCreateTexture(desc, lifeCycle, texels);
|
||||
tex = this->onCreateTexture(desc, budgeted, texels);
|
||||
}
|
||||
if (tex) {
|
||||
if (!caps->reuseScratchTextures() && !isRT) {
|
||||
|
@ -529,10 +529,10 @@ private:
|
||||
// Texture size and sample size will have already been validated in base class before
|
||||
// onCreateTexture/CompressedTexture are called.
|
||||
virtual GrTexture* onCreateTexture(const GrSurfaceDesc& desc,
|
||||
GrGpuResource::LifeCycle lifeCycle,
|
||||
SkBudgeted budgeted,
|
||||
const SkTArray<GrMipLevel>& texels) = 0;
|
||||
virtual GrTexture* onCreateCompressedTexture(const GrSurfaceDesc& desc,
|
||||
GrGpuResource::LifeCycle lifeCycle,
|
||||
SkBudgeted budgeted,
|
||||
const SkTArray<GrMipLevel>& texels) = 0;
|
||||
|
||||
virtual GrTexture* onWrapBackendTexture(const GrBackendTextureDesc&, GrWrapOwnership) = 0;
|
||||
|
@ -19,15 +19,26 @@ static inline GrResourceCache* get_resource_cache(GrGpu* gpu) {
|
||||
return gpu->getContext()->getResourceCache();
|
||||
}
|
||||
|
||||
GrGpuResource::GrGpuResource(GrGpu* gpu, LifeCycle lifeCycle)
|
||||
GrGpuResource::GrGpuResource(GrGpu* gpu)
|
||||
: fGpu(gpu)
|
||||
, fGpuMemorySize(kInvalidGpuMemorySize)
|
||||
, fLifeCycle(lifeCycle)
|
||||
, fBudgeted(SkBudgeted::kNo)
|
||||
, fRefsWrappedObjects(false)
|
||||
, fUniqueID(CreateUniqueID()) {
|
||||
SkDEBUGCODE(fCacheArrayIndex = -1);
|
||||
}
|
||||
|
||||
void GrGpuResource::registerWithCache() {
|
||||
void GrGpuResource::registerWithCache(SkBudgeted budgeted) {
|
||||
SkASSERT(fBudgeted == SkBudgeted::kNo);
|
||||
fBudgeted = budgeted;
|
||||
this->computeScratchKey(&fScratchKey);
|
||||
get_resource_cache(fGpu)->resourceAccess().insertResource(this);
|
||||
}
|
||||
|
||||
void GrGpuResource::registerWithCacheWrapped() {
|
||||
SkASSERT(fBudgeted == SkBudgeted::kNo);
|
||||
// Currently resources referencing wrapped objects are not budgeted.
|
||||
fRefsWrappedObjects = true;
|
||||
get_resource_cache(fGpu)->resourceAccess().insertResource(this);
|
||||
}
|
||||
|
||||
@ -164,16 +175,6 @@ bool GrGpuResource::notifyRefCountIsZero() const {
|
||||
return false;
|
||||
}
|
||||
|
||||
void GrGpuResource::setScratchKey(const GrScratchKey& scratchKey) {
|
||||
SkASSERT(!fScratchKey.isValid());
|
||||
SkASSERT(scratchKey.isValid());
|
||||
// Wrapped resources can never have a scratch key.
|
||||
if (this->resourcePriv().isExternal()) {
|
||||
return;
|
||||
}
|
||||
fScratchKey = scratchKey;
|
||||
}
|
||||
|
||||
void GrGpuResource::removeScratchKey() {
|
||||
if (!this->wasDestroyed() && fScratchKey.isValid()) {
|
||||
get_resource_cache(fGpu)->resourceAccess().willRemoveScratchKey(this);
|
||||
@ -182,16 +183,18 @@ void GrGpuResource::removeScratchKey() {
|
||||
}
|
||||
|
||||
void GrGpuResource::makeBudgeted() {
|
||||
if (!this->wasDestroyed() && GrGpuResource::kUncached_LifeCycle == fLifeCycle) {
|
||||
fLifeCycle = kCached_LifeCycle;
|
||||
if (!this->wasDestroyed() && SkBudgeted::kNo == fBudgeted) {
|
||||
// Currently resources referencing wrapped objects are not budgeted.
|
||||
SkASSERT(!fRefsWrappedObjects);
|
||||
fBudgeted = SkBudgeted::kYes;
|
||||
get_resource_cache(fGpu)->resourceAccess().didChangeBudgetStatus(this);
|
||||
}
|
||||
}
|
||||
|
||||
void GrGpuResource::makeUnbudgeted() {
|
||||
if (!this->wasDestroyed() && GrGpuResource::kCached_LifeCycle == fLifeCycle &&
|
||||
if (!this->wasDestroyed() && SkBudgeted::kYes == fBudgeted &&
|
||||
!fUniqueKey.isValid()) {
|
||||
fLifeCycle = kUncached_LifeCycle;
|
||||
fBudgeted = SkBudgeted::kNo;
|
||||
get_resource_cache(fGpu)->resourceAccess().didChangeBudgetStatus(this);
|
||||
}
|
||||
}
|
||||
|
@ -29,18 +29,6 @@ private:
|
||||
SkBudgeted::kYes == fResource->resourcePriv().isBudgeted();
|
||||
}
|
||||
|
||||
/**
|
||||
* Is the resource object wrapping an externally allocated GPU resource that Skia has not taken
|
||||
* ownership of.
|
||||
*/
|
||||
bool isBorrowed() const { return GrGpuResource::kBorrowed_LifeCycle == fResource->fLifeCycle; }
|
||||
|
||||
/**
|
||||
* Is the resource object wrapping an externally allocated GPU resource that Skia has taken
|
||||
* ownership of.
|
||||
*/
|
||||
bool isAdopted() const { return GrGpuResource::kAdopted_LifeCycle == fResource->fLifeCycle; }
|
||||
|
||||
/**
|
||||
* Called by the cache to delete the resource under normal circumstances.
|
||||
*/
|
||||
|
@ -44,7 +44,7 @@ public:
|
||||
* Does the resource count against the resource budget?
|
||||
*/
|
||||
SkBudgeted isBudgeted() const {
|
||||
bool ret = GrGpuResource::kCached_LifeCycle == fResource->fLifeCycle;
|
||||
bool ret = SkBudgeted::kYes == fResource->fBudgeted;
|
||||
SkASSERT(ret || !fResource->getUniqueKey().isValid());
|
||||
return SkBudgeted(ret);
|
||||
}
|
||||
@ -52,7 +52,7 @@ public:
|
||||
/**
|
||||
* Is the resource object wrapping an externally allocated GPU resource?
|
||||
*/
|
||||
bool isExternal() const { return fResource->isExternal(); }
|
||||
bool refsWrappedObjects() const { return fResource->fRefsWrappedObjects; }
|
||||
|
||||
/**
|
||||
* If this resource can be used as a scratch resource this returns a valid scratch key.
|
||||
|
@ -20,7 +20,7 @@ public:
|
||||
* Initialize to a path with a fixed stroke. Stroke must not be hairline.
|
||||
*/
|
||||
GrPath(GrGpu* gpu, const SkPath& skPath, const GrStrokeInfo& stroke)
|
||||
: INHERITED(gpu, kCached_LifeCycle)
|
||||
: INHERITED(gpu)
|
||||
, fBounds(SkRect::MakeEmpty())
|
||||
, fFillType(GrPathRendering::kWinding_FillType)
|
||||
#ifdef SK_DEBUG
|
||||
|
@ -10,7 +10,7 @@
|
||||
|
||||
GrPathRange::GrPathRange(GrGpu* gpu,
|
||||
PathGenerator* pathGenerator)
|
||||
: INHERITED(gpu, kCached_LifeCycle),
|
||||
: INHERITED(gpu),
|
||||
fPathGenerator(SkRef(pathGenerator)),
|
||||
fNumPaths(fPathGenerator->getNumPaths()) {
|
||||
const int numGroups = (fNumPaths + kPathsPerGroup - 1) / kPathsPerGroup;
|
||||
@ -20,7 +20,7 @@ GrPathRange::GrPathRange(GrGpu* gpu,
|
||||
|
||||
GrPathRange::GrPathRange(GrGpu* gpu,
|
||||
int numPaths)
|
||||
: INHERITED(gpu, kCached_LifeCycle),
|
||||
: INHERITED(gpu),
|
||||
fNumPaths(numPaths) {
|
||||
}
|
||||
|
||||
|
@ -146,7 +146,7 @@ void GrResourceCache::insertResource(GrGpuResource* resource) {
|
||||
#endif
|
||||
}
|
||||
if (resource->resourcePriv().getScratchKey().isValid()) {
|
||||
SkASSERT(!resource->resourcePriv().isExternal());
|
||||
SkASSERT(!resource->resourcePriv().refsWrappedObjects());
|
||||
fScratchMap.insert(resource->resourcePriv().getScratchKey(), resource);
|
||||
}
|
||||
|
||||
@ -376,7 +376,7 @@ void GrResourceCache::notifyCntReachedZero(GrGpuResource* resource, uint32_t fla
|
||||
|
||||
if (SkBudgeted::kNo == resource->resourcePriv().isBudgeted()) {
|
||||
// Check whether this resource could still be used as a scratch resource.
|
||||
if (!resource->resourcePriv().isExternal() &&
|
||||
if (!resource->resourcePriv().refsWrappedObjects() &&
|
||||
resource->resourcePriv().getScratchKey().isValid()) {
|
||||
// We won't purge an existing resource to make room for this one.
|
||||
if (fBudgetedCount < fMaxCount &&
|
||||
@ -661,19 +661,19 @@ void GrResourceCache::validate() const {
|
||||
SkASSERT(!resource->getUniqueKey().isValid());
|
||||
++fScratch;
|
||||
SkASSERT(fScratchMap->countForKey(resource->resourcePriv().getScratchKey()));
|
||||
SkASSERT(!resource->resourcePriv().isExternal());
|
||||
SkASSERT(!resource->resourcePriv().refsWrappedObjects());
|
||||
} else if (resource->resourcePriv().getScratchKey().isValid()) {
|
||||
SkASSERT(SkBudgeted::kNo == resource->resourcePriv().isBudgeted() ||
|
||||
resource->getUniqueKey().isValid());
|
||||
++fCouldBeScratch;
|
||||
SkASSERT(fScratchMap->countForKey(resource->resourcePriv().getScratchKey()));
|
||||
SkASSERT(!resource->resourcePriv().isExternal());
|
||||
SkASSERT(!resource->resourcePriv().refsWrappedObjects());
|
||||
}
|
||||
const GrUniqueKey& uniqueKey = resource->getUniqueKey();
|
||||
if (uniqueKey.isValid()) {
|
||||
++fContent;
|
||||
SkASSERT(fUniqueHash->find(uniqueKey) == resource);
|
||||
SkASSERT(!resource->resourcePriv().isExternal());
|
||||
SkASSERT(!resource->resourcePriv().refsWrappedObjects());
|
||||
SkASSERT(SkBudgeted::kYes == resource->resourcePriv().isBudgeted());
|
||||
}
|
||||
|
||||
|
@ -188,9 +188,7 @@ public:
|
||||
int fNumNonPurgeable;
|
||||
|
||||
int fScratch;
|
||||
int fExternal;
|
||||
int fBorrowed;
|
||||
int fAdopted;
|
||||
int fWrapped;
|
||||
size_t fUnbudgetedSize;
|
||||
|
||||
Stats() { this->reset(); }
|
||||
@ -200,9 +198,7 @@ public:
|
||||
fNumPurgeable = 0;
|
||||
fNumNonPurgeable = 0;
|
||||
fScratch = 0;
|
||||
fExternal = 0;
|
||||
fBorrowed = 0;
|
||||
fAdopted = 0;
|
||||
fWrapped = 0;
|
||||
fUnbudgetedSize = 0;
|
||||
}
|
||||
|
||||
@ -210,14 +206,8 @@ public:
|
||||
if (resource->cacheAccess().isScratch()) {
|
||||
++fScratch;
|
||||
}
|
||||
if (resource->resourcePriv().isExternal()) {
|
||||
++fExternal;
|
||||
}
|
||||
if (resource->cacheAccess().isBorrowed()) {
|
||||
++fBorrowed;
|
||||
}
|
||||
if (resource->cacheAccess().isAdopted()) {
|
||||
++fAdopted;
|
||||
if (resource->resourcePriv().refsWrappedObjects()) {
|
||||
++fWrapped;
|
||||
}
|
||||
if (SkBudgeted::kNo == resource->resourcePriv().isBudgeted()) {
|
||||
fUnbudgetedSize += resource->gpuMemorySize();
|
||||
|
@ -52,9 +52,9 @@ public:
|
||||
GrUniqueKey* key);
|
||||
|
||||
protected:
|
||||
GrStencilAttachment(GrGpu* gpu, LifeCycle lifeCycle, int width, int height, int bits,
|
||||
GrStencilAttachment(GrGpu* gpu, int width, int height, int bits,
|
||||
int sampleCnt)
|
||||
: GrGpuResource(gpu, lifeCycle)
|
||||
: GrGpuResource(gpu)
|
||||
, fWidth(width)
|
||||
, fHeight(height)
|
||||
, fBits(bits)
|
||||
|
@ -86,16 +86,10 @@ GrSurfaceOrigin resolve_origin(const GrSurfaceDesc& desc) {
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////////
|
||||
GrTexture::GrTexture(GrGpu* gpu, LifeCycle lifeCycle, const GrSurfaceDesc& desc,
|
||||
GrSLType samplerType, bool wasMipMapDataProvided)
|
||||
: INHERITED(gpu, lifeCycle, desc)
|
||||
GrTexture::GrTexture(GrGpu* gpu, const GrSurfaceDesc& desc, GrSLType samplerType,
|
||||
bool wasMipMapDataProvided)
|
||||
: INHERITED(gpu, desc)
|
||||
, fSamplerType(samplerType) {
|
||||
if (!this->isExternal() && !GrPixelConfigIsCompressed(desc.fConfig)) {
|
||||
GrScratchKey key;
|
||||
GrTexturePriv::ComputeScratchKey(desc, &key);
|
||||
this->setScratchKey(key);
|
||||
}
|
||||
|
||||
if (wasMipMapDataProvided) {
|
||||
fMipMapsStatus = kValid_MipMapsStatus;
|
||||
fMaxMipMapLevel = SkMipMap::ComputeLevelCount(fDesc.fWidth, fDesc.fHeight);
|
||||
@ -105,6 +99,12 @@ GrTexture::GrTexture(GrGpu* gpu, LifeCycle lifeCycle, const GrSurfaceDesc& desc,
|
||||
}
|
||||
}
|
||||
|
||||
void GrTexture::computeScratchKey(GrScratchKey* key) const {
|
||||
if (!GrPixelConfigIsCompressed(fDesc.fConfig)) {
|
||||
GrTexturePriv::ComputeScratchKey(fDesc, key);
|
||||
}
|
||||
}
|
||||
|
||||
void GrTexturePriv::ComputeScratchKey(const GrSurfaceDesc& desc, GrScratchKey* key) {
|
||||
static const GrScratchKey::ResourceType kType = GrScratchKey::GenerateResourceType();
|
||||
|
||||
|
@ -128,7 +128,7 @@ GrGLBuffer::GrGLBuffer(GrGLGpu* gpu, size_t size, GrBufferType intendedType,
|
||||
}
|
||||
}
|
||||
VALIDATE();
|
||||
this->registerWithCache();
|
||||
this->registerWithCache(SkBudgeted::kYes);
|
||||
}
|
||||
|
||||
inline GrGLGpu* GrGLBuffer::glGpu() const {
|
||||
|
@ -649,13 +649,10 @@ GrTexture* GrGLGpu::onWrapBackendTexture(const GrBackendTextureDesc& desc,
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
switch (ownership) {
|
||||
case kAdopt_GrWrapOwnership:
|
||||
idDesc.fLifeCycle = GrGpuResource::kAdopted_LifeCycle;
|
||||
break;
|
||||
case kBorrow_GrWrapOwnership:
|
||||
idDesc.fLifeCycle = GrGpuResource::kBorrowed_LifeCycle;
|
||||
break;
|
||||
if (kAdopt_GrWrapOwnership == ownership) {
|
||||
idDesc.fOwnership = GrBackendObjectOwnership::kOwned;
|
||||
} else {
|
||||
idDesc.fOwnership = GrBackendObjectOwnership::kBorrowed;
|
||||
}
|
||||
|
||||
surfDesc.fFlags = (GrSurfaceFlags) desc.fFlags;
|
||||
@ -676,13 +673,12 @@ GrTexture* GrGLGpu::onWrapBackendTexture(const GrBackendTextureDesc& desc,
|
||||
GrGLTexture* texture = nullptr;
|
||||
if (renderTarget) {
|
||||
GrGLRenderTarget::IDDesc rtIDDesc;
|
||||
if (!this->createRenderTargetObjects(surfDesc, GrGpuResource::kUncached_LifeCycle,
|
||||
idDesc.fInfo, &rtIDDesc)) {
|
||||
if (!this->createRenderTargetObjects(surfDesc, idDesc.fInfo, &rtIDDesc)) {
|
||||
return nullptr;
|
||||
}
|
||||
texture = new GrGLTextureRenderTarget(this, surfDesc, idDesc, rtIDDesc);
|
||||
texture = GrGLTextureRenderTarget::CreateWrapped(this, surfDesc, idDesc, rtIDDesc);
|
||||
} else {
|
||||
texture = new GrGLTexture(this, surfDesc, idDesc);
|
||||
texture = GrGLTexture::CreateWrapped(this, surfDesc, idDesc);
|
||||
}
|
||||
if (nullptr == texture) {
|
||||
return nullptr;
|
||||
@ -697,13 +693,10 @@ GrRenderTarget* GrGLGpu::onWrapBackendRenderTarget(const GrBackendRenderTargetDe
|
||||
idDesc.fRTFBOID = static_cast<GrGLuint>(wrapDesc.fRenderTargetHandle);
|
||||
idDesc.fMSColorRenderbufferID = 0;
|
||||
idDesc.fTexFBOID = GrGLRenderTarget::kUnresolvableFBOID;
|
||||
switch (ownership) {
|
||||
case kAdopt_GrWrapOwnership:
|
||||
idDesc.fLifeCycle = GrGpuResource::kAdopted_LifeCycle;
|
||||
break;
|
||||
case kBorrow_GrWrapOwnership:
|
||||
idDesc.fLifeCycle = GrGpuResource::kBorrowed_LifeCycle;
|
||||
break;
|
||||
if (kAdopt_GrWrapOwnership == ownership) {
|
||||
idDesc.fRTFBOOwnership = GrBackendObjectOwnership::kOwned;
|
||||
} else {
|
||||
idDesc.fRTFBOOwnership = GrBackendObjectOwnership::kBorrowed;
|
||||
}
|
||||
idDesc.fSampleConfig = GrRenderTarget::kUnified_SampleConfig;
|
||||
|
||||
@ -765,8 +758,7 @@ GrRenderTarget* GrGLGpu::onWrapBackendTextureAsRenderTarget(const GrBackendTextu
|
||||
}
|
||||
|
||||
GrGLRenderTarget::IDDesc rtIDDesc;
|
||||
if (!this->createRenderTargetObjects(surfDesc, GrGpuResource::kUncached_LifeCycle,
|
||||
texInfo, &rtIDDesc)) {
|
||||
if (!this->createRenderTargetObjects(surfDesc, texInfo, &rtIDDesc)) {
|
||||
return nullptr;
|
||||
}
|
||||
return GrGLRenderTarget::CreateWrapped(this, surfDesc, rtIDDesc, 0);
|
||||
@ -1487,13 +1479,12 @@ static bool renderbuffer_storage_msaa(const GrGLContext& ctx,
|
||||
}
|
||||
|
||||
bool GrGLGpu::createRenderTargetObjects(const GrSurfaceDesc& desc,
|
||||
GrGpuResource::LifeCycle lifeCycle,
|
||||
const GrGLTextureInfo& texInfo,
|
||||
GrGLRenderTarget::IDDesc* idDesc) {
|
||||
idDesc->fMSColorRenderbufferID = 0;
|
||||
idDesc->fRTFBOID = 0;
|
||||
idDesc->fRTFBOOwnership = GrBackendObjectOwnership::kOwned;
|
||||
idDesc->fTexFBOID = 0;
|
||||
idDesc->fLifeCycle = lifeCycle;
|
||||
idDesc->fSampleConfig = (GrGLCaps::kMixedSamples_MSFBOType == this->glCaps().msFBOType() &&
|
||||
desc.fSampleCnt > 0) ? GrRenderTarget::kStencil_SampleConfig :
|
||||
GrRenderTarget::kUnified_SampleConfig;
|
||||
@ -1605,12 +1596,11 @@ static size_t as_size_t(int x) {
|
||||
}
|
||||
#endif
|
||||
|
||||
static GrGLTexture::IDDesc generate_gl_texture(const GrGLInterface* interface,
|
||||
GrGpuResource::LifeCycle lifeCycle) {
|
||||
static GrGLTexture::IDDesc generate_gl_texture(const GrGLInterface* interface) {
|
||||
GrGLTexture::IDDesc idDesc;
|
||||
idDesc.fInfo.fID = 0;
|
||||
GR_GL_CALL(interface, GenTextures(1, &idDesc.fInfo.fID));
|
||||
idDesc.fLifeCycle = lifeCycle;
|
||||
idDesc.fOwnership = GrBackendObjectOwnership::kOwned;
|
||||
// When we create the texture, we only
|
||||
// create GL_TEXTURE_2D at the moment.
|
||||
// External clients can do something different.
|
||||
@ -1645,7 +1635,7 @@ static void set_initial_texture_params(const GrGLInterface* interface,
|
||||
}
|
||||
|
||||
GrTexture* GrGLGpu::onCreateTexture(const GrSurfaceDesc& desc,
|
||||
GrGpuResource::LifeCycle lifeCycle,
|
||||
SkBudgeted budgeted,
|
||||
const SkTArray<GrMipLevel>& texels) {
|
||||
// We fail if the MSAA was requested and is not available.
|
||||
if (GrGLCaps::kNone_MSFBOType == this->glCaps().msFBOType() && desc.fSampleCnt) {
|
||||
@ -1656,7 +1646,7 @@ GrTexture* GrGLGpu::onCreateTexture(const GrSurfaceDesc& desc,
|
||||
bool renderTarget = SkToBool(desc.fFlags & kRenderTarget_GrSurfaceFlag);
|
||||
|
||||
GrGLTexture::IDDesc idDesc;
|
||||
idDesc.fLifeCycle = lifeCycle;
|
||||
idDesc.fOwnership = GrBackendObjectOwnership::kOwned;
|
||||
GrGLTexture::TexParams initialTexParams;
|
||||
if (!this->createTextureImpl(desc, &idDesc.fInfo, renderTarget, &initialTexParams, texels)) {
|
||||
return return_null_texture();
|
||||
@ -1668,17 +1658,17 @@ GrTexture* GrGLGpu::onCreateTexture(const GrSurfaceDesc& desc,
|
||||
GL_CALL(BindTexture(idDesc.fInfo.fTarget, 0));
|
||||
GrGLRenderTarget::IDDesc rtIDDesc;
|
||||
|
||||
if (!this->createRenderTargetObjects(desc, lifeCycle, idDesc.fInfo, &rtIDDesc)) {
|
||||
if (!this->createRenderTargetObjects(desc, idDesc.fInfo, &rtIDDesc)) {
|
||||
GL_CALL(DeleteTextures(1, &idDesc.fInfo.fID));
|
||||
return return_null_texture();
|
||||
}
|
||||
tex = new GrGLTextureRenderTarget(this, desc, idDesc, rtIDDesc);
|
||||
tex = new GrGLTextureRenderTarget(this, budgeted, desc, idDesc, rtIDDesc);
|
||||
} else {
|
||||
bool wasMipMapDataProvided = false;
|
||||
if (texels.count() > 1) {
|
||||
wasMipMapDataProvided = true;
|
||||
}
|
||||
tex = new GrGLTexture(this, desc, idDesc, wasMipMapDataProvided);
|
||||
tex = new GrGLTexture(this, budgeted, desc, idDesc, wasMipMapDataProvided);
|
||||
}
|
||||
tex->setCachedTexParams(initialTexParams, this->getResetTimestamp());
|
||||
#ifdef TRACE_TEXTURE_CREATION
|
||||
@ -1689,14 +1679,14 @@ GrTexture* GrGLGpu::onCreateTexture(const GrSurfaceDesc& desc,
|
||||
}
|
||||
|
||||
GrTexture* GrGLGpu::onCreateCompressedTexture(const GrSurfaceDesc& desc,
|
||||
GrGpuResource::LifeCycle lifeCycle,
|
||||
SkBudgeted budgeted,
|
||||
const SkTArray<GrMipLevel>& texels) {
|
||||
// Make sure that we're not flipping Y.
|
||||
if (kBottomLeft_GrSurfaceOrigin == desc.fOrigin) {
|
||||
return return_null_texture();
|
||||
}
|
||||
|
||||
GrGLTexture::IDDesc idDesc = generate_gl_texture(this->glInterface(), lifeCycle);
|
||||
GrGLTexture::IDDesc idDesc = generate_gl_texture(this->glInterface());
|
||||
if (!idDesc.fInfo.fID) {
|
||||
return return_null_texture();
|
||||
}
|
||||
@ -1713,7 +1703,7 @@ GrTexture* GrGLGpu::onCreateCompressedTexture(const GrSurfaceDesc& desc,
|
||||
}
|
||||
|
||||
GrGLTexture* tex;
|
||||
tex = new GrGLTexture(this, desc, idDesc);
|
||||
tex = new GrGLTexture(this, budgeted, desc, idDesc);
|
||||
tex->setCachedTexParams(initialTexParams, this->getResetTimestamp());
|
||||
#ifdef TRACE_TEXTURE_CREATION
|
||||
SkDebugf("--- new compressed texture [%d] size=(%d %d) config=%d\n",
|
||||
|
@ -126,10 +126,10 @@ private:
|
||||
|
||||
void xferBarrier(GrRenderTarget*, GrXferBarrierType) override;
|
||||
|
||||
GrTexture* onCreateTexture(const GrSurfaceDesc& desc, GrGpuResource::LifeCycle lifeCycle,
|
||||
GrTexture* onCreateTexture(const GrSurfaceDesc& desc, SkBudgeted budgeted,
|
||||
const SkTArray<GrMipLevel>& texels) override;
|
||||
GrTexture* onCreateCompressedTexture(const GrSurfaceDesc& desc,
|
||||
GrGpuResource::LifeCycle lifeCycle,
|
||||
SkBudgeted budgeted,
|
||||
const SkTArray<GrMipLevel>& texels) override;
|
||||
|
||||
GrBuffer* onCreateBuffer(size_t size, GrBufferType intendedType, GrAccessPattern,
|
||||
@ -347,8 +347,8 @@ private:
|
||||
int left = 0, int top = 0,
|
||||
int width = -1, int height = -1);
|
||||
|
||||
bool createRenderTargetObjects(const GrSurfaceDesc&, GrGpuResource::LifeCycle lifeCycle,
|
||||
const GrGLTextureInfo& texInfo, GrGLRenderTarget::IDDesc*);
|
||||
bool createRenderTargetObjects(const GrSurfaceDesc&, const GrGLTextureInfo& texInfo,
|
||||
GrGLRenderTarget::IDDesc*);
|
||||
|
||||
enum TempFBOTarget {
|
||||
kSrc_TempFBOTarget,
|
||||
|
@ -330,11 +330,11 @@ GrGLPath::GrGLPath(GrGLGpu* gpu, const SkPath& origSkPath, const GrStrokeInfo& o
|
||||
}
|
||||
}
|
||||
|
||||
this->registerWithCache();
|
||||
this->registerWithCache(SkBudgeted::kYes);
|
||||
}
|
||||
|
||||
void GrGLPath::onRelease() {
|
||||
if (0 != fPathID && this->shouldFreeResources()) {
|
||||
if (0 != fPathID) {
|
||||
static_cast<GrGLGpu*>(this->getGpu())->glPathRendering()->deletePaths(fPathID, 1);
|
||||
fPathID = 0;
|
||||
}
|
||||
|
@ -16,7 +16,7 @@ GrGLPathRange::GrGLPathRange(GrGLGpu* gpu, PathGenerator* pathGenerator, const G
|
||||
fBasePathID(gpu->glPathRendering()->genPaths(this->getNumPaths())),
|
||||
fGpuMemorySize(0) {
|
||||
this->init();
|
||||
this->registerWithCache();
|
||||
this->registerWithCache(SkBudgeted::kYes);
|
||||
}
|
||||
|
||||
GrGLPathRange::GrGLPathRange(GrGLGpu* gpu,
|
||||
@ -29,7 +29,7 @@ GrGLPathRange::GrGLPathRange(GrGLGpu* gpu,
|
||||
fBasePathID(basePathID),
|
||||
fGpuMemorySize(gpuMemorySize) {
|
||||
this->init();
|
||||
this->registerWithCache();
|
||||
this->registerWithCache(SkBudgeted::kYes);
|
||||
}
|
||||
|
||||
void GrGLPathRange::init() {
|
||||
@ -101,7 +101,7 @@ void GrGLPathRange::onInitPath(int index, const SkPath& origSkPath) const {
|
||||
void GrGLPathRange::onRelease() {
|
||||
SkASSERT(this->getGpu());
|
||||
|
||||
if (0 != fBasePathID && this->shouldFreeResources()) {
|
||||
if (0 != fBasePathID) {
|
||||
static_cast<GrGLGpu*>(this->getGpu())->glPathRendering()->deletePaths(fBasePathID,
|
||||
this->getNumPaths());
|
||||
fBasePathID = 0;
|
||||
|
@ -7,29 +7,31 @@
|
||||
|
||||
#include "GrGLRenderTarget.h"
|
||||
|
||||
#include "GrRenderTargetPriv.h"
|
||||
#include "GrGLGpu.h"
|
||||
#include "GrGLUtil.h"
|
||||
#include "GrGpuResourcePriv.h"
|
||||
#include "GrRenderTargetPriv.h"
|
||||
#include "SkTraceMemoryDump.h"
|
||||
|
||||
#define GPUGL static_cast<GrGLGpu*>(this->getGpu())
|
||||
#define GL_CALL(X) GR_GL_CALL(GPUGL->glInterface(), X)
|
||||
|
||||
// Because this class is virtually derived from GrSurface we must explicitly call its constructor.
|
||||
// Constructor for wrapped render targets.
|
||||
GrGLRenderTarget::GrGLRenderTarget(GrGLGpu* gpu,
|
||||
const GrSurfaceDesc& desc,
|
||||
const IDDesc& idDesc,
|
||||
GrGLStencilAttachment* stencil)
|
||||
: GrSurface(gpu, idDesc.fLifeCycle, desc)
|
||||
, INHERITED(gpu, idDesc.fLifeCycle, desc, idDesc.fSampleConfig, stencil) {
|
||||
: GrSurface(gpu, desc)
|
||||
, INHERITED(gpu, desc, idDesc.fSampleConfig, stencil) {
|
||||
this->init(desc, idDesc);
|
||||
this->registerWithCache();
|
||||
this->registerWithCacheWrapped();
|
||||
}
|
||||
|
||||
GrGLRenderTarget::GrGLRenderTarget(GrGLGpu* gpu, const GrSurfaceDesc& desc, const IDDesc& idDesc,
|
||||
Derived)
|
||||
: GrSurface(gpu, idDesc.fLifeCycle, desc)
|
||||
, INHERITED(gpu, idDesc.fLifeCycle, desc, idDesc.fSampleConfig) {
|
||||
GrGLRenderTarget::GrGLRenderTarget(GrGLGpu* gpu, const GrSurfaceDesc& desc,
|
||||
const IDDesc& idDesc)
|
||||
: GrSurface(gpu, desc)
|
||||
, INHERITED(gpu, desc, idDesc.fSampleConfig) {
|
||||
this->init(desc, idDesc);
|
||||
}
|
||||
|
||||
@ -37,7 +39,7 @@ void GrGLRenderTarget::init(const GrSurfaceDesc& desc, const IDDesc& idDesc) {
|
||||
fRTFBOID = idDesc.fRTFBOID;
|
||||
fTexFBOID = idDesc.fTexFBOID;
|
||||
fMSColorRenderbufferID = idDesc.fMSColorRenderbufferID;
|
||||
fRTLifecycle = idDesc.fLifeCycle;
|
||||
fRTFBOOwnership = idDesc.fRTFBOOwnership;
|
||||
|
||||
fViewport.fLeft = 0;
|
||||
fViewport.fBottom = 0;
|
||||
@ -127,7 +129,7 @@ bool GrGLRenderTarget::completeStencilAttachment() {
|
||||
}
|
||||
|
||||
void GrGLRenderTarget::onRelease() {
|
||||
if (kBorrowed_LifeCycle != fRTLifecycle) {
|
||||
if (GrBackendObjectOwnership::kBorrowed != fRTFBOOwnership) {
|
||||
if (fTexFBOID) {
|
||||
GL_CALL(DeleteFramebuffers(1, &fTexFBOID));
|
||||
}
|
||||
@ -156,6 +158,13 @@ GrGLGpu* GrGLRenderTarget::getGLGpu() const {
|
||||
return static_cast<GrGLGpu*>(this->getGpu());
|
||||
}
|
||||
|
||||
bool GrGLRenderTarget::canAttemptStencilAttachment() const {
|
||||
// When we have not created the FBO ID we do not attempt to modify its attachments.
|
||||
// Direct GrGLRenderTarget instances are always created with CreateWrapped.
|
||||
SkASSERT(this->resourcePriv().refsWrappedObjects());
|
||||
return false;
|
||||
}
|
||||
|
||||
void GrGLRenderTarget::dumpMemoryStatistics(SkTraceMemoryDump* traceMemoryDump) const {
|
||||
// Don't log the backing texture's contribution to the memory size. This will be handled by the
|
||||
// texture object.
|
||||
|
@ -24,9 +24,9 @@ public:
|
||||
|
||||
struct IDDesc {
|
||||
GrGLuint fRTFBOID;
|
||||
GrBackendObjectOwnership fRTFBOOwnership;
|
||||
GrGLuint fTexFBOID;
|
||||
GrGLuint fMSColorRenderbufferID;
|
||||
GrGpuResource::LifeCycle fLifeCycle;
|
||||
GrRenderTarget::SampleConfig fSampleConfig;
|
||||
};
|
||||
|
||||
@ -61,21 +61,15 @@ public:
|
||||
|
||||
GrBackendObject getRenderTargetHandle() const override { return fRTFBOID; }
|
||||
|
||||
/** When we don't own the FBO ID we don't attempt to modify its attachments. */
|
||||
bool canAttemptStencilAttachment() const override {
|
||||
return kCached_LifeCycle == fRTLifecycle || kUncached_LifeCycle == fRTLifecycle;
|
||||
}
|
||||
bool canAttemptStencilAttachment() const override;
|
||||
|
||||
// GrGLRenderTarget overrides dumpMemoryStatistics so it can log its texture and renderbuffer
|
||||
// components seperately.
|
||||
void dumpMemoryStatistics(SkTraceMemoryDump* traceMemoryDump) const override;
|
||||
|
||||
protected:
|
||||
// The public constructor registers this object with the cache. However, only the most derived
|
||||
// class should register with the cache. This constructor does not do the registration and
|
||||
// rather moves that burden onto the derived class.
|
||||
enum Derived { kDerived };
|
||||
GrGLRenderTarget(GrGLGpu*, const GrSurfaceDesc&, const IDDesc&, Derived);
|
||||
// Constructor for subclasses.
|
||||
GrGLRenderTarget(GrGLGpu*, const GrSurfaceDesc&, const IDDesc&);
|
||||
|
||||
void init(const GrSurfaceDesc&, const IDDesc&);
|
||||
|
||||
@ -86,8 +80,7 @@ protected:
|
||||
size_t onGpuMemorySize() const override;
|
||||
|
||||
private:
|
||||
// This ctor is used only for creating wrapped render targets and is only called for the static
|
||||
// create function CreateWrapped(...).
|
||||
// Constructor for instances wrapping backend objects.
|
||||
GrGLRenderTarget(GrGLGpu*, const GrSurfaceDesc&, const IDDesc&, GrGLStencilAttachment*);
|
||||
|
||||
GrGLGpu* getGLGpu() const;
|
||||
@ -103,9 +96,7 @@ private:
|
||||
GrGLuint fTexFBOID;
|
||||
GrGLuint fMSColorRenderbufferID;
|
||||
|
||||
// We track this separately from GrGpuResource because this may be both a texture and a render
|
||||
// target, and the texture may be wrapped while the render target is not.
|
||||
LifeCycle fRTLifecycle;
|
||||
GrBackendObjectOwnership fRTFBOOwnership;
|
||||
|
||||
// when we switch to this render target we want to set the viewport to
|
||||
// only render to content area (as opposed to the whole allocation) and
|
||||
|
@ -19,7 +19,7 @@ size_t GrGLStencilAttachment::onGpuMemorySize() const {
|
||||
}
|
||||
|
||||
void GrGLStencilAttachment::onRelease() {
|
||||
if (0 != fRenderbufferID && this->shouldFreeResources()) {
|
||||
if (0 != fRenderbufferID) {
|
||||
GrGLGpu* gpuGL = (GrGLGpu*) this->getGpu();
|
||||
const GrGLInterface* gl = gpuGL->glInterface();
|
||||
GR_GL_CALL(gl, DeleteRenderbuffers(1, &fRenderbufferID));
|
||||
|
@ -24,20 +24,19 @@ public:
|
||||
};
|
||||
|
||||
struct IDDesc {
|
||||
IDDesc() : fRenderbufferID(0), fLifeCycle(kCached_LifeCycle) {}
|
||||
IDDesc() : fRenderbufferID(0) {}
|
||||
GrGLuint fRenderbufferID;
|
||||
GrGpuResource::LifeCycle fLifeCycle;
|
||||
};
|
||||
|
||||
GrGLStencilAttachment(GrGpu* gpu,
|
||||
const IDDesc& idDesc,
|
||||
int width, int height,
|
||||
int sampleCnt,
|
||||
const Format& format)
|
||||
: GrStencilAttachment(gpu, idDesc.fLifeCycle, width, height, format.fStencilBits, sampleCnt)
|
||||
const IDDesc& idDesc,
|
||||
int width, int height,
|
||||
int sampleCnt,
|
||||
const Format& format)
|
||||
: GrStencilAttachment(gpu, width, height, format.fStencilBits, sampleCnt)
|
||||
, fFormat(format)
|
||||
, fRenderbufferID(idDesc.fRenderbufferID) {
|
||||
this->registerWithCache();
|
||||
this->registerWithCache(SkBudgeted::kYes);
|
||||
}
|
||||
|
||||
GrGLuint renderbufferID() const {
|
||||
|
@ -26,24 +26,33 @@ inline static GrSLType sampler_type(const GrGLTexture::IDDesc& idDesc, const GrG
|
||||
}
|
||||
|
||||
// Because this class is virtually derived from GrSurface we must explicitly call its constructor.
|
||||
GrGLTexture::GrGLTexture(GrGLGpu* gpu, const GrSurfaceDesc& desc, const IDDesc& idDesc)
|
||||
: GrSurface(gpu, idDesc.fLifeCycle, desc)
|
||||
, INHERITED(gpu, idDesc.fLifeCycle, desc, sampler_type(idDesc, gpu), false) {
|
||||
GrGLTexture::GrGLTexture(GrGLGpu* gpu, SkBudgeted budgeted, const GrSurfaceDesc& desc,
|
||||
const IDDesc& idDesc)
|
||||
: GrSurface(gpu, desc)
|
||||
, INHERITED(gpu, desc, sampler_type(idDesc, gpu), false) {
|
||||
this->init(desc, idDesc);
|
||||
this->registerWithCache();
|
||||
this->registerWithCache(budgeted);
|
||||
}
|
||||
|
||||
GrGLTexture::GrGLTexture(GrGLGpu* gpu, const GrSurfaceDesc& desc, const IDDesc& idDesc,
|
||||
GrGLTexture::GrGLTexture(GrGLGpu* gpu, SkBudgeted budgeted, const GrSurfaceDesc& desc,
|
||||
const IDDesc& idDesc,
|
||||
bool wasMipMapDataProvided)
|
||||
: GrSurface(gpu, idDesc.fLifeCycle, desc)
|
||||
, INHERITED(gpu, idDesc.fLifeCycle, desc, sampler_type(idDesc, gpu), wasMipMapDataProvided) {
|
||||
: GrSurface(gpu, desc)
|
||||
, INHERITED(gpu, desc, sampler_type(idDesc, gpu), wasMipMapDataProvided) {
|
||||
this->init(desc, idDesc);
|
||||
this->registerWithCache();
|
||||
this->registerWithCache(budgeted);
|
||||
}
|
||||
|
||||
GrGLTexture::GrGLTexture(GrGLGpu* gpu, const GrSurfaceDesc& desc, const IDDesc& idDesc, Derived)
|
||||
: GrSurface(gpu, idDesc.fLifeCycle, desc)
|
||||
, INHERITED(gpu, idDesc.fLifeCycle, desc, sampler_type(idDesc, gpu), false) {
|
||||
GrGLTexture::GrGLTexture(GrGLGpu* gpu, Wrapped, const GrSurfaceDesc& desc, const IDDesc& idDesc)
|
||||
: GrSurface(gpu, desc)
|
||||
, INHERITED(gpu, desc, sampler_type(idDesc, gpu), false) {
|
||||
this->init(desc, idDesc);
|
||||
this->registerWithCacheWrapped();
|
||||
}
|
||||
|
||||
GrGLTexture::GrGLTexture(GrGLGpu* gpu, const GrSurfaceDesc& desc, const IDDesc& idDesc)
|
||||
: GrSurface(gpu, desc)
|
||||
, INHERITED(gpu, desc, sampler_type(idDesc, gpu), false) {
|
||||
this->init(desc, idDesc);
|
||||
}
|
||||
|
||||
@ -52,12 +61,12 @@ void GrGLTexture::init(const GrSurfaceDesc& desc, const IDDesc& idDesc) {
|
||||
fTexParams.invalidate();
|
||||
fTexParamsTimestamp = GrGpu::kExpiredTimestamp;
|
||||
fInfo = idDesc.fInfo;
|
||||
fTextureIDLifecycle = idDesc.fLifeCycle;
|
||||
fTextureIDOwnership = idDesc.fOwnership;
|
||||
}
|
||||
|
||||
void GrGLTexture::onRelease() {
|
||||
if (fInfo.fID) {
|
||||
if (GrGpuResource::kBorrowed_LifeCycle != fTextureIDLifecycle) {
|
||||
if (GrBackendObjectOwnership::kBorrowed != fTextureIDOwnership) {
|
||||
GL_CALL(DeleteTextures(1, &fInfo.fID));
|
||||
}
|
||||
fInfo.fID = 0;
|
||||
@ -86,3 +95,9 @@ void GrGLTexture::setMemoryBacking(SkTraceMemoryDump* traceMemoryDump,
|
||||
traceMemoryDump->setMemoryBacking(dumpName.c_str(), "gl_texture",
|
||||
texture_id.c_str());
|
||||
}
|
||||
|
||||
GrGLTexture* GrGLTexture::CreateWrapped(GrGLGpu* gpu, const GrSurfaceDesc& desc,
|
||||
const IDDesc& idDesc) {
|
||||
return new GrGLTexture(gpu, kWrapped, desc, idDesc);
|
||||
}
|
||||
|
||||
|
@ -16,7 +16,6 @@
|
||||
class GrGLGpu;
|
||||
|
||||
class GrGLTexture : public GrTexture {
|
||||
|
||||
public:
|
||||
struct TexParams {
|
||||
GrGLenum fMinFilter;
|
||||
@ -31,11 +30,11 @@ public:
|
||||
|
||||
struct IDDesc {
|
||||
GrGLTextureInfo fInfo;
|
||||
GrGpuResource::LifeCycle fLifeCycle;
|
||||
GrBackendObjectOwnership fOwnership;
|
||||
};
|
||||
|
||||
GrGLTexture(GrGLGpu*, const GrSurfaceDesc&, const IDDesc&);
|
||||
GrGLTexture(GrGLGpu*, const GrSurfaceDesc&, const IDDesc&, bool wasMipMapDataProvided);
|
||||
GrGLTexture(GrGLGpu*, SkBudgeted, const GrSurfaceDesc&, const IDDesc&);
|
||||
GrGLTexture(GrGLGpu*, SkBudgeted, const GrSurfaceDesc&, const IDDesc&,
|
||||
bool wasMipMapDataProvided);
|
||||
|
||||
GrBackendObject getTextureHandle() const override;
|
||||
|
||||
@ -57,12 +56,14 @@ public:
|
||||
|
||||
GrGLenum target() const { return fInfo.fTarget; }
|
||||
|
||||
static GrGLTexture* CreateWrapped(GrGLGpu*, const GrSurfaceDesc&, const IDDesc&);
|
||||
protected:
|
||||
// The public constructor registers this object with the cache. However, only the most derived
|
||||
// class should register with the cache. This constructor does not do the registration and
|
||||
// rather moves that burden onto the derived class.
|
||||
enum Derived { kDerived };
|
||||
GrGLTexture(GrGLGpu*, const GrSurfaceDesc&, const IDDesc&, Derived);
|
||||
// Constructor for subclasses.
|
||||
GrGLTexture(GrGLGpu*, const GrSurfaceDesc&, const IDDesc&);
|
||||
|
||||
enum Wrapped { kWrapped };
|
||||
// Constructor for instances wrapping backend objects.
|
||||
GrGLTexture(GrGLGpu*, Wrapped, const GrSurfaceDesc&, const IDDesc&);
|
||||
|
||||
void init(const GrSurfaceDesc&, const IDDesc&);
|
||||
|
||||
@ -77,10 +78,7 @@ private:
|
||||
// Holds the texture target and ID. A pointer to this may be shared to external clients for
|
||||
// direct interaction with the GL object.
|
||||
GrGLTextureInfo fInfo;
|
||||
|
||||
// We track this separately from GrGpuResource because this may be both a texture and a render
|
||||
// target, and the texture may be wrapped while the render target is not.
|
||||
LifeCycle fTextureIDLifecycle;
|
||||
GrBackendObjectOwnership fTextureIDOwnership;
|
||||
|
||||
typedef GrTexture INHERITED;
|
||||
};
|
||||
|
@ -37,3 +37,16 @@ void GrGLTextureRenderTarget::dumpMemoryStatistics(
|
||||
traceMemoryDump->setMemoryBacking(dumpName.c_str(), "gl_texture",
|
||||
texture_id.c_str());
|
||||
}
|
||||
|
||||
bool GrGLTextureRenderTarget::canAttemptStencilAttachment() const {
|
||||
// The RT FBO of GrGLTextureRenderTarget is never created from a
|
||||
// wrapped FBO.
|
||||
return true;
|
||||
}
|
||||
|
||||
GrGLTextureRenderTarget* GrGLTextureRenderTarget::CreateWrapped(GrGLGpu* gpu,
|
||||
const GrSurfaceDesc& desc,
|
||||
const GrGLTexture::IDDesc& texIDDesc,
|
||||
const GrGLRenderTarget::IDDesc& rtIDDesc) {
|
||||
return new GrGLTextureRenderTarget(gpu, desc, texIDDesc, rtIDDesc);
|
||||
}
|
||||
|
@ -26,17 +26,23 @@ public:
|
||||
// We're virtually derived from GrSurface (via both GrGLTexture and GrGLRenderTarget) so its
|
||||
// constructor must be explicitly called.
|
||||
GrGLTextureRenderTarget(GrGLGpu* gpu,
|
||||
SkBudgeted budgeted,
|
||||
const GrSurfaceDesc& desc,
|
||||
const GrGLTexture::IDDesc& texIDDesc,
|
||||
const GrGLRenderTarget::IDDesc& rtIDDesc)
|
||||
: GrSurface(gpu, texIDDesc.fLifeCycle, desc)
|
||||
, GrGLTexture(gpu, desc, texIDDesc, GrGLTexture::kDerived)
|
||||
, GrGLRenderTarget(gpu, desc, rtIDDesc, GrGLRenderTarget::kDerived) {
|
||||
this->registerWithCache();
|
||||
: GrSurface(gpu, desc)
|
||||
, GrGLTexture(gpu, desc, texIDDesc)
|
||||
, GrGLRenderTarget(gpu, desc, rtIDDesc) {
|
||||
this->registerWithCache(budgeted);
|
||||
}
|
||||
|
||||
bool canAttemptStencilAttachment() const override;
|
||||
|
||||
void dumpMemoryStatistics(SkTraceMemoryDump* traceMemoryDump) const override;
|
||||
|
||||
static GrGLTextureRenderTarget* CreateWrapped(GrGLGpu* gpu, const GrSurfaceDesc& desc,
|
||||
const GrGLTexture::IDDesc& texIDDesc,
|
||||
const GrGLRenderTarget::IDDesc& rtIDDesc);
|
||||
protected:
|
||||
void onAbandon() override {
|
||||
GrGLRenderTarget::onAbandon();
|
||||
@ -49,6 +55,17 @@ protected:
|
||||
}
|
||||
|
||||
private:
|
||||
// Constructor for instances wrapping backend objects.
|
||||
GrGLTextureRenderTarget(GrGLGpu* gpu,
|
||||
const GrSurfaceDesc& desc,
|
||||
const GrGLTexture::IDDesc& texIDDesc,
|
||||
const GrGLRenderTarget::IDDesc& rtIDDesc)
|
||||
: GrSurface(gpu, desc)
|
||||
, GrGLTexture(gpu, desc, texIDDesc)
|
||||
, GrGLRenderTarget(gpu, desc, rtIDDesc) {
|
||||
this->registerWithCacheWrapped();
|
||||
}
|
||||
|
||||
// GrGLRenderTarget accounts for the texture's memory and any MSAA renderbuffer's memory.
|
||||
size_t onGpuMemorySize() const override {
|
||||
return GrGLRenderTarget::onGpuMemorySize();
|
||||
|
@ -438,7 +438,7 @@ bool GrVkGpu::uploadTexData(GrVkTexture* tex,
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
GrTexture* GrVkGpu::onCreateTexture(const GrSurfaceDesc& desc, GrGpuResource::LifeCycle lifeCycle,
|
||||
GrTexture* GrVkGpu::onCreateTexture(const GrSurfaceDesc& desc, SkBudgeted budgeted,
|
||||
const SkTArray<GrMipLevel>& texels) {
|
||||
bool renderTarget = SkToBool(desc.fFlags & kRenderTarget_GrSurfaceFlag);
|
||||
|
||||
@ -493,10 +493,10 @@ GrTexture* GrVkGpu::onCreateTexture(const GrSurfaceDesc& desc, GrGpuResource::Li
|
||||
|
||||
GrVkTexture* tex;
|
||||
if (renderTarget) {
|
||||
tex = GrVkTextureRenderTarget::CreateNewTextureRenderTarget(this, desc, lifeCycle,
|
||||
tex = GrVkTextureRenderTarget::CreateNewTextureRenderTarget(this, budgeted, desc,
|
||||
imageDesc);
|
||||
} else {
|
||||
tex = GrVkTexture::CreateNewTexture(this, desc, lifeCycle, imageDesc);
|
||||
tex = GrVkTexture::CreateNewTexture(this, budgeted, desc, imageDesc);
|
||||
}
|
||||
|
||||
if (!tex) {
|
||||
@ -548,10 +548,6 @@ GrTexture* GrVkGpu::onWrapBackendTexture(const GrBackendTextureDesc& desc,
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
GrGpuResource::LifeCycle lifeCycle = (kAdopt_GrWrapOwnership == ownership)
|
||||
? GrGpuResource::kAdopted_LifeCycle
|
||||
: GrGpuResource::kBorrowed_LifeCycle;
|
||||
|
||||
GrSurfaceDesc surfDesc;
|
||||
// next line relies on GrBackendTextureDesc's flags matching GrTexture's
|
||||
surfDesc.fFlags = (GrSurfaceFlags)desc.fFlags;
|
||||
@ -567,11 +563,10 @@ GrTexture* GrVkGpu::onWrapBackendTexture(const GrBackendTextureDesc& desc,
|
||||
GrVkTexture* texture = nullptr;
|
||||
if (renderTarget) {
|
||||
texture = GrVkTextureRenderTarget::CreateWrappedTextureRenderTarget(this, surfDesc,
|
||||
lifeCycle, format,
|
||||
ownership, format,
|
||||
info);
|
||||
} else {
|
||||
texture = GrVkTexture::CreateWrappedTexture(this, surfDesc, lifeCycle, format,
|
||||
info);
|
||||
texture = GrVkTexture::CreateWrappedTexture(this, surfDesc, ownership, format, info);
|
||||
}
|
||||
if (!texture) {
|
||||
return nullptr;
|
||||
@ -590,10 +585,6 @@ GrRenderTarget* GrVkGpu::onWrapBackendRenderTarget(const GrBackendRenderTargetDe
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
GrGpuResource::LifeCycle lifeCycle = (kAdopt_GrWrapOwnership == ownership)
|
||||
? GrGpuResource::kAdopted_LifeCycle
|
||||
: GrGpuResource::kBorrowed_LifeCycle;
|
||||
|
||||
GrSurfaceDesc desc;
|
||||
desc.fConfig = wrapDesc.fConfig;
|
||||
desc.fFlags = kCheckAllocation_GrSurfaceFlag;
|
||||
@ -604,7 +595,7 @@ GrRenderTarget* GrVkGpu::onWrapBackendRenderTarget(const GrBackendRenderTargetDe
|
||||
desc.fOrigin = resolve_origin(wrapDesc.fOrigin);
|
||||
|
||||
GrVkRenderTarget* tgt = GrVkRenderTarget::CreateWrappedRenderTarget(this, desc,
|
||||
lifeCycle,
|
||||
ownership,
|
||||
info);
|
||||
if (tgt && wrapDesc.fStencilBits) {
|
||||
if (!createStencilAttachmentForRenderTarget(tgt, desc.fWidth, desc.fHeight)) {
|
||||
@ -652,7 +643,6 @@ GrStencilAttachment* GrVkGpu::createStencilAttachmentForRenderTarget(const GrRen
|
||||
const GrVkCaps::StencilFormat& sFmt = this->vkCaps().preferedStencilFormat();
|
||||
|
||||
GrVkStencilAttachment* stencil(GrVkStencilAttachment::Create(this,
|
||||
GrGpuResource::kCached_LifeCycle,
|
||||
width,
|
||||
height,
|
||||
samples,
|
||||
|
@ -117,10 +117,10 @@ private:
|
||||
|
||||
void onResetContext(uint32_t resetBits) override {}
|
||||
|
||||
GrTexture* onCreateTexture(const GrSurfaceDesc& desc, GrGpuResource::LifeCycle,
|
||||
GrTexture* onCreateTexture(const GrSurfaceDesc& desc, SkBudgeted budgeted,
|
||||
const SkTArray<GrMipLevel>&) override;
|
||||
|
||||
GrTexture* onCreateCompressedTexture(const GrSurfaceDesc& desc, GrGpuResource::LifeCycle,
|
||||
GrTexture* onCreateCompressedTexture(const GrSurfaceDesc& desc, SkBudgeted,
|
||||
const SkTArray<GrMipLevel>&) override { return NULL; }
|
||||
|
||||
GrTexture* onWrapBackendTexture(const GrBackendTextureDesc&, GrWrapOwnership) override;
|
||||
|
@ -13,7 +13,7 @@ GrVkIndexBuffer::GrVkIndexBuffer(GrVkGpu* gpu, const GrVkBuffer::Desc& desc,
|
||||
: INHERITED(gpu, desc.fSizeInBytes, kIndex_GrBufferType,
|
||||
desc.fDynamic ? kDynamic_GrAccessPattern : kStatic_GrAccessPattern, false)
|
||||
, GrVkBuffer(desc, bufferResource) {
|
||||
this->registerWithCache();
|
||||
this->registerWithCache(SkBudgeted::kYes);
|
||||
}
|
||||
|
||||
GrVkIndexBuffer* GrVkIndexBuffer::Create(GrVkGpu* gpu, size_t size, bool dynamic) {
|
||||
|
@ -22,16 +22,16 @@
|
||||
// We're virtually derived from GrSurface (via GrRenderTarget) so its
|
||||
// constructor must be explicitly called.
|
||||
GrVkRenderTarget::GrVkRenderTarget(GrVkGpu* gpu,
|
||||
SkBudgeted budgeted,
|
||||
const GrSurfaceDesc& desc,
|
||||
GrGpuResource::LifeCycle lifeCycle,
|
||||
const GrVkImage::Resource* imageResource,
|
||||
const GrVkImage::Resource* msaaResource,
|
||||
const GrVkImageView* colorAttachmentView,
|
||||
const GrVkImageView* resolveAttachmentView)
|
||||
: GrSurface(gpu, lifeCycle, desc)
|
||||
: GrSurface(gpu, desc)
|
||||
, GrVkImage(imageResource)
|
||||
// for the moment we only support 1:1 color to stencil
|
||||
, GrRenderTarget(gpu, lifeCycle, desc, kUnified_SampleConfig)
|
||||
, GrRenderTarget(gpu, desc, kUnified_SampleConfig)
|
||||
, fFramebuffer(nullptr)
|
||||
, fColorAttachmentView(colorAttachmentView)
|
||||
, fMSAAImageResource(msaaResource)
|
||||
@ -41,7 +41,7 @@ GrVkRenderTarget::GrVkRenderTarget(GrVkGpu* gpu,
|
||||
// The plus 1 is to account for the resolve texture.
|
||||
fColorValuesPerPixel = desc.fSampleCnt + 1; // TODO: this still correct?
|
||||
this->createFramebuffer(gpu);
|
||||
this->registerWithCache();
|
||||
this->registerWithCache(budgeted);
|
||||
msaaResource->ref();
|
||||
}
|
||||
|
||||
@ -49,16 +49,14 @@ GrVkRenderTarget::GrVkRenderTarget(GrVkGpu* gpu,
|
||||
// constructor must be explicitly called.
|
||||
GrVkRenderTarget::GrVkRenderTarget(GrVkGpu* gpu,
|
||||
const GrSurfaceDesc& desc,
|
||||
GrGpuResource::LifeCycle lifeCycle,
|
||||
const GrVkImage::Resource* imageResource,
|
||||
const GrVkImage::Resource* msaaResource,
|
||||
const GrVkImageView* colorAttachmentView,
|
||||
const GrVkImageView* resolveAttachmentView,
|
||||
Derived)
|
||||
: GrSurface(gpu, lifeCycle, desc)
|
||||
const GrVkImageView* resolveAttachmentView)
|
||||
: GrSurface(gpu, desc)
|
||||
, GrVkImage(imageResource)
|
||||
// for the moment we only support 1:1 color to stencil
|
||||
, GrRenderTarget(gpu, lifeCycle, desc, kUnified_SampleConfig)
|
||||
, GrRenderTarget(gpu, desc, kUnified_SampleConfig)
|
||||
, fFramebuffer(nullptr)
|
||||
, fColorAttachmentView(colorAttachmentView)
|
||||
, fMSAAImageResource(msaaResource)
|
||||
@ -74,13 +72,13 @@ GrVkRenderTarget::GrVkRenderTarget(GrVkGpu* gpu,
|
||||
// We're virtually derived from GrSurface (via GrRenderTarget) so its
|
||||
// constructor must be explicitly called.
|
||||
GrVkRenderTarget::GrVkRenderTarget(GrVkGpu* gpu,
|
||||
SkBudgeted budgeted,
|
||||
const GrSurfaceDesc& desc,
|
||||
GrGpuResource::LifeCycle lifeCycle,
|
||||
const GrVkImage::Resource* imageResource,
|
||||
const GrVkImageView* colorAttachmentView)
|
||||
: GrSurface(gpu, lifeCycle, desc)
|
||||
: GrSurface(gpu, desc)
|
||||
, GrVkImage(imageResource)
|
||||
, GrRenderTarget(gpu, lifeCycle, desc, kUnified_SampleConfig)
|
||||
, GrRenderTarget(gpu, desc, kUnified_SampleConfig)
|
||||
, fFramebuffer(nullptr)
|
||||
, fColorAttachmentView(colorAttachmentView)
|
||||
, fMSAAImageResource(nullptr)
|
||||
@ -89,20 +87,18 @@ GrVkRenderTarget::GrVkRenderTarget(GrVkGpu* gpu,
|
||||
SkASSERT(!desc.fSampleCnt);
|
||||
fColorValuesPerPixel = 1;
|
||||
this->createFramebuffer(gpu);
|
||||
this->registerWithCache();
|
||||
this->registerWithCache(budgeted);
|
||||
}
|
||||
|
||||
// We're virtually derived from GrSurface (via GrRenderTarget) so its
|
||||
// constructor must be explicitly called.
|
||||
GrVkRenderTarget::GrVkRenderTarget(GrVkGpu* gpu,
|
||||
const GrSurfaceDesc& desc,
|
||||
GrGpuResource::LifeCycle lifeCycle,
|
||||
const GrVkImage::Resource* imageResource,
|
||||
const GrVkImageView* colorAttachmentView,
|
||||
Derived)
|
||||
: GrSurface(gpu, lifeCycle, desc)
|
||||
const GrVkImageView* colorAttachmentView)
|
||||
: GrSurface(gpu, desc)
|
||||
, GrVkImage(imageResource)
|
||||
, GrRenderTarget(gpu, lifeCycle, desc, kUnified_SampleConfig)
|
||||
, GrRenderTarget(gpu, desc, kUnified_SampleConfig)
|
||||
, fFramebuffer(nullptr)
|
||||
, fColorAttachmentView(colorAttachmentView)
|
||||
, fMSAAImageResource(nullptr)
|
||||
@ -115,8 +111,8 @@ GrVkRenderTarget::GrVkRenderTarget(GrVkGpu* gpu,
|
||||
|
||||
GrVkRenderTarget*
|
||||
GrVkRenderTarget::Create(GrVkGpu* gpu,
|
||||
SkBudgeted budgeted,
|
||||
const GrSurfaceDesc& desc,
|
||||
GrGpuResource::LifeCycle lifeCycle,
|
||||
const GrVkImage::Resource* imageResource) {
|
||||
VkFormat pixelFormat;
|
||||
GrPixelConfigToVkFormat(desc.fConfig, &pixelFormat);
|
||||
@ -172,11 +168,11 @@ GrVkRenderTarget::Create(GrVkGpu* gpu,
|
||||
|
||||
GrVkRenderTarget* texRT;
|
||||
if (msaaResource) {
|
||||
texRT = new GrVkRenderTarget(gpu, desc, lifeCycle, imageResource, msaaResource,
|
||||
texRT = new GrVkRenderTarget(gpu, budgeted, desc, imageResource, msaaResource,
|
||||
colorAttachmentView, resolveAttachmentView);
|
||||
msaaResource->unref(gpu);
|
||||
} else {
|
||||
texRT = new GrVkRenderTarget(gpu, desc, lifeCycle, imageResource,
|
||||
texRT = new GrVkRenderTarget(gpu, budgeted, desc, imageResource,
|
||||
colorAttachmentView);
|
||||
}
|
||||
|
||||
@ -185,8 +181,8 @@ GrVkRenderTarget::Create(GrVkGpu* gpu,
|
||||
|
||||
GrVkRenderTarget*
|
||||
GrVkRenderTarget::CreateNewRenderTarget(GrVkGpu* gpu,
|
||||
SkBudgeted budgeted,
|
||||
const GrSurfaceDesc& desc,
|
||||
GrGpuResource::LifeCycle lifeCycle,
|
||||
const GrVkImage::ImageDesc& imageDesc) {
|
||||
SkASSERT(imageDesc.fUsageFlags & VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT);
|
||||
|
||||
@ -195,7 +191,7 @@ GrVkRenderTarget::CreateNewRenderTarget(GrVkGpu* gpu,
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
GrVkRenderTarget* rt = GrVkRenderTarget::Create(gpu, desc, lifeCycle, imageResource);
|
||||
GrVkRenderTarget* rt = GrVkRenderTarget::Create(gpu, budgeted, desc, imageResource);
|
||||
// Create() will increment the refCount of the image resource if it succeeds
|
||||
imageResource->unref(gpu);
|
||||
return rt;
|
||||
@ -204,18 +200,18 @@ GrVkRenderTarget::CreateNewRenderTarget(GrVkGpu* gpu,
|
||||
GrVkRenderTarget*
|
||||
GrVkRenderTarget::CreateWrappedRenderTarget(GrVkGpu* gpu,
|
||||
const GrSurfaceDesc& desc,
|
||||
GrGpuResource::LifeCycle lifeCycle,
|
||||
GrWrapOwnership ownership,
|
||||
const GrVkTextureInfo* info) {
|
||||
SkASSERT(info);
|
||||
// We can wrap a rendertarget without its allocation, as long as we don't take ownership
|
||||
SkASSERT(VK_NULL_HANDLE != info->fImage);
|
||||
SkASSERT(VK_NULL_HANDLE != info->fAlloc || kAdopted_LifeCycle != lifeCycle);
|
||||
SkASSERT(VK_NULL_HANDLE != info->fAlloc || kAdopt_GrWrapOwnership != ownership);
|
||||
|
||||
GrVkImage::Resource::Flags flags = (VK_IMAGE_TILING_LINEAR == info->fImageTiling)
|
||||
? Resource::kLinearTiling_Flag : Resource::kNo_Flags;
|
||||
|
||||
const GrVkImage::Resource* imageResource;
|
||||
if (kBorrowed_LifeCycle == lifeCycle) {
|
||||
if (kBorrow_GrWrapOwnership == ownership) {
|
||||
imageResource = new GrVkImage::BorrowedResource(info->fImage,
|
||||
info->fAlloc,
|
||||
flags,
|
||||
@ -227,7 +223,7 @@ GrVkRenderTarget::CreateWrappedRenderTarget(GrVkGpu* gpu,
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
GrVkRenderTarget* rt = GrVkRenderTarget::Create(gpu, desc, lifeCycle, imageResource);
|
||||
GrVkRenderTarget* rt = GrVkRenderTarget::Create(gpu, SkBudgeted::kNo, desc, imageResource);
|
||||
if (rt) {
|
||||
rt->fCurrentLayout = info->fImageLayout;
|
||||
}
|
||||
@ -367,12 +363,7 @@ void GrVkRenderTarget::abandonInternalObjects() {
|
||||
|
||||
void GrVkRenderTarget::onRelease() {
|
||||
this->releaseInternalObjects();
|
||||
if (this->shouldFreeResources()) {
|
||||
this->releaseImage(this->getVkGpu());
|
||||
} else {
|
||||
this->abandonImage();
|
||||
}
|
||||
|
||||
this->releaseImage(this->getVkGpu());
|
||||
GrRenderTarget::onRelease();
|
||||
}
|
||||
|
||||
|
@ -30,12 +30,11 @@ struct GrVkTextureInfo;
|
||||
|
||||
class GrVkRenderTarget: public GrRenderTarget, public virtual GrVkImage {
|
||||
public:
|
||||
static GrVkRenderTarget* CreateNewRenderTarget(GrVkGpu*, const GrSurfaceDesc&,
|
||||
GrGpuResource::LifeCycle,
|
||||
static GrVkRenderTarget* CreateNewRenderTarget(GrVkGpu*, SkBudgeted, const GrSurfaceDesc&,
|
||||
const GrVkImage::ImageDesc&);
|
||||
|
||||
static GrVkRenderTarget* CreateWrappedRenderTarget(GrVkGpu*, const GrSurfaceDesc&,
|
||||
GrGpuResource::LifeCycle,
|
||||
GrWrapOwnership,
|
||||
const GrVkTextureInfo*);
|
||||
|
||||
~GrVkRenderTarget() override;
|
||||
@ -67,11 +66,9 @@ public:
|
||||
void addResources(GrVkCommandBuffer& commandBuffer) const;
|
||||
|
||||
protected:
|
||||
enum Derived { kDerived };
|
||||
|
||||
GrVkRenderTarget(GrVkGpu* gpu,
|
||||
SkBudgeted,
|
||||
const GrSurfaceDesc& desc,
|
||||
GrGpuResource::LifeCycle,
|
||||
const GrVkImage::Resource* imageResource,
|
||||
const GrVkImage::Resource* msaaImageResource,
|
||||
const GrVkImageView* colorAttachmentView,
|
||||
@ -79,28 +76,23 @@ protected:
|
||||
|
||||
GrVkRenderTarget(GrVkGpu* gpu,
|
||||
const GrSurfaceDesc& desc,
|
||||
GrGpuResource::LifeCycle,
|
||||
const GrVkImage::Resource* imageResource,
|
||||
const GrVkImage::Resource* msaaImageResource,
|
||||
const GrVkImageView* colorAttachmentView,
|
||||
const GrVkImageView* resolveAttachmentView,
|
||||
Derived);
|
||||
const GrVkImageView* resolveAttachmentView);
|
||||
|
||||
GrVkRenderTarget(GrVkGpu* gpu,
|
||||
SkBudgeted,
|
||||
const GrSurfaceDesc& desc,
|
||||
GrGpuResource::LifeCycle,
|
||||
const GrVkImage::Resource* imageResource,
|
||||
const GrVkImageView* colorAttachmentView);
|
||||
|
||||
GrVkRenderTarget(GrVkGpu* gpu,
|
||||
const GrSurfaceDesc& desc,
|
||||
GrGpuResource::LifeCycle,
|
||||
const GrVkImage::Resource* imageResource,
|
||||
const GrVkImageView* colorAttachmentView,
|
||||
Derived);
|
||||
const GrVkImageView* colorAttachmentView);
|
||||
|
||||
static GrVkRenderTarget* Create(GrVkGpu*, const GrSurfaceDesc&,
|
||||
GrGpuResource::LifeCycle,
|
||||
static GrVkRenderTarget* Create(GrVkGpu*, SkBudgeted, const GrSurfaceDesc&,
|
||||
const GrVkImage::Resource* imageResource);
|
||||
|
||||
GrVkGpu* getVkGpu() const;
|
||||
|
@ -14,22 +14,20 @@
|
||||
#define VK_CALL(GPU, X) GR_VK_CALL(GPU->vkInterface(), X)
|
||||
|
||||
GrVkStencilAttachment::GrVkStencilAttachment(GrVkGpu* gpu,
|
||||
GrGpuResource::LifeCycle lifeCycle,
|
||||
const Format& format,
|
||||
const GrVkImage::ImageDesc& desc,
|
||||
const GrVkImage::Resource* imageResource,
|
||||
const GrVkImageView* stencilView)
|
||||
: GrStencilAttachment(gpu, lifeCycle, desc.fWidth, desc.fHeight,
|
||||
: GrStencilAttachment(gpu, desc.fWidth, desc.fHeight,
|
||||
format.fStencilBits, desc.fSamples)
|
||||
, GrVkImage(imageResource)
|
||||
, fFormat(format)
|
||||
, fStencilView(stencilView) {
|
||||
this->registerWithCache();
|
||||
this->registerWithCache(SkBudgeted::kYes);
|
||||
stencilView->ref();
|
||||
}
|
||||
|
||||
GrVkStencilAttachment* GrVkStencilAttachment::Create(GrVkGpu* gpu,
|
||||
GrGpuResource::LifeCycle lifeCycle,
|
||||
int width,
|
||||
int height,
|
||||
int sampleCnt,
|
||||
@ -59,7 +57,7 @@ GrVkStencilAttachment* GrVkStencilAttachment::Create(GrVkGpu* gpu,
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
GrVkStencilAttachment* stencil = new GrVkStencilAttachment(gpu, lifeCycle, format, imageDesc,
|
||||
GrVkStencilAttachment* stencil = new GrVkStencilAttachment(gpu, format, imageDesc,
|
||||
imageResource, imageView);
|
||||
imageResource->unref(gpu);
|
||||
imageView->unref(gpu);
|
||||
|
@ -24,8 +24,7 @@ public:
|
||||
bool fPacked;
|
||||
};
|
||||
|
||||
static GrVkStencilAttachment* Create(GrVkGpu* gpu, GrGpuResource::LifeCycle lifeCycle,
|
||||
int width, int height,
|
||||
static GrVkStencilAttachment* Create(GrVkGpu* gpu, int width, int height,
|
||||
int sampleCnt, const Format& format);
|
||||
|
||||
~GrVkStencilAttachment() override;
|
||||
@ -43,7 +42,6 @@ private:
|
||||
size_t onGpuMemorySize() const override;
|
||||
|
||||
GrVkStencilAttachment(GrVkGpu* gpu,
|
||||
GrGpuResource::LifeCycle lifeCycle,
|
||||
const Format& format,
|
||||
const GrVkImage::ImageDesc&,
|
||||
const GrVkImage::Resource*,
|
||||
|
@ -16,35 +16,47 @@
|
||||
|
||||
// Because this class is virtually derived from GrSurface we must explicitly call its constructor.
|
||||
GrVkTexture::GrVkTexture(GrVkGpu* gpu,
|
||||
SkBudgeted budgeted,
|
||||
const GrSurfaceDesc& desc,
|
||||
GrGpuResource::LifeCycle lifeCycle,
|
||||
const GrVkImage::Resource* imageResource,
|
||||
const GrVkImageView* view)
|
||||
: GrSurface(gpu, lifeCycle, desc)
|
||||
: GrSurface(gpu, desc)
|
||||
, GrVkImage(imageResource)
|
||||
, INHERITED(gpu, lifeCycle, desc, kSampler2D_GrSLType,
|
||||
, INHERITED(gpu, desc, kSampler2D_GrSLType,
|
||||
false) // false because we don't upload MIP data in Vk yet
|
||||
, fTextureView(view) {
|
||||
this->registerWithCache();
|
||||
this->registerWithCache(budgeted);
|
||||
}
|
||||
|
||||
GrVkTexture::GrVkTexture(GrVkGpu* gpu,
|
||||
Wrapped,
|
||||
const GrSurfaceDesc& desc,
|
||||
const GrVkImage::Resource* imageResource,
|
||||
const GrVkImageView* view)
|
||||
: GrSurface(gpu, desc)
|
||||
, GrVkImage(imageResource)
|
||||
, INHERITED(gpu, desc, kSampler2D_GrSLType,
|
||||
false) // false because we don't upload MIP data in Vk yet
|
||||
, fTextureView(view) {
|
||||
this->registerWithCacheWrapped();
|
||||
}
|
||||
|
||||
// Because this class is virtually derived from GrSurface we must explicitly call its constructor.
|
||||
GrVkTexture::GrVkTexture(GrVkGpu* gpu,
|
||||
const GrSurfaceDesc& desc,
|
||||
GrGpuResource::LifeCycle lifeCycle,
|
||||
const GrVkImage::Resource* imageResource,
|
||||
const GrVkImageView* view,
|
||||
Derived)
|
||||
: GrSurface(gpu, lifeCycle, desc)
|
||||
const GrVkImageView* view)
|
||||
: GrSurface(gpu, desc)
|
||||
, GrVkImage(imageResource)
|
||||
, INHERITED(gpu, lifeCycle, desc, kSampler2D_GrSLType,
|
||||
, INHERITED(gpu, desc, kSampler2D_GrSLType,
|
||||
false) // false because we don't upload MIP data in Vk yet
|
||||
, fTextureView(view) {}
|
||||
|
||||
|
||||
template<typename ResourceType>
|
||||
GrVkTexture* GrVkTexture::Create(GrVkGpu* gpu,
|
||||
ResourceType type,
|
||||
const GrSurfaceDesc& desc,
|
||||
GrGpuResource::LifeCycle lifeCycle,
|
||||
VkFormat format,
|
||||
const GrVkImage::Resource* imageResource) {
|
||||
VkImage image = imageResource->fImage;
|
||||
@ -54,11 +66,11 @@ GrVkTexture* GrVkTexture::Create(GrVkGpu* gpu,
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
return new GrVkTexture(gpu, desc, lifeCycle, imageResource, imageView);
|
||||
return new GrVkTexture(gpu, type, desc, imageResource, imageView);
|
||||
}
|
||||
|
||||
GrVkTexture* GrVkTexture::CreateNewTexture(GrVkGpu* gpu, const GrSurfaceDesc& desc,
|
||||
GrGpuResource::LifeCycle lifeCycle,
|
||||
GrVkTexture* GrVkTexture::CreateNewTexture(GrVkGpu* gpu, SkBudgeted budgeted,
|
||||
const GrSurfaceDesc& desc,
|
||||
const GrVkImage::ImageDesc& imageDesc) {
|
||||
SkASSERT(imageDesc.fUsageFlags & VK_IMAGE_USAGE_SAMPLED_BIT);
|
||||
|
||||
@ -67,15 +79,16 @@ GrVkTexture* GrVkTexture::CreateNewTexture(GrVkGpu* gpu, const GrSurfaceDesc& de
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
GrVkTexture* texture = Create(gpu, desc, lifeCycle, imageDesc.fFormat, imageResource);
|
||||
GrVkTexture* texture = Create(gpu, budgeted, desc, imageDesc.fFormat, imageResource);
|
||||
// Create() will increment the refCount of the image resource if it succeeds
|
||||
imageResource->unref(gpu);
|
||||
|
||||
return texture;
|
||||
}
|
||||
|
||||
GrVkTexture* GrVkTexture::CreateWrappedTexture(GrVkGpu* gpu, const GrSurfaceDesc& desc,
|
||||
GrGpuResource::LifeCycle lifeCycle,
|
||||
GrVkTexture* GrVkTexture::CreateWrappedTexture(GrVkGpu* gpu,
|
||||
const GrSurfaceDesc& desc,
|
||||
GrWrapOwnership ownership,
|
||||
VkFormat format,
|
||||
const GrVkTextureInfo* info) {
|
||||
SkASSERT(info);
|
||||
@ -86,7 +99,7 @@ GrVkTexture* GrVkTexture::CreateWrappedTexture(GrVkGpu* gpu, const GrSurfaceDesc
|
||||
? Resource::kLinearTiling_Flag : Resource::kNo_Flags;
|
||||
|
||||
const GrVkImage::Resource* imageResource;
|
||||
if (kBorrowed_LifeCycle == lifeCycle) {
|
||||
if (kBorrow_GrWrapOwnership == ownership) {
|
||||
imageResource = new GrVkImage::BorrowedResource(info->fImage,
|
||||
info->fAlloc,
|
||||
flags,
|
||||
@ -98,7 +111,7 @@ GrVkTexture* GrVkTexture::CreateWrappedTexture(GrVkGpu* gpu, const GrSurfaceDesc
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
GrVkTexture* texture = Create(gpu, desc, lifeCycle, format, imageResource);
|
||||
GrVkTexture* texture = Create(gpu, kWrapped, desc, format, imageResource);
|
||||
if (texture) {
|
||||
texture->fCurrentLayout = info->fImageLayout;
|
||||
}
|
||||
@ -120,11 +133,7 @@ void GrVkTexture::onRelease() {
|
||||
fTextureView = nullptr;
|
||||
}
|
||||
|
||||
if (this->shouldFreeResources()) {
|
||||
this->releaseImage(this->getVkGpu());
|
||||
} else {
|
||||
this->abandonImage();
|
||||
}
|
||||
this->releaseImage(this->getVkGpu());
|
||||
|
||||
INHERITED::onRelease();
|
||||
}
|
||||
|
@ -18,12 +18,11 @@ struct GrVkTextureInfo;
|
||||
|
||||
class GrVkTexture : public GrTexture, public virtual GrVkImage {
|
||||
public:
|
||||
static GrVkTexture* CreateNewTexture(GrVkGpu*, const GrSurfaceDesc&,
|
||||
GrGpuResource::LifeCycle,
|
||||
static GrVkTexture* CreateNewTexture(GrVkGpu*, SkBudgeted budgeted, const GrSurfaceDesc&,
|
||||
const GrVkImage::ImageDesc&);
|
||||
|
||||
static GrVkTexture* CreateWrappedTexture(GrVkGpu*, const GrSurfaceDesc&,
|
||||
GrGpuResource::LifeCycle,
|
||||
GrWrapOwnership,
|
||||
VkFormat, const GrVkTextureInfo*);
|
||||
|
||||
~GrVkTexture() override;
|
||||
@ -35,16 +34,11 @@ public:
|
||||
const GrVkImageView* textureView() const { return fTextureView; }
|
||||
|
||||
protected:
|
||||
enum Derived { kDerived };
|
||||
|
||||
GrVkTexture(GrVkGpu*, const GrSurfaceDesc&, GrGpuResource::LifeCycle,
|
||||
GrVkTexture(GrVkGpu*, const GrSurfaceDesc&,
|
||||
const GrVkImage::Resource*, const GrVkImageView* imageView);
|
||||
|
||||
GrVkTexture(GrVkGpu*, const GrSurfaceDesc&, GrGpuResource::LifeCycle,
|
||||
const GrVkImage::Resource*, const GrVkImageView* imageView, Derived);
|
||||
|
||||
static GrVkTexture* Create(GrVkGpu*, const GrSurfaceDesc&,
|
||||
GrGpuResource::LifeCycle, VkFormat,
|
||||
template<typename ResourceType>
|
||||
static GrVkTexture* Create(GrVkGpu*, ResourceType, const GrSurfaceDesc&, VkFormat,
|
||||
const GrVkImage::Resource* texImpl);
|
||||
|
||||
GrVkGpu* getVkGpu() const;
|
||||
@ -53,6 +47,13 @@ protected:
|
||||
void onRelease() override;
|
||||
|
||||
private:
|
||||
enum Wrapped { kWrapped };
|
||||
GrVkTexture(GrVkGpu*, SkBudgeted, const GrSurfaceDesc&,
|
||||
const GrVkImage::Resource*, const GrVkImageView* imageView);
|
||||
GrVkTexture(GrVkGpu*, Wrapped, const GrSurfaceDesc&,
|
||||
const GrVkImage::Resource*, const GrVkImageView* imageView);
|
||||
|
||||
|
||||
const GrVkImageView* fTextureView;
|
||||
|
||||
typedef GrTexture INHERITED;
|
||||
|
@ -16,13 +16,12 @@
|
||||
|
||||
#define VK_CALL(GPU, X) GR_VK_CALL(GPU->vkInterface(), X)
|
||||
|
||||
GrVkTextureRenderTarget*
|
||||
GrVkTextureRenderTarget::Create(GrVkGpu* gpu,
|
||||
const GrSurfaceDesc& desc,
|
||||
GrGpuResource::LifeCycle lifeCycle,
|
||||
VkFormat format,
|
||||
const GrVkImage::Resource* imageResource) {
|
||||
|
||||
template<typename ResourceType>
|
||||
GrVkTextureRenderTarget* GrVkTextureRenderTarget::Create(GrVkGpu* gpu,
|
||||
ResourceType resourceType,
|
||||
const GrSurfaceDesc& desc,
|
||||
VkFormat format,
|
||||
const GrVkImage::Resource* imageResource) {
|
||||
VkImage image = imageResource->fImage;
|
||||
// Create the texture ImageView
|
||||
const GrVkImageView* imageView = GrVkImageView::Create(gpu, image, format,
|
||||
@ -99,16 +98,15 @@ GrVkTextureRenderTarget::Create(GrVkGpu* gpu,
|
||||
return nullptr;
|
||||
}
|
||||
}
|
||||
|
||||
GrVkTextureRenderTarget* texRT;
|
||||
if (msaaImageResource) {
|
||||
texRT = new GrVkTextureRenderTarget(gpu, desc, lifeCycle,
|
||||
texRT = new GrVkTextureRenderTarget(gpu, resourceType, desc,
|
||||
imageResource, imageView, msaaImageResource,
|
||||
colorAttachmentView,
|
||||
resolveAttachmentView);
|
||||
msaaImageResource->unref(gpu);
|
||||
} else {
|
||||
texRT = new GrVkTextureRenderTarget(gpu, desc, lifeCycle,
|
||||
texRT = new GrVkTextureRenderTarget(gpu, resourceType, desc,
|
||||
imageResource, imageView,
|
||||
colorAttachmentView);
|
||||
}
|
||||
@ -117,9 +115,9 @@ GrVkTextureRenderTarget::Create(GrVkGpu* gpu,
|
||||
|
||||
GrVkTextureRenderTarget*
|
||||
GrVkTextureRenderTarget::CreateNewTextureRenderTarget(GrVkGpu* gpu,
|
||||
const GrSurfaceDesc& desc,
|
||||
GrGpuResource::LifeCycle lifeCycle,
|
||||
const GrVkImage::ImageDesc& imageDesc) {
|
||||
SkBudgeted budgeted,
|
||||
const GrSurfaceDesc& desc,
|
||||
const GrVkImage::ImageDesc& imageDesc) {
|
||||
SkASSERT(imageDesc.fUsageFlags & VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT);
|
||||
SkASSERT(imageDesc.fUsageFlags & VK_IMAGE_USAGE_SAMPLED_BIT);
|
||||
|
||||
@ -129,8 +127,8 @@ GrVkTextureRenderTarget::CreateNewTextureRenderTarget(GrVkGpu* gpu,
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
GrVkTextureRenderTarget* trt = GrVkTextureRenderTarget::Create(gpu, desc, lifeCycle,
|
||||
imageDesc.fFormat, imageRsrc);
|
||||
GrVkTextureRenderTarget* trt = Create(gpu, budgeted, desc, imageDesc.fFormat,
|
||||
imageRsrc);
|
||||
// Create() will increment the refCount of the image resource if it succeeds
|
||||
imageRsrc->unref(gpu);
|
||||
|
||||
@ -140,7 +138,7 @@ GrVkTextureRenderTarget::CreateNewTextureRenderTarget(GrVkGpu* gpu,
|
||||
GrVkTextureRenderTarget*
|
||||
GrVkTextureRenderTarget::CreateWrappedTextureRenderTarget(GrVkGpu* gpu,
|
||||
const GrSurfaceDesc& desc,
|
||||
GrGpuResource::LifeCycle lifeCycle,
|
||||
GrWrapOwnership ownership,
|
||||
VkFormat format,
|
||||
const GrVkTextureInfo* info) {
|
||||
SkASSERT(info);
|
||||
@ -151,7 +149,7 @@ GrVkTextureRenderTarget::CreateWrappedTextureRenderTarget(GrVkGpu* gpu,
|
||||
? Resource::kLinearTiling_Flag : Resource::kNo_Flags;
|
||||
|
||||
const GrVkImage::Resource* imageResource;
|
||||
if (kBorrowed_LifeCycle == lifeCycle) {
|
||||
if (kBorrow_GrWrapOwnership == ownership) {
|
||||
imageResource = new GrVkImage::BorrowedResource(info->fImage,
|
||||
info->fAlloc,
|
||||
flags,
|
||||
@ -162,9 +160,7 @@ GrVkTextureRenderTarget::CreateWrappedTextureRenderTarget(GrVkGpu* gpu,
|
||||
if (!imageResource) {
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
GrVkTextureRenderTarget* trt = GrVkTextureRenderTarget::Create(gpu, desc, lifeCycle,
|
||||
format, imageResource);
|
||||
GrVkTextureRenderTarget* trt = Create(gpu, kWrapped, desc, format, imageResource);
|
||||
if (trt) {
|
||||
trt->fCurrentLayout = info->fImageLayout;
|
||||
}
|
||||
|
@ -24,13 +24,13 @@ struct GrVkTextureInfo;
|
||||
|
||||
class GrVkTextureRenderTarget: public GrVkTexture, public GrVkRenderTarget {
|
||||
public:
|
||||
static GrVkTextureRenderTarget* CreateNewTextureRenderTarget(GrVkGpu*, const GrSurfaceDesc&,
|
||||
GrGpuResource::LifeCycle,
|
||||
static GrVkTextureRenderTarget* CreateNewTextureRenderTarget(GrVkGpu*, SkBudgeted,
|
||||
const GrSurfaceDesc&,
|
||||
const GrVkImage::ImageDesc&);
|
||||
|
||||
static GrVkTextureRenderTarget* CreateWrappedTextureRenderTarget(GrVkGpu*,
|
||||
const GrSurfaceDesc&,
|
||||
GrGpuResource::LifeCycle,
|
||||
GrWrapOwnership,
|
||||
VkFormat,
|
||||
const GrVkTextureInfo*);
|
||||
|
||||
@ -47,38 +47,68 @@ protected:
|
||||
|
||||
private:
|
||||
GrVkTextureRenderTarget(GrVkGpu* gpu,
|
||||
SkBudgeted budgeted,
|
||||
const GrSurfaceDesc& desc,
|
||||
GrGpuResource::LifeCycle lifeCycle,
|
||||
const GrVkImage::Resource* imageResource,
|
||||
const GrVkImageView* texView,
|
||||
const GrVkImage::Resource* msaaResource,
|
||||
const GrVkImageView* colorAttachmentView,
|
||||
const GrVkImageView* resolveAttachmentView)
|
||||
: GrSurface(gpu, lifeCycle, desc)
|
||||
: GrSurface(gpu, desc)
|
||||
, GrVkImage(imageResource)
|
||||
, GrVkTexture(gpu, desc, lifeCycle, imageResource, texView, GrVkTexture::kDerived)
|
||||
, GrVkRenderTarget(gpu, desc, lifeCycle, imageResource, msaaResource, colorAttachmentView,
|
||||
resolveAttachmentView, GrVkRenderTarget::kDerived) {
|
||||
this->registerWithCache();
|
||||
, GrVkTexture(gpu, desc, imageResource, texView)
|
||||
, GrVkRenderTarget(gpu, desc, imageResource, msaaResource, colorAttachmentView,
|
||||
resolveAttachmentView) {
|
||||
this->registerWithCache(budgeted);
|
||||
}
|
||||
|
||||
GrVkTextureRenderTarget(GrVkGpu* gpu,
|
||||
SkBudgeted budgeted,
|
||||
const GrSurfaceDesc& desc,
|
||||
GrGpuResource::LifeCycle lifeCycle,
|
||||
const GrVkImage::Resource* imageResource,
|
||||
const GrVkImageView* texView,
|
||||
const GrVkImageView* colorAttachmentView)
|
||||
: GrSurface(gpu, lifeCycle, desc)
|
||||
: GrSurface(gpu, desc)
|
||||
, GrVkImage(imageResource)
|
||||
, GrVkTexture(gpu, desc, lifeCycle, imageResource, texView, GrVkTexture::kDerived)
|
||||
, GrVkRenderTarget(gpu, desc, lifeCycle, imageResource, colorAttachmentView,
|
||||
GrVkRenderTarget::kDerived) {
|
||||
this->registerWithCache();
|
||||
, GrVkTexture(gpu, desc, imageResource, texView)
|
||||
, GrVkRenderTarget(gpu, desc, imageResource, colorAttachmentView) {
|
||||
this->registerWithCache(budgeted);
|
||||
}
|
||||
enum Wrapped { kWrapped };
|
||||
GrVkTextureRenderTarget(GrVkGpu* gpu,
|
||||
Wrapped,
|
||||
const GrSurfaceDesc& desc,
|
||||
const GrVkImage::Resource* imageResource,
|
||||
const GrVkImageView* texView,
|
||||
const GrVkImage::Resource* msaaResource,
|
||||
const GrVkImageView* colorAttachmentView,
|
||||
const GrVkImageView* resolveAttachmentView)
|
||||
: GrSurface(gpu, desc)
|
||||
, GrVkImage(imageResource)
|
||||
, GrVkTexture(gpu, desc, imageResource, texView)
|
||||
, GrVkRenderTarget(gpu, desc, imageResource, msaaResource, colorAttachmentView,
|
||||
resolveAttachmentView) {
|
||||
this->registerWithCacheWrapped();
|
||||
}
|
||||
|
||||
static GrVkTextureRenderTarget* Create(GrVkGpu*, const GrSurfaceDesc&,
|
||||
GrGpuResource::LifeCycle,
|
||||
VkFormat format,
|
||||
GrVkTextureRenderTarget(GrVkGpu* gpu,
|
||||
Wrapped,
|
||||
const GrSurfaceDesc& desc,
|
||||
const GrVkImage::Resource* imageResource,
|
||||
const GrVkImageView* texView,
|
||||
const GrVkImageView* colorAttachmentView)
|
||||
: GrSurface(gpu, desc)
|
||||
, GrVkImage(imageResource)
|
||||
, GrVkTexture(gpu, desc, imageResource, texView)
|
||||
, GrVkRenderTarget(gpu, desc, imageResource, colorAttachmentView) {
|
||||
this->registerWithCacheWrapped();
|
||||
}
|
||||
|
||||
template <typename ResourceType>
|
||||
static GrVkTextureRenderTarget* Create(GrVkGpu*,
|
||||
ResourceType,
|
||||
const GrSurfaceDesc&,
|
||||
VkFormat,
|
||||
const GrVkImage::Resource* imageResource);
|
||||
|
||||
// GrGLRenderTarget accounts for the texture's memory and any MSAA renderbuffer's memory.
|
||||
|
@ -36,7 +36,7 @@ GrVkTransferBuffer::GrVkTransferBuffer(GrVkGpu* gpu, const GrVkBuffer::Desc& des
|
||||
kXferCpuToGpu_GrBufferType : kXferGpuToCpu_GrBufferType,
|
||||
kStream_GrAccessPattern, false)
|
||||
, GrVkBuffer(desc, bufferResource) {
|
||||
this->registerWithCache();
|
||||
this->registerWithCache(SkBudgeted::kYes);
|
||||
}
|
||||
|
||||
void GrVkTransferBuffer::onRelease() {
|
||||
|
@ -13,7 +13,7 @@ GrVkVertexBuffer::GrVkVertexBuffer(GrVkGpu* gpu, const GrVkBuffer::Desc& desc,
|
||||
: INHERITED(gpu, desc.fSizeInBytes, kVertex_GrBufferType,
|
||||
desc.fDynamic ? kDynamic_GrAccessPattern : kStatic_GrAccessPattern, false)
|
||||
, GrVkBuffer(desc, bufferResource) {
|
||||
this->registerWithCache();
|
||||
this->registerWithCache(SkBudgeted::kYes);
|
||||
}
|
||||
|
||||
GrVkVertexBuffer* GrVkVertexBuffer::Create(GrVkGpu* gpu, size_t size, bool dynamic) {
|
||||
|
@ -85,7 +85,7 @@ sk_sp<SkImage> SkSurface_Gpu::onNewImageSnapshot(SkBudgeted budgeted, ForceCopyM
|
||||
// If the original render target is a buffer originally created by the client, then we don't
|
||||
// want to ever retarget the SkSurface at another buffer we create. Force a copy now to avoid
|
||||
// copy-on-write.
|
||||
if (kYes_ForceCopyMode == forceCopyMode || !tex || rt->resourcePriv().isExternal()) {
|
||||
if (kYes_ForceCopyMode == forceCopyMode || !tex || rt->resourcePriv().refsWrappedObjects()) {
|
||||
GrSurfaceDesc desc = fDevice->accessRenderTarget()->desc();
|
||||
GrContext* ctx = fDevice->context();
|
||||
desc.fFlags = desc.fFlags & ~kRenderTarget_GrSurfaceFlag;
|
||||
|
@ -249,35 +249,22 @@ public:
|
||||
* For example, textures have width, height, ... */
|
||||
enum SimulatedProperty { kA_SimulatedProperty, kB_SimulatedProperty };
|
||||
|
||||
TestResource(GrGpu* gpu, size_t size, GrGpuResource::LifeCycle lifeCycle)
|
||||
: INHERITED(gpu, lifeCycle)
|
||||
TestResource(GrGpu* gpu, SkBudgeted budgeted = SkBudgeted::kYes, size_t size = kDefaultSize)
|
||||
: INHERITED(gpu)
|
||||
, fToDelete(nullptr)
|
||||
, fSize(size)
|
||||
, fProperty(kA_SimulatedProperty) {
|
||||
, fProperty(kA_SimulatedProperty)
|
||||
, fIsScratch(false) {
|
||||
++fNumAlive;
|
||||
this->registerWithCache();
|
||||
this->registerWithCache(budgeted);
|
||||
}
|
||||
|
||||
TestResource(GrGpu* gpu, GrGpuResource::LifeCycle lifeCycle)
|
||||
: INHERITED(gpu, lifeCycle)
|
||||
, fToDelete(nullptr)
|
||||
, fSize(kDefaultSize)
|
||||
, fProperty(kA_SimulatedProperty) {
|
||||
++fNumAlive;
|
||||
this->registerWithCache();
|
||||
static TestResource* CreateScratch(GrGpu* gpu, SkBudgeted budgeted,
|
||||
SimulatedProperty property) {
|
||||
return new TestResource(gpu, budgeted, property, kScratchConstructor);
|
||||
}
|
||||
|
||||
TestResource(GrGpu* gpu)
|
||||
: INHERITED(gpu, kCached_LifeCycle)
|
||||
, fToDelete(nullptr)
|
||||
, fSize(kDefaultSize)
|
||||
, fProperty(kA_SimulatedProperty) {
|
||||
++fNumAlive;
|
||||
this->registerWithCache();
|
||||
}
|
||||
|
||||
static TestResource* CreateScratch(GrGpu* gpu, SimulatedProperty property, bool cached = true) {
|
||||
return new TestResource(gpu, property, cached, kScratchConstructor);
|
||||
static TestResource* CreateWrapped(GrGpu* gpu, size_t size = kDefaultSize) {
|
||||
return new TestResource(gpu, size);
|
||||
}
|
||||
|
||||
~TestResource() {
|
||||
@ -307,20 +294,34 @@ public:
|
||||
static size_t ExpectedScratchKeySize() {
|
||||
return sizeof(uint32_t) * (kScratchKeyFieldCnt + GrScratchKey::kMetaDataCnt);
|
||||
}
|
||||
|
||||
private:
|
||||
static const int kScratchKeyFieldCnt = 6;
|
||||
|
||||
TestResource(GrGpu* gpu, SimulatedProperty property, bool cached, ScratchConstructor)
|
||||
: INHERITED(gpu, cached ? kCached_LifeCycle : kUncached_LifeCycle)
|
||||
TestResource(GrGpu* gpu, SkBudgeted budgeted, SimulatedProperty property, ScratchConstructor)
|
||||
: INHERITED(gpu)
|
||||
, fToDelete(nullptr)
|
||||
, fSize(kDefaultSize)
|
||||
, fProperty(property) {
|
||||
GrScratchKey scratchKey;
|
||||
ComputeScratchKey(fProperty, &scratchKey);
|
||||
this->setScratchKey(scratchKey);
|
||||
, fProperty(property)
|
||||
, fIsScratch(true) {
|
||||
++fNumAlive;
|
||||
this->registerWithCache();
|
||||
this->registerWithCache(budgeted);
|
||||
}
|
||||
|
||||
// Constructor for simulating resources that wrap backend objects.
|
||||
TestResource(GrGpu* gpu, size_t size)
|
||||
: INHERITED(gpu)
|
||||
, fToDelete(nullptr)
|
||||
, fSize(size)
|
||||
, fProperty(kA_SimulatedProperty)
|
||||
, fIsScratch(false) {
|
||||
++fNumAlive;
|
||||
this->registerWithCacheWrapped();
|
||||
}
|
||||
|
||||
void computeScratchKey(GrScratchKey* key) const override {
|
||||
if (fIsScratch) {
|
||||
ComputeScratchKey(fProperty, key);
|
||||
}
|
||||
}
|
||||
|
||||
size_t onGpuMemorySize() const override { return fSize; }
|
||||
@ -329,6 +330,7 @@ private:
|
||||
size_t fSize;
|
||||
static int fNumAlive;
|
||||
SimulatedProperty fProperty;
|
||||
bool fIsScratch;
|
||||
typedef GrGpuResource INHERITED;
|
||||
};
|
||||
int TestResource::fNumAlive = 0;
|
||||
@ -418,15 +420,15 @@ static void test_budgeting(skiatest::Reporter* reporter) {
|
||||
|
||||
// Create a scratch, a unique, and a wrapped resource
|
||||
TestResource* scratch =
|
||||
TestResource::CreateScratch(context->getGpu(), TestResource::kB_SimulatedProperty);
|
||||
TestResource::CreateScratch(context->getGpu(), SkBudgeted::kYes, TestResource::kB_SimulatedProperty);
|
||||
scratch->setSize(10);
|
||||
TestResource* unique = new TestResource(context->getGpu());
|
||||
unique->setSize(11);
|
||||
unique->resourcePriv().setUniqueKey(uniqueKey);
|
||||
TestResource* wrapped = new TestResource(context->getGpu(), GrGpuResource::kBorrowed_LifeCycle);
|
||||
TestResource* wrapped = TestResource::CreateWrapped(context->getGpu());
|
||||
wrapped->setSize(12);
|
||||
TestResource* unbudgeted =
|
||||
new TestResource(context->getGpu(), GrGpuResource::kUncached_LifeCycle);
|
||||
new TestResource(context->getGpu(), SkBudgeted::kNo);
|
||||
unbudgeted->setSize(13);
|
||||
|
||||
// Make sure we can't add a unique key to the wrapped resource
|
||||
@ -461,7 +463,7 @@ static void test_budgeting(skiatest::Reporter* reporter) {
|
||||
unbudgeted->gpuMemorySize() == cache->getResourceBytes());
|
||||
|
||||
// Now try freeing the budgeted resources first
|
||||
wrapped = new TestResource(context->getGpu(), GrGpuResource::kBorrowed_LifeCycle);
|
||||
wrapped = TestResource::CreateWrapped(context->getGpu());
|
||||
scratch->setSize(12);
|
||||
unique->unref();
|
||||
cache->purgeAllUnlocked();
|
||||
@ -506,7 +508,9 @@ static void test_unbudgeted(skiatest::Reporter* reporter) {
|
||||
TestResource* unbudgeted;
|
||||
|
||||
// A large uncached or wrapped resource shouldn't evict anything.
|
||||
scratch = TestResource::CreateScratch(context->getGpu(), TestResource::kB_SimulatedProperty);
|
||||
scratch = TestResource::CreateScratch(context->getGpu(), SkBudgeted::kYes,
|
||||
TestResource::kB_SimulatedProperty);
|
||||
|
||||
scratch->setSize(10);
|
||||
scratch->unref();
|
||||
REPORTER_ASSERT(reporter, 1 == cache->getResourceCount());
|
||||
@ -524,7 +528,7 @@ static void test_unbudgeted(skiatest::Reporter* reporter) {
|
||||
REPORTER_ASSERT(reporter, 21 == cache->getBudgetedResourceBytes());
|
||||
|
||||
size_t large = 2 * cache->getResourceBytes();
|
||||
unbudgeted = new TestResource(context->getGpu(), large, GrGpuResource::kUncached_LifeCycle);
|
||||
unbudgeted = new TestResource(context->getGpu(), SkBudgeted::kNo, large);
|
||||
REPORTER_ASSERT(reporter, 3 == cache->getResourceCount());
|
||||
REPORTER_ASSERT(reporter, 21 + large == cache->getResourceBytes());
|
||||
REPORTER_ASSERT(reporter, 2 == cache->getBudgetedResourceCount());
|
||||
@ -536,7 +540,7 @@ static void test_unbudgeted(skiatest::Reporter* reporter) {
|
||||
REPORTER_ASSERT(reporter, 2 == cache->getBudgetedResourceCount());
|
||||
REPORTER_ASSERT(reporter, 21 == cache->getBudgetedResourceBytes());
|
||||
|
||||
wrapped = new TestResource(context->getGpu(), large, GrGpuResource::kBorrowed_LifeCycle);
|
||||
wrapped = TestResource::CreateWrapped(context->getGpu(), large);
|
||||
REPORTER_ASSERT(reporter, 3 == cache->getResourceCount());
|
||||
REPORTER_ASSERT(reporter, 21 + large == cache->getResourceBytes());
|
||||
REPORTER_ASSERT(reporter, 2 == cache->getBudgetedResourceCount());
|
||||
@ -563,7 +567,8 @@ void test_unbudgeted_to_scratch(skiatest::Reporter* reporter);
|
||||
GrResourceCache* cache = mock.cache();
|
||||
|
||||
TestResource* resource =
|
||||
TestResource::CreateScratch(context->getGpu(), TestResource::kA_SimulatedProperty, false);
|
||||
TestResource::CreateScratch(context->getGpu(), SkBudgeted::kNo,
|
||||
TestResource::kA_SimulatedProperty);
|
||||
GrScratchKey key;
|
||||
TestResource::ComputeScratchKey(TestResource::kA_SimulatedProperty, &key);
|
||||
|
||||
@ -623,8 +628,10 @@ static void test_duplicate_scratch_key(skiatest::Reporter* reporter) {
|
||||
|
||||
// Create two resources that have the same scratch key.
|
||||
TestResource* a = TestResource::CreateScratch(context->getGpu(),
|
||||
SkBudgeted::kYes,
|
||||
TestResource::kB_SimulatedProperty);
|
||||
TestResource* b = TestResource::CreateScratch(context->getGpu(),
|
||||
SkBudgeted::kYes,
|
||||
TestResource::kB_SimulatedProperty);
|
||||
a->setSize(11);
|
||||
b->setSize(12);
|
||||
@ -667,9 +674,9 @@ static void test_remove_scratch_key(skiatest::Reporter* reporter) {
|
||||
GrResourceCache* cache = mock.cache();
|
||||
|
||||
// Create two resources that have the same scratch key.
|
||||
TestResource* a = TestResource::CreateScratch(context->getGpu(),
|
||||
TestResource* a = TestResource::CreateScratch(context->getGpu(), SkBudgeted::kYes,
|
||||
TestResource::kB_SimulatedProperty);
|
||||
TestResource* b = TestResource::CreateScratch(context->getGpu(),
|
||||
TestResource* b = TestResource::CreateScratch(context->getGpu(), SkBudgeted::kYes,
|
||||
TestResource::kB_SimulatedProperty);
|
||||
a->unref();
|
||||
b->unref();
|
||||
@ -726,9 +733,9 @@ static void test_scratch_key_consistency(skiatest::Reporter* reporter) {
|
||||
GrResourceCache* cache = mock.cache();
|
||||
|
||||
// Create two resources that have the same scratch key.
|
||||
TestResource* a = TestResource::CreateScratch(context->getGpu(),
|
||||
TestResource* a = TestResource::CreateScratch(context->getGpu(), SkBudgeted::kYes,
|
||||
TestResource::kB_SimulatedProperty);
|
||||
TestResource* b = TestResource::CreateScratch(context->getGpu(),
|
||||
TestResource* b = TestResource::CreateScratch(context->getGpu(), SkBudgeted::kYes,
|
||||
TestResource::kB_SimulatedProperty);
|
||||
a->unref();
|
||||
b->unref();
|
||||
@ -888,7 +895,7 @@ static void test_purge_invalidated(skiatest::Reporter* reporter) {
|
||||
// Add three resources to the cache. Only c is usable as scratch.
|
||||
TestResource* a = new TestResource(context->getGpu());
|
||||
TestResource* b = new TestResource(context->getGpu());
|
||||
TestResource* c = TestResource::CreateScratch(context->getGpu(),
|
||||
TestResource* c = TestResource::CreateScratch(context->getGpu(), SkBudgeted::kYes,
|
||||
TestResource::kA_SimulatedProperty);
|
||||
a->resourcePriv().setUniqueKey(key1);
|
||||
b->resourcePriv().setUniqueKey(key2);
|
||||
|
@ -222,10 +222,9 @@ void GrResourceCache::dumpStats(SkString* out) const {
|
||||
|
||||
out->appendf("Budget: %d items %d bytes\n", fMaxCount, (int)fMaxBytes);
|
||||
out->appendf("\t\tEntry Count: current %d"
|
||||
" (%d budgeted, %d external(%d borrowed, %d adopted), %d locked, %d scratch %.2g%% full), high %d\n",
|
||||
stats.fTotal, fBudgetedCount, stats.fExternal, stats.fBorrowed,
|
||||
stats.fAdopted, stats.fNumNonPurgeable, stats.fScratch, countUtilization,
|
||||
fHighWaterCount);
|
||||
" (%d budgeted, %d wrapped, %d locked, %d scratch %.2g%% full), high %d\n",
|
||||
stats.fTotal, fBudgetedCount, stats.fWrapped, stats.fNumNonPurgeable,
|
||||
stats.fScratch, countUtilization, fHighWaterCount);
|
||||
out->appendf("\t\tEntry Bytes: current %d (budgeted %d, %.2g%% full, %d unbudgeted) high %d\n",
|
||||
SkToInt(fBytes), SkToInt(fBudgetedBytes), byteUtilization,
|
||||
SkToInt(stats.fUnbudgetedSize), SkToInt(fHighWaterBytes));
|
||||
@ -323,12 +322,12 @@ private:
|
||||
|
||||
void xferBarrier(GrRenderTarget*, GrXferBarrierType) override {}
|
||||
|
||||
GrTexture* onCreateTexture(const GrSurfaceDesc& desc, GrGpuResource::LifeCycle lifeCycle,
|
||||
GrTexture* onCreateTexture(const GrSurfaceDesc& desc, SkBudgeted budgeted,
|
||||
const SkTArray<GrMipLevel>& texels) override {
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
GrTexture* onCreateCompressedTexture(const GrSurfaceDesc& desc, GrGpuResource::LifeCycle,
|
||||
GrTexture* onCreateCompressedTexture(const GrSurfaceDesc& desc, SkBudgeted budgeted,
|
||||
const SkTArray<GrMipLevel>& texels) override {
|
||||
return nullptr;
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user