457469c7a0
This makes sure resources are released and free'd as soon as possible if we no longer need them. Bug: skia: Change-Id: Ic216987649c54183f8cbbff90a633860a97754b3 Reviewed-on: https://skia-review.googlesource.com/105721 Commit-Queue: Greg Daniel <egdaniel@google.com> Reviewed-by: Robert Phillips <robertphillips@google.com>
262 lines
10 KiB
C++
262 lines
10 KiB
C++
/*
|
|
* Copyright 2018 Google Inc.
|
|
*
|
|
* Use of this source code is governed by a BSD-style license that can be
|
|
* found in the LICENSE file.
|
|
*/
|
|
|
|
#ifndef GrProxyProvider_DEFINED
|
|
#define GrProxyProvider_DEFINED
|
|
|
|
#include "GrResourceKey.h"
|
|
#include "GrTextureProxy.h"
|
|
#include "GrTypes.h"
|
|
#include "SkRefCnt.h"
|
|
#include "SkTDynamicHash.h"
|
|
|
|
class GrCaps;
|
|
class GrResourceProvider;
|
|
class GrSingleOwner;
|
|
class GrBackendRenderTarget;
|
|
class SkBitmap;
|
|
class SkImage;
|
|
|
|
/*
|
|
* A factory for creating GrSurfaceProxy-derived objects.
|
|
*/
|
|
class GrProxyProvider {
|
|
public:
|
|
GrProxyProvider(GrResourceProvider*, GrResourceCache*, sk_sp<const GrCaps>, GrSingleOwner*);
|
|
|
|
~GrProxyProvider();
|
|
|
|
/*
|
|
* Assigns a unique key to a proxy. The proxy will be findable via this key using
|
|
* findProxyByUniqueKey(). It is an error if an existing proxy already has a key.
|
|
*/
|
|
bool assignUniqueKeyToProxy(const GrUniqueKey&, GrTextureProxy*);
|
|
|
|
/*
|
|
* Sets the unique key of the provided proxy to the unique key of the surface. The surface must
|
|
* have a valid unique key.
|
|
*/
|
|
void adoptUniqueKeyFromSurface(GrTextureProxy* proxy, const GrSurface*);
|
|
|
|
/*
|
|
* Removes a unique key from a proxy. If the proxy has already been instantiated, it will
|
|
* also remove the unique key from the target GrSurface.
|
|
*/
|
|
void removeUniqueKeyFromProxy(const GrUniqueKey&, GrTextureProxy*);
|
|
|
|
/*
|
|
* Finds a proxy by unique key.
|
|
*/
|
|
sk_sp<GrTextureProxy> findProxyByUniqueKey(const GrUniqueKey&, GrSurfaceOrigin);
|
|
|
|
/*
|
|
* Finds a proxy by unique key or creates a new one that wraps a resource matching the unique
|
|
* key.
|
|
*/
|
|
sk_sp<GrTextureProxy> findOrCreateProxyByUniqueKey(const GrUniqueKey&, GrSurfaceOrigin);
|
|
|
|
/*
|
|
* Create a texture proxy that is backed by an instantiated GrSurface. This is almost entirely
|
|
* used by Skia's testing code.
|
|
* DDL TODO: remove the remaining Skia-internal use of this method and make it truly
|
|
* testing-only.
|
|
*/
|
|
sk_sp<GrTextureProxy> createInstantiatedProxy(const GrSurfaceDesc&, SkBackingFit, SkBudgeted,
|
|
uint32_t flags = 0);
|
|
|
|
/*
|
|
* Create an un-mipmapped texture proxy with data.
|
|
* DDL TODO: need to refine ownership semantics of 'srcData' if we're in completely
|
|
* deferred mode
|
|
*/
|
|
sk_sp<GrTextureProxy> createTextureProxy(const GrSurfaceDesc&, SkBudgeted,
|
|
const void* srcData, size_t rowBytes);
|
|
|
|
/*
|
|
* Create an un-mipmapped texture proxy with data. The SkImage must be a raster backend image.
|
|
* Since the SkImage is ref counted, we simply take a ref on it to keep the data alive until we
|
|
* actually upload the data to the gpu.
|
|
*/
|
|
sk_sp<GrTextureProxy> createTextureProxy(sk_sp<SkImage> srcImage,
|
|
GrSurfaceFlags flags,
|
|
GrSurfaceOrigin origin,
|
|
int sampleCnt,
|
|
SkBudgeted budgeted,
|
|
SkBackingFit fit);
|
|
|
|
/*
|
|
* Create a mipmapped texture proxy with data.
|
|
*
|
|
* @param desc Description of the texture properties.
|
|
* @param budgeted Does the texture count against the resource cache budget?
|
|
* @param texels A contiguous array of mipmap levels
|
|
* @param mipLevelCount The amount of elements in the texels array
|
|
*/
|
|
sk_sp<GrTextureProxy> createMipMapProxy(const GrSurfaceDesc&, SkBudgeted,
|
|
const GrMipLevel texels[], int mipLevelCount,
|
|
SkDestinationSurfaceColorMode mipColorMode =
|
|
SkDestinationSurfaceColorMode::kLegacy);
|
|
|
|
/*
|
|
* Create a mipmapped texture proxy without any data.
|
|
*
|
|
* Like the call above but there are no texels to upload. A texture proxy is returned that
|
|
* simply has space allocated for the mips. We will allocated the full amount of mip levels
|
|
* based on the width and height in the GrSurfaceDesc.
|
|
*/
|
|
sk_sp<GrTextureProxy> createMipMapProxy(const GrSurfaceDesc&, SkBudgeted);
|
|
|
|
/*
|
|
* Creates a new mipmapped texture proxy for the bitmap with mip levels generated by the cpu.
|
|
*/
|
|
sk_sp<GrTextureProxy> createMipMapProxyFromBitmap(const SkBitmap& bitmap,
|
|
SkColorSpace* dstColorSpace);
|
|
|
|
/*
|
|
* Create a GrSurfaceProxy without any data.
|
|
*/
|
|
sk_sp<GrTextureProxy> createProxy(const GrSurfaceDesc&, SkBackingFit, SkBudgeted,
|
|
uint32_t flags = 0);
|
|
|
|
// These match the definitions in SkImage & GrTexture.h, for whence they came
|
|
typedef void* ReleaseContext;
|
|
typedef void (*ReleaseProc)(ReleaseContext);
|
|
|
|
/*
|
|
* Create a texture proxy that wraps a (non-renderable) backend texture.
|
|
*/
|
|
sk_sp<GrTextureProxy> createWrappedTextureProxy(const GrBackendTexture&, GrSurfaceOrigin,
|
|
GrWrapOwnership = kBorrow_GrWrapOwnership,
|
|
ReleaseProc = nullptr,
|
|
ReleaseContext = nullptr);
|
|
|
|
/*
|
|
* Create a texture proxy that wraps a backend texture and is both texture-able and renderable
|
|
*/
|
|
sk_sp<GrTextureProxy> createWrappedTextureProxy(const GrBackendTexture&,
|
|
GrSurfaceOrigin,
|
|
int sampleCnt);
|
|
|
|
/*
|
|
* Create a render target proxy that wraps a backend rendertarget
|
|
*/
|
|
sk_sp<GrSurfaceProxy> createWrappedRenderTargetProxy(const GrBackendRenderTarget&,
|
|
GrSurfaceOrigin);
|
|
|
|
/*
|
|
* Create a render target proxy that wraps a backend texture?
|
|
*/
|
|
sk_sp<GrSurfaceProxy> createWrappedRenderTargetProxy(const GrBackendTexture& tex,
|
|
GrSurfaceOrigin origin,
|
|
int sampleCnt);
|
|
|
|
using LazyInstantiateCallback = std::function<sk_sp<GrSurface>(GrResourceProvider*,
|
|
GrSurfaceOrigin* outOrigin)>;
|
|
enum class Textureable : bool {
|
|
kNo = false,
|
|
kYes = true
|
|
};
|
|
|
|
enum class Renderable : bool {
|
|
kNo = false,
|
|
kYes = true
|
|
};
|
|
|
|
/**
|
|
* Creates a texture proxy that will be instantiated by a user-supplied callback during flush.
|
|
* (Stencil is not supported by this method.) The width and height must either both be greater
|
|
* than 0 or both less than or equal to zero. A non-positive value is a signal that the width
|
|
* and height are currently unknown.
|
|
*
|
|
* When called, the callback must be able to cleanup any resources that it captured at creation.
|
|
* It also must support being passed in a null GrResourceProvider. When this happens, the
|
|
* callback should cleanup any resources it captured and return an empty sk_sp<GrTextureProxy>.
|
|
*/
|
|
sk_sp<GrTextureProxy> createLazyProxy(LazyInstantiateCallback&&, const GrSurfaceDesc&,
|
|
GrMipMapped, SkBackingFit, SkBudgeted);
|
|
|
|
sk_sp<GrTextureProxy> createFullyLazyProxy(LazyInstantiateCallback&&,
|
|
Renderable, GrPixelConfig);
|
|
|
|
sk_sp<GrRenderTargetProxy> createLazyRenderTargetProxy(LazyInstantiateCallback&&,
|
|
const GrSurfaceDesc&, Textureable,
|
|
GrMipMapped, SkBackingFit, SkBudgeted);
|
|
|
|
// 'proxy' is about to be used as a texture src or drawn to. This query can be used to
|
|
// determine if it is going to need a texture domain or a full clear.
|
|
static bool IsFunctionallyExact(GrSurfaceProxy* proxy);
|
|
|
|
/**
|
|
* Either the proxy attached to the unique key is being deleted (in which case we
|
|
* don't want it cluttering up the hash table) or the client has indicated that
|
|
* it will never refer to the unique key again. In either case, remove the key
|
|
* from the hash table.
|
|
* Note: this does not, by itself, alter unique key attached to the underlying GrTexture.
|
|
*/
|
|
void processInvalidProxyUniqueKey(const GrUniqueKey&);
|
|
|
|
/**
|
|
* Same as above, but you must pass in a GrTextureProxy to save having to search for it. The
|
|
* GrUniqueKey of the proxy must be valid and it must match the passed in key. This function
|
|
* also gives the option to invalidate the GrUniqueKey on the underlying GrTexture.
|
|
*/
|
|
void processInvalidProxyUniqueKey(const GrUniqueKey&, GrTextureProxy*, bool invalidateSurface);
|
|
|
|
const GrCaps* caps() const { return fCaps.get(); }
|
|
|
|
void abandon() {
|
|
fResourceCache = nullptr;
|
|
fResourceProvider = nullptr;
|
|
fAbandoned = true;
|
|
}
|
|
|
|
bool isAbandoned() const {
|
|
#ifdef SK_DEBUG
|
|
if (fAbandoned) {
|
|
SkASSERT(!fResourceCache && !fResourceProvider);
|
|
}
|
|
#endif
|
|
return fAbandoned;
|
|
}
|
|
|
|
int numUniqueKeyProxies_TestOnly() const;
|
|
|
|
void removeAllUniqueKeys();
|
|
|
|
/**
|
|
* Helper function for callers who are wrapping a bitmap into an SkImage so they know whether or
|
|
* not that bitmap should be copied or not.
|
|
*/
|
|
bool mutableBitmapsNeedCopy() const { return !SkToBool(fResourceProvider); }
|
|
|
|
private:
|
|
friend class GrAHardwareBufferImageGenerator; // for createWrapped
|
|
|
|
sk_sp<GrTextureProxy> createWrapped(sk_sp<GrTexture> tex, GrSurfaceOrigin origin);
|
|
|
|
struct UniquelyKeyedProxyHashTraits {
|
|
static const GrUniqueKey& GetKey(const GrTextureProxy& p) { return p.getUniqueKey(); }
|
|
|
|
static uint32_t Hash(const GrUniqueKey& key) { return key.hash(); }
|
|
};
|
|
typedef SkTDynamicHash<GrTextureProxy, GrUniqueKey, UniquelyKeyedProxyHashTraits> UniquelyKeyedProxyHash;
|
|
|
|
// This holds the texture proxies that have unique keys. The resourceCache does not get a ref
|
|
// on these proxies but they must send a message to the resourceCache when they are deleted.
|
|
UniquelyKeyedProxyHash fUniquelyKeyedProxies;
|
|
|
|
GrResourceProvider* fResourceProvider;
|
|
GrResourceCache* fResourceCache;
|
|
bool fAbandoned;
|
|
sk_sp<const GrCaps> fCaps;
|
|
|
|
// In debug builds we guard against improper thread handling
|
|
SkDEBUGCODE(mutable GrSingleOwner* fSingleOwner;)
|
|
};
|
|
|
|
#endif
|