aboutsummaryrefslogtreecommitdiffhomepage
diff options
context:
space:
mode:
-rw-r--r--include/gpu/GrContext.h1
-rw-r--r--src/gpu/GrClipMaskManager.cpp95
-rw-r--r--src/gpu/GrClipMaskManager.h99
-rw-r--r--src/gpu/GrGpu.cpp8
-rw-r--r--src/gpu/GrGpu.h1
-rw-r--r--tests/ClipCacheTest.cpp49
6 files changed, 145 insertions, 108 deletions
diff --git a/include/gpu/GrContext.h b/include/gpu/GrContext.h
index b26d2b3aee..bb661c90b7 100644
--- a/include/gpu/GrContext.h
+++ b/include/gpu/GrContext.h
@@ -853,6 +853,7 @@ public:
GrContext::kApprox_ScratchTexMatch) {
if (NULL != fContext) {
fContext->unlockTexture(fEntry);
+ fEntry.reset();
}
fContext = context;
if (NULL != fContext) {
diff --git a/src/gpu/GrClipMaskManager.cpp b/src/gpu/GrClipMaskManager.cpp
index 2e9a4b9bd4..43b27431ba 100644
--- a/src/gpu/GrClipMaskManager.cpp
+++ b/src/gpu/GrClipMaskManager.cpp
@@ -338,7 +338,6 @@ bool GrClipMaskManager::drawClipShape(GrGpu* gpu,
void GrClipMaskManager::drawTexture(GrGpu* gpu,
GrTexture* target,
- const GrRect& rect,
GrTexture* texture) {
GrDrawState* drawState = gpu->drawState();
GrAssert(NULL != drawState);
@@ -354,6 +353,9 @@ void GrClipMaskManager::drawTexture(GrGpu* gpu,
GrSamplerState::kNearest_Filter,
sampleM);
+ GrRect rect = GrRect::MakeWH(SkIntToScalar(target->width()),
+ SkIntToScalar(target->height()));
+
gpu->drawSimpleRect(rect, NULL, 1 << 0);
drawState->setTexture(0, NULL);
@@ -372,10 +374,13 @@ void clear(GrGpu* gpu,
gpu->clear(NULL, color);
}
+}
+
// 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
-void get_temp(GrGpu *gpu, const GrRect& bounds, GrTexture** temp) {
- if (NULL != *temp) {
+void GrClipMaskManager::getTemp(const GrRect& bounds,
+ GrAutoScratchTexture* temp) {
+ if (NULL != temp->texture()) {
// we've already allocated the temp texture
return;
}
@@ -388,38 +393,26 @@ void get_temp(GrGpu *gpu, const GrRect& bounds, GrTexture** temp) {
0 // samples
};
- *temp = gpu->createTexture(desc, NULL, 0);
+ temp->set(fAACache.getContext(), desc);
}
-}
-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);
- }
+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();
- GrAssert(1 == (*accum)->getRefCnt());
-}
+ const GrTextureDesc desc = {
+ kRenderTarget_GrTextureFlagBit|kNoStencil_GrTextureFlagBit,
+ SkScalarCeilToInt(bounds.width()),
+ SkScalarCeilToInt(bounds.height()),
+ kAlpha_8_GrPixelConfig,
+ 0 // samples
+ };
+ fAACache.acquireMask(clipIn, desc, bounds);
+}
////////////////////////////////////////////////////////////////////////////////
// Shared preamble between gpu and SW-only AA clip mask creation paths.
@@ -429,8 +422,7 @@ void GrClipMaskManager::getAccum(GrGpu* gpu,
bool GrClipMaskManager::clipMaskPreamble(GrGpu* gpu,
const GrClip& clipIn,
GrTexture** result,
- GrRect *resultBounds,
- GrTexture** maskStorage) {
+ GrRect *resultBounds) {
GrDrawState* origDrawState = gpu->drawState();
GrAssert(origDrawState->isClipState());
@@ -441,7 +433,6 @@ bool GrClipMaskManager::clipMaskPreamble(GrGpu* gpu,
rtRect.setLTRB(0, 0,
GrIntToScalar(rt->width()), GrIntToScalar(rt->height()));
-
// 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
GrRect bounds;
@@ -477,7 +468,8 @@ bool GrClipMaskManager::clipMaskPreamble(GrGpu* gpu,
return true;
}
- this->getAccum(gpu, bounds, maskStorage);
+ this->setupCache(clipIn, bounds);
+
*resultBounds = bounds;
return false;
}
@@ -489,19 +481,17 @@ bool GrClipMaskManager::createAlphaClipMask(GrGpu* gpu,
GrTexture** result,
GrRect *resultBounds) {
- GrTexture* accum = NULL;
- if (this->clipMaskPreamble(gpu, clipIn, result, resultBounds, &accum)) {
+ if (this->clipMaskPreamble(gpu, clipIn, result, resultBounds)) {
return true;
}
+ GrTexture* accum = fAACache.getLastMask();
if (NULL == accum) {
fClipMaskInAlpha = false;
+ fAACache.reset();
return false;
}
- GrRect newRTBounds;
- newRTBounds.setLTRB(0, 0, resultBounds->width(), resultBounds->height());
-
GrDrawTarget::AutoStateRestore asr(gpu, GrDrawTarget::kReset_ASRInit);
GrDrawState* drawState = gpu->drawState();
@@ -528,7 +518,7 @@ bool GrClipMaskManager::createAlphaClipMask(GrGpu* gpu,
clear(gpu, accum, clearToInside ? 0xffffffff : 0x00000000);
- GrTexture* temp = NULL;
+ GrAutoScratchTexture temp;
// walk through each clip element and perform its set op
for (int c = start; c < count; ++c) {
@@ -555,18 +545,18 @@ bool GrClipMaskManager::createAlphaClipMask(GrGpu* gpu,
continue;
}
- get_temp(gpu, *resultBounds, &temp);
- if (NULL == temp) {
+ getTemp(*resultBounds, &temp);
+ if (NULL == temp.texture()) {
fClipMaskInAlpha = false;
- SkSafeUnref(accum);
+ fAACache.reset();
return false;
}
// clear the temp target & draw into it
- clear(gpu, temp, 0x00000000);
+ clear(gpu, temp.texture(), 0x00000000);
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
// 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
// and the temp buffer as a texture
setup_boolean_blendcoeffs(drawState, op);
- this->drawTexture(gpu, accum, newRTBounds, temp);
+ this->drawTexture(gpu, accum, temp.texture());
if (0 != resultBounds->fTop || 0 != resultBounds->fLeft) {
GrMatrix m;
@@ -600,10 +590,7 @@ bool GrClipMaskManager::createAlphaClipMask(GrGpu* gpu,
}
}
- fAACache.set(clipIn, accum, *resultBounds);
*result = accum;
- SkSafeUnref(accum); // fAACache still has a ref to accum
- SkSafeUnref(temp);
return true;
}
@@ -784,13 +771,14 @@ bool GrClipMaskManager::createSoftwareClipMask(GrGpu* gpu,
GrTexture** result,
GrRect *resultBounds) {
- GrTexture* accum = NULL;
- if (this->clipMaskPreamble(gpu, clipIn, result, resultBounds, &accum)) {
+ if (this->clipMaskPreamble(gpu, clipIn, result, resultBounds)) {
return true;
}
+ GrTexture* accum = fAACache.getLastMask();
if (NULL == accum) {
fClipMaskInAlpha = false;
+ fAACache.reset();
return false;
}
@@ -819,9 +807,7 @@ bool GrClipMaskManager::createSoftwareClipMask(GrGpu* gpu,
// TODO: need to get pixels out of SkRasterClip & into the texture!
#endif
- fAACache.set(clipIn, accum, *resultBounds);
*result = accum;
- SkSafeUnref(accum); // fAACache still has a ref to accum
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
GrSafeSetNull(fPathRendererChain);
+ fAACache.releaseResources();
}
diff --git a/src/gpu/GrClipMaskManager.h b/src/gpu/GrClipMaskManager.h
index 5ab189d50e..c87bb7c32a 100644
--- a/src/gpu/GrClipMaskManager.h
+++ b/src/gpu/GrClipMaskManager.h
@@ -16,6 +16,7 @@
#include "SkRefCnt.h"
#include "GrTexture.h"
#include "SkDeque.h"
+#include "GrContext.h"
class GrGpu;
class GrPathRenderer;
@@ -44,7 +45,8 @@ struct ScissoringSettings {
class GrClipMaskCache : public GrNoncopyable {
public:
GrClipMaskCache()
- : fStack(sizeof(GrClipStackFrame)) {
+ : fContext(NULL)
+ , fStack(sizeof(GrClipStackFrame)) {
// We need an initial frame to capture the clip state prior to
// any pushes
new (fStack.push_back()) GrClipStackFrame();
@@ -68,9 +70,9 @@ public:
GrClipStackFrame* back = (GrClipStackFrame*) fStack.back();
- if (back->fLastMask &&
- back->fLastMask->width() >= width &&
- back->fLastMask->height() >= height &&
+ if (back->fLastMask.texture() &&
+ back->fLastMask.texture()->width() >= width &&
+ back->fLastMask.texture()->height() >= height &&
clip == back->fLastClip) {
return true;
}
@@ -78,21 +80,6 @@ public:
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() {
if (fStack.empty()) {
GrAssert(false);
@@ -147,7 +134,7 @@ public:
GrClipStackFrame* back = (GrClipStackFrame*) fStack.back();
- return back->fLastMask.get();
+ return back->fLastMask.texture();
}
const GrTexture* getLastMask() const {
@@ -159,19 +146,21 @@ public:
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()) {
GrAssert(false);
- return NULL;
+ return;
}
GrClipStackFrame* back = (GrClipStackFrame*) fStack.back();
- return back->fLastMask.detach();
+ back->acquireMask(fContext, clip, desc, bound);
}
int getLastMaskWidth() const {
@@ -183,11 +172,11 @@ public:
GrClipStackFrame* back = (GrClipStackFrame*) fStack.back();
- if (NULL == back->fLastMask.get()) {
+ if (NULL == back->fLastMask.texture()) {
return -1;
}
- return back->fLastMask.get()->width();
+ return back->fLastMask.texture()->width();
}
int getLastMaskHeight() const {
@@ -199,11 +188,11 @@ public:
GrClipStackFrame* back = (GrClipStackFrame*) fStack.back();
- if (NULL == back->fLastMask.get()) {
+ if (NULL == back->fLastMask.texture()) {
return -1;
}
- return back->fLastMask.get()->height();
+ return back->fLastMask.texture()->height();
}
void getLastBound(GrRect* bound) const {
@@ -219,6 +208,24 @@ public:
*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:
private:
struct GrClipStackFrame {
@@ -227,22 +234,39 @@ private:
reset();
}
+ void acquireMask(GrContext* context,
+ const GrClip& clip,
+ const GrTextureDesc& desc,
+ const GrRect& bound) {
+
+ fLastClip = clip;
+
+ fLastMask.set(context, desc);
+
+ fLastBound = bound;
+ }
+
void reset () {
fLastClip.setEmpty();
- fLastMask.reset(NULL);
+
+ const GrTextureDesc desc = { kNone_GrTextureFlags, 0, 0,
+ kUnknown_GrPixelConfig, 0 };
+
+ fLastMask.set(NULL, desc);
fLastBound.setEmpty();
}
GrClip fLastClip;
// The mask's width & height values are used in setupDrawStateAAClip to
// 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
// space. The left and top fields are used to offset the uvs for
// geometry drawn with this mask (in setupDrawStateAAClip)
GrRect fLastBound;
};
+ GrContext* fContext;
SkDeque fStack;
typedef GrNoncopyable INHERITED;
@@ -268,7 +292,7 @@ public:
const GrClip& clip,
ScissoringSettings* scissorSettings);
- void freeResources();
+ void releaseResources();
bool isClipInStencil() const { return fClipMaskInStencil; }
bool isClipInAlpha() const { return fClipMaskInAlpha; }
@@ -277,6 +301,10 @@ public:
fClipMaskInStencil = false;
}
+ void setContext(GrContext* context) {
+ fAACache.setContext(context);
+ }
+
protected:
private:
bool fClipMaskInStencil; // is the clip mask in the stencil buffer?
@@ -302,8 +330,7 @@ private:
bool clipMaskPreamble(GrGpu* gpu,
const GrClip& clipIn,
GrTexture** result,
- GrRect *resultBounds,
- GrTexture** maskStorage);
+ GrRect *resultBounds);
bool drawPath(GrGpu* gpu,
const SkPath& path,
@@ -317,10 +344,12 @@ private:
void drawTexture(GrGpu* gpu,
GrTexture* target,
- const GrRect& rect,
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.
GrPathRenderer* getClipPathRenderer(GrGpu* gpu,
diff --git a/src/gpu/GrGpu.cpp b/src/gpu/GrGpu.cpp
index a5c7284ce8..4839e4f045 100644
--- a/src/gpu/GrGpu.cpp
+++ b/src/gpu/GrGpu.cpp
@@ -66,6 +66,8 @@ GrGpu::~GrGpu() {
void GrGpu::abandonResources() {
+ fClipMaskManager.releaseResources();
+
while (NULL != fResourceHead) {
fResourceHead->abandon();
}
@@ -79,12 +81,12 @@ void GrGpu::abandonResources() {
fVertexPool = NULL;
delete fIndexPool;
fIndexPool = NULL;
-
- fClipMaskManager.freeResources();
}
void GrGpu::releaseResources() {
+ fClipMaskManager.releaseResources();
+
while (NULL != fResourceHead) {
fResourceHead->release();
}
@@ -98,8 +100,6 @@ void GrGpu::releaseResources() {
fVertexPool = NULL;
delete fIndexPool;
fIndexPool = NULL;
-
- fClipMaskManager.freeResources();
}
void GrGpu::insertResource(GrResource* resource) {
diff --git a/src/gpu/GrGpu.h b/src/gpu/GrGpu.h
index de14935e7f..aeb51f829a 100644
--- a/src/gpu/GrGpu.h
+++ b/src/gpu/GrGpu.h
@@ -87,6 +87,7 @@ public:
void setContext(GrContext* context) {
GrAssert(NULL == fContext);
fContext = context;
+ fClipMaskManager.setContext(context);
}
GrContext* getContext() { return fContext; }
const GrContext* getContext() const { return fContext; }
diff --git a/tests/ClipCacheTest.cpp b/tests/ClipCacheTest.cpp
index 93c6aebee7..1fc5d45b8f 100644
--- a/tests/ClipCacheTest.cpp
+++ b/tests/ClipCacheTest.cpp
@@ -61,6 +61,8 @@ static void test_cache(skiatest::Reporter* reporter, GrContext* context) {
GrClipMaskCache cache;
+ cache.setContext(context);
+
GrClip emptyClip;
emptyClip.setEmpty();
@@ -77,25 +79,32 @@ static void test_cache(skiatest::Reporter* reporter, GrContext* context) {
GrClip clip1;
clip1.setFromRect(bound1);
- SkAutoTUnref<GrTexture> texture(createTexture(context));
- REPORTER_ASSERT(reporter, texture.get());
+ const GrTextureDesc desc = {
+ kRenderTarget_GrTextureFlagBit,
+ X_SIZE,
+ Y_SIZE,
+ kSkia8888_PM_GrPixelConfig,
+ 0
+ };
+
+ cache.acquireMask(clip1, desc, bound1);
- if (NULL == texture.get()) {
+ GrTexture* texture1 = cache.getLastMask();
+ REPORTER_ASSERT(reporter, texture1);
+ if (NULL == texture1) {
return;
}
- cache.set(clip1, texture.get(), bound1);
-
// check that the set took
- check_state(reporter, cache, clip1, texture.get(), bound1);
- REPORTER_ASSERT(reporter, 2 == texture.get()->getRefCnt());
+ check_state(reporter, cache, clip1, texture1, bound1);
+ REPORTER_ASSERT(reporter, 1 == texture1->getRefCnt());
// push the state
cache.push();
// verify that the pushed state is initially empty
check_state(reporter, cache, emptyClip, NULL, emptyBound);
- REPORTER_ASSERT(reporter, 2 == texture.get()->getRefCnt());
+ REPORTER_ASSERT(reporter, 1 == texture1->getRefCnt());
// modify the new state
GrRect bound2;
@@ -105,11 +114,18 @@ static void test_cache(skiatest::Reporter* reporter, GrContext* context) {
clip2.setEmpty();
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_state(reporter, cache, clip2, texture.get(), bound2);
- REPORTER_ASSERT(reporter, 3 == texture.get()->getRefCnt());
+ check_state(reporter, cache, clip2, texture2, bound2);
+ REPORTER_ASSERT(reporter, 1 == texture1->getRefCnt());
+ REPORTER_ASSERT(reporter, 1 == texture2->getRefCnt());
// check to make sure canReuse works
REPORTER_ASSERT(reporter, cache.canReuse(clip2, 10, 10));
@@ -119,15 +135,17 @@ static void test_cache(skiatest::Reporter* reporter, GrContext* context) {
cache.pop();
// verify that the old state is restored
- check_state(reporter, cache, clip1, texture.get(), bound1);
- REPORTER_ASSERT(reporter, 2 == texture.get()->getRefCnt());
+ check_state(reporter, cache, clip1, texture1, bound1);
+ REPORTER_ASSERT(reporter, 1 == texture1->getRefCnt());
+ REPORTER_ASSERT(reporter, 1 == texture2->getRefCnt());
// manually clear the state
cache.reset();
// verify it is now empty
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
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
check_state(reporter, cache, emptyClip, NULL, emptyBound);
#endif
- REPORTER_ASSERT(reporter, 1 == texture.get()->getRefCnt());
+ REPORTER_ASSERT(reporter, 1 == texture1->getRefCnt());
+ REPORTER_ASSERT(reporter, 1 == texture2->getRefCnt());
}
////////////////////////////////////////////////////////////////////////////////