Convert AAClipCache's GrRects to GrIRects

http://codereview.appspot.com/6210057/



git-svn-id: http://skia.googlecode.com/svn/trunk@3942 2bbb7eff-a529-9590-31e7-b0007b416f81
This commit is contained in:
robertphillips@google.com 2012-05-15 16:47:23 +00:00
parent 921374d4cc
commit 6623fcd1ee
4 changed files with 69 additions and 50 deletions

View File

@ -144,7 +144,7 @@ struct SK_API SkIRect {
/** Inset the rectangle by (dx,dy). If dx is positive, then the sides are moved inwards,
making the rectangle narrower. If dx is negative, then the sides are moved outwards,
making the rectangle wider. The same hods true for dy and the top and bottom.
making the rectangle wider. The same holds true for dy and the top and bottom.
*/
void inset(int32_t dx, int32_t dy) {
fLeft += dx;
@ -153,6 +153,13 @@ struct SK_API SkIRect {
fBottom -= dy;
}
/** Outset the rectangle by (dx,dy). If dx is positive, then the sides are
moved outwards, making the rectangle wider. If dx is negative, then the
sides are moved inwards, making the rectangle narrower. The same holds
true for dy and the top and bottom.
*/
void outset(int32_t dx, int32_t dy) { this->inset(-dx, -dy); }
bool quickReject(int l, int t, int r, int b) const {
return l >= fRight || fLeft >= r || t >= fBottom || fTop >= b;
}
@ -481,7 +488,7 @@ struct SK_API SkRect {
/** Outset the rectangle by (dx,dy). If dx is positive, then the sides are
moved outwards, making the rectangle wider. If dx is negative, then the
sides are moved inwards, making the rectangle narrower. The same hods
sides are moved inwards, making the rectangle narrower. The same holds
true for dy and the top and bottom.
*/
void outset(SkScalar dx, SkScalar dy) { this->inset(-dx, -dy); }

View File

@ -32,7 +32,7 @@ namespace {
// sampler matrix this also alters the vertex layout
void setup_drawstate_aaclip(GrGpu* gpu,
GrTexture* result,
const GrRect &bound) {
const GrIRect &bound) {
GrDrawState* drawState = gpu->drawState();
GrAssert(drawState);
@ -40,7 +40,7 @@ void setup_drawstate_aaclip(GrGpu* gpu,
GrMatrix mat;
mat.setIDiv(result->width(), result->height());
mat.preTranslate(-bound.fLeft, -bound.fTop);
mat.preTranslate(SkIntToScalar(-bound.fLeft), SkIntToScalar(-bound.fTop));
mat.preConcat(drawState->getViewMatrix());
drawState->sampler(maskStage)->reset(GrSamplerState::kClamp_WrapMode,
@ -89,7 +89,7 @@ bool GrClipMaskManager::createClipMask(GrGpu* gpu,
// The clip geometry is complex enough that it will be more
// efficient to create it entirely in software
GrTexture* result = NULL;
GrRect bound;
GrIRect bound;
if (this->createSoftwareClipMask(gpu, clipIn, &result, &bound)) {
fClipMaskInAlpha = true;
@ -108,7 +108,7 @@ bool GrClipMaskManager::createClipMask(GrGpu* gpu,
// render target) we aren't going to use scissoring like the stencil
// path does (see scissorSettings below)
GrTexture* result = NULL;
GrRect bound;
GrIRect bound;
if (this->createAlphaClipMask(gpu, clipIn, &result, &bound)) {
fClipMaskInAlpha = true;
@ -165,12 +165,25 @@ bool GrClipMaskManager::createClipMask(GrGpu* gpu,
#endif
namespace {
/**
* Does "container" contain "containee"? If either is empty then
* no containment is possible.
*/
bool contains(const SkRect& container, const SkIRect& containee) {
return !containee.isEmpty() && !container.isEmpty() &&
container.fLeft <= SkIntToScalar(containee.fLeft) &&
container.fTop <= SkIntToScalar(containee.fTop) &&
container.fRight >= SkIntToScalar(containee.fRight) &&
container.fBottom >= SkIntToScalar(containee.fBottom);
}
////////////////////////////////////////////////////////////////////////////////
// determines how many elements at the head of the clip can be skipped and
// whether the initial clear should be to the inside- or outside-the-clip value,
// and what op should be used to draw the first element that isn't skipped.
int process_initial_clip_elements(const GrClip& clip,
const GrRect& bounds,
const GrIRect& bounds,
bool* clearToInside,
SkRegion::Op* startOp) {
@ -196,7 +209,7 @@ int process_initial_clip_elements(const GrClip& clip,
// if this element contains the entire bounds then we
// can skip it.
if (kRect_ClipType == clip.getElementType(curr)
&& clip.getRect(curr).contains(bounds)) {
&& contains(clip.getRect(curr), bounds)) {
break;
}
// if everything is initially clearToInside then intersect is
@ -378,7 +391,7 @@ void clear(GrGpu* gpu,
// 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 GrClipMaskManager::getTemp(const GrRect& bounds,
void GrClipMaskManager::getTemp(const GrIRect& bounds,
GrAutoScratchTexture* temp) {
if (NULL != temp->texture()) {
// we've already allocated the temp texture
@ -387,8 +400,8 @@ void GrClipMaskManager::getTemp(const GrRect& bounds,
const GrTextureDesc desc = {
kRenderTarget_GrTextureFlagBit|kNoStencil_GrTextureFlagBit,
SkScalarCeilToInt(bounds.width()),
SkScalarCeilToInt(bounds.height()),
bounds.width(),
bounds.height(),
kAlpha_8_GrPixelConfig,
0 // samples
};
@ -398,15 +411,15 @@ void GrClipMaskManager::getTemp(const GrRect& bounds,
void GrClipMaskManager::setupCache(const GrClip& clipIn,
const GrRect& bounds) {
const GrIRect& 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()),
bounds.width(),
bounds.height(),
kAlpha_8_GrPixelConfig,
0 // samples
};
@ -422,7 +435,7 @@ void GrClipMaskManager::setupCache(const GrClip& clipIn,
bool GrClipMaskManager::clipMaskPreamble(GrGpu* gpu,
const GrClip& clipIn,
GrTexture** result,
GrRect *resultBounds) {
GrIRect *resultBounds) {
GrDrawState* origDrawState = gpu->drawState();
GrAssert(origDrawState->isClipState());
@ -449,28 +462,26 @@ bool GrClipMaskManager::clipMaskPreamble(GrGpu* gpu,
bounds = rtRect;
}
bounds.roundOut();
GrIRect intBounds;
bounds.roundOut(&intBounds);
// need to outset a pixel since the standard bounding box computation
// path doesn't leave any room for antialiasing (esp. w.r.t. rects)
bounds.outset(SkIntToScalar(1), SkIntToScalar(1));
intBounds.outset(1, 1);
// TODO: make sure we don't outset if bounds are still 0,0 @ min
GrAssert(SkScalarIsInt(bounds.width()));
GrAssert(SkScalarIsInt(bounds.height()));
if (fAACache.canReuse(clipIn,
SkScalarCeilToInt(bounds.width()),
SkScalarCeilToInt(bounds.height()))) {
intBounds.width(),
intBounds.height())) {
*result = fAACache.getLastMask();
fAACache.getLastBound(resultBounds);
return true;
}
this->setupCache(clipIn, bounds);
this->setupCache(clipIn, intBounds);
*resultBounds = bounds;
*resultBounds = intBounds;
return false;
}
@ -479,7 +490,7 @@ bool GrClipMaskManager::clipMaskPreamble(GrGpu* gpu,
bool GrClipMaskManager::createAlphaClipMask(GrGpu* gpu,
const GrClip& clipIn,
GrTexture** result,
GrRect *resultBounds) {
GrIRect *resultBounds) {
if (this->clipMaskPreamble(gpu, clipIn, result, resultBounds)) {
return true;
@ -504,7 +515,8 @@ bool GrClipMaskManager::createAlphaClipMask(GrGpu* gpu,
// offset the paths & rects that will be used to compute it
GrMatrix m;
m.setTranslate(-resultBounds->fLeft, -resultBounds->fTop);
m.setTranslate(SkIntToScalar(-resultBounds->fLeft),
SkIntToScalar(-resultBounds->fTop));
drawState->setViewMatrix(m);
}
@ -541,7 +553,7 @@ bool GrClipMaskManager::createAlphaClipMask(GrGpu* gpu,
// there is no point in intersecting a screen filling rectangle.
if (SkRegion::kIntersect_Op == op &&
kRect_ClipType == clipIn.getElementType(c) &&
clipIn.getRect(c).contains(*resultBounds)) {
contains(clipIn.getRect(c), *resultBounds)) {
continue;
}
@ -564,7 +576,8 @@ bool GrClipMaskManager::createAlphaClipMask(GrGpu* gpu,
if (0 != resultBounds->fTop || 0 != resultBounds->fLeft) {
GrMatrix m;
m.setTranslate(resultBounds->fLeft, resultBounds->fTop);
m.setTranslate(SkIntToScalar(resultBounds->fLeft),
SkIntToScalar(resultBounds->fTop));
drawState->preConcatViewMatrix(m);
}
@ -577,7 +590,8 @@ bool GrClipMaskManager::createAlphaClipMask(GrGpu* gpu,
if (0 != resultBounds->fTop || 0 != resultBounds->fLeft) {
GrMatrix m;
m.setTranslate(-resultBounds->fLeft, -resultBounds->fTop);
m.setTranslate(SkIntToScalar(-resultBounds->fLeft),
SkIntToScalar(-resultBounds->fTop));
drawState->preConcatViewMatrix(m);
}
@ -643,9 +657,7 @@ bool GrClipMaskManager::createStencilClipMask(GrGpu* gpu,
"Ganesh only handles 16b or smaller stencil buffers");
clipBit = (1 << (clipBit-1));
GrRect rtRect;
rtRect.setLTRB(0, 0,
GrIntToScalar(rt->width()), GrIntToScalar(rt->height()));
GrIRect rtRect = GrIRect::MakeWH(rt->width(), rt->height());
bool clearToInside;
SkRegion::Op startOp = SkRegion::kReplace_Op; // suppress warning
@ -681,7 +693,7 @@ bool GrClipMaskManager::createStencilClipMask(GrGpu* gpu,
// there is no point in intersecting a screen filling
// rectangle.
if (SkRegion::kIntersect_Op == op &&
clipCopy.getRect(c).contains(rtRect)) {
contains(clipCopy.getRect(c), rtRect)) {
continue;
}
} else {
@ -769,7 +781,7 @@ bool GrClipMaskManager::createStencilClipMask(GrGpu* gpu,
bool GrClipMaskManager::createSoftwareClipMask(GrGpu* gpu,
const GrClip& clipIn,
GrTexture** result,
GrRect *resultBounds) {
GrIRect *resultBounds) {
if (this->clipMaskPreamble(gpu, clipIn, result, resultBounds)) {
return true;

View File

@ -151,7 +151,7 @@ public:
void acquireMask(const GrClip& clip,
const GrTextureDesc& desc,
const GrRect& bound) {
const GrIRect& bound) {
if (fStack.empty()) {
GrAssert(false);
@ -195,7 +195,7 @@ public:
return back->fLastMask.texture()->height();
}
void getLastBound(GrRect* bound) const {
void getLastBound(GrIRect* bound) const {
if (fStack.empty()) {
GrAssert(false);
@ -237,7 +237,7 @@ private:
void acquireMask(GrContext* context,
const GrClip& clip,
const GrTextureDesc& desc,
const GrRect& bound) {
const GrIRect& bound) {
fLastClip = clip;
@ -263,7 +263,7 @@ private:
// 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;
GrIRect fLastBound;
};
GrContext* fContext;
@ -322,15 +322,15 @@ private:
bool createAlphaClipMask(GrGpu* gpu,
const GrClip& clipIn,
GrTexture** result,
GrRect *resultBounds);
GrIRect *resultBounds);
bool createSoftwareClipMask(GrGpu* gpu,
const GrClip& clipIn,
GrTexture** result,
GrRect *resultBounds);
GrIRect *resultBounds);
bool clipMaskPreamble(GrGpu* gpu,
const GrClip& clipIn,
GrTexture** result,
GrRect *resultBounds);
GrIRect *resultBounds);
bool drawPath(GrGpu* gpu,
const SkPath& path,
@ -346,10 +346,10 @@ private:
GrTexture* target,
GrTexture* texture);
void getTemp(const GrRect& bounds, GrAutoScratchTexture* temp);
void getTemp(const GrIRect& bounds, GrAutoScratchTexture* temp);
void setupCache(const GrClip& clip,
const GrRect& bounds);
const GrIRect& bounds);
// determines the path renderer used to draw a clip path element.
GrPathRenderer* getClipPathRenderer(GrGpu* gpu,

View File

@ -42,14 +42,14 @@ static void check_state(skiatest::Reporter* reporter,
const GrClipMaskCache& cache,
const GrClip& clip,
GrTexture* mask,
const GrRect& bound) {
const GrIRect& bound) {
GrClip cacheClip;
cache.getLastClip(&cacheClip);
REPORTER_ASSERT(reporter, clip == cacheClip);
REPORTER_ASSERT(reporter, mask == cache.getLastMask());
GrRect cacheBound;
GrIRect cacheBound;
cache.getLastBound(&cacheBound);
REPORTER_ASSERT(reporter, bound == cacheBound);
}
@ -66,18 +66,18 @@ static void test_cache(skiatest::Reporter* reporter, GrContext* context) {
GrClip emptyClip;
emptyClip.setEmpty();
GrRect emptyBound;
GrIRect emptyBound;
emptyBound.setEmpty();
// check initial state
check_state(reporter, cache, emptyClip, NULL, emptyBound);
// set the current state
GrRect bound1;
GrIRect bound1;
bound1.set(0, 0, 100, 100);
GrClip clip1;
clip1.setFromRect(bound1);
clip1.setFromIRect(bound1);
const GrTextureDesc desc = {
kRenderTarget_GrTextureFlagBit,
@ -107,12 +107,12 @@ static void test_cache(skiatest::Reporter* reporter, GrContext* context) {
REPORTER_ASSERT(reporter, 1 == texture1->getRefCnt());
// modify the new state
GrRect bound2;
GrIRect bound2;
bound2.set(-10, -10, 10, 10);
GrClip clip2;
clip2.setEmpty();
clip2.setFromRect(bound2);
clip2.setFromIRect(bound2);
cache.acquireMask(clip2, desc, bound2);