Add support for clipstack to Gr. GrClip is now a list of rects and paths with set operations to combine them. The stencil buffer is used to perform the set operations to put the clip into the stencil buffer. Building Gr's clip from Skia's clipStack is currently disabled due to the fact that Skia's clipStack is relative to the root layer not the current layer. This will be fixed in a subsequent CL.
git-svn-id: http://skia.googlecode.com/svn/trunk@878 2bbb7eff-a529-9590-31e7-b0007b416f81
diff --git a/src/core/SkCanvas.cpp b/src/core/SkCanvas.cpp
index e2d6af4..e636d2b 100644
--- a/src/core/SkCanvas.cpp
+++ b/src/core/SkCanvas.cpp
@@ -264,7 +264,7 @@
}
// fCurrLayer may be NULL now
- fCanvas->prepareForDeviceDraw(fDevice, *fMatrix, *fClip);
+ fCanvas->prepareForDeviceDraw(fDevice, *fMatrix, *fClip, *fClipStack);
return true;
}
return false;
@@ -632,10 +632,11 @@
}
void SkCanvas::prepareForDeviceDraw(SkDevice* device, const SkMatrix& matrix,
- const SkRegion& clip) {
+ const SkRegion& clip,
+ const SkClipStack& clipStack) {
SkASSERT(device);
if (fLastDeviceToGainFocus != device) {
- device->gainFocus(this, matrix, clip);
+ device->gainFocus(this, matrix, clip, clipStack);
fLastDeviceToGainFocus = device;
}
}
diff --git a/src/core/SkClipStack.cpp b/src/core/SkClipStack.cpp
index 2b63aea..864f23a 100644
--- a/src/core/SkClipStack.cpp
+++ b/src/core/SkClipStack.cpp
@@ -116,7 +116,11 @@
///////////////////////////////////////////////////////////////////////////////
-SkClipStack::B2FIter::B2FIter(const SkClipStack& stack) : fIter(stack.fDeque) {
+SkClipStack::B2FIter::B2FIter() {
+}
+
+SkClipStack::B2FIter::B2FIter(const SkClipStack& stack) {
+ this->reset(stack);
}
const SkClipStack::B2FIter::Clip* SkClipStack::B2FIter::next() {
@@ -142,3 +146,7 @@
fClip.fOp = rec->fOp;
return &fClip;
}
+
+void SkClipStack::B2FIter::reset(const SkClipStack& stack) {
+ fIter.reset(stack.fDeque);
+}
diff --git a/src/core/SkDeque.cpp b/src/core/SkDeque.cpp
index 2c6ce64..9d685ee 100644
--- a/src/core/SkDeque.cpp
+++ b/src/core/SkDeque.cpp
@@ -225,12 +225,12 @@
///////////////////////////////////////////////////////////////////////////////
-SkDeque::F2BIter::F2BIter(const SkDeque& d) : fElemSize(d.fElemSize) {
- fHead = d.fFront;
- while (fHead != NULL && fHead->fBegin == NULL) {
- fHead = fHead->fNext;
- }
- fPos = fHead ? fHead->fBegin : NULL;
+SkDeque::F2BIter::F2BIter() {
+ fPos = NULL;
+}
+
+SkDeque::F2BIter::F2BIter(const SkDeque& d) {
+ this->reset(d);
}
void* SkDeque::F2BIter::next() {
@@ -250,3 +250,11 @@
return pos;
}
+void SkDeque::F2BIter::reset(const SkDeque& d) {
+ fElemSize = d.fElemSize;
+ fHead = d.fFront;
+ while (fHead != NULL && fHead->fBegin == NULL) {
+ fHead = fHead->fNext;
+ }
+ fPos = fHead ? fHead->fBegin : NULL;
+}
diff --git a/src/gpu/SkGpuDevice.cpp b/src/gpu/SkGpuDevice.cpp
index 3dfe02a..e925e53 100644
--- a/src/gpu/SkGpuDevice.cpp
+++ b/src/gpu/SkGpuDevice.cpp
@@ -267,19 +267,30 @@
///////////////////////////////////////////////////////////////////////////////
+#define USE_CLIP_STACK 0
+
static void convert_matrixclip(GrContext* context, const SkMatrix& matrix,
- const SkRegion& clip) {
+ const SkClipStack& clipStack,
+ const SkRegion& clipRegion) {
GrMatrix grmat;
SkGr::SkMatrix2GrMatrix(matrix, &grmat);
context->setMatrix(grmat);
+#if USE_CLIP_STACK
SkGrClipIterator iter;
- iter.reset(clip);
- GrClip grc(&iter);
- if (context->getClip() == grc) {
- } else {
- context->setClip(grc);
- }
+ iter.reset(clipStack);
+#else
+ SkGrRegionIterator iter;
+ iter.reset(clipRegion);
+#endif
+ const SkIRect& skBounds = clipRegion.getBounds();
+ GrRect bounds;
+ bounds.setLTRB(GrIntToScalar(skBounds.fLeft),
+ GrIntToScalar(skBounds.fTop),
+ GrIntToScalar(skBounds.fRight),
+ GrIntToScalar(skBounds.fBottom));
+ GrClip grc(&iter, NULL);
+ context->setClip(grc);
}
// call this ever each draw call, to ensure that the context reflects our state,
@@ -289,7 +300,9 @@
fContext->getRenderTarget() != fRenderTarget) {
fContext->setRenderTarget(fRenderTarget);
- convert_matrixclip(fContext, *draw.fMatrix, *draw.fClip);
+ SkASSERT(draw.fClipStack);
+ convert_matrixclip(fContext, *draw.fMatrix,
+ *draw.fClipStack, *draw.fClip);
fNeedPrepareRenderTarget = false;
}
}
@@ -298,16 +311,17 @@
const SkClipStack& clipStack) {
this->INHERITED::setMatrixClip(matrix, clip, clipStack);
- convert_matrixclip(fContext, matrix, clip);
+ convert_matrixclip(fContext, matrix, clipStack, clip);
}
void SkGpuDevice::gainFocus(SkCanvas* canvas, const SkMatrix& matrix,
- const SkRegion& clip) {
+ const SkRegion& clip, const SkClipStack& clipStack) {
+
fContext->setRenderTarget(fRenderTarget);
- this->INHERITED::gainFocus(canvas, matrix, clip);
+ this->INHERITED::gainFocus(canvas, matrix, clip, clipStack);
- convert_matrixclip(fContext, matrix, clip);
+ convert_matrixclip(fContext, matrix, clipStack, clip);
if (fNeedClear) {
fContext->eraseColor(0x0);
diff --git a/src/gpu/SkGr.cpp b/src/gpu/SkGr.cpp
index 41cf1bd..4c7bf6c 100644
--- a/src/gpu/SkGr.cpp
+++ b/src/gpu/SkGr.cpp
@@ -135,22 +135,80 @@
}
void SkGrPathIter::rewind() {
- fIter.setPath(fPath, false);
+ fIter.setPath(*fPath, false);
}
GrPathIter::ConvexHint SkGrPathIter::hint() const {
- return fPath.isConvex() ? GrPathIter::kConvex_ConvexHint :
- GrPathIter::kNone_ConvexHint;
+ return fPath->isConvex() ? GrPathIter::kConvex_ConvexHint :
+ GrPathIter::kNone_ConvexHint;
}
///////////////////////////////////////////////////////////////////////////////
-void SkGrClipIterator::computeBounds(GrIRect* bounds) {
- const SkRegion* rgn = fIter.rgn();
- if (rgn) {
- SkGr::SetIRect(bounds, rgn->getBounds());
+void SkGrClipIterator::reset(const SkClipStack& clipStack) {
+ fClipStack = &clipStack;
+ fIter.reset(clipStack);
+ // Gr has no notion of replace, skip to the
+ // last replace in the clip stack.
+ int lastReplace = 0;
+ int curr = 0;
+ while (NULL != (fCurr = fIter.next())) {
+ if (SkRegion::kReplace_Op == fCurr->fOp) {
+ lastReplace = curr;
+ }
+ ++curr;
+ }
+ fIter.reset(clipStack);
+ for (int i = 0; i < lastReplace+1; ++i) {
+ fCurr = fIter.next();
+ }
+}
+
+GrClipType SkGrClipIterator::getType() const {
+ GrAssert(!this->isDone());
+ if (NULL != fCurr->fRect) {
+ return kRect_ClipType;
} else {
- bounds->setEmpty();
+ GrAssert(NULL != fCurr->fPath);
+ return kPath_ClipType;
+ }
+}
+
+GrSetOp SkGrClipIterator::getOp() const {
+ // we skipped to the last "replace" op
+ // when this iter was reset.
+ // GrClip doesn't allow replace, so treat it as
+ // intersect.
+ GrSetOp skToGrOps[] = {
+ kDifference_SetOp, // kDifference_Op
+ kIntersect_SetOp, // kIntersect_Op
+ kUnion_SetOp, // kUnion_Op
+ kXor_SetOp, // kXOR_Op
+ kReverseDifference_SetOp, // kReverseDifference_Op
+ kIntersect_SetOp // kReplace_op
+ };
+ GR_STATIC_ASSERT(0 == SkRegion::kDifference_Op);
+ GR_STATIC_ASSERT(1 == SkRegion::kIntersect_Op);
+ GR_STATIC_ASSERT(2 == SkRegion::kUnion_Op);
+ GR_STATIC_ASSERT(3 == SkRegion::kXOR_Op);
+ GR_STATIC_ASSERT(4 == SkRegion::kReverseDifference_Op);
+ GR_STATIC_ASSERT(5 == SkRegion::kReplace_Op);
+ return skToGrOps[fCurr->fOp];
+}
+
+GrPathFill SkGrClipIterator::getPathFill() const {
+ switch (fCurr->fPath->getFillType()) {
+ case SkPath::kWinding_FillType:
+ return kWinding_PathFill;
+ case SkPath::kEvenOdd_FillType:
+ return kEvenOdd_PathFill;
+ case SkPath::kInverseWinding_FillType:
+ return kInverseWinding_PathFill;
+ case SkPath::kInverseEvenOdd_FillType:
+ return kInverseEvenOdd_PathFill;
+ default:
+ GrCrash("Unsupported path fill in clip.");
+ return kWinding_PathFill; // suppress warning
}
}
diff --git a/src/utils/mac/SkOSWindow_Mac.cpp b/src/utils/mac/SkOSWindow_Mac.cpp
index 7716185..05f97a7 100644
--- a/src/utils/mac/SkOSWindow_Mac.cpp
+++ b/src/utils/mac/SkOSWindow_Mac.cpp
@@ -531,7 +531,6 @@
void SkOSWindow::presentGL() {
aglSwapBuffers((AGLContext)fAGLCtx);
- glFlush();
}
#endif
diff --git a/src/utils/win/SkOSWindow_Win.cpp b/src/utils/win/SkOSWindow_Win.cpp
index 3594c2f..96a026d 100644
--- a/src/utils/win/SkOSWindow_Win.cpp
+++ b/src/utils/win/SkOSWindow_Win.cpp
@@ -444,10 +444,6 @@
}
}
if (wglMakeCurrent(GetDC((HWND)fHWND), (HGLRC)fHGLRC)) {
- glViewport(0, 0, this->width(), this->height());
- glClearColor(0, 0, 0, 0);
- glClearStencil(0);
- glClear(GL_COLOR_BUFFER_BIT | GL_STENCIL_BUFFER_BIT);
fGLAttached = true;
return true;
}
@@ -462,9 +458,6 @@
void SkOSWindow::presentGL() {
glFlush();
SwapBuffers(GetDC((HWND)fHWND));
- glClearColor(0,0,0,0);
- glClearStencil(0);
- glClear(GL_STENCIL_BUFFER_BIT | GL_COLOR_BUFFER_BIT);
}
IDirect3DDevice9* create_d3d9_device(HWND hwnd) {