Remove separate cache for clip mask textures
Review URL: https://codereview.chromium.org/1377943003
diff --git a/gyp/gpu.gypi b/gyp/gpu.gypi
index 4670057..1025a1e 100644
--- a/gyp/gpu.gypi
+++ b/gyp/gpu.gypi
@@ -78,8 +78,6 @@
'<(skia_src_path)/gpu/GrBufferAllocPool.h',
'<(skia_src_path)/gpu/GrCaps.cpp',
'<(skia_src_path)/gpu/GrClip.cpp',
- '<(skia_src_path)/gpu/GrClipMaskCache.h',
- '<(skia_src_path)/gpu/GrClipMaskCache.cpp',
'<(skia_src_path)/gpu/GrClipMaskManager.h',
'<(skia_src_path)/gpu/GrClipMaskManager.cpp',
'<(skia_src_path)/gpu/GrContext.cpp',
diff --git a/include/gpu/GrContext.h b/include/gpu/GrContext.h
index 5c02d37..59ce867 100644
--- a/include/gpu/GrContext.h
+++ b/include/gpu/GrContext.h
@@ -430,7 +430,6 @@
void abandon();
bool abandoned() const { return NULL == fDrawTarget; }
- void purgeResources();
void reset();
void flush();
diff --git a/src/gpu/GrClipMaskCache.cpp b/src/gpu/GrClipMaskCache.cpp
deleted file mode 100644
index 42a5d46..0000000
--- a/src/gpu/GrClipMaskCache.cpp
+++ /dev/null
@@ -1,19 +0,0 @@
-
-/*
- * Copyright 2012 Google Inc.
- *
- * Use of this source code is governed by a BSD-style license that can be
- * found in the LICENSE file.
- */
-
-#include "GrClipMaskCache.h"
-
-GrClipMaskCache::GrClipMaskCache(GrResourceProvider* resourceProvider)
- : fStack(sizeof(GrClipStackFrame))
- , fResourceProvider(resourceProvider) {
- // We need an initial frame to capture the clip state prior to
- // any pushes
- new (fStack.push_back()) GrClipStackFrame;
-}
-
-void GrClipMaskCache::push() { new (fStack.push_back()) GrClipStackFrame; }
diff --git a/src/gpu/GrClipMaskCache.h b/src/gpu/GrClipMaskCache.h
deleted file mode 100644
index 56b0e97..0000000
--- a/src/gpu/GrClipMaskCache.h
+++ /dev/null
@@ -1,231 +0,0 @@
-/*
- * Copyright 2012 Google Inc.
- *
- * Use of this source code is governed by a BSD-style license that can be
- * found in the LICENSE file.
- */
-
-#ifndef GrClipMaskCache_DEFINED
-#define GrClipMaskCache_DEFINED
-
-#include "GrResourceProvider.h"
-#include "SkClipStack.h"
-#include "SkTypes.h"
-
-class GrTexture;
-
-/**
- * The stencil buffer stores the last clip path - providing a single entry
- * "cache". This class provides similar functionality for AA clip paths
- */
-class GrClipMaskCache : SkNoncopyable {
-public:
- GrClipMaskCache(GrResourceProvider*);
-
- ~GrClipMaskCache() {
- while (!fStack.empty()) {
- GrClipStackFrame* temp = (GrClipStackFrame*) fStack.back();
- temp->~GrClipStackFrame();
- fStack.pop_back();
- }
- }
-
- bool canReuse(int32_t clipGenID, const SkIRect& bounds) {
-
- SkASSERT(clipGenID != SkClipStack::kWideOpenGenID);
- SkASSERT(clipGenID != SkClipStack::kEmptyGenID);
-
- GrClipStackFrame* back = (GrClipStackFrame*) fStack.back();
-
- // 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 &&
- !back->fLastMask->wasDestroyed() &&
- back->fLastBound == bounds &&
- back->fLastClipGenID == clipGenID) {
- return true;
- }
-
- return false;
- }
-
- void reset() {
- if (fStack.empty()) {
-// SkASSERT(false);
- return;
- }
-
- GrClipStackFrame* back = (GrClipStackFrame*) fStack.back();
-
- back->reset();
- }
-
- /**
- * After a "push" the clip state is entirely open. Currently, the
- * entire clip stack will be re-rendered into a new clip mask.
- * TODO: can we take advantage of the nested nature of the clips to
- * reduce the mask creation cost?
- */
- void push();
-
- void pop() {
- //SkASSERT(!fStack.empty());
-
- if (!fStack.empty()) {
- GrClipStackFrame* back = (GrClipStackFrame*) fStack.back();
-
- back->~GrClipStackFrame();
- fStack.pop_back();
- }
- }
-
- int32_t getLastClipGenID() const {
-
- if (fStack.empty()) {
- return SkClipStack::kInvalidGenID;
- }
-
- return ((GrClipStackFrame*) fStack.back())->fLastClipGenID;
- }
-
- GrTexture* getLastMask() {
-
- if (fStack.empty()) {
- SkASSERT(false);
- return nullptr;
- }
-
- GrClipStackFrame* back = (GrClipStackFrame*) fStack.back();
-
- return back->fLastMask;
- }
-
- const GrTexture* getLastMask() const {
-
- if (fStack.empty()) {
- SkASSERT(false);
- return nullptr;
- }
-
- GrClipStackFrame* back = (GrClipStackFrame*) fStack.back();
-
- return back->fLastMask;
- }
-
- void acquireMask(int32_t clipGenID,
- const GrSurfaceDesc& desc,
- const SkIRect& bound) {
-
- if (fStack.empty()) {
- SkASSERT(false);
- return;
- }
-
- GrClipStackFrame* back = (GrClipStackFrame*) fStack.back();
-
- back->acquireMask(fResourceProvider, clipGenID, desc, bound);
- }
-
- int getLastMaskWidth() const {
-
- if (fStack.empty()) {
- SkASSERT(false);
- return -1;
- }
-
- GrClipStackFrame* back = (GrClipStackFrame*) fStack.back();
-
- if (nullptr == back->fLastMask) {
- return -1;
- }
-
- return back->fLastMask->width();
- }
-
- int getLastMaskHeight() const {
-
- if (fStack.empty()) {
- SkASSERT(false);
- return -1;
- }
-
- GrClipStackFrame* back = (GrClipStackFrame*) fStack.back();
-
- if (nullptr == back->fLastMask) {
- return -1;
- }
-
- return back->fLastMask->height();
- }
-
- void getLastBound(SkIRect* bound) const {
-
- if (fStack.empty()) {
- SkASSERT(false);
- bound->setEmpty();
- return;
- }
-
- GrClipStackFrame* back = (GrClipStackFrame*) fStack.back();
-
- *bound = back->fLastBound;
- }
-
- // 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 != nullptr;
- frame = (GrClipStackFrame*) iter.next()) {
- frame->reset();
- }
- }
-
-private:
- struct GrClipStackFrame {
-
- GrClipStackFrame() {
- this->reset();
- }
-
- void acquireMask(GrResourceProvider* resourceProvider,
- int32_t clipGenID,
- const GrSurfaceDesc& desc,
- const SkIRect& bound) {
-
- fLastClipGenID = clipGenID;
-
- // TODO: Determine if we really need the NoPendingIO flag anymore.
- // (http://skbug.com/4156)
- static const uint32_t kFlags = GrResourceProvider::kNoPendingIO_Flag;
- fLastMask.reset(resourceProvider->createApproxTexture(desc, kFlags));
-
- fLastBound = bound;
- }
-
- void reset () {
- fLastClipGenID = SkClipStack::kInvalidGenID;
-
- GrSurfaceDesc desc;
-
- fLastMask.reset(nullptr);
- fLastBound.setEmpty();
- }
-
- 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. TODO: This should be a cache key
- // and not a hard ref to a texture.
- SkAutoTUnref<GrTexture> 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.
- SkIRect fLastBound;
- };
-
- SkDeque fStack;
- GrResourceProvider* fResourceProvider;
-
- typedef SkNoncopyable INHERITED;
-};
-
-#endif // GrClipMaskCache_DEFINED
diff --git a/src/gpu/GrClipMaskManager.cpp b/src/gpu/GrClipMaskManager.cpp
index 0df74a6..1ddcef1 100644
--- a/src/gpu/GrClipMaskManager.cpp
+++ b/src/gpu/GrClipMaskManager.cpp
@@ -9,10 +9,12 @@
#include "GrCaps.h"
#include "GrDrawContext.h"
#include "GrDrawTarget.h"
+#include "GrGpuResourcePriv.h"
#include "GrPaint.h"
#include "GrPathRenderer.h"
#include "GrRenderTarget.h"
#include "GrRenderTargetPriv.h"
+#include "GrResourceProvider.h"
#include "GrStencilAttachment.h"
#include "GrSWMaskHelper.h"
#include "SkRasterClip.h"
@@ -78,7 +80,6 @@
GrClipMaskManager::GrClipMaskManager(GrDrawTarget* drawTarget)
: fCurrClipMaskType(kNone_ClipMaskType)
- , fAACache(drawTarget->cmmAccess().resourceProvider())
, fDrawTarget(drawTarget)
, fClipMode(kIgnoreClip_StencilClipMode) {
}
@@ -344,13 +345,6 @@
// if alpha clip mask creation fails fall through to the non-AA code paths
}
- // Either a hard (stencil buffer) clip was explicitly requested or an anti-aliased clip couldn't
- // be created. In either case, free up the texture in the anti-aliased mask cache.
- // TODO: this may require more investigation. Ganesh performs a lot of utility draws (e.g.,
- // clears, GrBufferedDrawTarget playbacks) that hit the stencil buffer path. These may be
- // "incorrectly" clearing the AA cache.
- fAACache.reset();
-
// use the stencil clip if we can't represent the clip as a rectangle.
SkIPoint clipSpaceToStencilSpaceOffset = -clip.origin();
this->createStencilClipMask(rt,
@@ -516,62 +510,55 @@
}
////////////////////////////////////////////////////////////////////////////////
-// Return the texture currently in the cache if it exists. Otherwise, return nullptr
-GrTexture* GrClipMaskManager::getCachedMaskTexture(int32_t elementsGenID,
- const SkIRect& clipSpaceIBounds) {
- bool cached = fAACache.canReuse(elementsGenID, clipSpaceIBounds);
- if (!cached) {
+// Create a 8-bit clip mask in alpha
+
+static void GetClipMaskKey(int32_t clipGenID, const SkIRect& bounds, GrUniqueKey* key) {
+ static const GrUniqueKey::Domain kDomain = GrUniqueKey::GenerateDomain();
+ GrUniqueKey::Builder builder(key, kDomain, 3);
+ builder[0] = clipGenID;
+ builder[1] = SkToU16(bounds.fLeft) | (SkToU16(bounds.fRight) << 16);
+ builder[2] = SkToU16(bounds.fTop) | (SkToU16(bounds.fBottom) << 16);
+}
+
+GrTexture* GrClipMaskManager::createCachedMask(int width, int height, const GrUniqueKey& key,
+ bool renderTarget) {
+ GrSurfaceDesc desc;
+ desc.fWidth = width;
+ desc.fHeight = height;
+ desc.fFlags = renderTarget ? kRenderTarget_GrSurfaceFlag : kNone_GrSurfaceFlags;
+ if (!renderTarget || fDrawTarget->caps()->isConfigRenderable(kAlpha_8_GrPixelConfig, false)) {
+ desc.fConfig = kAlpha_8_GrPixelConfig;
+ } else {
+ desc.fConfig = kRGBA_8888_GrPixelConfig;
+ }
+
+ GrTexture* texture = fDrawTarget->cmmAccess().resourceProvider()->createApproxTexture(desc, 0);
+ if (!texture) {
return nullptr;
}
-
- return fAACache.getLastMask();
+ texture->resourcePriv().setUniqueKey(key);
+ return texture;
}
-////////////////////////////////////////////////////////////////////////////////
-// Allocate a texture in the texture cache. This function returns the texture
-// allocated (or nullptr on error).
-GrTexture* GrClipMaskManager::allocMaskTexture(int32_t elementsGenID,
- const SkIRect& clipSpaceIBounds,
- bool willUpload) {
- // Since we are setting up the cache we should free up the
- // currently cached mask so it can be reused.
- fAACache.reset();
-
- GrSurfaceDesc desc;
- desc.fFlags = willUpload ? kNone_GrSurfaceFlags : kRenderTarget_GrSurfaceFlag;
- desc.fWidth = clipSpaceIBounds.width();
- desc.fHeight = clipSpaceIBounds.height();
- desc.fConfig = kRGBA_8888_GrPixelConfig;
- if (willUpload ||
- this->getContext()->caps()->isConfigRenderable(kAlpha_8_GrPixelConfig, false)) {
- // We would always like A8 but it isn't supported on all platforms
- desc.fConfig = kAlpha_8_GrPixelConfig;
- }
-
- fAACache.acquireMask(elementsGenID, desc, clipSpaceIBounds);
- return fAACache.getLastMask();
-}
-
-////////////////////////////////////////////////////////////////////////////////
-// Create a 8-bit clip mask in alpha
GrTexture* GrClipMaskManager::createAlphaClipMask(int32_t elementsGenID,
GrReducedClip::InitialState initialState,
const GrReducedClip::ElementList& elements,
const SkVector& clipToMaskOffset,
const SkIRect& clipSpaceIBounds) {
SkASSERT(kNone_ClipMaskType == fCurrClipMaskType);
-
- // First, check for cached texture
- GrTexture* result = this->getCachedMaskTexture(elementsGenID, clipSpaceIBounds);
- if (result) {
+ GrResourceProvider* resourceProvider = fDrawTarget->cmmAccess().resourceProvider();
+ GrUniqueKey key;
+ GetClipMaskKey(elementsGenID, clipSpaceIBounds, &key);
+ if (GrTexture* texture = resourceProvider->findAndRefTextureByUniqueKey(key)) {
fCurrClipMaskType = kAlpha_ClipMaskType;
- return result;
+ return texture;
}
+ SkAutoTUnref<GrTexture> texture(this->createCachedMask(
+ clipSpaceIBounds.width(), clipSpaceIBounds.height(), key, true));
+
// There's no texture in the cache. Let's try to allocate it then.
- result = this->allocMaskTexture(elementsGenID, clipSpaceIBounds, false);
- if (nullptr == result) {
- fAACache.reset();
+ if (!texture) {
return nullptr;
}
@@ -589,7 +576,7 @@
fDrawTarget->clear(&maskSpaceIBounds,
GrReducedClip::kAllIn_InitialState == initialState ? 0xffffffff : 0x00000000,
true,
- result->asRenderTarget());
+ texture->asRenderTarget());
// When we use the stencil in the below loop it is important to have this clip installed.
// The second pass that zeros the stencil buffer renders the rect maskSpaceIBounds so the first
@@ -608,7 +595,7 @@
pipelineBuilder.setClip(clip);
GrPathRenderer* pr = nullptr;
- bool useTemp = !this->canStencilAndDrawElement(&pipelineBuilder, result, &pr, element);
+ bool useTemp = !this->canStencilAndDrawElement(&pipelineBuilder, texture, &pr, element);
GrTexture* dst;
// This is the bounds of the clip element in the space of the alpha-mask. The temporary
// mask buffer can be substantially larger than the actually clip stack element. We
@@ -629,7 +616,7 @@
temp.reset(this->createTempMask(maskSpaceIBounds.fRight,
maskSpaceIBounds.fBottom));
if (!temp) {
- fAACache.reset();
+ texture->resourcePriv().removeUniqueKey();
return nullptr;
}
}
@@ -643,7 +630,7 @@
} else {
// draw directly into the result with the stencil set to make the pixels affected
// by the clip shape be non-zero.
- dst = result;
+ dst = texture;
GR_STATIC_CONST_SAME_STENCIL(kStencilInElement,
kReplace_StencilOp,
kReplace_StencilOp,
@@ -656,25 +643,25 @@
}
if (!this->drawElement(&pipelineBuilder, translate, dst, element, pr)) {
- fAACache.reset();
+ texture->resourcePriv().removeUniqueKey();
return nullptr;
}
if (useTemp) {
GrPipelineBuilder backgroundPipelineBuilder;
- backgroundPipelineBuilder.setRenderTarget(result->asRenderTarget());
+ backgroundPipelineBuilder.setRenderTarget(texture->asRenderTarget());
// Now draw into the accumulator using the real operation and the temp buffer as a
// texture
this->mergeMask(&backgroundPipelineBuilder,
- result,
+ texture,
temp,
op,
maskSpaceIBounds,
maskSpaceElementIBounds);
} else {
GrPipelineBuilder backgroundPipelineBuilder;
- backgroundPipelineBuilder.setRenderTarget(result->asRenderTarget());
+ backgroundPipelineBuilder.setRenderTarget(texture->asRenderTarget());
set_coverage_drawing_xpf(op, !invert, &backgroundPipelineBuilder);
// Draw to the exterior pixels (those with a zero stencil value).
@@ -697,12 +684,12 @@
// all the remaining ops can just be directly draw into the accumulation buffer
set_coverage_drawing_xpf(op, false, &pipelineBuilder);
// The color passed in here does not matter since the coverageSetOpXP won't read it.
- this->drawElement(&pipelineBuilder, translate, result, element);
+ this->drawElement(&pipelineBuilder, translate, texture, element);
}
}
fCurrClipMaskType = kAlpha_ClipMaskType;
- return result;
+ return texture.detach();
}
////////////////////////////////////////////////////////////////////////////////
@@ -1079,10 +1066,11 @@
const SkVector& clipToMaskOffset,
const SkIRect& clipSpaceIBounds) {
SkASSERT(kNone_ClipMaskType == fCurrClipMaskType);
-
- GrTexture* result = this->getCachedMaskTexture(elementsGenID, clipSpaceIBounds);
- if (result) {
- return result;
+ GrUniqueKey key;
+ GetClipMaskKey(elementsGenID, clipSpaceIBounds, &key);
+ GrResourceProvider* resourceProvider = fDrawTarget->cmmAccess().resourceProvider();
+ if (GrTexture* texture = resourceProvider->findAndRefTextureByUniqueKey(key)) {
+ return texture;
}
// The mask texture may be larger than necessary. We round out the clip space bounds and pin
@@ -1133,9 +1121,9 @@
}
// Allocate clip mask texture
- result = this->allocMaskTexture(elementsGenID, clipSpaceIBounds, true);
+ GrTexture* result = this->createCachedMask(clipSpaceIBounds.width(), clipSpaceIBounds.height(),
+ key, false);
if (nullptr == result) {
- fAACache.reset();
return nullptr;
}
helper.toTexture(result);
@@ -1145,9 +1133,6 @@
}
////////////////////////////////////////////////////////////////////////////////
-void GrClipMaskManager::purgeResources() {
- fAACache.purgeResources();
-}
void GrClipMaskManager::adjustPathStencilParams(const GrStencilAttachment* stencilAttachment,
GrStencilSettings* settings) {
diff --git a/src/gpu/GrClipMaskManager.h b/src/gpu/GrClipMaskManager.h
index 26afd2c..0c0c10c 100644
--- a/src/gpu/GrClipMaskManager.h
+++ b/src/gpu/GrClipMaskManager.h
@@ -7,7 +7,6 @@
#ifndef GrClipMaskManager_DEFINED
#define GrClipMaskManager_DEFINED
-#include "GrClipMaskCache.h"
#include "GrPipelineBuilder.h"
#include "GrReducedClip.h"
#include "GrStencil.h"
@@ -49,12 +48,6 @@
GrScissorState*,
const SkRect* devBounds);
- /**
- * Purge resources to free up memory. TODO: This class shouldn't hold any long lived refs
- * which will allow GrResourceCache to automatically purge anything this class has created.
- */
- void purgeResources();
-
bool isClipInStencil() const {
return kStencil_ClipMaskType == fCurrClipMaskType;
}
@@ -113,17 +106,7 @@
const SkVector& clipToMaskOffset,
const SkIRect& clipSpaceIBounds);
- // Returns the cached mask texture if it matches the elementsGenID and the clipSpaceIBounds.
- // Returns nullptr if not found.
- GrTexture* getCachedMaskTexture(int32_t elementsGenID, const SkIRect& clipSpaceIBounds);
-
- // Handles allocation (if needed) of a clip alpha-mask texture for both the sw-upload
- // or gpu-rendered cases.
- GrTexture* allocMaskTexture(int32_t elementsGenID,
- const SkIRect& clipSpaceIBounds,
- bool willUpload);
-
- bool useSWOnlyPath(const GrPipelineBuilder&,
+ bool useSWOnlyPath(const GrPipelineBuilder&,
const SkVector& clipToMaskOffset,
const GrReducedClip::ElementList& elements);
@@ -153,8 +136,6 @@
GrTexture* createTempMask(int width, int height);
- void setupCache(const SkClipStack& clip,
- const SkIRect& bounds);
/**
* Called prior to return control back the GrGpu in setupClipping. It updates the
* GrPipelineBuilder with stencil settings that account for stencil-based clipping.
@@ -170,6 +151,8 @@
StencilClipMode mode,
int stencilBitCnt);
+ GrTexture* createCachedMask(int width, int height, const GrUniqueKey& key, bool renderTarget);
+
/**
* We may represent the clip as a mask in the stencil buffer or as an alpha
* texture. It may be neither because the scissor rect suffices or we
@@ -181,7 +164,6 @@
kAlpha_ClipMaskType,
} fCurrClipMaskType;
- GrClipMaskCache fAACache; // cache for the AA path
GrDrawTarget* fDrawTarget; // This is our owning draw target.
StencilClipMode fClipMode;
diff --git a/src/gpu/GrContext.cpp b/src/gpu/GrContext.cpp
index 4d6b6b8..065d61b 100644
--- a/src/gpu/GrContext.cpp
+++ b/src/gpu/GrContext.cpp
@@ -87,12 +87,6 @@
}
}
-void GrContext::DrawingMgr::purgeResources() {
- if (fDrawTarget) {
- fDrawTarget->purgeResources();
- }
-}
-
void GrContext::DrawingMgr::reset() {
if (fDrawTarget) {
fDrawTarget->reset();
@@ -243,8 +237,6 @@
void GrContext::freeGpuResources() {
this->flush();
- fDrawingMgr.purgeResources();
-
fBatchFontCache->freeAll();
fLayerCache->freeAll();
// a path renderer may be holding onto resources
diff --git a/src/gpu/GrDrawContext.cpp b/src/gpu/GrDrawContext.cpp
index 1969bd0..0a63eb8 100644
--- a/src/gpu/GrDrawContext.cpp
+++ b/src/gpu/GrDrawContext.cpp
@@ -14,6 +14,7 @@
#include "GrPathRenderer.h"
#include "GrRenderTarget.h"
#include "GrRenderTargetPriv.h"
+#include "GrResourceProvider.h"
#include "GrStencilAndCoverTextContext.h"
#include "batches/GrBatch.h"
diff --git a/src/gpu/GrDrawTarget.h b/src/gpu/GrDrawTarget.h
index b12ac99..3c28b1e 100644
--- a/src/gpu/GrDrawTarget.h
+++ b/src/gpu/GrDrawTarget.h
@@ -20,6 +20,8 @@
#include "GrVertexBuffer.h"
#include "GrXferProcessor.h"
+#include "batches/GrDrawBatch.h"
+
#include "SkClipStack.h"
#include "SkMatrix.h"
#include "SkPath.h"
@@ -34,7 +36,6 @@
class GrClip;
class GrCaps;
class GrPath;
-class GrDrawBatch;
class GrDrawPathBatchBase;
class GrPathRangeDraw;
@@ -170,15 +171,6 @@
GrSurface* src,
const SkIRect& srcRect,
const SkIPoint& dstPoint);
- /**
- * Release any resources that are cached but not currently in use. This
- * is intended to give an application some recourse when resources are low.
- * TODO: Stop holding on to resources.
- */
- virtual void purgeResources() {
- // The clip mask manager can rebuild all its clip masks so just get rid of them all.
- fClipMaskManager->purgeResources();
- };
bool programUnitTest(GrContext* owner, int maxStages);
diff --git a/src/gpu/GrResourceProvider.h b/src/gpu/GrResourceProvider.h
index 33a9f3b..a709c70 100644
--- a/src/gpu/GrResourceProvider.h
+++ b/src/gpu/GrResourceProvider.h
@@ -90,6 +90,7 @@
using GrTextureProvider::assignUniqueKeyToResource;
using GrTextureProvider::findAndRefResourceByUniqueKey;
+ using GrTextureProvider::findAndRefTextureByUniqueKey;
using GrTextureProvider::abandon;
enum Flags {
@@ -142,6 +143,8 @@
*/
GrStencilAttachment* attachStencilAttachment(GrRenderTarget* rt);
+ const GrCaps* caps() { return this->gpu()->caps(); }
+
private:
const GrIndexBuffer* createInstancedIndexBuffer(const uint16_t* pattern,
int patternSize,
diff --git a/tests/ClipBoundsTest.cpp b/tests/ClipBoundsTest.cpp
new file mode 100644
index 0000000..781ee87
--- /dev/null
+++ b/tests/ClipBoundsTest.cpp
@@ -0,0 +1,85 @@
+
+/*
+ * Copyright 2015 Google Inc.
+ *
+ * Use of this source code is governed by a BSD-style license that can be
+ * found in the LICENSE file.
+ */
+
+#include "Test.h"
+// This is a GR test
+#if SK_SUPPORT_GPU
+#include "GrClipMaskManager.h"
+#include "GrContextFactory.h"
+#include "SkGpuDevice.h"
+
+// Ensure that the 'getConservativeBounds' calls are returning bounds clamped
+// to the render target
+static void test_clip_bounds(skiatest::Reporter* reporter, GrContext* context) {
+
+ static const int kXSize = 100;
+ static const int kYSize = 100;
+
+ GrSurfaceDesc desc;
+ desc.fFlags = kRenderTarget_GrSurfaceFlag;
+ desc.fConfig = kAlpha_8_GrPixelConfig;
+ desc.fWidth = kXSize;
+ desc.fHeight = kYSize;
+
+ SkAutoTUnref<GrTexture> texture(
+ context->textureProvider()->createTexture(desc, false, nullptr, 0));
+ if (!texture) {
+ return;
+ }
+
+ SkIRect intScreen = SkIRect::MakeWH(kXSize, kYSize);
+ SkRect screen = SkRect::Make(intScreen);
+
+ SkRect clipRect(screen);
+ clipRect.outset(10, 10);
+
+ // create a clip stack that will (trivially) reduce to a single rect that
+ // is larger than the screen
+ SkClipStack stack;
+ stack.clipDevRect(clipRect, SkRegion::kReplace_Op, false);
+
+ bool isIntersectionOfRects = true;
+ SkRect devStackBounds;
+
+ stack.getConservativeBounds(0, 0, kXSize, kYSize,
+ &devStackBounds,
+ &isIntersectionOfRects);
+
+ // make sure that the SkClipStack is behaving itself
+ REPORTER_ASSERT(reporter, screen == devStackBounds);
+ REPORTER_ASSERT(reporter, isIntersectionOfRects);
+
+ // wrap the SkClipStack in a GrClip
+ GrClip clipData;
+ clipData.setClipStack(&stack);
+
+ SkIRect devGrClipBound;
+ clipData.getConservativeBounds(texture,
+ &devGrClipBound,
+ &isIntersectionOfRects);
+
+ // make sure that GrClip is behaving itself
+ REPORTER_ASSERT(reporter, intScreen == devGrClipBound);
+ REPORTER_ASSERT(reporter, isIntersectionOfRects);
+}
+
+DEF_GPUTEST(GrClipBounds, reporter, factory) {
+ for (int type = 0; type < GrContextFactory::kLastGLContextType; ++type) {
+ GrContextFactory::GLContextType glType = static_cast<GrContextFactory::GLContextType>(type);
+ if (!GrContextFactory::IsRenderingGLContext(glType)) {
+ continue;
+ }
+ GrContext* context = factory->get(glType);
+ if (nullptr == context) {
+ continue;
+ }
+ test_clip_bounds(reporter, context);
+ }
+}
+
+#endif
diff --git a/tests/ClipCacheTest.cpp b/tests/ClipCacheTest.cpp
deleted file mode 100644
index c57fb37..0000000
--- a/tests/ClipCacheTest.cpp
+++ /dev/null
@@ -1,231 +0,0 @@
-/*
- * Copyright 2012 Google Inc.
- *
- * Use of this source code is governed by a BSD-style license that can be
- * found in the LICENSE file.
- */
-
-#include "Test.h"
-// This is a GR test
-#if SK_SUPPORT_GPU
-#include "GrClipMaskManager.h"
-#include "GrContextFactory.h"
-#include "SkGpuDevice.h"
-
-static const int X_SIZE = 12;
-static const int Y_SIZE = 12;
-
-////////////////////////////////////////////////////////////////////////////////
-// note: this is unused
-static GrTexture* create_texture(GrContext* context) {
- unsigned char textureData[X_SIZE][Y_SIZE][4];
-
- memset(textureData, 0, 4* X_SIZE * Y_SIZE);
-
- GrSurfaceDesc desc;
-
- // let Skia know we will be using this texture as a render target
- desc.fFlags = kRenderTarget_GrSurfaceFlag;
- desc.fConfig = kSkia8888_GrPixelConfig;
- desc.fWidth = X_SIZE;
- desc.fHeight = Y_SIZE;
-
- // We are initializing the texture with zeros here
- GrTexture* texture = context->textureProvider()->createTexture(desc, false, textureData, 0);
- if (!texture) {
- return nullptr;
- }
-
- return texture;
-}
-
-// Ensure that the 'getConservativeBounds' calls are returning bounds clamped
-// to the render target
-static void test_clip_bounds(skiatest::Reporter* reporter, GrContext* context) {
-
- static const int kXSize = 100;
- static const int kYSize = 100;
-
- GrSurfaceDesc desc;
- desc.fFlags = kRenderTarget_GrSurfaceFlag;
- desc.fConfig = kAlpha_8_GrPixelConfig;
- desc.fWidth = kXSize;
- desc.fHeight = kYSize;
-
- GrTexture* texture = context->textureProvider()->createTexture(desc, false, nullptr, 0);
- if (!texture) {
- return;
- }
-
- SkAutoTUnref<GrTexture> au(texture);
-
- SkIRect intScreen = SkIRect::MakeWH(kXSize, kYSize);
- SkRect screen;
-
- screen = SkRect::MakeWH(SkIntToScalar(kXSize),
- SkIntToScalar(kYSize));
-
- SkRect clipRect(screen);
- clipRect.outset(10, 10);
-
- // create a clip stack that will (trivially) reduce to a single rect that
- // is larger than the screen
- SkClipStack stack;
- stack.clipDevRect(clipRect, SkRegion::kReplace_Op, false);
-
- bool isIntersectionOfRects = true;
- SkRect devStackBounds;
-
- stack.getConservativeBounds(0, 0, kXSize, kYSize,
- &devStackBounds,
- &isIntersectionOfRects);
-
- // make sure that the SkClipStack is behaving itself
- REPORTER_ASSERT(reporter, screen == devStackBounds);
- REPORTER_ASSERT(reporter, isIntersectionOfRects);
-
- // wrap the SkClipStack in a GrClip
- GrClip clipData;
- clipData.setClipStack(&stack);
-
- SkIRect devGrClipBound;
- clipData.getConservativeBounds(texture,
- &devGrClipBound,
- &isIntersectionOfRects);
-
- // make sure that GrClip is behaving itself
- REPORTER_ASSERT(reporter, intScreen == devGrClipBound);
- REPORTER_ASSERT(reporter, isIntersectionOfRects);
-}
-
-////////////////////////////////////////////////////////////////////////////////
-// verify that the top state of the stack matches the passed in state
-static void check_state(skiatest::Reporter* reporter,
- const GrClipMaskCache& cache,
- const SkClipStack& clip,
- GrTexture* mask,
- const SkIRect& bound) {
- REPORTER_ASSERT(reporter, clip.getTopmostGenID() == cache.getLastClipGenID());
-
- REPORTER_ASSERT(reporter, mask == cache.getLastMask());
-
- SkIRect cacheBound;
- cache.getLastBound(&cacheBound);
- REPORTER_ASSERT(reporter, bound == cacheBound);
-}
-
-static void check_empty_state(skiatest::Reporter* reporter,
- const GrClipMaskCache& cache) {
- REPORTER_ASSERT(reporter, SkClipStack::kInvalidGenID == cache.getLastClipGenID());
- REPORTER_ASSERT(reporter, nullptr == cache.getLastMask());
-
- SkIRect emptyBound;
- emptyBound.setEmpty();
-
- SkIRect cacheBound;
- cache.getLastBound(&cacheBound);
- REPORTER_ASSERT(reporter, emptyBound == cacheBound);
-}
-
-////////////////////////////////////////////////////////////////////////////////
-// basic test of the cache's base functionality:
-// push, pop, set, canReuse & getters
-static void test_cache(skiatest::Reporter* reporter, GrContext* context) {
-
- if (false) { // avoid bit rot, suppress warning
- create_texture(context);
- }
- GrClipMaskCache cache(context->resourceProvider());
-
- // check initial state
- check_empty_state(reporter, cache);
-
- // set the current state
- SkIRect bound1;
- bound1.set(0, 0, 100, 100);
-
- SkClipStack clip1(bound1);
-
- GrSurfaceDesc desc;
- desc.fFlags = kRenderTarget_GrSurfaceFlag;
- desc.fWidth = X_SIZE;
- desc.fHeight = Y_SIZE;
- desc.fConfig = kSkia8888_GrPixelConfig;
-
- cache.acquireMask(clip1.getTopmostGenID(), desc, bound1);
-
- GrTexture* texture1 = cache.getLastMask();
- REPORTER_ASSERT(reporter, texture1);
- if (nullptr == texture1) {
- return;
- }
-
- // check that the set took
- check_state(reporter, cache, clip1, texture1, bound1);
-
- // push the state
- cache.push();
-
- // verify that the pushed state is initially empty
- check_empty_state(reporter, cache);
-
- // modify the new state
- SkIRect bound2;
- bound2.set(-10, -10, 10, 10);
-
- SkClipStack clip2(bound2);
-
- cache.acquireMask(clip2.getTopmostGenID(), desc, bound2);
-
- GrTexture* texture2 = cache.getLastMask();
- REPORTER_ASSERT(reporter, texture2);
- if (nullptr == texture2) {
- return;
- }
-
- // check that the changes took
- check_state(reporter, cache, clip2, texture2, bound2);
-
- // check to make sure canReuse works
- REPORTER_ASSERT(reporter, cache.canReuse(clip2.getTopmostGenID(), bound2));
- REPORTER_ASSERT(reporter, !cache.canReuse(clip1.getTopmostGenID(), bound1));
-
- // pop the state
- cache.pop();
-
- // verify that the old state is restored
- check_state(reporter, cache, clip1, texture1, bound1);
-
- // manually clear the state
- cache.reset();
-
- // verify it is now empty
- check_empty_state(reporter, cache);
-
- // pop again - so there is no state
- cache.pop();
-
-#if !defined(SK_DEBUG)
- // verify that the getters don't crash
- // only do in release since it generates asserts in debug
- check_empty_state(reporter, cache);
-#endif
-}
-
-DEF_GPUTEST(ClipCache, reporter, factory) {
- for (int type = 0; type < GrContextFactory::kLastGLContextType; ++type) {
- GrContextFactory::GLContextType glType = static_cast<GrContextFactory::GLContextType>(type);
- if (!GrContextFactory::IsRenderingGLContext(glType)) {
- continue;
- }
- GrContext* context = factory->get(glType);
- if (nullptr == context) {
- continue;
- }
-
- test_cache(reporter, context);
- test_clip_bounds(reporter, context);
- }
-}
-
-#endif
diff --git a/tests/ResourceCacheTest.cpp b/tests/ResourceCacheTest.cpp
index 0036f83..83e4535 100644
--- a/tests/ResourceCacheTest.cpp
+++ b/tests/ResourceCacheTest.cpp
@@ -18,6 +18,7 @@
#include "GrRenderTarget.h"
#include "GrRenderTargetPriv.h"
#include "GrResourceCache.h"
+#include "GrResourceProvider.h"
#include "GrTest.h"
#include "SkCanvas.h"
#include "SkGr.h"