Add GrResourceCache2.
Currently it just replaces GrGpu as the owner of the linked list of resources. Committed: https://skia.googlesource.com/skia/+/94ce9ac8624dbb45656b8f5c992fad9c9ff3ee5f R=mtklein@google.com, robertphillips@google.com Author: bsalomon@google.com Review URL: https://codereview.chromium.org/481443002
This commit is contained in:
parent
78fc1dbed0
commit
c8dc1f74b6
@ -114,6 +114,8 @@
|
||||
'<(skia_src_path)/gpu/GrReducedClip.h',
|
||||
'<(skia_src_path)/gpu/GrResourceCache.cpp',
|
||||
'<(skia_src_path)/gpu/GrResourceCache.h',
|
||||
'<(skia_src_path)/gpu/GrResourceCache2.cpp',
|
||||
'<(skia_src_path)/gpu/GrResourceCache2.h',
|
||||
'<(skia_src_path)/gpu/GrStencil.cpp',
|
||||
'<(skia_src_path)/gpu/GrStencil.h',
|
||||
'<(skia_src_path)/gpu/GrStencilAndCoverPathRenderer.cpp',
|
||||
|
@ -35,6 +35,7 @@ class GrPath;
|
||||
class GrPathRenderer;
|
||||
class GrResourceEntry;
|
||||
class GrResourceCache;
|
||||
class GrResourceCache2;
|
||||
class GrStencilBuffer;
|
||||
class GrTestTarget;
|
||||
class GrTextContext;
|
||||
@ -926,6 +927,7 @@ public:
|
||||
GrDrawTarget* getTextTarget();
|
||||
const GrIndexBuffer* getQuadIndexBuffer() const;
|
||||
GrAARectRenderer* getAARectRenderer() { return fAARectRenderer; }
|
||||
GrResourceCache2* getResourceCache2() { return fResourceCache2; }
|
||||
|
||||
// Called by tests that draw directly to the context via GrDrawTarget
|
||||
void getTestTarget(GrTestTarget*);
|
||||
@ -973,6 +975,7 @@ private:
|
||||
GrDrawState* fDrawState;
|
||||
|
||||
GrResourceCache* fResourceCache;
|
||||
GrResourceCache2* fResourceCache2;
|
||||
GrFontCache* fFontCache;
|
||||
SkAutoTDelete<GrLayerCache> fLayerCache;
|
||||
|
||||
|
@ -12,6 +12,7 @@
|
||||
#include "SkTInternalLList.h"
|
||||
|
||||
class GrResourceCacheEntry;
|
||||
class GrResourceCache2;
|
||||
class GrGpu;
|
||||
class GrContext;
|
||||
|
||||
@ -118,12 +119,13 @@ private:
|
||||
|
||||
static uint32_t CreateUniqueID();
|
||||
|
||||
// We're in an internal doubly linked list
|
||||
// We're in an internal doubly linked list owned by GrResourceCache2
|
||||
SK_DECLARE_INTERNAL_LLIST_INTERFACE(GrGpuResource);
|
||||
|
||||
GrGpu* fGpu; // not reffed. The GrGpu can be deleted while there
|
||||
// are still live GrGpuResources. It will call
|
||||
// release() on all such objects in its destructor.
|
||||
// This is not ref'ed but abandon() or release() will be called before the GrGpu object
|
||||
// is destroyed. Those calls set will this to NULL.
|
||||
GrGpu* fGpu;
|
||||
|
||||
enum Flags {
|
||||
/**
|
||||
* This object wraps a GPU object given to us by the user.
|
||||
|
@ -41,6 +41,7 @@ public:
|
||||
// We could reuse the mask if bounds is a subset of last bounds. We'd have to communicate
|
||||
// an offset to the caller.
|
||||
if (back->fLastMask.texture() &&
|
||||
!back->fLastMask.texture()->wasDestroyed() &&
|
||||
back->fLastBound == bounds &&
|
||||
back->fLastClipGenID == clipGenID) {
|
||||
return true;
|
||||
@ -179,8 +180,8 @@ public:
|
||||
return fContext;
|
||||
}
|
||||
|
||||
void releaseResources() {
|
||||
|
||||
// TODO: Remove this when we hold cache keys instead of refs to textures.
|
||||
void purgeResources() {
|
||||
SkDeque::F2BIter iter(fStack);
|
||||
for (GrClipStackFrame* frame = (GrClipStackFrame*) iter.next();
|
||||
frame != NULL;
|
||||
@ -219,7 +220,8 @@ private:
|
||||
|
||||
int32_t fLastClipGenID;
|
||||
// The mask's width & height values are used by GrClipMaskManager to correctly scale the
|
||||
// texture coords for the geometry drawn with this mask.
|
||||
// texture coords for the geometry drawn with this mask. TODO: This should be a cache key
|
||||
// and not a hard ref to a texture.
|
||||
GrAutoScratchTexture fLastMask;
|
||||
// fLastBound stores the bounding box of the clip mask in clip-stack space. This rect is
|
||||
// used by GrClipMaskManager to position a rect and compute texture coords for the mask.
|
||||
|
@ -1112,8 +1112,8 @@ GrTexture* GrClipMaskManager::createSoftwareClipMask(int32_t elementsGenID,
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
void GrClipMaskManager::releaseResources() {
|
||||
fAACache.releaseResources();
|
||||
void GrClipMaskManager::purgeResources() {
|
||||
fAACache.purgeResources();
|
||||
}
|
||||
|
||||
void GrClipMaskManager::setGpu(GrGpu* gpu) {
|
||||
|
@ -53,7 +53,11 @@ public:
|
||||
bool setupClipping(const GrClipData* clipDataIn, GrDrawState::AutoRestoreEffects*,
|
||||
const SkRect* devBounds);
|
||||
|
||||
void releaseResources();
|
||||
/**
|
||||
* Purge resources to free up memory. TODO: This class shouldn't hold any long lived refs
|
||||
* which will allow ResourceCache2 to automatically purge anything this class has created.
|
||||
*/
|
||||
void purgeResources();
|
||||
|
||||
bool isClipInStencil() const {
|
||||
return kStencil_ClipMaskType == fCurrClipMaskType;
|
||||
|
@ -25,6 +25,7 @@
|
||||
#include "GrPathRenderer.h"
|
||||
#include "GrPathUtils.h"
|
||||
#include "GrResourceCache.h"
|
||||
#include "GrResourceCache2.h"
|
||||
#include "GrSoftwarePathRenderer.h"
|
||||
#include "GrStencilBuffer.h"
|
||||
#include "GrStencilAndCoverTextContext.h"
|
||||
@ -108,6 +109,7 @@ GrContext::GrContext(const Options& opts) : fOptions(opts) {
|
||||
fPathRendererChain = NULL;
|
||||
fSoftwarePathRenderer = NULL;
|
||||
fResourceCache = NULL;
|
||||
fResourceCache2 = NULL;
|
||||
fFontCache = NULL;
|
||||
fDrawBuffer = NULL;
|
||||
fDrawBufferVBAllocPool = NULL;
|
||||
@ -133,6 +135,7 @@ bool GrContext::init(GrBackend backend, GrBackendContext backendContext) {
|
||||
fResourceCache = SkNEW_ARGS(GrResourceCache, (MAX_RESOURCE_CACHE_COUNT,
|
||||
MAX_RESOURCE_CACHE_BYTES));
|
||||
fResourceCache->setOverbudgetCallback(OverbudgetCB, this);
|
||||
fResourceCache2 = SkNEW(GrResourceCache2);
|
||||
|
||||
fFontCache = SkNEW_ARGS(GrFontCache, (fGpu));
|
||||
|
||||
@ -161,10 +164,8 @@ GrContext::~GrContext() {
|
||||
(*fCleanUpData[i].fFunc)(this, fCleanUpData[i].fInfo);
|
||||
}
|
||||
|
||||
// Since the gpu can hold scratch textures, give it a chance to let go
|
||||
// of them before freeing the texture cache
|
||||
fGpu->purgeResources();
|
||||
|
||||
delete fResourceCache2;
|
||||
fResourceCache2 = NULL;
|
||||
delete fResourceCache;
|
||||
fResourceCache = NULL;
|
||||
delete fFontCache;
|
||||
@ -184,7 +185,9 @@ GrContext::~GrContext() {
|
||||
void GrContext::abandonContext() {
|
||||
// abandon first to so destructors
|
||||
// don't try to free the resources in the API.
|
||||
fGpu->abandonResources();
|
||||
fResourceCache2->abandonAll();
|
||||
|
||||
fGpu->contextAbandonded();
|
||||
|
||||
// a path renderer may be holding onto resources that
|
||||
// are now unusable
|
||||
@ -207,7 +210,6 @@ void GrContext::abandonContext() {
|
||||
|
||||
fFontCache->freeAll();
|
||||
fLayerCache->freeAll();
|
||||
fGpu->markContextDirty();
|
||||
}
|
||||
|
||||
void GrContext::resetContext(uint32_t state) {
|
||||
@ -218,6 +220,9 @@ void GrContext::freeGpuResources() {
|
||||
this->flush();
|
||||
|
||||
fGpu->purgeResources();
|
||||
if (NULL != fDrawBuffer) {
|
||||
fDrawBuffer->purgeResources();
|
||||
}
|
||||
|
||||
fAARectRenderer->reset();
|
||||
fOvalRenderer->reset();
|
||||
@ -540,6 +545,15 @@ void GrContext::addExistingTextureToCache(GrTexture* texture) {
|
||||
}
|
||||
|
||||
void GrContext::unlockScratchTexture(GrTexture* texture) {
|
||||
if (texture->wasDestroyed()) {
|
||||
if (texture->getCacheEntry()->key().isScratch()) {
|
||||
// This texture was detached from the cache but the cache still had a ref to it but
|
||||
// not a pointer to it.
|
||||
texture->unref();
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
ASSERT_OWNED_RESOURCE(texture);
|
||||
SkASSERT(NULL != texture->getCacheEntry());
|
||||
|
||||
|
@ -50,18 +50,6 @@ GrGpu::GrGpu(GrContext* context)
|
||||
}
|
||||
|
||||
GrGpu::~GrGpu() {
|
||||
this->releaseResources();
|
||||
}
|
||||
|
||||
void GrGpu::abandonResources() {
|
||||
|
||||
fClipMaskManager.releaseResources();
|
||||
|
||||
while (NULL != fObjectList.head()) {
|
||||
fObjectList.head()->abandon();
|
||||
}
|
||||
|
||||
SkASSERT(NULL == fQuadIndexBuffer || fQuadIndexBuffer->wasDestroyed());
|
||||
SkSafeSetNull(fQuadIndexBuffer);
|
||||
delete fVertexPool;
|
||||
fVertexPool = NULL;
|
||||
@ -69,42 +57,7 @@ void GrGpu::abandonResources() {
|
||||
fIndexPool = NULL;
|
||||
}
|
||||
|
||||
void GrGpu::releaseResources() {
|
||||
|
||||
fClipMaskManager.releaseResources();
|
||||
|
||||
while (NULL != fObjectList.head()) {
|
||||
fObjectList.head()->release();
|
||||
}
|
||||
|
||||
SkASSERT(NULL == fQuadIndexBuffer || fQuadIndexBuffer->wasDestroyed());
|
||||
SkSafeSetNull(fQuadIndexBuffer);
|
||||
delete fVertexPool;
|
||||
fVertexPool = NULL;
|
||||
delete fIndexPool;
|
||||
fIndexPool = NULL;
|
||||
}
|
||||
|
||||
void GrGpu::insertObject(GrGpuResource* object) {
|
||||
SkASSERT(NULL != object);
|
||||
SkASSERT(this == object->getGpu());
|
||||
|
||||
fObjectList.addToHead(object);
|
||||
}
|
||||
|
||||
void GrGpu::removeObject(GrGpuResource* object) {
|
||||
SkASSERT(NULL != object);
|
||||
SkASSERT(this == object->getGpu());
|
||||
|
||||
fObjectList.remove(object);
|
||||
}
|
||||
|
||||
|
||||
void GrGpu::unimpl(const char msg[]) {
|
||||
#ifdef SK_DEBUG
|
||||
GrPrintf("--- GrGpu unimplemented(\"%s\")\n", msg);
|
||||
#endif
|
||||
}
|
||||
void GrGpu::contextAbandonded() {}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
@ -318,7 +271,8 @@ static inline void fill_indices(uint16_t* indices, int quadCount) {
|
||||
}
|
||||
|
||||
const GrIndexBuffer* GrGpu::getQuadIndexBuffer() const {
|
||||
if (NULL == fQuadIndexBuffer) {
|
||||
if (NULL == fQuadIndexBuffer || fQuadIndexBuffer->wasDestroyed()) {
|
||||
SkSafeUnref(fQuadIndexBuffer);
|
||||
static const int SIZE = sizeof(uint16_t) * 6 * MAX_QUADS;
|
||||
GrGpu* me = const_cast<GrGpu*>(this);
|
||||
fQuadIndexBuffer = me->createIndexBuffer(SIZE, false);
|
||||
|
@ -59,6 +59,12 @@ public:
|
||||
return fPathRendering.get();
|
||||
}
|
||||
|
||||
// Called by GrContext when the underlying backend context has been destroyed.
|
||||
// GrGpu should use this to ensure that no backend API calls will be made from
|
||||
// here onward, including in its destructor. Subclasses should call
|
||||
// INHERITED::contextAbandonded() if they override this.
|
||||
virtual void contextAbandonded();
|
||||
|
||||
/**
|
||||
* The GrGpu object normally assumes that no outsider is setting state
|
||||
* within the underlying 3D API's context/device/whatever. This call informs
|
||||
@ -253,30 +259,6 @@ public:
|
||||
GrPixelConfig config, const void* buffer,
|
||||
size_t rowBytes);
|
||||
|
||||
/**
|
||||
* Called to tell GrGpu that all GrGpuResources have been lost and should
|
||||
* be abandoned. Overrides must call INHERITED::abandonResources().
|
||||
*/
|
||||
virtual void abandonResources();
|
||||
|
||||
/**
|
||||
* Called to tell GrGpu to release all GrGpuResources. Overrides must call
|
||||
* INHERITED::releaseResources().
|
||||
*/
|
||||
void releaseResources();
|
||||
|
||||
/**
|
||||
* Add object to list of objects. Should only be called by GrGpuResource.
|
||||
* @param resource the resource to add.
|
||||
*/
|
||||
void insertObject(GrGpuResource* object);
|
||||
|
||||
/**
|
||||
* Remove object from list of objects. Should only be called by GrGpuResource.
|
||||
* @param resource the resource to remove.
|
||||
*/
|
||||
void removeObject(GrGpuResource* object);
|
||||
|
||||
// GrDrawTarget overrides
|
||||
virtual void clear(const SkIRect* rect,
|
||||
GrColor color,
|
||||
@ -286,7 +268,7 @@ public:
|
||||
virtual void purgeResources() SK_OVERRIDE {
|
||||
// The clip mask manager can rebuild all its clip masks so just
|
||||
// get rid of them all.
|
||||
fClipMaskManager.releaseResources();
|
||||
fClipMaskManager.purgeResources();
|
||||
}
|
||||
|
||||
// After the client interacts directly with the 3D context state the GrGpu
|
||||
@ -523,7 +505,6 @@ private:
|
||||
enum {
|
||||
kPreallocGeomPoolStateStackCnt = 4,
|
||||
};
|
||||
typedef SkTInternalLList<GrGpuResource> ObjectList;
|
||||
SkSTArray<kPreallocGeomPoolStateStackCnt, GeometryPoolState, true> fGeomPoolStateStack;
|
||||
ResetTimestamp fResetTimestamp;
|
||||
uint32_t fResetBits;
|
||||
@ -534,9 +515,6 @@ private:
|
||||
int fIndexPoolUseCnt;
|
||||
// these are mutable so they can be created on-demand
|
||||
mutable GrIndexBuffer* fQuadIndexBuffer;
|
||||
// Used to abandon/release all resources created by this GrGpu. TODO: Move this
|
||||
// functionality to GrResourceCache.
|
||||
ObjectList fObjectList;
|
||||
|
||||
typedef GrDrawTarget INHERITED;
|
||||
};
|
||||
|
@ -8,19 +8,27 @@
|
||||
|
||||
|
||||
#include "GrGpuResource.h"
|
||||
#include "GrResourceCache2.h"
|
||||
#include "GrGpu.h"
|
||||
|
||||
static inline GrResourceCache2* get_resource_cache2(GrGpu* gpu) {
|
||||
SkASSERT(NULL != gpu);
|
||||
SkASSERT(NULL != gpu->getContext());
|
||||
SkASSERT(NULL != gpu->getContext()->getResourceCache2());
|
||||
return gpu->getContext()->getResourceCache2();
|
||||
}
|
||||
|
||||
GrGpuResource::GrGpuResource(GrGpu* gpu, bool isWrapped)
|
||||
: fRefCnt(1)
|
||||
: fGpu(gpu)
|
||||
, fRefCnt(1)
|
||||
, fCacheEntry(NULL)
|
||||
, fUniqueID(CreateUniqueID()) {
|
||||
fGpu = gpu;
|
||||
if (isWrapped) {
|
||||
fFlags = kWrapped_FlagBit;
|
||||
} else {
|
||||
fFlags = 0;
|
||||
}
|
||||
fGpu->insertObject(this);
|
||||
get_resource_cache2(fGpu)->insertResource(this);
|
||||
}
|
||||
|
||||
GrGpuResource::~GrGpuResource() {
|
||||
@ -32,7 +40,7 @@ GrGpuResource::~GrGpuResource() {
|
||||
void GrGpuResource::release() {
|
||||
if (NULL != fGpu) {
|
||||
this->onRelease();
|
||||
fGpu->removeObject(this);
|
||||
get_resource_cache2(fGpu)->removeResource(this);
|
||||
fGpu = NULL;
|
||||
}
|
||||
}
|
||||
@ -40,7 +48,7 @@ void GrGpuResource::release() {
|
||||
void GrGpuResource::abandon() {
|
||||
if (NULL != fGpu) {
|
||||
this->onAbandon();
|
||||
fGpu->removeObject(this);
|
||||
get_resource_cache2(fGpu)->removeResource(this);
|
||||
fGpu = NULL;
|
||||
}
|
||||
}
|
||||
|
@ -112,7 +112,7 @@ void GrLayerCache::freeAll() {
|
||||
fAtlas.free();
|
||||
// GrLayerCache always assumes an atlas exists so recreate it. The atlas
|
||||
// lazily allocates a replacement texture so reallocating a new
|
||||
// atlas here won't disrupt a GrContext::contextDestroyed or freeGpuResources.
|
||||
// atlas here won't disrupt a GrContext::abandonContext or freeGpuResources.
|
||||
// TODO: Make GrLayerCache lazily allocate the atlas manager?
|
||||
this->initAtlas();
|
||||
}
|
||||
|
@ -267,7 +267,7 @@ void GrResourceCache::makeExclusive(GrResourceCacheEntry* entry) {
|
||||
void GrResourceCache::removeInvalidResource(GrResourceCacheEntry* entry) {
|
||||
// If the resource went invalid while it was detached then purge it
|
||||
// This can happen when a 3D context was lost,
|
||||
// the client called GrContext::contextDestroyed() to notify Gr,
|
||||
// the client called GrContext::abandonContext() to notify Gr,
|
||||
// and then later an SkGpuDevice's destructor releases its backing
|
||||
// texture (which was invalidated at contextDestroyed time).
|
||||
// TODO: Safely delete the GrResourceCacheEntry as well.
|
||||
|
47
src/gpu/GrResourceCache2.cpp
Normal file
47
src/gpu/GrResourceCache2.cpp
Normal file
@ -0,0 +1,47 @@
|
||||
|
||||
/*
|
||||
* Copyright 2014 Google Inc.
|
||||
*
|
||||
* Use of this source code is governed by a BSD-style license that can be
|
||||
* found in the LICENSE file.
|
||||
*/
|
||||
|
||||
|
||||
#include "GrResourceCache2.h"
|
||||
#include "GrGpuResource.h"
|
||||
|
||||
GrResourceCache2::~GrResourceCache2() {
|
||||
this->releaseAll();
|
||||
}
|
||||
|
||||
void GrResourceCache2::insertResource(GrGpuResource* resource) {
|
||||
SkASSERT(NULL != resource);
|
||||
SkASSERT(!resource->wasDestroyed());
|
||||
fResources.addToHead(resource);
|
||||
++fCount;
|
||||
}
|
||||
|
||||
void GrResourceCache2::removeResource(GrGpuResource* resource) {
|
||||
fResources.remove(resource);
|
||||
--fCount;
|
||||
}
|
||||
|
||||
void GrResourceCache2::abandonAll() {
|
||||
while (GrGpuResource* head = fResources.head()) {
|
||||
SkASSERT(!head->wasDestroyed());
|
||||
head->abandon();
|
||||
// abandon should have already removed this from the list.
|
||||
SkASSERT(head != fResources.head());
|
||||
}
|
||||
SkASSERT(!fCount);
|
||||
}
|
||||
|
||||
void GrResourceCache2::releaseAll() {
|
||||
while (GrGpuResource* head = fResources.head()) {
|
||||
SkASSERT(!head->wasDestroyed());
|
||||
head->release();
|
||||
// release should have already removed this from the list.
|
||||
SkASSERT(head != fResources.head());
|
||||
}
|
||||
SkASSERT(!fCount);
|
||||
}
|
40
src/gpu/GrResourceCache2.h
Normal file
40
src/gpu/GrResourceCache2.h
Normal file
@ -0,0 +1,40 @@
|
||||
|
||||
/*
|
||||
* Copyright 2014 Google Inc.
|
||||
*
|
||||
* Use of this source code is governed by a BSD-style license that can be
|
||||
* found in the LICENSE file.
|
||||
*/
|
||||
|
||||
#ifndef GrResourceCache2_DEFINED
|
||||
#define GrResourceCache2_DEFINED
|
||||
|
||||
#include "GrTypes.h"
|
||||
#include "SkTInternalLList.h"
|
||||
|
||||
class GrGpuResource;
|
||||
|
||||
/**
|
||||
* Eventual replacement for GrResourceCache. Currently it simply holds a list
|
||||
* of all GrGpuResource objects for a GrContext. It is used to invalidate all
|
||||
* the resources when necessary.
|
||||
*/
|
||||
class GrResourceCache2 {
|
||||
public:
|
||||
GrResourceCache2() : fCount(0) {};
|
||||
~GrResourceCache2();
|
||||
|
||||
void insertResource(GrGpuResource* resource);
|
||||
|
||||
void removeResource(GrGpuResource* resource);
|
||||
|
||||
void abandonAll();
|
||||
|
||||
void releaseAll();
|
||||
|
||||
private:
|
||||
int fCount;
|
||||
SkTInternalLList<GrGpuResource> fResources;
|
||||
};
|
||||
|
||||
#endif
|
@ -164,9 +164,15 @@ GrGpuGL::~GrGpuGL() {
|
||||
|
||||
// This must be called by before the GrDrawTarget destructor
|
||||
this->releaseGeometry();
|
||||
// This subclass must do this before the base class destructor runs
|
||||
// since we will unref the GrGLInterface.
|
||||
this->releaseResources();
|
||||
}
|
||||
|
||||
void GrGpuGL::contextAbandonded() {
|
||||
INHERITED::contextAbandonded();
|
||||
fProgramCache->abandon();
|
||||
fHWProgramID = 0;
|
||||
if (this->glCaps().pathRenderingSupport()) {
|
||||
this->glPathRendering()->abandonGpuResources();
|
||||
}
|
||||
}
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
|
@ -30,6 +30,8 @@ public:
|
||||
GrGpuGL(const GrGLContext& ctx, GrContext* context);
|
||||
virtual ~GrGpuGL();
|
||||
|
||||
virtual void contextAbandonded() SK_OVERRIDE;
|
||||
|
||||
const GrGLContext& glContext() const { return fGLContext; }
|
||||
|
||||
const GrGLInterface* glInterface() const { return fGLContext.interface(); }
|
||||
@ -75,8 +77,6 @@ public:
|
||||
|
||||
virtual void initCopySurfaceDstDesc(const GrSurface* src, GrTextureDesc* desc) SK_OVERRIDE;
|
||||
|
||||
virtual void abandonResources() SK_OVERRIDE;
|
||||
|
||||
// These functions should be used to bind GL objects. They track the GL state and skip redundant
|
||||
// bindings. Making the equivalent glBind calls directly will confuse the state tracking.
|
||||
void bindVertexArray(GrGLuint id) {
|
||||
|
@ -199,17 +199,6 @@ GrGLProgram* GrGpuGL::ProgramCache::getProgram(const GrGLProgramDesc& desc,
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
void GrGpuGL::abandonResources(){
|
||||
INHERITED::abandonResources();
|
||||
fProgramCache->abandon();
|
||||
fHWProgramID = 0;
|
||||
if (this->glCaps().pathRenderingSupport()) {
|
||||
this->glPathRendering()->abandonGpuResources();
|
||||
}
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
#define GL_CALL(X) GR_GL_CALL(this->glInterface(), X)
|
||||
|
||||
bool GrGpuGL::flushGraphicsState(DrawType type, const GrDeviceCoordTexture* dstCopy) {
|
||||
|
Loading…
Reference in New Issue
Block a user