Made clip mask cache use Scratch Texture system

http://codereview.appspot.com/6210044/



git-svn-id: http://skia.googlecode.com/svn/trunk@3920 2bbb7eff-a529-9590-31e7-b0007b416f81
This commit is contained in:
robertphillips@google.com 2012-05-14 12:18:26 +00:00
parent 18c464b460
commit f105b10926
6 changed files with 147 additions and 110 deletions

View File

@ -853,6 +853,7 @@ public:
GrContext::kApprox_ScratchTexMatch) { GrContext::kApprox_ScratchTexMatch) {
if (NULL != fContext) { if (NULL != fContext) {
fContext->unlockTexture(fEntry); fContext->unlockTexture(fEntry);
fEntry.reset();
} }
fContext = context; fContext = context;
if (NULL != fContext) { if (NULL != fContext) {

View File

@ -338,7 +338,6 @@ bool GrClipMaskManager::drawClipShape(GrGpu* gpu,
void GrClipMaskManager::drawTexture(GrGpu* gpu, void GrClipMaskManager::drawTexture(GrGpu* gpu,
GrTexture* target, GrTexture* target,
const GrRect& rect,
GrTexture* texture) { GrTexture* texture) {
GrDrawState* drawState = gpu->drawState(); GrDrawState* drawState = gpu->drawState();
GrAssert(NULL != drawState); GrAssert(NULL != drawState);
@ -354,6 +353,9 @@ void GrClipMaskManager::drawTexture(GrGpu* gpu,
GrSamplerState::kNearest_Filter, GrSamplerState::kNearest_Filter,
sampleM); sampleM);
GrRect rect = GrRect::MakeWH(SkIntToScalar(target->width()),
SkIntToScalar(target->height()));
gpu->drawSimpleRect(rect, NULL, 1 << 0); gpu->drawSimpleRect(rect, NULL, 1 << 0);
drawState->setTexture(0, NULL); drawState->setTexture(0, NULL);
@ -372,10 +374,13 @@ void clear(GrGpu* gpu,
gpu->clear(NULL, color); gpu->clear(NULL, color);
} }
}
// get a texture to act as a temporary buffer for AA clip boolean operations // get a texture to act as a temporary buffer for AA clip boolean operations
// TODO: given the expense of createTexture we may want to just cache this too // TODO: given the expense of createTexture we may want to just cache this too
void get_temp(GrGpu *gpu, const GrRect& bounds, GrTexture** temp) { void GrClipMaskManager::getTemp(const GrRect& bounds,
if (NULL != *temp) { GrAutoScratchTexture* temp) {
if (NULL != temp->texture()) {
// we've already allocated the temp texture // we've already allocated the temp texture
return; return;
} }
@ -388,39 +393,27 @@ void get_temp(GrGpu *gpu, const GrRect& bounds, GrTexture** temp) {
0 // samples 0 // samples
}; };
*temp = gpu->createTexture(desc, NULL, 0); temp->set(fAACache.getContext(), desc);
} }
void GrClipMaskManager::setupCache(const GrClip& clipIn,
const GrRect& bounds) {
// Since we are setting up the cache we know the last lookup was a miss
// Free up the currently cached mask so it can be reused
fAACache.reset();
const GrTextureDesc desc = {
kRenderTarget_GrTextureFlagBit|kNoStencil_GrTextureFlagBit,
SkScalarCeilToInt(bounds.width()),
SkScalarCeilToInt(bounds.height()),
kAlpha_8_GrPixelConfig,
0 // samples
};
fAACache.acquireMask(clipIn, desc, bounds);
} }
void GrClipMaskManager::getAccum(GrGpu* gpu,
const GrRect& bounds,
GrTexture** accum) {
GrAssert(NULL == *accum);
// since we are getting an accumulator we know our cache is shot. See
// if we can reuse the texture stored in the cache
if (fAACache.getLastMaskWidth() >= bounds.width() &&
fAACache.getLastMaskHeight() >= bounds.height()) {
// we can just reuse the existing texture
*accum = fAACache.detachLastMask();
fAACache.reset();
} else {
const GrTextureDesc desc = {
kRenderTarget_GrTextureFlagBit|kNoStencil_GrTextureFlagBit,
SkScalarCeilToInt(bounds.width()),
SkScalarCeilToInt(bounds.height()),
kAlpha_8_GrPixelConfig,
0 // samples
};
*accum = gpu->createTexture(desc, NULL, 0);
}
GrAssert(1 == (*accum)->getRefCnt());
}
//////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////
// Shared preamble between gpu and SW-only AA clip mask creation paths. // Shared preamble between gpu and SW-only AA clip mask creation paths.
// Handles caching, determination of clip mask bound & allocation (if needed) // Handles caching, determination of clip mask bound & allocation (if needed)
@ -429,8 +422,7 @@ void GrClipMaskManager::getAccum(GrGpu* gpu,
bool GrClipMaskManager::clipMaskPreamble(GrGpu* gpu, bool GrClipMaskManager::clipMaskPreamble(GrGpu* gpu,
const GrClip& clipIn, const GrClip& clipIn,
GrTexture** result, GrTexture** result,
GrRect *resultBounds, GrRect *resultBounds) {
GrTexture** maskStorage) {
GrDrawState* origDrawState = gpu->drawState(); GrDrawState* origDrawState = gpu->drawState();
GrAssert(origDrawState->isClipState()); GrAssert(origDrawState->isClipState());
@ -441,7 +433,6 @@ bool GrClipMaskManager::clipMaskPreamble(GrGpu* gpu,
rtRect.setLTRB(0, 0, rtRect.setLTRB(0, 0,
GrIntToScalar(rt->width()), GrIntToScalar(rt->height())); GrIntToScalar(rt->width()), GrIntToScalar(rt->height()));
// unlike the stencil path the alpha path is not bound to the size of the // unlike the stencil path the alpha path is not bound to the size of the
// render target - determine the minimum size required for the mask // render target - determine the minimum size required for the mask
GrRect bounds; GrRect bounds;
@ -477,7 +468,8 @@ bool GrClipMaskManager::clipMaskPreamble(GrGpu* gpu,
return true; return true;
} }
this->getAccum(gpu, bounds, maskStorage); this->setupCache(clipIn, bounds);
*resultBounds = bounds; *resultBounds = bounds;
return false; return false;
} }
@ -489,19 +481,17 @@ bool GrClipMaskManager::createAlphaClipMask(GrGpu* gpu,
GrTexture** result, GrTexture** result,
GrRect *resultBounds) { GrRect *resultBounds) {
GrTexture* accum = NULL; if (this->clipMaskPreamble(gpu, clipIn, result, resultBounds)) {
if (this->clipMaskPreamble(gpu, clipIn, result, resultBounds, &accum)) {
return true; return true;
} }
GrTexture* accum = fAACache.getLastMask();
if (NULL == accum) { if (NULL == accum) {
fClipMaskInAlpha = false; fClipMaskInAlpha = false;
fAACache.reset();
return false; return false;
} }
GrRect newRTBounds;
newRTBounds.setLTRB(0, 0, resultBounds->width(), resultBounds->height());
GrDrawTarget::AutoStateRestore asr(gpu, GrDrawTarget::kReset_ASRInit); GrDrawTarget::AutoStateRestore asr(gpu, GrDrawTarget::kReset_ASRInit);
GrDrawState* drawState = gpu->drawState(); GrDrawState* drawState = gpu->drawState();
@ -528,7 +518,7 @@ bool GrClipMaskManager::createAlphaClipMask(GrGpu* gpu,
clear(gpu, accum, clearToInside ? 0xffffffff : 0x00000000); clear(gpu, accum, clearToInside ? 0xffffffff : 0x00000000);
GrTexture* temp = NULL; GrAutoScratchTexture temp;
// walk through each clip element and perform its set op // walk through each clip element and perform its set op
for (int c = start; c < count; ++c) { for (int c = start; c < count; ++c) {
@ -555,18 +545,18 @@ bool GrClipMaskManager::createAlphaClipMask(GrGpu* gpu,
continue; continue;
} }
get_temp(gpu, *resultBounds, &temp); getTemp(*resultBounds, &temp);
if (NULL == temp) { if (NULL == temp.texture()) {
fClipMaskInAlpha = false; fClipMaskInAlpha = false;
SkSafeUnref(accum); fAACache.reset();
return false; return false;
} }
// clear the temp target & draw into it // clear the temp target & draw into it
clear(gpu, temp, 0x00000000); clear(gpu, temp.texture(), 0x00000000);
setup_boolean_blendcoeffs(drawState, SkRegion::kReplace_Op); setup_boolean_blendcoeffs(drawState, SkRegion::kReplace_Op);
this->drawClipShape(gpu, temp, clipIn, c); this->drawClipShape(gpu, temp.texture(), clipIn, c);
// TODO: rather than adding these two translations here // TODO: rather than adding these two translations here
// compute the bounding box needed to render the texture // compute the bounding box needed to render the texture
@ -582,7 +572,7 @@ bool GrClipMaskManager::createAlphaClipMask(GrGpu* gpu,
// Now draw into the accumulator using the real operation // Now draw into the accumulator using the real operation
// and the temp buffer as a texture // and the temp buffer as a texture
setup_boolean_blendcoeffs(drawState, op); setup_boolean_blendcoeffs(drawState, op);
this->drawTexture(gpu, accum, newRTBounds, temp); this->drawTexture(gpu, accum, temp.texture());
if (0 != resultBounds->fTop || 0 != resultBounds->fLeft) { if (0 != resultBounds->fTop || 0 != resultBounds->fLeft) {
GrMatrix m; GrMatrix m;
@ -600,10 +590,7 @@ bool GrClipMaskManager::createAlphaClipMask(GrGpu* gpu,
} }
} }
fAACache.set(clipIn, accum, *resultBounds);
*result = accum; *result = accum;
SkSafeUnref(accum); // fAACache still has a ref to accum
SkSafeUnref(temp);
return true; return true;
} }
@ -784,13 +771,14 @@ bool GrClipMaskManager::createSoftwareClipMask(GrGpu* gpu,
GrTexture** result, GrTexture** result,
GrRect *resultBounds) { GrRect *resultBounds) {
GrTexture* accum = NULL; if (this->clipMaskPreamble(gpu, clipIn, result, resultBounds)) {
if (this->clipMaskPreamble(gpu, clipIn, result, resultBounds, &accum)) {
return true; return true;
} }
GrTexture* accum = fAACache.getLastMask();
if (NULL == accum) { if (NULL == accum) {
fClipMaskInAlpha = false; fClipMaskInAlpha = false;
fAACache.reset();
return false; return false;
} }
@ -819,9 +807,7 @@ bool GrClipMaskManager::createSoftwareClipMask(GrGpu* gpu,
// TODO: need to get pixels out of SkRasterClip & into the texture! // TODO: need to get pixels out of SkRasterClip & into the texture!
#endif #endif
fAACache.set(clipIn, accum, *resultBounds);
*result = accum; *result = accum;
SkSafeUnref(accum); // fAACache still has a ref to accum
return true; return true;
} }
@ -841,7 +827,8 @@ GrPathRenderer* GrClipMaskManager::getClipPathRenderer(GrGpu* gpu,
} }
//////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////
void GrClipMaskManager::freeResources() { void GrClipMaskManager::releaseResources() {
// in case path renderer has any GrResources, start from scratch // in case path renderer has any GrResources, start from scratch
GrSafeSetNull(fPathRendererChain); GrSafeSetNull(fPathRendererChain);
fAACache.releaseResources();
} }

View File

@ -16,6 +16,7 @@
#include "SkRefCnt.h" #include "SkRefCnt.h"
#include "GrTexture.h" #include "GrTexture.h"
#include "SkDeque.h" #include "SkDeque.h"
#include "GrContext.h"
class GrGpu; class GrGpu;
class GrPathRenderer; class GrPathRenderer;
@ -44,7 +45,8 @@ struct ScissoringSettings {
class GrClipMaskCache : public GrNoncopyable { class GrClipMaskCache : public GrNoncopyable {
public: public:
GrClipMaskCache() GrClipMaskCache()
: fStack(sizeof(GrClipStackFrame)) { : fContext(NULL)
, fStack(sizeof(GrClipStackFrame)) {
// We need an initial frame to capture the clip state prior to // We need an initial frame to capture the clip state prior to
// any pushes // any pushes
new (fStack.push_back()) GrClipStackFrame(); new (fStack.push_back()) GrClipStackFrame();
@ -68,9 +70,9 @@ public:
GrClipStackFrame* back = (GrClipStackFrame*) fStack.back(); GrClipStackFrame* back = (GrClipStackFrame*) fStack.back();
if (back->fLastMask && if (back->fLastMask.texture() &&
back->fLastMask->width() >= width && back->fLastMask.texture()->width() >= width &&
back->fLastMask->height() >= height && back->fLastMask.texture()->height() >= height &&
clip == back->fLastClip) { clip == back->fLastClip) {
return true; return true;
} }
@ -78,21 +80,6 @@ public:
return false; return false;
} }
void set(const GrClip& clip, GrTexture* mask, const GrRect& bound) {
if (fStack.empty()) {
GrAssert(false);
return;
}
GrClipStackFrame* back = (GrClipStackFrame*) fStack.back();
back->fLastClip = clip;
SkSafeRef(mask);
back->fLastMask.reset(mask);
back->fLastBound = bound;
}
void reset() { void reset() {
if (fStack.empty()) { if (fStack.empty()) {
GrAssert(false); GrAssert(false);
@ -147,7 +134,7 @@ public:
GrClipStackFrame* back = (GrClipStackFrame*) fStack.back(); GrClipStackFrame* back = (GrClipStackFrame*) fStack.back();
return back->fLastMask.get(); return back->fLastMask.texture();
} }
const GrTexture* getLastMask() const { const GrTexture* getLastMask() const {
@ -159,19 +146,21 @@ public:
GrClipStackFrame* back = (GrClipStackFrame*) fStack.back(); GrClipStackFrame* back = (GrClipStackFrame*) fStack.back();
return back->fLastMask.get(); return back->fLastMask.texture();
} }
GrTexture* detachLastMask() { void acquireMask(const GrClip& clip,
const GrTextureDesc& desc,
const GrRect& bound) {
if (fStack.empty()) { if (fStack.empty()) {
GrAssert(false); GrAssert(false);
return NULL; return;
} }
GrClipStackFrame* back = (GrClipStackFrame*) fStack.back(); GrClipStackFrame* back = (GrClipStackFrame*) fStack.back();
return back->fLastMask.detach(); back->acquireMask(fContext, clip, desc, bound);
} }
int getLastMaskWidth() const { int getLastMaskWidth() const {
@ -183,11 +172,11 @@ public:
GrClipStackFrame* back = (GrClipStackFrame*) fStack.back(); GrClipStackFrame* back = (GrClipStackFrame*) fStack.back();
if (NULL == back->fLastMask.get()) { if (NULL == back->fLastMask.texture()) {
return -1; return -1;
} }
return back->fLastMask.get()->width(); return back->fLastMask.texture()->width();
} }
int getLastMaskHeight() const { int getLastMaskHeight() const {
@ -199,11 +188,11 @@ public:
GrClipStackFrame* back = (GrClipStackFrame*) fStack.back(); GrClipStackFrame* back = (GrClipStackFrame*) fStack.back();
if (NULL == back->fLastMask.get()) { if (NULL == back->fLastMask.texture()) {
return -1; return -1;
} }
return back->fLastMask.get()->height(); return back->fLastMask.texture()->height();
} }
void getLastBound(GrRect* bound) const { void getLastBound(GrRect* bound) const {
@ -219,6 +208,24 @@ public:
*bound = back->fLastBound; *bound = back->fLastBound;
} }
void setContext(GrContext* context) {
fContext = context;
}
GrContext* getContext() {
return fContext;
}
void releaseResources() {
SkDeque::F2BIter iter(fStack);
for (GrClipStackFrame* frame = (GrClipStackFrame*) iter.next();
frame != NULL;
frame = (GrClipStackFrame*) iter.next()) {
frame->reset();
}
}
protected: protected:
private: private:
struct GrClipStackFrame { struct GrClipStackFrame {
@ -227,22 +234,39 @@ private:
reset(); reset();
} }
void acquireMask(GrContext* context,
const GrClip& clip,
const GrTextureDesc& desc,
const GrRect& bound) {
fLastClip = clip;
fLastMask.set(context, desc);
fLastBound = bound;
}
void reset () { void reset () {
fLastClip.setEmpty(); fLastClip.setEmpty();
fLastMask.reset(NULL);
const GrTextureDesc desc = { kNone_GrTextureFlags, 0, 0,
kUnknown_GrPixelConfig, 0 };
fLastMask.set(NULL, desc);
fLastBound.setEmpty(); fLastBound.setEmpty();
} }
GrClip fLastClip; GrClip fLastClip;
// The mask's width & height values are used in setupDrawStateAAClip to // The mask's width & height values are used in setupDrawStateAAClip to
// correctly scale the uvs for geometry drawn with this mask // correctly scale the uvs for geometry drawn with this mask
SkAutoTUnref<GrTexture> fLastMask; GrAutoScratchTexture fLastMask;
// fLastBound stores the bounding box of the clip mask in canvas // fLastBound stores the bounding box of the clip mask in canvas
// space. The left and top fields are used to offset the uvs for // space. The left and top fields are used to offset the uvs for
// geometry drawn with this mask (in setupDrawStateAAClip) // geometry drawn with this mask (in setupDrawStateAAClip)
GrRect fLastBound; GrRect fLastBound;
}; };
GrContext* fContext;
SkDeque fStack; SkDeque fStack;
typedef GrNoncopyable INHERITED; typedef GrNoncopyable INHERITED;
@ -268,7 +292,7 @@ public:
const GrClip& clip, const GrClip& clip,
ScissoringSettings* scissorSettings); ScissoringSettings* scissorSettings);
void freeResources(); void releaseResources();
bool isClipInStencil() const { return fClipMaskInStencil; } bool isClipInStencil() const { return fClipMaskInStencil; }
bool isClipInAlpha() const { return fClipMaskInAlpha; } bool isClipInAlpha() const { return fClipMaskInAlpha; }
@ -277,6 +301,10 @@ public:
fClipMaskInStencil = false; fClipMaskInStencil = false;
} }
void setContext(GrContext* context) {
fAACache.setContext(context);
}
protected: protected:
private: private:
bool fClipMaskInStencil; // is the clip mask in the stencil buffer? bool fClipMaskInStencil; // is the clip mask in the stencil buffer?
@ -302,8 +330,7 @@ private:
bool clipMaskPreamble(GrGpu* gpu, bool clipMaskPreamble(GrGpu* gpu,
const GrClip& clipIn, const GrClip& clipIn,
GrTexture** result, GrTexture** result,
GrRect *resultBounds, GrRect *resultBounds);
GrTexture** maskStorage);
bool drawPath(GrGpu* gpu, bool drawPath(GrGpu* gpu,
const SkPath& path, const SkPath& path,
@ -317,10 +344,12 @@ private:
void drawTexture(GrGpu* gpu, void drawTexture(GrGpu* gpu,
GrTexture* target, GrTexture* target,
const GrRect& rect,
GrTexture* texture); GrTexture* texture);
void getAccum(GrGpu* gpu, const GrRect& bounds, GrTexture** accum); void getTemp(const GrRect& bounds, GrAutoScratchTexture* temp);
void setupCache(const GrClip& clip,
const GrRect& bounds);
// determines the path renderer used to draw a clip path element. // determines the path renderer used to draw a clip path element.
GrPathRenderer* getClipPathRenderer(GrGpu* gpu, GrPathRenderer* getClipPathRenderer(GrGpu* gpu,

View File

@ -66,6 +66,8 @@ GrGpu::~GrGpu() {
void GrGpu::abandonResources() { void GrGpu::abandonResources() {
fClipMaskManager.releaseResources();
while (NULL != fResourceHead) { while (NULL != fResourceHead) {
fResourceHead->abandon(); fResourceHead->abandon();
} }
@ -79,12 +81,12 @@ void GrGpu::abandonResources() {
fVertexPool = NULL; fVertexPool = NULL;
delete fIndexPool; delete fIndexPool;
fIndexPool = NULL; fIndexPool = NULL;
fClipMaskManager.freeResources();
} }
void GrGpu::releaseResources() { void GrGpu::releaseResources() {
fClipMaskManager.releaseResources();
while (NULL != fResourceHead) { while (NULL != fResourceHead) {
fResourceHead->release(); fResourceHead->release();
} }
@ -98,8 +100,6 @@ void GrGpu::releaseResources() {
fVertexPool = NULL; fVertexPool = NULL;
delete fIndexPool; delete fIndexPool;
fIndexPool = NULL; fIndexPool = NULL;
fClipMaskManager.freeResources();
} }
void GrGpu::insertResource(GrResource* resource) { void GrGpu::insertResource(GrResource* resource) {

View File

@ -87,6 +87,7 @@ public:
void setContext(GrContext* context) { void setContext(GrContext* context) {
GrAssert(NULL == fContext); GrAssert(NULL == fContext);
fContext = context; fContext = context;
fClipMaskManager.setContext(context);
} }
GrContext* getContext() { return fContext; } GrContext* getContext() { return fContext; }
const GrContext* getContext() const { return fContext; } const GrContext* getContext() const { return fContext; }

View File

@ -61,6 +61,8 @@ static void test_cache(skiatest::Reporter* reporter, GrContext* context) {
GrClipMaskCache cache; GrClipMaskCache cache;
cache.setContext(context);
GrClip emptyClip; GrClip emptyClip;
emptyClip.setEmpty(); emptyClip.setEmpty();
@ -77,25 +79,32 @@ static void test_cache(skiatest::Reporter* reporter, GrContext* context) {
GrClip clip1; GrClip clip1;
clip1.setFromRect(bound1); clip1.setFromRect(bound1);
SkAutoTUnref<GrTexture> texture(createTexture(context)); const GrTextureDesc desc = {
REPORTER_ASSERT(reporter, texture.get()); kRenderTarget_GrTextureFlagBit,
X_SIZE,
Y_SIZE,
kSkia8888_PM_GrPixelConfig,
0
};
if (NULL == texture.get()) { cache.acquireMask(clip1, desc, bound1);
GrTexture* texture1 = cache.getLastMask();
REPORTER_ASSERT(reporter, texture1);
if (NULL == texture1) {
return; return;
} }
cache.set(clip1, texture.get(), bound1);
// check that the set took // check that the set took
check_state(reporter, cache, clip1, texture.get(), bound1); check_state(reporter, cache, clip1, texture1, bound1);
REPORTER_ASSERT(reporter, 2 == texture.get()->getRefCnt()); REPORTER_ASSERT(reporter, 1 == texture1->getRefCnt());
// push the state // push the state
cache.push(); cache.push();
// verify that the pushed state is initially empty // verify that the pushed state is initially empty
check_state(reporter, cache, emptyClip, NULL, emptyBound); check_state(reporter, cache, emptyClip, NULL, emptyBound);
REPORTER_ASSERT(reporter, 2 == texture.get()->getRefCnt()); REPORTER_ASSERT(reporter, 1 == texture1->getRefCnt());
// modify the new state // modify the new state
GrRect bound2; GrRect bound2;
@ -105,11 +114,18 @@ static void test_cache(skiatest::Reporter* reporter, GrContext* context) {
clip2.setEmpty(); clip2.setEmpty();
clip2.setFromRect(bound2); clip2.setFromRect(bound2);
cache.set(clip2, texture.get(), bound2); cache.acquireMask(clip2, desc, bound2);
GrTexture* texture2 = cache.getLastMask();
REPORTER_ASSERT(reporter, texture2);
if (NULL == texture2) {
return;
}
// check that the changes took // check that the changes took
check_state(reporter, cache, clip2, texture.get(), bound2); check_state(reporter, cache, clip2, texture2, bound2);
REPORTER_ASSERT(reporter, 3 == texture.get()->getRefCnt()); REPORTER_ASSERT(reporter, 1 == texture1->getRefCnt());
REPORTER_ASSERT(reporter, 1 == texture2->getRefCnt());
// check to make sure canReuse works // check to make sure canReuse works
REPORTER_ASSERT(reporter, cache.canReuse(clip2, 10, 10)); REPORTER_ASSERT(reporter, cache.canReuse(clip2, 10, 10));
@ -119,15 +135,17 @@ static void test_cache(skiatest::Reporter* reporter, GrContext* context) {
cache.pop(); cache.pop();
// verify that the old state is restored // verify that the old state is restored
check_state(reporter, cache, clip1, texture.get(), bound1); check_state(reporter, cache, clip1, texture1, bound1);
REPORTER_ASSERT(reporter, 2 == texture.get()->getRefCnt()); REPORTER_ASSERT(reporter, 1 == texture1->getRefCnt());
REPORTER_ASSERT(reporter, 1 == texture2->getRefCnt());
// manually clear the state // manually clear the state
cache.reset(); cache.reset();
// verify it is now empty // verify it is now empty
check_state(reporter, cache, emptyClip, NULL, emptyBound); check_state(reporter, cache, emptyClip, NULL, emptyBound);
REPORTER_ASSERT(reporter, 1 == texture.get()->getRefCnt()); REPORTER_ASSERT(reporter, 1 == texture1->getRefCnt());
REPORTER_ASSERT(reporter, 1 == texture2->getRefCnt());
// pop again - so there is no state // pop again - so there is no state
cache.pop(); cache.pop();
@ -137,7 +155,8 @@ static void test_cache(skiatest::Reporter* reporter, GrContext* context) {
// only do in release since it generates asserts in debug // only do in release since it generates asserts in debug
check_state(reporter, cache, emptyClip, NULL, emptyBound); check_state(reporter, cache, emptyClip, NULL, emptyBound);
#endif #endif
REPORTER_ASSERT(reporter, 1 == texture.get()->getRefCnt()); REPORTER_ASSERT(reporter, 1 == texture1->getRefCnt());
REPORTER_ASSERT(reporter, 1 == texture2->getRefCnt());
} }
//////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////