Change PromiseImage API to take GrContextThreadSafeProxy

This detaches PromiseImages from any specific context, just to
a certain family.

Next up is to remove the tileSpecificSKP code from the DDLTileHelper.

Currently we have this janky PromiseImageDummy GrImageContext that
we make for each promise image. It's not ideal but it'll tide us over.

Bug: skia:10286
Change-Id: I12ab0bb7df9360a08af594da80de9df14cc2a44f
Reviewed-on: https://skia-review.googlesource.com/c/skia/+/372516
Commit-Queue: Adlai Holler <adlai@google.com>
Reviewed-by: Robert Phillips <robertphillips@google.com>
This commit is contained in:
Adlai Holler 2021-02-19 12:33:46 -05:00 committed by Skia Commit-Bot
parent 6e88e041d9
commit dced31f62b
13 changed files with 102 additions and 37 deletions

View File

@ -13,7 +13,9 @@
class GrImageContextPriv;
// CONTEXT TODO: Remove this once SkImage_Gpu is migrated to holding just a ThreadSafeProxy.
// This is now just a view on a ThreadSafeProxy, that SkImages can attempt to
// downcast to a GrDirectContext as a backdoor to some operations. Once we remove the backdoors,
// this goes away and SkImages just hold ThreadSafeProxies.
class GrImageContext : public GrContext_Base {
public:
~GrImageContext() override;
@ -36,9 +38,15 @@ protected:
GrImageContext* asImageContext() override { return this; }
private:
// When making promise images, we currently need a placeholder GrImageContext instance to give
// to the SkImage that has no real power, just a wrapper around the ThreadSafeProxy.
// TODO: De-power SkImage to ThreadSafeProxy or at least figure out a way to share one instance.
static sk_sp<GrImageContext> MakeForPromiseImage(sk_sp<GrContextThreadSafeProxy>);
// In debug builds we guard against improper thread handling
// This guard is passed to the GrDrawingManager and, from there to all the
// GrSurfaceDrawContexts. It is also passed to the GrResourceProvider and SkGpuDevice.
// TODO: Move this down to GrRecordingContext.
mutable GrSingleOwner fSingleOwner;
using INHERITED = GrContext_Base;

View File

@ -246,7 +246,10 @@ sk_sp<SkImage> SkDeferredDisplayListRecorder::makePromiseTexture(
PromiseImageTextureFulfillProc textureFulfillProc,
PromiseImageTextureReleaseProc textureReleaseProc,
PromiseImageTextureContext textureContext) {
return SkImage_Gpu::MakePromiseTexture(fContext.get(),
if (!fContext) {
return nullptr;
}
return SkImage_Gpu::MakePromiseTexture(fContext->threadSafeProxy(),
backendFormat,
{width, height},
mipMapped,
@ -265,7 +268,10 @@ sk_sp<SkImage> SkDeferredDisplayListRecorder::makeYUVAPromiseTexture(
PromiseImageTextureFulfillProc textureFulfillProc,
PromiseImageTextureReleaseProc textureReleaseProc,
PromiseImageTextureContext textureContexts[]) {
return SkImage_GpuYUVA::MakePromiseYUVATexture(fContext.get(),
if (!fContext) {
return nullptr;
}
return SkImage_GpuYUVA::MakePromiseYUVATexture(fContext->threadSafeProxy(),
yuvaBackendTextureInfo,
std::move(imageColorSpace),
textureFulfillProc,

View File

@ -30,6 +30,10 @@ bool GrImageContext::abandoned() {
return fThreadSafeProxy->priv().abandoned();
}
sk_sp<GrImageContext> GrImageContext::MakeForPromiseImage(sk_sp<GrContextThreadSafeProxy> tsp) {
return sk_sp<GrImageContext>(new GrImageContext(std::move(tsp)));
}
///////////////////////////////////////////////////////////////////////////////////////////////////
sk_sp<const GrCaps> GrImageContextPriv::refCaps() const {
return fContext->refCaps();

View File

@ -10,6 +10,8 @@
#include "include/private/GrImageContext.h"
#include "include/gpu/GrContextThreadSafeProxy.h"
/** Class that exposes methods on GrImageContext that are only intended for use internal to Skia.
This class is purely a privileged window into GrImageContext. It should never have
additional data members or virtual methods. */
@ -30,6 +32,10 @@ public:
bool abandoned() const { return fContext->abandoned(); }
static sk_sp<GrImageContext> MakeForPromiseImage(sk_sp<GrContextThreadSafeProxy> tsp) {
return GrImageContext::MakeForPromiseImage(std::move(tsp));
}
/** This is only useful for debug purposes */
SkDEBUGCODE(GrSingleOwner* singleOwner() const { return fContext->singleOwner(); } )

View File

@ -20,6 +20,7 @@
#include "src/core/SkMipmap.h"
#include "src/core/SkTraceEvent.h"
#include "src/gpu/GrCaps.h"
#include "src/gpu/GrContextThreadSafeProxyPriv.h"
#include "src/gpu/GrDirectContextPriv.h"
#include "src/gpu/GrImageContextPriv.h"
#include "src/gpu/GrRenderTarget.h"
@ -666,6 +667,41 @@ sk_sp<GrRenderTargetProxy> GrProxyProvider::wrapVulkanSecondaryCBAsRenderTarget(
std::move(rt), UseAllocator::kNo, GrRenderTargetProxy::WrapsVkSecondaryCB::kYes));
}
sk_sp<GrTextureProxy> GrProxyProvider::CreatePromiseProxy(GrContextThreadSafeProxy* threadSafeProxy,
LazyInstantiateCallback&& callback,
const GrBackendFormat& format,
SkISize dimensions,
GrMipmapped mipMapped) {
if (threadSafeProxy->priv().abandoned()) {
return nullptr;
}
SkASSERT((dimensions.fWidth <= 0 && dimensions.fHeight <= 0) ||
(dimensions.fWidth > 0 && dimensions.fHeight > 0));
if (dimensions.fWidth > threadSafeProxy->priv().caps()->maxTextureSize() ||
dimensions.fHeight > threadSafeProxy->priv().caps()->maxTextureSize()) {
return nullptr;
}
// Ganesh assumes that, when wrapping a mipmapped backend texture from a client, that its
// mipmaps are fully fleshed out.
GrMipmapStatus mipmapStatus = (GrMipmapped::kYes == mipMapped) ? GrMipmapStatus::kValid
: GrMipmapStatus::kNotAllocated;
// We pass kReadOnly here since we should treat content of the client's texture as immutable.
// The promise API provides no way for the client to indicate that the texture is protected.
return sk_sp<GrTextureProxy>(new GrTextureProxy(std::move(callback),
format,
dimensions,
mipMapped,
mipmapStatus,
SkBackingFit::kExact,
SkBudgeted::kNo,
GrProtected::kNo,
GrInternalSurfaceFlags::kReadOnly,
GrSurfaceProxy::UseAllocator::kYes,
GrDDLProvider::kYes));
}
sk_sp<GrTextureProxy> GrProxyProvider::createLazyProxy(LazyInstantiateCallback&& callback,
const GrBackendFormat& format,
SkISize dimensions,

View File

@ -150,6 +150,16 @@ public:
GrTextureType fTextureType;
};
/**
* Similar to createLazyProxy below, except narrowed to the use case of shared promise images
* i.e. static so it doesn't have access to mutable state. Used by MakePromiseImageLazyProxy().
*/
static sk_sp<GrTextureProxy> CreatePromiseProxy(GrContextThreadSafeProxy*,
LazyInstantiateCallback&&,
const GrBackendFormat&,
SkISize dimensions,
GrMipmapped);
/**
* Creates a texture proxy that will be instantiated by a user-supplied callback during flush.
* The width and height must either both be greater than 0 or both less than or equal to zero. A

View File

@ -25,6 +25,7 @@
#include "src/gpu/GrBitmapTextureMaker.h"
#include "src/gpu/GrCaps.h"
#include "src/gpu/GrColorSpaceXform.h"
#include "src/gpu/GrContextThreadSafeProxyPriv.h"
#include "src/gpu/GrDirectContextPriv.h"
#include "src/gpu/GrDrawingManager.h"
#include "src/gpu/GrGpu.h"
@ -373,7 +374,7 @@ sk_sp<SkImage> SkImage::makeTextureImage(GrDirectContext* dContext,
///////////////////////////////////////////////////////////////////////////////////////////////////
sk_sp<SkImage> SkImage_Gpu::MakePromiseTexture(GrRecordingContext* context,
sk_sp<SkImage> SkImage_Gpu::MakePromiseTexture(sk_sp<GrContextThreadSafeProxy> threadSafeProxy,
const GrBackendFormat& backendFormat,
SkISize dimensions,
GrMipmapped mipMapped,
@ -393,7 +394,7 @@ sk_sp<SkImage> SkImage_Gpu::MakePromiseTexture(GrRecordingContext* context,
return nullptr;
}
if (!context) {
if (!threadSafeProxy) {
return nullptr;
}
@ -401,18 +402,19 @@ sk_sp<SkImage> SkImage_Gpu::MakePromiseTexture(GrRecordingContext* context,
return nullptr;
}
GrColorType grColorType = SkColorTypeAndFormatToGrColorType(context->priv().caps(),
GrColorType grColorType = SkColorTypeAndFormatToGrColorType(threadSafeProxy->priv().caps(),
colorType,
backendFormat);
if (GrColorType::kUnknown == grColorType) {
return nullptr;
}
if (!context->priv().caps()->areColorTypeAndFormatCompatible(grColorType, backendFormat)) {
if (!threadSafeProxy->priv().caps()->areColorTypeAndFormatCompatible(grColorType,
backendFormat)) {
return nullptr;
}
auto proxy = MakePromiseImageLazyProxy(context,
auto proxy = MakePromiseImageLazyProxy(threadSafeProxy.get(),
dimensions,
backendFormat,
mipMapped,
@ -421,10 +423,11 @@ sk_sp<SkImage> SkImage_Gpu::MakePromiseTexture(GrRecordingContext* context,
if (!proxy) {
return nullptr;
}
GrSwizzle swizzle = context->priv().caps()->getReadSwizzle(backendFormat, grColorType);
GrSwizzle swizzle = threadSafeProxy->priv().caps()->getReadSwizzle(backendFormat, grColorType);
GrSurfaceProxyView view(std::move(proxy), origin, swizzle);
return sk_make_sp<SkImage_Gpu>(sk_ref_sp(context), kNeedNewImageUniqueID,
std::move(view), colorType, alphaType, std::move(colorSpace));
sk_sp<GrImageContext> ctx(GrImageContextPriv::MakeForPromiseImage(std::move(threadSafeProxy)));
return sk_make_sp<SkImage_Gpu>(std::move(ctx), kNeedNewImageUniqueID, std::move(view),
colorType, alphaType, std::move(colorSpace));
}
///////////////////////////////////////////////////////////////////////////////////////////////////

View File

@ -78,8 +78,9 @@ public:
/**
* This is the implementation of SkDeferredDisplayListRecorder::makePromiseImage.
* TODO: Make this public, and remove the SkDDLRecorder entry point.
*/
static sk_sp<SkImage> MakePromiseTexture(GrRecordingContext*,
static sk_sp<SkImage> MakePromiseTexture(sk_sp<GrContextThreadSafeProxy>,
const GrBackendFormat& backendFormat,
SkISize dimensions,
GrMipmapped mipMapped,

View File

@ -204,13 +204,13 @@ bool SkImage_GpuBase::onIsValid(GrRecordingContext* context) const {
}
sk_sp<GrTextureProxy> SkImage_GpuBase::MakePromiseImageLazyProxy(
GrRecordingContext* context,
GrContextThreadSafeProxy* tsp,
SkISize dimensions,
GrBackendFormat backendFormat,
GrMipmapped mipMapped,
PromiseImageTextureFulfillProc fulfillProc,
sk_sp<GrRefCntedCallback> releaseHelper) {
SkASSERT(context);
SkASSERT(tsp);
SkASSERT(!dimensions.isEmpty());
SkASSERT(releaseHelper);
@ -361,17 +361,6 @@ sk_sp<GrTextureProxy> SkImage_GpuBase::MakePromiseImageLazyProxy(
bool fFulfillProcFailed = false;
} callback(fulfillProc, std::move(releaseHelper));
GrProxyProvider* proxyProvider = context->priv().proxyProvider();
// Ganesh assumes that, when wrapping a mipmapped backend texture from a client, that its
// mipmaps are fully fleshed out.
GrMipmapStatus mipmapStatus = (GrMipmapped::kYes == mipMapped) ? GrMipmapStatus::kValid
: GrMipmapStatus::kNotAllocated;
// We pass kReadOnly here since we should treat content of the client's texture as immutable.
// The promise API provides no way for the client to indicated that the texture is protected.
return proxyProvider->createLazyProxy(std::move(callback), backendFormat, dimensions, mipMapped,
mipmapStatus, GrInternalSurfaceFlags::kReadOnly,
SkBackingFit::kExact, SkBudgeted::kNo, GrProtected::kNo,
GrSurfaceProxy::UseAllocator::kYes);
return GrProxyProvider::CreatePromiseProxy(tsp, std::move(callback), backendFormat, dimensions,
mipMapped);
}

View File

@ -61,7 +61,7 @@ protected:
// if not null, immediately if this function fails. Othwerwise, it is installed in the
// proxy along with the TextureFulfillProc and TextureReleaseProc. PromiseDoneProc must not
// be null.
static sk_sp<GrTextureProxy> MakePromiseImageLazyProxy(GrRecordingContext*,
static sk_sp<GrTextureProxy> MakePromiseImageLazyProxy(GrContextThreadSafeProxy*,
SkISize dimensions,
GrBackendFormat,
GrMipmapped,

View File

@ -380,7 +380,7 @@ sk_sp<SkImage> SkImage::MakeFromYUVAPixmaps(GrRecordingContext* context,
/////////////////////////////////////////////////////////////////////////////////////////////////
sk_sp<SkImage> SkImage_GpuYUVA::MakePromiseYUVATexture(
GrRecordingContext* context,
sk_sp<GrContextThreadSafeProxy> threadSafeProxy,
const GrYUVABackendTextureInfo& yuvaBackendTextureInfo,
sk_sp<SkColorSpace> imageColorSpace,
PromiseImageTextureFulfillProc textureFulfillProc,
@ -401,7 +401,7 @@ sk_sp<SkImage> SkImage_GpuYUVA::MakePromiseYUVATexture(
releaseHelpers[i] = GrRefCntedCallback::Make(textureReleaseProc, textureContexts[i]);
}
if (!context) {
if (!threadSafeProxy) {
return nullptr;
}
@ -416,7 +416,7 @@ sk_sp<SkImage> SkImage_GpuYUVA::MakePromiseYUVATexture(
// Make a lazy proxy for each plane and wrap in a view.
sk_sp<GrSurfaceProxy> proxies[4];
for (int i = 0; i < n; ++i) {
proxies[i] = MakePromiseImageLazyProxy(context,
proxies[i] = MakePromiseImageLazyProxy(threadSafeProxy.get(),
planeDimensions[i],
yuvaBackendTextureInfo.planeFormat(i),
GrMipmapped::kNo,
@ -430,7 +430,8 @@ sk_sp<SkImage> SkImage_GpuYUVA::MakePromiseYUVATexture(
proxies,
yuvaBackendTextureInfo.textureOrigin());
SkASSERT(yuvaTextureProxies.isValid());
return sk_make_sp<SkImage_GpuYUVA>(sk_ref_sp(context),
sk_sp<GrImageContext> ctx(GrImageContextPriv::MakeForPromiseImage(std::move(threadSafeProxy)));
return sk_make_sp<SkImage_GpuYUVA>(std::move(ctx),
kNeedNewImageUniqueID,
std::move(yuvaTextureProxies),
std::move(imageColorSpace));

View File

@ -65,8 +65,9 @@ public:
/**
* This is the implementation of SkDeferredDisplayListRecorder::makeYUVAPromiseTexture.
* TODO: Make this public, and remove the SkDDLRecorder entry point.
*/
static sk_sp<SkImage> MakePromiseYUVATexture(GrRecordingContext*,
static sk_sp<SkImage> MakePromiseYUVATexture(sk_sp<GrContextThreadSafeProxy>,
const GrYUVABackendTextureInfo&,
sk_sp<SkColorSpace> imageColorSpace,
PromiseImageTextureFulfillProc textureFulfillProc,

View File

@ -140,7 +140,7 @@ DEF_GPUTEST_FOR_RENDERING_CONTEXTS(PromiseImageTest, reporter, ctxInfo) {
PromiseTextureChecker promiseChecker(backendTex, reporter, false);
GrSurfaceOrigin texOrigin = kTopLeft_GrSurfaceOrigin;
sk_sp<SkImage> refImg(SkImage_Gpu::MakePromiseTexture(ctx,
sk_sp<SkImage> refImg(SkImage_Gpu::MakePromiseTexture(ctx->threadSafeProxy(),
backendFormat,
{kWidth, kHeight},
GrMipmapped::kNo,
@ -247,7 +247,7 @@ DEF_GPUTEST(PromiseImageTextureShutdown, reporter, ctxInfo) {
SkCanvas* canvas = surface->getCanvas();
PromiseTextureChecker promiseChecker(mbet->texture(), reporter, false);
sk_sp<SkImage> image(SkImage_Gpu::MakePromiseTexture(ctx,
sk_sp<SkImage> image(SkImage_Gpu::MakePromiseTexture(ctx->threadSafeProxy(),
mbet->texture().getBackendFormat(),
{kWidth, kHeight},
GrMipmapped::kNo,
@ -291,7 +291,7 @@ DEF_GPUTEST_FOR_RENDERING_CONTEXTS(PromiseImageTextureFullCache, reporter, ctxIn
SkCanvas* canvas = surface->getCanvas();
PromiseTextureChecker promiseChecker(backendTex, reporter, false);
sk_sp<SkImage> image(SkImage_Gpu::MakePromiseTexture(dContext,
sk_sp<SkImage> image(SkImage_Gpu::MakePromiseTexture(dContext->threadSafeProxy(),
backendTex.getBackendFormat(),
{kWidth, kHeight},
GrMipmapped::kNo,
@ -370,7 +370,7 @@ DEF_GPUTEST_FOR_RENDERING_CONTEXTS(PromiseImageNullFulfill, reporter, ctxInfo) {
++static_cast<Counts*>(ctx)->fReleaseCount;
};
GrSurfaceOrigin texOrigin = kTopLeft_GrSurfaceOrigin;
sk_sp<SkImage> refImg(SkImage_Gpu::MakePromiseTexture(dContext,
sk_sp<SkImage> refImg(SkImage_Gpu::MakePromiseTexture(dContext->threadSafeProxy(),
backendFormat,
{kWidth, kHeight},
GrMipmapped::kNo,