GrBackendTextureImageGenerator proxy callback uses unique key to find existing GrTexture.
This removes a case where we can get the first ref on a GrGpuResource outside of GrResourceCache. Bug: skia:8927 Change-Id: I4068aff2f91a2e11ada059f4ef406a620140319b Reviewed-on: https://skia-review.googlesource.com/c/skia/+/204770 Commit-Queue: Brian Salomon <bsalomon@google.com> Reviewed-by: Robert Phillips <robertphillips@google.com>
This commit is contained in:
parent
acc10fa32b
commit
b916b7b227
@ -24,8 +24,14 @@
|
||||
#include "SkMessageBus.h"
|
||||
#include "gl/GrGLTexture.h"
|
||||
|
||||
GrBackendTextureImageGenerator::RefHelper::RefHelper(GrTexture* texture, uint32_t owningContextID)
|
||||
: fOriginalTexture(texture)
|
||||
, fOwningContextID(owningContextID)
|
||||
, fBorrowingContextReleaseProc(nullptr)
|
||||
, fBorrowingContextID(SK_InvalidGenID) {}
|
||||
|
||||
GrBackendTextureImageGenerator::RefHelper::~RefHelper() {
|
||||
SkASSERT(nullptr == fBorrowedTexture);
|
||||
SkASSERT(fBorrowingContextID == SK_InvalidUniqueID);
|
||||
|
||||
// Generator has been freed, and no one is borrowing the texture. Notify the original cache
|
||||
// that it can free the last ref, so it happens on the correct thread.
|
||||
@ -68,12 +74,12 @@ GrBackendTextureImageGenerator::GrBackendTextureImageGenerator(const SkImageInfo
|
||||
uint32_t owningContextID,
|
||||
sk_sp<GrSemaphore> semaphore,
|
||||
const GrBackendTexture& backendTex)
|
||||
: INHERITED(info)
|
||||
, fRefHelper(new RefHelper(texture, owningContextID))
|
||||
, fSemaphore(std::move(semaphore))
|
||||
, fBackendTexture(backendTex)
|
||||
, fConfig(backendTex.config())
|
||||
, fSurfaceOrigin(origin) { }
|
||||
: INHERITED(info)
|
||||
, fRefHelper(new RefHelper(texture, owningContextID))
|
||||
, fSemaphore(std::move(semaphore))
|
||||
, fBackendTexture(backendTex)
|
||||
, fConfig(backendTex.config())
|
||||
, fSurfaceOrigin(origin) {}
|
||||
|
||||
GrBackendTextureImageGenerator::~GrBackendTextureImageGenerator() {
|
||||
fRefHelper->unref();
|
||||
@ -85,7 +91,6 @@ void GrBackendTextureImageGenerator::ReleaseRefHelper_TextureReleaseProc(void* c
|
||||
RefHelper* refHelper = static_cast<RefHelper*>(ctx);
|
||||
SkASSERT(refHelper);
|
||||
|
||||
refHelper->fBorrowedTexture = nullptr;
|
||||
refHelper->fBorrowingContextReleaseProc = nullptr;
|
||||
refHelper->fBorrowingContextID = SK_InvalidGenID;
|
||||
refHelper->unref();
|
||||
@ -126,6 +131,11 @@ sk_sp<GrTextureProxy> GrBackendTextureImageGenerator::onGenerateTexture(
|
||||
fRefHelper->fBorrowingContextReleaseProc = releaseProcHelper.get();
|
||||
}
|
||||
fRefHelper->fBorrowingContextID = context->priv().contextID();
|
||||
if (!fRefHelper->fBorrowedTextureKey.isValid()) {
|
||||
static const auto kDomain = GrUniqueKey::GenerateDomain();
|
||||
GrUniqueKey::Builder builder(&fRefHelper->fBorrowedTextureKey, kDomain, 1);
|
||||
builder[0] = this->uniqueID();
|
||||
}
|
||||
fBorrowingMutex.release();
|
||||
|
||||
SkASSERT(fRefHelper->fBorrowingContextID == context->priv().contextID());
|
||||
@ -149,14 +159,17 @@ sk_sp<GrTextureProxy> GrBackendTextureImageGenerator::onGenerateTexture(
|
||||
resourceProvider->priv().gpu()->waitSemaphore(semaphore);
|
||||
}
|
||||
|
||||
// If a client re-draws the same image multiple times, the texture we return
|
||||
// will be cached and re-used. If they draw a subset, though, we may be
|
||||
// re-called. In that case, we want to re-use the borrowed texture we've
|
||||
// previously created.
|
||||
sk_sp<GrTexture> tex;
|
||||
if (refHelper->fBorrowedTexture) {
|
||||
// If a client re-draws the same image multiple times, the texture we return
|
||||
// will be cached and re-used. If they draw a subset, though, we may be
|
||||
// re-called. In that case, we want to re-use the borrowed texture we've
|
||||
// previously created.
|
||||
tex = sk_ref_sp(refHelper->fBorrowedTexture);
|
||||
SkASSERT(tex);
|
||||
SkASSERT(refHelper->fBorrowedTextureKey.isValid());
|
||||
auto surf = resourceProvider->findByUniqueKey<GrSurface>(
|
||||
refHelper->fBorrowedTextureKey);
|
||||
if (surf) {
|
||||
SkASSERT(surf->asTexture());
|
||||
tex = sk_ref_sp(surf->asTexture());
|
||||
} else {
|
||||
// We just gained access to the texture. If we're on the original context, we
|
||||
// could use the original texture, but we'd have no way of detecting that it's
|
||||
@ -171,11 +184,12 @@ sk_sp<GrTextureProxy> GrBackendTextureImageGenerator::onGenerateTexture(
|
||||
if (!tex) {
|
||||
return {};
|
||||
}
|
||||
refHelper->fBorrowedTexture = tex.get();
|
||||
|
||||
tex->setRelease(releaseProcHelper);
|
||||
tex->resourcePriv().setUniqueKey(refHelper->fBorrowedTextureKey);
|
||||
}
|
||||
return std::move(tex);
|
||||
// We use keys to avoid re-wrapping the GrBackendTexture in a GrTexture. This is
|
||||
// unrelated to the whatever SkImage key may be assigned to the proxy.
|
||||
return {std::move(tex), GrSurfaceProxy::LazyInstantiationKeyMode::kUnsynced};
|
||||
},
|
||||
format, desc, fSurfaceOrigin, mipMapped, GrInternalSurfaceFlags::kReadOnly,
|
||||
SkBackingFit::kExact, SkBudgeted::kNo);
|
||||
|
@ -7,9 +7,9 @@
|
||||
#ifndef GrBackendTextureImageGenerator_DEFINED
|
||||
#define GrBackendTextureImageGenerator_DEFINED
|
||||
|
||||
#include "SkImageGenerator.h"
|
||||
|
||||
#include "GrBackendSurface.h"
|
||||
#include "GrResourceKey.h"
|
||||
#include "SkImageGenerator.h"
|
||||
#include "SkMutex.h"
|
||||
|
||||
class GrSemaphore;
|
||||
@ -52,27 +52,21 @@ private:
|
||||
|
||||
class RefHelper : public SkNVRefCnt<RefHelper> {
|
||||
public:
|
||||
RefHelper(GrTexture* texture, uint32_t owningContextID)
|
||||
: fOriginalTexture(texture)
|
||||
, fOwningContextID(owningContextID)
|
||||
, fBorrowedTexture(nullptr)
|
||||
, fBorrowingContextReleaseProc(nullptr)
|
||||
, fBorrowingContextID(SK_InvalidGenID) {}
|
||||
RefHelper(GrTexture*, uint32_t owningContextID);
|
||||
|
||||
~RefHelper();
|
||||
|
||||
GrTexture* fOriginalTexture;
|
||||
uint32_t fOwningContextID;
|
||||
|
||||
// There is never a ref associated with this pointer. We rely on our atomic bookkeeping
|
||||
// with the context ID to know when this pointer is valid and safe to use. This lets us
|
||||
// avoid releasing a ref from another thread, or get into races during context shutdown.
|
||||
GrTexture* fBorrowedTexture;
|
||||
// For the same reason as the fBorrowedTexture, there is no ref associated with this
|
||||
// pointer. The fBorrowingContextReleaseProc is used to make sure all uses of the wrapped
|
||||
// texture are finished on the borrowing context before we open this back up to other
|
||||
// contexts. In general a ref to this release proc is owned by all proxies and gpu uses of
|
||||
// the backend texture.
|
||||
// We use this key so that we don't rewrap the GrBackendTexture in a GrTexture for each
|
||||
// proxy created from this generator for a particular borrowing context.
|
||||
GrUniqueKey fBorrowedTextureKey;
|
||||
// There is no ref associated with this pointer. We rely on our atomic bookkeeping with the
|
||||
// context ID to know when this pointer is valid and safe to use. This is used to make sure
|
||||
// all uses of the wrapped texture are finished on the borrowing context before we open
|
||||
// this back up to other contexts. In general a ref to this release proc is owned by all
|
||||
// proxies and gpu uses of the backend texture.
|
||||
GrRefCntedCallback* fBorrowingContextReleaseProc;
|
||||
uint32_t fBorrowingContextID;
|
||||
};
|
||||
|
Loading…
Reference in New Issue
Block a user