Add "lazy" texture proxies
Adds ultra-deferred proxies that are instantiated by a user-supplied callback during flush. Bug: skia:7190 Change-Id: I75a7ac6dba953c3b0a99febc203a7f4d2f3789fc Reviewed-on: https://skia-review.googlesource.com/76461 Commit-Queue: Chris Dalton <csmartdalton@google.com> Reviewed-by: Robert Phillips <robertphillips@google.com>
This commit is contained in:
parent
de2f1dfebd
commit
706a6ff60c
@ -124,6 +124,7 @@ tests_sources = [
|
||||
"$_tests/IsClosedSingleContourTest.cpp",
|
||||
"$_tests/LayerDrawLooperTest.cpp",
|
||||
"$_tests/LayerRasterizerTest.cpp",
|
||||
"$_tests/LazyProxyTest.cpp",
|
||||
"$_tests/LListTest.cpp",
|
||||
"$_tests/LRUCacheTest.cpp",
|
||||
"$_tests/MallocPixelRefTest.cpp",
|
||||
|
@ -67,6 +67,9 @@ protected:
|
||||
GrRenderTargetProxy(const GrCaps&, const GrSurfaceDesc&,
|
||||
SkBackingFit, SkBudgeted, uint32_t flags);
|
||||
|
||||
// Lazy-callback version
|
||||
GrRenderTargetProxy(LazyInstantiateCallback&&, GrPixelConfig);
|
||||
|
||||
// Wrapped version
|
||||
GrRenderTargetProxy(sk_sp<GrSurface>, GrSurfaceOrigin);
|
||||
|
||||
@ -74,6 +77,7 @@ protected:
|
||||
|
||||
private:
|
||||
size_t onUninstantiatedGpuMemorySize() const override;
|
||||
SkDEBUGCODE(void validateLazyTexture(const GrTexture*) override { SkASSERT(0); })
|
||||
|
||||
int fSampleCnt;
|
||||
bool fNeedsStencil;
|
||||
|
@ -212,15 +212,34 @@ public:
|
||||
|
||||
static sk_sp<GrTextureProxy> MakeWrappedBackend(GrContext*, GrBackendTexture&, GrSurfaceOrigin);
|
||||
|
||||
using LazyInstantiateCallback = std::function<sk_sp<GrTexture>(GrResourceProvider*,
|
||||
GrSurfaceOrigin* outOrigin)>;
|
||||
|
||||
enum class Renderable : bool {
|
||||
kNo = false,
|
||||
kYes = true
|
||||
};
|
||||
|
||||
/**
|
||||
* Creates a texture proxy that will be instantiated by a user-supplied callback during flush.
|
||||
* (Mipmapping, MSAA, and stencil are not supported by this method.)
|
||||
*/
|
||||
static sk_sp<GrTextureProxy> MakeLazy(LazyInstantiateCallback&&, Renderable, GrPixelConfig);
|
||||
|
||||
GrPixelConfig config() const { return fConfig; }
|
||||
int width() const { SkASSERT(!this->isPendingLazyInstantiation()); return fWidth; }
|
||||
int height() const { SkASSERT(!this->isPendingLazyInstantiation()); return fHeight; }
|
||||
int worstCaseWidth() const;
|
||||
int worstCaseHeight() const;
|
||||
GrSurfaceOrigin origin() const {
|
||||
SkASSERT(!this->isPendingLazyInstantiation());
|
||||
SkASSERT(kTopLeft_GrSurfaceOrigin == fOrigin || kBottomLeft_GrSurfaceOrigin == fOrigin);
|
||||
return fOrigin;
|
||||
}
|
||||
int width() const { return fWidth; }
|
||||
int height() const { return fHeight; }
|
||||
int worstCaseWidth() const;
|
||||
int worstCaseHeight() const;
|
||||
GrPixelConfig config() const { return fConfig; }
|
||||
|
||||
// If the client gave us a LazyInstantiateCallback (via MakeLazy), then we will invoke that
|
||||
// callback during flush. fWidth, fHeight, and fOrigin will be undefined until that time.
|
||||
bool isPendingLazyInstantiation() const { return SkToBool(fLazyInstantiateCallback); }
|
||||
|
||||
class UniqueID {
|
||||
public:
|
||||
@ -230,7 +249,7 @@ public:
|
||||
|
||||
// wrapped
|
||||
explicit UniqueID(const GrGpuResource::UniqueID& id) : fID(id.asUInt()) { }
|
||||
// deferred
|
||||
// deferred and lazy-callback
|
||||
UniqueID() : fID(GrGpuResource::CreateUniqueID()) { }
|
||||
|
||||
uint32_t asUInt() const { return fID; }
|
||||
@ -281,7 +300,10 @@ public:
|
||||
/**
|
||||
* Helper that gets the width and height of the surface as a bounding rectangle.
|
||||
*/
|
||||
SkRect getBoundsRect() const { return SkRect::MakeIWH(this->width(), this->height()); }
|
||||
SkRect getBoundsRect() const {
|
||||
SkASSERT(!this->isPendingLazyInstantiation());
|
||||
return SkRect::MakeIWH(this->width(), this->height());
|
||||
}
|
||||
|
||||
/**
|
||||
* @return the texture proxy associated with the surface proxy, may be NULL.
|
||||
@ -314,6 +336,7 @@ public:
|
||||
* @return the amount of GPU memory used in bytes
|
||||
*/
|
||||
size_t gpuMemorySize() const {
|
||||
SkASSERT(!this->isPendingLazyInstantiation());
|
||||
if (fTarget) {
|
||||
return fTarget->gpuMemorySize();
|
||||
}
|
||||
@ -363,6 +386,9 @@ protected:
|
||||
// Note: this ctor pulls a new uniqueID from the same pool at the GrGpuResources
|
||||
}
|
||||
|
||||
// Lazy-callback version
|
||||
GrSurfaceProxy(LazyInstantiateCallback&& callback, GrPixelConfig config);
|
||||
|
||||
// Wrapped version
|
||||
GrSurfaceProxy(sk_sp<GrSurface> surface, GrSurfaceOrigin origin, SkBackingFit fit);
|
||||
|
||||
@ -392,23 +418,28 @@ protected:
|
||||
GrSurfaceFlags flags, GrMipMapped mipMapped,
|
||||
SkDestinationSurfaceColorMode mipColorMode, const GrUniqueKey*);
|
||||
|
||||
private:
|
||||
// For wrapped resources, 'fConfig', 'fWidth', 'fHeight', and 'fOrigin; will always be filled in
|
||||
// from the wrapped resource.
|
||||
GrPixelConfig fConfig;
|
||||
int fWidth;
|
||||
int fHeight;
|
||||
GrSurfaceOrigin fOrigin;
|
||||
SkBackingFit fFit; // always exact for wrapped resources
|
||||
mutable SkBudgeted fBudgeted; // set from the backing resource for wrapped resources
|
||||
SkBackingFit fFit; // always kApprox for lazy-callback resources
|
||||
// always kExact for wrapped resources
|
||||
mutable SkBudgeted fBudgeted; // always kYes for lazy-callback resources
|
||||
// set from the backing resource for wrapped resources
|
||||
// mutable bc of SkSurface/SkImage wishy-washiness
|
||||
const uint32_t fFlags;
|
||||
|
||||
const UniqueID fUniqueID; // set from the backing resource for wrapped resources
|
||||
|
||||
LazyInstantiateCallback fLazyInstantiateCallback;
|
||||
SkDEBUGCODE(virtual void validateLazyTexture(const GrTexture*) = 0;)
|
||||
|
||||
static const size_t kInvalidGpuMemorySize = ~static_cast<size_t>(0);
|
||||
SkDEBUGCODE(size_t getRawGpuMemorySize_debugOnly() const { return fGpuMemorySize; })
|
||||
|
||||
private:
|
||||
virtual size_t onUninstantiatedGpuMemorySize() const = 0;
|
||||
|
||||
bool fNeedsClear;
|
||||
|
@ -67,6 +67,10 @@ protected:
|
||||
// Deferred version
|
||||
GrTextureProxy(const GrSurfaceDesc& srcDesc, SkBackingFit, SkBudgeted,
|
||||
const void* srcData, size_t srcRowBytes, uint32_t flags);
|
||||
|
||||
// Lazy-callback version
|
||||
GrTextureProxy(LazyInstantiateCallback&&, GrPixelConfig);
|
||||
|
||||
// Wrapped version
|
||||
GrTextureProxy(sk_sp<GrSurface>, GrSurfaceOrigin);
|
||||
|
||||
@ -94,6 +98,8 @@ private:
|
||||
void setUniqueKey(GrResourceCache*, const GrUniqueKey&);
|
||||
void clearUniqueKey();
|
||||
|
||||
SkDEBUGCODE(void validateLazyTexture(const GrTexture*) override;)
|
||||
|
||||
// For wrapped proxies the GrTexture pointer is stored in GrIORefProxy.
|
||||
// For deferred proxies that pointer will be filled in when we need to instantiate
|
||||
// the deferred resource
|
||||
|
@ -24,6 +24,8 @@ using GrStdSteadyClock = std::chrono::monotonic_clock;
|
||||
using GrStdSteadyClock = std::chrono::steady_clock;
|
||||
#endif
|
||||
|
||||
static constexpr GrSurfaceOrigin kGrUnknownSurfaceOrigin = static_cast<GrSurfaceOrigin>(-1);
|
||||
|
||||
/** This enum is used to specify the load operation to be used when an
|
||||
* opList/GrGpuCommandBuffer begins execution.
|
||||
*/
|
||||
|
@ -21,6 +21,8 @@
|
||||
#include "GrSurfaceProxyPriv.h"
|
||||
#include "GrTextureContext.h"
|
||||
#include "GrTextureOpList.h"
|
||||
#include "GrTextureProxy.h"
|
||||
#include "GrTextureProxyPriv.h"
|
||||
#include "SkSurface_Gpu.h"
|
||||
#include "SkTTopoSort.h"
|
||||
|
||||
@ -150,10 +152,18 @@ GrSemaphoresSubmitted GrDrawingManager::internalFlush(GrSurfaceProxy*,
|
||||
fFlushingOpListIDs.begin(), fFlushingOpListIDs.count(),
|
||||
&renderTargetContexts);
|
||||
for (const sk_sp<GrRenderTargetContext>& rtc : renderTargetContexts) {
|
||||
sk_sp<GrOpList> onFlushOpList = sk_ref_sp(rtc->getOpList());
|
||||
sk_sp<GrRenderTargetOpList> onFlushOpList = sk_ref_sp(rtc->getRTOpList());
|
||||
if (!onFlushOpList) {
|
||||
continue; // Odd - but not a big deal
|
||||
}
|
||||
#ifdef SK_DEBUG
|
||||
// OnFlush callbacks are already invoked during flush, and are therefore expected to
|
||||
// handle resource allocation & usage on their own. (No deferred or lazy proxies!)
|
||||
onFlushOpList->visitProxies_debugOnly([](GrSurfaceProxy* p) {
|
||||
SkASSERT(!p->asTextureProxy() || !p->asTextureProxy()->texPriv().isDeferred());
|
||||
SkASSERT(!p->isPendingLazyInstantiation());
|
||||
});
|
||||
#endif
|
||||
onFlushOpList->makeClosed(*fContext->caps());
|
||||
onFlushOpList->prepare(&fFlushState);
|
||||
fOnFlushCBOpLists.push_back(std::move(onFlushOpList));
|
||||
|
@ -109,6 +109,7 @@ public:
|
||||
}
|
||||
|
||||
uint32_t testingOnly_addDrawOp(std::unique_ptr<GrDrawOp>);
|
||||
uint32_t testingOnly_addDrawOp(const GrClip&, std::unique_ptr<GrDrawOp>);
|
||||
|
||||
bool refsWrappedObjects() const {
|
||||
return fRenderTargetContext->fRenderTargetProxy->refsWrappedObjects();
|
||||
|
@ -60,6 +60,12 @@ void GrRenderTargetOpList::dump() const {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void GrRenderTargetOpList::visitProxies_debugOnly(const GrOp::VisitProxyFunc& func) const {
|
||||
for (const RecordedOp& recordedOp : fRecordedOps) {
|
||||
recordedOp.visitProxies(func);
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
void GrRenderTargetOpList::onPrepare(GrOpFlushState* flushState) {
|
||||
|
@ -125,6 +125,7 @@ public:
|
||||
|
||||
SkDEBUGCODE(int numOps() const override { return fRecordedOps.count(); })
|
||||
SkDEBUGCODE(int numClips() const override { return fNumClips; })
|
||||
SkDEBUGCODE(void visitProxies_debugOnly(const GrOp::VisitProxyFunc&) const;)
|
||||
|
||||
private:
|
||||
friend class GrRenderTargetContextPriv; // for stencil clip state. TODO: this is invasive
|
||||
|
@ -34,12 +34,20 @@ GrRenderTargetProxy::GrRenderTargetProxy(const GrCaps& caps, const GrSurfaceDesc
|
||||
}
|
||||
}
|
||||
|
||||
// Lazy-callback version
|
||||
GrRenderTargetProxy::GrRenderTargetProxy(LazyInstantiateCallback&& callback, GrPixelConfig config)
|
||||
: INHERITED(std::move(callback), config)
|
||||
, fSampleCnt(0)
|
||||
, fNeedsStencil(false)
|
||||
, fRenderTargetFlags(GrRenderTargetFlags::kNone) {
|
||||
}
|
||||
|
||||
// Wrapped version
|
||||
GrRenderTargetProxy::GrRenderTargetProxy(sk_sp<GrSurface> surf, GrSurfaceOrigin origin)
|
||||
: INHERITED(std::move(surf), origin, SkBackingFit::kExact)
|
||||
, fSampleCnt(fTarget->asRenderTarget()->numStencilSamples())
|
||||
, fNeedsStencil(false)
|
||||
, fRenderTargetFlags(fTarget->asRenderTarget()->renderTargetPriv().flags()) {
|
||||
: INHERITED(std::move(surf), origin, SkBackingFit::kExact)
|
||||
, fSampleCnt(fTarget->asRenderTarget()->numStencilSamples())
|
||||
, fNeedsStencil(false)
|
||||
, fRenderTargetFlags(fTarget->asRenderTarget()->renderTargetPriv().flags()) {
|
||||
}
|
||||
|
||||
int GrRenderTargetProxy::maxWindowRectangles(const GrCaps& caps) const {
|
||||
@ -85,8 +93,8 @@ size_t GrRenderTargetProxy::onUninstantiatedGpuMemorySize() const {
|
||||
int colorSamplesPerPixel = this->numColorSamples() + 1;
|
||||
|
||||
// TODO: do we have enough information to improve this worst case estimate?
|
||||
return GrSurface::ComputeSize(fConfig, fWidth, fHeight, colorSamplesPerPixel, GrMipMapped::kNo,
|
||||
SkBackingFit::kApprox == fFit);
|
||||
return GrSurface::ComputeSize(this->config(), this->width(), this->height(),
|
||||
colorSamplesPerPixel, GrMipMapped::kNo, !this->priv().isExact());
|
||||
}
|
||||
|
||||
bool GrRenderTargetProxy::refsWrappedObjects() const {
|
||||
|
@ -73,6 +73,13 @@ void GrResourceAllocator::addInterval(GrSurfaceProxy* proxy, unsigned int start,
|
||||
|
||||
fIntvlList.insertByIncreasingStart(newIntvl);
|
||||
fIntvlHash.add(newIntvl);
|
||||
|
||||
#ifdef SK_DISABLE_EXPLICIT_GPU_RESOURCE_ALLOCATION
|
||||
// FIXME: remove this once we can do the lazy instantiation from assign instead.
|
||||
if (proxy->isPendingLazyInstantiation()) {
|
||||
proxy->priv().doLazyInstantiation(fResourceProvider);
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
GrResourceAllocator::Interval* GrResourceAllocator::IntervalList::popHead() {
|
||||
@ -224,8 +231,9 @@ bool GrResourceAllocator::assign(int* startIndex, int* stopIndex) {
|
||||
continue;
|
||||
}
|
||||
|
||||
sk_sp<GrSurface> surface = this->findSurfaceFor(cur->proxy(), needsStencil);
|
||||
if (surface) {
|
||||
if (cur->proxy()->isPendingLazyInstantiation()) {
|
||||
cur->proxy()->priv().doLazyInstantiation(fResourceProvider);
|
||||
} else if (sk_sp<GrSurface> surface = this->findSurfaceFor(cur->proxy(), needsStencil)) {
|
||||
// TODO: make getUniqueKey virtual on GrSurfaceProxy
|
||||
GrTextureProxy* tex = cur->proxy()->asTextureProxy();
|
||||
if (tex && tex->getUniqueKey().isValid()) {
|
||||
|
@ -21,6 +21,23 @@
|
||||
#include "SkMathPriv.h"
|
||||
#include "SkMipMap.h"
|
||||
|
||||
// Lazy-callback version
|
||||
GrSurfaceProxy::GrSurfaceProxy(LazyInstantiateCallback&& callback, GrPixelConfig config)
|
||||
: fConfig(config)
|
||||
, fWidth(-1) // Width, height, and origin will be initialized upon lazy instantiation.
|
||||
, fHeight(-1)
|
||||
, fOrigin(kGrUnknownSurfaceOrigin)
|
||||
, fFit(SkBackingFit::kApprox)
|
||||
, fBudgeted(SkBudgeted::kYes)
|
||||
, fFlags(GrResourceProvider::kNoPendingIO_Flag)
|
||||
, fLazyInstantiateCallback(std::move(callback))
|
||||
, fNeedsClear(false)
|
||||
, fGpuMemorySize(kInvalidGpuMemorySize)
|
||||
, fLastOpList(nullptr) {
|
||||
// NOTE: the default fUniqueID ctor pulls a value from the same pool as the GrGpuResources.
|
||||
}
|
||||
|
||||
// Wrapped version
|
||||
GrSurfaceProxy::GrSurfaceProxy(sk_sp<GrSurface> surface, GrSurfaceOrigin origin, SkBackingFit fit)
|
||||
: INHERITED(std::move(surface))
|
||||
, fConfig(fTarget->config())
|
||||
@ -64,6 +81,7 @@ sk_sp<GrSurface> GrSurfaceProxy::createSurfaceImpl(
|
||||
int sampleCnt, bool needsStencil,
|
||||
GrSurfaceFlags flags, GrMipMapped mipMapped,
|
||||
SkDestinationSurfaceColorMode mipColorMode) const {
|
||||
SkASSERT(!this->isPendingLazyInstantiation());
|
||||
SkASSERT(GrMipMapped::kNo == mipMapped);
|
||||
GrSurfaceDesc desc;
|
||||
desc.fFlags = flags;
|
||||
@ -96,6 +114,7 @@ sk_sp<GrSurface> GrSurfaceProxy::createSurfaceImpl(
|
||||
}
|
||||
|
||||
void GrSurfaceProxy::assign(sk_sp<GrSurface> surface) {
|
||||
SkASSERT(!this->isPendingLazyInstantiation());
|
||||
SkASSERT(!fTarget && surface);
|
||||
fTarget = surface.release();
|
||||
this->INHERITED::transferRefs();
|
||||
@ -111,6 +130,7 @@ bool GrSurfaceProxy::instantiateImpl(GrResourceProvider* resourceProvider, int s
|
||||
bool needsStencil, GrSurfaceFlags flags, GrMipMapped mipMapped,
|
||||
SkDestinationSurfaceColorMode mipColorMode,
|
||||
const GrUniqueKey* uniqueKey) {
|
||||
SkASSERT(!this->isPendingLazyInstantiation());
|
||||
if (fTarget) {
|
||||
if (uniqueKey) {
|
||||
SkASSERT(fTarget->getUniqueKey() == *uniqueKey);
|
||||
@ -135,6 +155,7 @@ bool GrSurfaceProxy::instantiateImpl(GrResourceProvider* resourceProvider, int s
|
||||
}
|
||||
|
||||
void GrSurfaceProxy::computeScratchKey(GrScratchKey* key) const {
|
||||
SkASSERT(!this->isPendingLazyInstantiation());
|
||||
const GrRenderTargetProxy* rtp = this->asRenderTargetProxy();
|
||||
int sampleCount = 0;
|
||||
if (rtp) {
|
||||
@ -377,7 +398,15 @@ sk_sp<GrTextureProxy> GrSurfaceProxy::MakeWrappedBackend(GrContext* context,
|
||||
return GrSurfaceProxy::MakeWrapped(std::move(tex), origin);
|
||||
}
|
||||
|
||||
sk_sp<GrTextureProxy> GrSurfaceProxy::MakeLazy(LazyInstantiateCallback&& callback,
|
||||
Renderable renderable, GrPixelConfig config) {
|
||||
return sk_sp<GrTextureProxy>(Renderable::kYes == renderable ?
|
||||
new GrTextureRenderTargetProxy(std::move(callback), config) :
|
||||
new GrTextureProxy(std::move(callback), config));
|
||||
}
|
||||
|
||||
int GrSurfaceProxy::worstCaseWidth() const {
|
||||
SkASSERT(!this->isPendingLazyInstantiation());
|
||||
if (fTarget) {
|
||||
return fTarget->width();
|
||||
}
|
||||
@ -389,6 +418,7 @@ int GrSurfaceProxy::worstCaseWidth() const {
|
||||
}
|
||||
|
||||
int GrSurfaceProxy::worstCaseHeight() const {
|
||||
SkASSERT(!this->isPendingLazyInstantiation());
|
||||
if (fTarget) {
|
||||
return fTarget->height();
|
||||
}
|
||||
@ -414,6 +444,7 @@ sk_sp<GrTextureProxy> GrSurfaceProxy::Copy(GrContext* context,
|
||||
GrMipMapped mipMapped,
|
||||
SkIRect srcRect,
|
||||
SkBudgeted budgeted) {
|
||||
SkASSERT(!src->isPendingLazyInstantiation());
|
||||
if (!srcRect.intersect(SkIRect::MakeWH(src->width(), src->height()))) {
|
||||
return nullptr;
|
||||
}
|
||||
@ -442,12 +473,13 @@ sk_sp<GrTextureProxy> GrSurfaceProxy::Copy(GrContext* context,
|
||||
|
||||
sk_sp<GrTextureProxy> GrSurfaceProxy::Copy(GrContext* context, GrSurfaceProxy* src,
|
||||
GrMipMapped mipMapped, SkBudgeted budgeted) {
|
||||
SkASSERT(!src->isPendingLazyInstantiation());
|
||||
return Copy(context, src, mipMapped, SkIRect::MakeWH(src->width(), src->height()), budgeted);
|
||||
}
|
||||
|
||||
sk_sp<GrSurfaceContext> GrSurfaceProxy::TestCopy(GrContext* context, const GrSurfaceDesc& dstDesc,
|
||||
GrSurfaceProxy* srcProxy) {
|
||||
|
||||
SkASSERT(!srcProxy->isPendingLazyInstantiation());
|
||||
sk_sp<GrSurfaceContext> dstContext(context->contextPriv().makeDeferredSurfaceContext(
|
||||
dstDesc,
|
||||
GrMipMapped::kNo,
|
||||
@ -465,6 +497,7 @@ sk_sp<GrSurfaceContext> GrSurfaceProxy::TestCopy(GrContext* context, const GrSur
|
||||
}
|
||||
|
||||
void GrSurfaceProxyPriv::exactify() {
|
||||
SkASSERT(!fProxy->isPendingLazyInstantiation());
|
||||
if (this->isExact()) {
|
||||
return;
|
||||
}
|
||||
@ -491,3 +524,30 @@ void GrSurfaceProxyPriv::exactify() {
|
||||
// exact amount.
|
||||
}
|
||||
|
||||
void GrSurfaceProxyPriv::doLazyInstantiation(GrResourceProvider* resourceProvider) {
|
||||
SkASSERT(fProxy->fLazyInstantiateCallback);
|
||||
SkASSERT(!fProxy->fTarget);
|
||||
|
||||
sk_sp<GrTexture> texture = fProxy->fLazyInstantiateCallback(resourceProvider, &fProxy->fOrigin);
|
||||
|
||||
// Indicate we are no longer pending lazy instantiation.
|
||||
fProxy->fLazyInstantiateCallback = nullptr;
|
||||
|
||||
if (!texture) {
|
||||
fProxy->fWidth = 0;
|
||||
fProxy->fHeight = 0;
|
||||
fProxy->fOrigin = kTopLeft_GrSurfaceOrigin;
|
||||
return;
|
||||
}
|
||||
|
||||
fProxy->fWidth = texture->width();
|
||||
fProxy->fHeight = texture->height();
|
||||
|
||||
SkASSERT(texture->config() == fProxy->fConfig);
|
||||
SkASSERT(kGrUnknownSurfaceOrigin != fProxy->origin());
|
||||
SkASSERT(kTopLeft_GrSurfaceOrigin == fProxy->fOrigin ||
|
||||
kBottomLeft_GrSurfaceOrigin == fProxy->fOrigin);
|
||||
SkDEBUGCODE(fProxy->validateLazyTexture(texture.get());)
|
||||
this->assign(std::move(texture));
|
||||
}
|
||||
|
||||
|
@ -68,6 +68,8 @@ public:
|
||||
// Don't. Just don't.
|
||||
void exactify();
|
||||
|
||||
void doLazyInstantiation(GrResourceProvider*);
|
||||
|
||||
static bool AttachStencilIfNeeded(GrResourceProvider*, GrSurface*, bool needsStencil);
|
||||
|
||||
private:
|
||||
|
@ -13,6 +13,7 @@
|
||||
#include "GrResourceCache.h"
|
||||
#include "GrTexturePriv.h"
|
||||
|
||||
// Deferred version
|
||||
GrTextureProxy::GrTextureProxy(const GrSurfaceDesc& srcDesc, SkBackingFit fit, SkBudgeted budgeted,
|
||||
const void* srcData, size_t /*rowBytes*/, uint32_t flags)
|
||||
: INHERITED(srcDesc, fit, budgeted, flags)
|
||||
@ -23,6 +24,16 @@ GrTextureProxy::GrTextureProxy(const GrSurfaceDesc& srcDesc, SkBackingFit fit, S
|
||||
SkASSERT(!srcData); // currently handled in Make()
|
||||
}
|
||||
|
||||
// Lazy-callback version
|
||||
GrTextureProxy::GrTextureProxy(LazyInstantiateCallback&& callback, GrPixelConfig config)
|
||||
: INHERITED(std::move(callback), config)
|
||||
, fMipMapped(GrMipMapped::kNo)
|
||||
, fMipColorMode(SkDestinationSurfaceColorMode::kLegacy)
|
||||
, fCache(nullptr)
|
||||
, fDeferredUploader(nullptr) {
|
||||
}
|
||||
|
||||
// Wrapped version
|
||||
GrTextureProxy::GrTextureProxy(sk_sp<GrSurface> surf, GrSurfaceOrigin origin)
|
||||
: INHERITED(std::move(surf), origin, SkBackingFit::kExact)
|
||||
, fMipMapped(fTarget->asTexture()->texturePriv().mipMapped())
|
||||
@ -109,8 +120,8 @@ GrSamplerState::Filter GrTextureProxy::highestFilterMode() const {
|
||||
}
|
||||
|
||||
size_t GrTextureProxy::onUninstantiatedGpuMemorySize() const {
|
||||
return GrSurface::ComputeSize(fConfig, fWidth, fHeight, 1, this->mipMapped(),
|
||||
SkBackingFit::kApprox == fFit);
|
||||
return GrSurface::ComputeSize(this->config(), this->width(), this->height(), 1,
|
||||
this->mipMapped(), !this->priv().isExact());
|
||||
}
|
||||
|
||||
void GrTextureProxy::setUniqueKey(GrResourceCache* cache, const GrUniqueKey& key) {
|
||||
@ -131,3 +142,10 @@ void GrTextureProxy::clearUniqueKey() {
|
||||
fCache = nullptr;
|
||||
}
|
||||
|
||||
#ifdef SK_DEBUG
|
||||
void GrTextureProxy::validateLazyTexture(const GrTexture* texture) {
|
||||
SkASSERT(!texture->asRenderTarget());
|
||||
SkASSERT(GrMipMapped::kNo == this->mipMapped());
|
||||
}
|
||||
#endif
|
||||
|
||||
|
@ -7,6 +7,10 @@
|
||||
|
||||
#include "GrTextureRenderTargetProxy.h"
|
||||
|
||||
#include "GrTexture.h"
|
||||
#include "GrRenderTarget.h"
|
||||
#include "GrSurfaceProxyPriv.h"
|
||||
|
||||
// Deferred version
|
||||
// This class is virtually derived from GrSurfaceProxy (via both GrTextureProxy and
|
||||
// GrRenderTargetProxy) so its constructor must be explicitly called.
|
||||
@ -15,10 +19,20 @@ GrTextureRenderTargetProxy::GrTextureRenderTargetProxy(const GrCaps& caps,
|
||||
SkBackingFit fit,
|
||||
SkBudgeted budgeted,
|
||||
uint32_t flags)
|
||||
: GrSurfaceProxy(desc, fit, budgeted, flags)
|
||||
// for now textures w/ data are always wrapped
|
||||
, GrTextureProxy(desc, fit, budgeted, nullptr, 0, flags)
|
||||
, GrRenderTargetProxy(caps, desc, fit, budgeted, flags) {
|
||||
: GrSurfaceProxy(desc, fit, budgeted, flags)
|
||||
// for now textures w/ data are always wrapped
|
||||
, GrTextureProxy(desc, fit, budgeted, nullptr, 0, flags)
|
||||
, GrRenderTargetProxy(caps, desc, fit, budgeted, flags) {
|
||||
}
|
||||
|
||||
// Lazy-callback version
|
||||
GrTextureRenderTargetProxy::GrTextureRenderTargetProxy(LazyInstantiateCallback&& callback,
|
||||
GrPixelConfig config)
|
||||
: GrSurfaceProxy(std::move(callback), config)
|
||||
// Since we have virtual inheritance, we initialize GrSurfaceProxy directly. Send null
|
||||
// callbacks to the texture and RT proxies simply to route to the appropriate constructors.
|
||||
, GrTextureProxy(LazyInstantiateCallback(), config)
|
||||
, GrRenderTargetProxy(LazyInstantiateCallback(), config) {
|
||||
}
|
||||
|
||||
// Wrapped version
|
||||
@ -26,9 +40,9 @@ GrTextureRenderTargetProxy::GrTextureRenderTargetProxy(const GrCaps& caps,
|
||||
// GrRenderTargetProxy) so its constructor must be explicitly called.
|
||||
GrTextureRenderTargetProxy::GrTextureRenderTargetProxy(sk_sp<GrSurface> surf,
|
||||
GrSurfaceOrigin origin)
|
||||
: GrSurfaceProxy(surf, origin, SkBackingFit::kExact)
|
||||
, GrTextureProxy(surf, origin)
|
||||
, GrRenderTargetProxy(surf, origin) {
|
||||
: GrSurfaceProxy(surf, origin, SkBackingFit::kExact)
|
||||
, GrTextureProxy(surf, origin)
|
||||
, GrRenderTargetProxy(surf, origin) {
|
||||
SkASSERT(surf->asTexture());
|
||||
SkASSERT(surf->asRenderTarget());
|
||||
}
|
||||
@ -37,8 +51,8 @@ size_t GrTextureRenderTargetProxy::onUninstantiatedGpuMemorySize() const {
|
||||
int colorSamplesPerPixel = this->numColorSamples() + 1;
|
||||
|
||||
// TODO: do we have enough information to improve this worst case estimate?
|
||||
return GrSurface::ComputeSize(fConfig, fWidth, fHeight, colorSamplesPerPixel, this->mipMapped(),
|
||||
SkBackingFit::kApprox == fFit);
|
||||
return GrSurface::ComputeSize(this->config(), this->width(), this->height(),
|
||||
colorSamplesPerPixel, this->mipMapped(), !this->priv().isExact());
|
||||
}
|
||||
|
||||
bool GrTextureRenderTargetProxy::instantiate(GrResourceProvider* resourceProvider) {
|
||||
@ -77,3 +91,11 @@ sk_sp<GrSurface> GrTextureRenderTargetProxy::createSurface(
|
||||
return surface;
|
||||
}
|
||||
|
||||
#ifdef SK_DEBUG
|
||||
void GrTextureRenderTargetProxy::validateLazyTexture(const GrTexture* texture) {
|
||||
SkASSERT(texture->asRenderTarget());
|
||||
SkASSERT(texture->asRenderTarget()->numStencilSamples() == this->numStencilSamples());
|
||||
SkASSERT(GrMipMapped::kNo == this->mipMapped());
|
||||
}
|
||||
#endif
|
||||
|
||||
|
@ -29,6 +29,9 @@ private:
|
||||
GrTextureRenderTargetProxy(const GrCaps&, const GrSurfaceDesc&,
|
||||
SkBackingFit, SkBudgeted, uint32_t flags);
|
||||
|
||||
// Lazy-callback version
|
||||
GrTextureRenderTargetProxy(LazyInstantiateCallback&&, GrPixelConfig);
|
||||
|
||||
// Wrapped version
|
||||
GrTextureRenderTargetProxy(sk_sp<GrSurface>, GrSurfaceOrigin);
|
||||
|
||||
@ -36,6 +39,8 @@ private:
|
||||
sk_sp<GrSurface> createSurface(GrResourceProvider*) const override;
|
||||
|
||||
size_t onUninstantiatedGpuMemorySize() const override;
|
||||
|
||||
SkDEBUGCODE(void validateLazyTexture(const GrTexture*) override;)
|
||||
};
|
||||
|
||||
#ifdef SK_BUILD_FOR_WIN
|
||||
|
189
tests/LazyProxyTest.cpp
Normal file
189
tests/LazyProxyTest.cpp
Normal file
@ -0,0 +1,189 @@
|
||||
/*
|
||||
* Copyright 2017 Google Inc.
|
||||
*
|
||||
* Use of this source code is governed by a BSD-style license that can be
|
||||
* found in the LICENSE file.
|
||||
*/
|
||||
|
||||
#include "Test.h"
|
||||
|
||||
#if SK_SUPPORT_GPU
|
||||
|
||||
#include "GrClip.h"
|
||||
#include "GrContextPriv.h"
|
||||
#include "GrOnFlushResourceProvider.h"
|
||||
#include "GrRenderTargetContext.h"
|
||||
#include "GrRenderTargetContextPriv.h"
|
||||
#include "GrSurfaceProxy.h"
|
||||
#include "GrTexture.h"
|
||||
#include "GrTextureProxy.h"
|
||||
#include "GrTextureProxyPriv.h"
|
||||
#include "SkMakeUnique.h"
|
||||
#include "mock/GrMockTypes.h"
|
||||
|
||||
// This test verifies that lazy proxy callbacks get invoked during flush, after onFlush callbacks,
|
||||
// but before Ops are executed. It also ensures that lazy proxy callbacks are invoked both for
|
||||
// regular Ops and for clips.
|
||||
class LazyProxyTest final : public GrOnFlushCallbackObject {
|
||||
public:
|
||||
LazyProxyTest(skiatest::Reporter* reporter)
|
||||
: fReporter(reporter)
|
||||
, fHasOpTexture(false)
|
||||
, fHasClipTexture(false) {
|
||||
}
|
||||
|
||||
~LazyProxyTest() override {
|
||||
REPORTER_ASSERT(fReporter, fHasOpTexture);
|
||||
REPORTER_ASSERT(fReporter, fHasClipTexture);
|
||||
}
|
||||
|
||||
void preFlush(GrOnFlushResourceProvider*, const uint32_t*, int,
|
||||
SkTArray<sk_sp<GrRenderTargetContext>>*) override {
|
||||
REPORTER_ASSERT(fReporter, !fHasOpTexture);
|
||||
REPORTER_ASSERT(fReporter, !fHasClipTexture);
|
||||
}
|
||||
|
||||
void postFlush(GrDeferredUploadToken, const uint32_t* opListIDs, int numOpListIDs) override {
|
||||
REPORTER_ASSERT(fReporter, fHasOpTexture);
|
||||
REPORTER_ASSERT(fReporter, fHasClipTexture);
|
||||
}
|
||||
|
||||
class Op final : public GrDrawOp {
|
||||
public:
|
||||
DEFINE_OP_CLASS_ID
|
||||
|
||||
Op(LazyProxyTest* test, bool nullTexture) : GrDrawOp(ClassID()), fTest(test) {
|
||||
fProxy = GrSurfaceProxy::MakeLazy([this, nullTexture](GrResourceProvider* rp,
|
||||
GrSurfaceOrigin* origin) {
|
||||
REPORTER_ASSERT(fTest->fReporter, !fTest->fHasOpTexture);
|
||||
fTest->fHasOpTexture = true;
|
||||
*origin = kTopLeft_GrSurfaceOrigin;
|
||||
if (nullTexture) {
|
||||
return sk_sp<GrTexture>();
|
||||
} else {
|
||||
GrSurfaceDesc desc;
|
||||
desc.fWidth = 1234;
|
||||
desc.fHeight = 567;
|
||||
desc.fOrigin = kTopLeft_GrSurfaceOrigin;
|
||||
desc.fConfig = kRGB_565_GrPixelConfig;
|
||||
sk_sp<GrTexture> texture = rp->createTexture(desc, SkBudgeted::kYes);
|
||||
REPORTER_ASSERT(fTest->fReporter, texture);
|
||||
return texture;
|
||||
}
|
||||
}, GrSurfaceProxy::Renderable::kNo, kRGB_565_GrPixelConfig);
|
||||
this->setBounds(SkRect::MakeLargest(), GrOp::HasAABloat::kNo, GrOp::IsZeroArea::kNo);
|
||||
}
|
||||
|
||||
void visitProxies(const VisitProxyFunc& func) const override {
|
||||
func(fProxy.get());
|
||||
}
|
||||
|
||||
void onExecute(GrOpFlushState*) override {
|
||||
REPORTER_ASSERT(fTest->fReporter, fTest->fHasOpTexture);
|
||||
REPORTER_ASSERT(fTest->fReporter, fTest->fHasClipTexture);
|
||||
}
|
||||
|
||||
private:
|
||||
const char* name() const override { return "LazyProxyTest::Op"; }
|
||||
FixedFunctionFlags fixedFunctionFlags() const override { return FixedFunctionFlags::kNone; }
|
||||
RequiresDstTexture finalize(const GrCaps&, const GrAppliedClip*,
|
||||
GrPixelConfigIsClamped) override {
|
||||
return RequiresDstTexture::kNo;
|
||||
}
|
||||
void wasRecorded(GrRenderTargetOpList*) override {}
|
||||
bool onCombineIfPossible(GrOp* other, const GrCaps& caps) override { return false; }
|
||||
void onPrepare(GrOpFlushState*) override {}
|
||||
|
||||
LazyProxyTest* const fTest;
|
||||
sk_sp<GrTextureProxy> fProxy;
|
||||
};
|
||||
|
||||
class ClipFP : public GrFragmentProcessor {
|
||||
public:
|
||||
ClipFP(LazyProxyTest* test, GrTextureProxy* atlas)
|
||||
: GrFragmentProcessor(kTestFP_ClassID, kNone_OptimizationFlags)
|
||||
, fTest(test)
|
||||
, fAtlas(atlas) {
|
||||
fLazyProxy = GrSurfaceProxy::MakeLazy([this](GrResourceProvider* rp,
|
||||
GrSurfaceOrigin* origin) {
|
||||
REPORTER_ASSERT(fTest->fReporter, !fTest->fHasClipTexture);
|
||||
fTest->fHasClipTexture = true;
|
||||
*origin = kBottomLeft_GrSurfaceOrigin;
|
||||
fAtlas->instantiate(rp);
|
||||
return sk_ref_sp(fAtlas->priv().peekTexture());
|
||||
}, GrSurfaceProxy::Renderable::kYes, kAlpha_half_GrPixelConfig);
|
||||
fAccess.reset(fLazyProxy, GrSamplerState::Filter::kNearest,
|
||||
GrSamplerState::WrapMode::kClamp, kFragment_GrShaderFlag);
|
||||
this->addTextureSampler(&fAccess);
|
||||
}
|
||||
|
||||
private:
|
||||
const char* name() const override { return "LazyProxyTest::ClipFP"; }
|
||||
std::unique_ptr<GrFragmentProcessor> clone() const override {
|
||||
return skstd::make_unique<ClipFP>(fTest, fAtlas);
|
||||
}
|
||||
GrGLSLFragmentProcessor* onCreateGLSLInstance() const override { return nullptr; }
|
||||
void onGetGLSLProcessorKey(const GrShaderCaps&, GrProcessorKeyBuilder*) const override {}
|
||||
bool onIsEqual(const GrFragmentProcessor&) const override { return false; }
|
||||
|
||||
LazyProxyTest* const fTest;
|
||||
GrTextureProxy* const fAtlas;
|
||||
sk_sp<GrTextureProxy> fLazyProxy;
|
||||
TextureSampler fAccess;
|
||||
};
|
||||
|
||||
|
||||
class Clip : public GrClip {
|
||||
public:
|
||||
Clip(LazyProxyTest* test, GrTextureProxy* atlas)
|
||||
: fTest(test)
|
||||
, fAtlas(atlas) {}
|
||||
|
||||
private:
|
||||
bool apply(GrContext*, GrRenderTargetContext*, bool, bool, GrAppliedClip* out,
|
||||
SkRect* bounds) const override {
|
||||
out->addCoverageFP(skstd::make_unique<ClipFP>(fTest, fAtlas));
|
||||
return true;
|
||||
}
|
||||
bool quickContains(const SkRect&) const final { return false; }
|
||||
bool isRRect(const SkRect& rtBounds, SkRRect* rr, GrAA*) const final { return false; }
|
||||
void getConservativeBounds(int width, int height, SkIRect* rect, bool* iior) const final {
|
||||
rect->set(0, 0, width, height);
|
||||
if (iior) {
|
||||
*iior = false;
|
||||
}
|
||||
}
|
||||
|
||||
LazyProxyTest* const fTest;
|
||||
GrTextureProxy* fAtlas;
|
||||
};
|
||||
|
||||
private:
|
||||
skiatest::Reporter* fReporter;
|
||||
bool fHasOpTexture;
|
||||
bool fHasClipTexture;
|
||||
};
|
||||
|
||||
DEF_GPUTEST(LazyProxyTest, reporter, /* options */) {
|
||||
GrMockOptions mockOptions;
|
||||
mockOptions.fConfigOptions[kAlpha_half_GrPixelConfig].fRenderable[0] = true;
|
||||
mockOptions.fConfigOptions[kAlpha_half_GrPixelConfig].fTexturable = true;
|
||||
sk_sp<GrContext> ctx = GrContext::MakeMock(&mockOptions, GrContextOptions());
|
||||
for (bool nullTexture : {false, true}) {
|
||||
LazyProxyTest test(reporter);
|
||||
ctx->contextPriv().addOnFlushCallbackObject(&test);
|
||||
sk_sp<GrRenderTargetContext> rtc =
|
||||
ctx->makeDeferredRenderTargetContext(SkBackingFit::kExact, 100, 100,
|
||||
kRGBA_8888_GrPixelConfig, nullptr);
|
||||
REPORTER_ASSERT(reporter, rtc);
|
||||
sk_sp<GrRenderTargetContext> mockAtlas =
|
||||
ctx->makeDeferredRenderTargetContext(SkBackingFit::kExact, 10, 10,
|
||||
kAlpha_half_GrPixelConfig, nullptr);
|
||||
REPORTER_ASSERT(reporter, mockAtlas);
|
||||
rtc->priv().testingOnly_addDrawOp(LazyProxyTest::Clip(&test, mockAtlas->asTextureProxy()),
|
||||
skstd::make_unique<LazyProxyTest::Op>(&test, nullTexture));
|
||||
ctx->contextPriv().testingOnly_flushAndRemoveOnFlushCallbackObject(&test);
|
||||
}
|
||||
}
|
||||
|
||||
#endif
|
@ -274,7 +274,13 @@ int GrResourceCache::countUniqueKeysWithTag(const char* tag) const {
|
||||
#define ASSERT_SINGLE_OWNER \
|
||||
SkDEBUGCODE(GrSingleOwner::AutoEnforce debug_SingleOwner(fRenderTargetContext->singleOwner());)
|
||||
|
||||
|
||||
uint32_t GrRenderTargetContextPriv::testingOnly_addDrawOp(std::unique_ptr<GrDrawOp> op) {
|
||||
return this->testingOnly_addDrawOp(GrNoClip(), std::move(op));
|
||||
}
|
||||
|
||||
uint32_t GrRenderTargetContextPriv::testingOnly_addDrawOp(const GrClip& clip,
|
||||
std::unique_ptr<GrDrawOp> op) {
|
||||
ASSERT_SINGLE_OWNER
|
||||
if (fRenderTargetContext->drawingManager()->wasAbandoned()) {
|
||||
return SK_InvalidUniqueID;
|
||||
@ -282,7 +288,7 @@ uint32_t GrRenderTargetContextPriv::testingOnly_addDrawOp(std::unique_ptr<GrDraw
|
||||
SkDEBUGCODE(fRenderTargetContext->validate());
|
||||
GR_AUDIT_TRAIL_AUTO_FRAME(fRenderTargetContext->fAuditTrail,
|
||||
"GrRenderTargetContext::testingOnly_addDrawOp");
|
||||
return fRenderTargetContext->addDrawOp(GrNoClip(), std::move(op));
|
||||
return fRenderTargetContext->addDrawOp(clip, std::move(op));
|
||||
}
|
||||
|
||||
#undef ASSERT_SINGLE_OWNER
|
||||
|
Loading…
Reference in New Issue
Block a user