aboutsummaryrefslogtreecommitdiffhomepage
diff options
context:
space:
mode:
-rw-r--r--src/gpu/GrGpu.cpp387
-rw-r--r--src/gpu/GrGpu.h91
-rw-r--r--src/gpu/GrStencil.h3
-rw-r--r--src/gpu/gl/GrGpuGL.cpp73
-rw-r--r--src/gpu/gl/GrGpuGL.h4
5 files changed, 342 insertions, 216 deletions
diff --git a/src/gpu/GrGpu.cpp b/src/gpu/GrGpu.cpp
index 57e73c4226..4acb4f6f3e 100644
--- a/src/gpu/GrGpu.cpp
+++ b/src/gpu/GrGpu.cpp
@@ -31,8 +31,7 @@ extern void gr_run_unittests();
#define DEBUG_INVAL_START_IDX -1
GrGpu::GrGpu()
- : fClipInStencil(false)
- , fContext(NULL)
+ : fContext(NULL)
, fResetTimestamp(kExpiredTimestamp+1)
, fVertexPool(NULL)
, fIndexPool(NULL)
@@ -40,7 +39,6 @@ GrGpu::GrGpu()
, fIndexPoolUseCnt(0)
, fQuadIndexBuffer(NULL)
, fUnitSquareVertexBuffer(NULL)
- , fPathRendererChain(NULL)
, fContextIsDirty(true)
, fResourceHead(NULL) {
@@ -82,8 +80,8 @@ void GrGpu::abandonResources() {
fVertexPool = NULL;
delete fIndexPool;
fIndexPool = NULL;
- // in case path renderer has any GrResources, start from scratch
- GrSafeSetNull(fPathRendererChain);
+
+ fClipMaskManager.freeResources();
}
void GrGpu::releaseResources() {
@@ -101,8 +99,8 @@ void GrGpu::releaseResources() {
fVertexPool = NULL;
delete fIndexPool;
fIndexPool = NULL;
- // in case path renderer has any GrResources, start from scratch
- GrSafeSetNull(fPathRendererChain);
+
+ fClipMaskManager.freeResources();
}
void GrGpu::insertResource(GrResource* resource) {
@@ -543,206 +541,255 @@ int process_initial_clip_elements(const GrClip& clip,
}
}
-bool GrGpu::setupClipAndFlushState(GrPrimitiveType type) {
- const GrIRect* r = NULL;
- GrIRect clipRect;
- GrDrawState* drawState = this->drawState();
+
+// sort out what kind of clip mask needs to be created: A8/R8, stencil or scissor
+bool GrClipMaskManager::createClipMask(GrGpu* gpu,
+ const GrClip& clipIn,
+ ScissoringSettings* scissorSettings) {
+
+ GrAssert(scissorSettings);
+
+ scissorSettings->fEnableScissoring = false;
+ fClipMaskInStencil = false;
+
+ GrDrawState* drawState = gpu->drawState();
+ if (!drawState->isClipState()) {
+ return true;
+ }
+
GrRenderTarget* rt = drawState->getRenderTarget();
// GrDrawTarget should have filtered this for us
GrAssert(NULL != rt);
- if (drawState->isClipState()) {
-
- GrRect bounds;
- GrRect rtRect;
- rtRect.setLTRB(0, 0,
- GrIntToScalar(rt->width()), GrIntToScalar(rt->height()));
- if (fClip.hasConservativeBounds()) {
- bounds = fClip.getConservativeBounds();
- if (!bounds.intersect(rtRect)) {
- bounds.setEmpty();
- }
- } else {
- bounds = rtRect;
+ GrRect bounds;
+ GrRect rtRect;
+ rtRect.setLTRB(0, 0,
+ GrIntToScalar(rt->width()), GrIntToScalar(rt->height()));
+ if (clipIn.hasConservativeBounds()) {
+ bounds = clipIn.getConservativeBounds();
+ if (!bounds.intersect(rtRect)) {
+ bounds.setEmpty();
}
+ } else {
+ bounds = rtRect;
+ }
- bounds.roundOut(&clipRect);
- if (clipRect.isEmpty()) {
- clipRect.setLTRB(0,0,0,0);
- }
- r = &clipRect;
+ bounds.roundOut(&scissorSettings->fScissorRect);
+ if (scissorSettings->fScissorRect.isEmpty()) {
+ scissorSettings->fScissorRect.setLTRB(0,0,0,0);
+ // TODO: I think we can do an early exit here - after refactoring try:
+ // set fEnableScissoring to true but leave fClipMaskInStencil false
+ // and return - everything is going to be scissored away anyway!
+ }
+ scissorSettings->fEnableScissoring = true;
- // use the stencil clip if we can't represent the clip as a rectangle.
- fClipInStencil = !fClip.isRect() && !fClip.isEmpty() &&
+ // use the stencil clip if we can't represent the clip as a rectangle.
+ fClipMaskInStencil = !clipIn.isRect() && !clipIn.isEmpty() &&
!bounds.isEmpty();
- // TODO: dynamically attach a SB when needed.
- GrStencilBuffer* stencilBuffer = rt->getStencilBuffer();
- if (fClipInStencil && NULL == stencilBuffer) {
- return false;
- }
+ if (fClipMaskInStencil) {
+ return this->createStencilClipMask(gpu, clipIn, bounds, scissorSettings);
+ }
+
+ return true;
+}
+
+// Create a 1-bit clip mask in the stencil buffer
+bool GrClipMaskManager::createStencilClipMask(GrGpu* gpu,
+ const GrClip& clipIn,
+ const GrRect& bounds,
+ ScissoringSettings* scissorSettings) {
+
+ GrAssert(fClipMaskInStencil);
+
+ GrDrawState* drawState = gpu->drawState();
+ GrAssert(drawState->isClipState());
+
+ GrRenderTarget* rt = drawState->getRenderTarget();
+ GrAssert(NULL != rt);
+
+ // TODO: dynamically attach a SB when needed.
+ GrStencilBuffer* stencilBuffer = rt->getStencilBuffer();
+ if (NULL == stencilBuffer) {
+ return false;
+ }
- if (fClipInStencil &&
- stencilBuffer->mustRenderClip(fClip, rt->width(), rt->height())) {
+ if (stencilBuffer->mustRenderClip(clipIn, rt->width(), rt->height())) {
- stencilBuffer->setLastClip(fClip, rt->width(), rt->height());
+ stencilBuffer->setLastClip(clipIn, rt->width(), rt->height());
- // we set the current clip to the bounds so that our recursive
- // draws are scissored to them. We use the copy of the complex clip
- // we just stashed on the SB to render from. We set it back after
- // we finish drawing it into the stencil.
- const GrClip& clip = stencilBuffer->getLastClip();
- fClip.setFromRect(bounds);
+ // we set the current clip to the bounds so that our recursive
+ // draws are scissored to them. We use the copy of the complex clip
+ // we just stashed on the SB to render from. We set it back after
+ // we finish drawing it into the stencil.
+ const GrClip& clipCopy = stencilBuffer->getLastClip();
+ gpu->setClip(GrClip(bounds));
- AutoStateRestore asr(this, GrDrawTarget::kReset_ASRInit);
- drawState = this->drawState();
- drawState->setRenderTarget(rt);
- AutoGeometryPush agp(this);
+ GrDrawTarget::AutoStateRestore asr(gpu, GrDrawTarget::kReset_ASRInit);
+ drawState = gpu->drawState();
+ drawState->setRenderTarget(rt);
+ GrDrawTarget::AutoGeometryPush agp(gpu);
- this->flushScissor(NULL);
+ gpu->disableScissor();
#if !VISUALIZE_COMPLEX_CLIP
- drawState->enableState(GrDrawState::kNoColorWrites_StateBit);
+ drawState->enableState(GrDrawState::kNoColorWrites_StateBit);
#endif
- int count = clip.getElementCount();
- int clipBit = stencilBuffer->bits();
- SkASSERT((clipBit <= 16) &&
- "Ganesh only handles 16b or smaller stencil buffers");
- clipBit = (1 << (clipBit-1));
-
- bool clearToInside;
- GrSetOp startOp = kReplace_SetOp; // suppress warning
- int start = process_initial_clip_elements(clip,
- rtRect,
- &clearToInside,
- &startOp);
-
- this->clearStencilClip(clipRect, clearToInside);
-
- // walk through each clip element and perform its set op
- // with the existing clip.
- for (int c = start; c < count; ++c) {
- GrPathFill fill;
- bool fillInverted;
- // enabled at bottom of loop
- drawState->disableState(kModifyStencilClip_StateBit);
-
- bool canRenderDirectToStencil; // can the clip element be drawn
- // directly to the stencil buffer
- // with a non-inverted fill rule
- // without extra passes to
- // resolve in/out status.
-
- GrPathRenderer* pr = NULL;
- const GrPath* clipPath = NULL;
- if (kRect_ClipType == clip.getElementType(c)) {
- canRenderDirectToStencil = true;
- fill = kEvenOdd_PathFill;
- fillInverted = false;
- // there is no point in intersecting a screen filling
- // rectangle.
- if (kIntersect_SetOp == clip.getOp(c) &&
- clip.getRect(c).contains(rtRect)) {
- continue;
- }
- } else {
- fill = clip.getPathFill(c);
- fillInverted = GrIsFillInverted(fill);
- fill = GrNonInvertedFill(fill);
- clipPath = &clip.getPath(c);
- pr = this->getClipPathRenderer(*clipPath, fill);
- if (NULL == pr) {
- fClipInStencil = false;
- fClip = clip;
- return false;
- }
- canRenderDirectToStencil =
- !pr->requiresStencilPass(*clipPath, fill, this);
+ int count = clipCopy.getElementCount();
+ int clipBit = stencilBuffer->bits();
+ SkASSERT((clipBit <= 16) &&
+ "Ganesh only handles 16b or smaller stencil buffers");
+ clipBit = (1 << (clipBit-1));
+
+ GrRect rtRect;
+ rtRect.setLTRB(0, 0,
+ GrIntToScalar(rt->width()), GrIntToScalar(rt->height()));
+
+ bool clearToInside;
+ GrSetOp startOp = kReplace_SetOp; // suppress warning
+ int start = process_initial_clip_elements(clipCopy,
+ rtRect,
+ &clearToInside,
+ &startOp);
+
+ gpu->clearStencilClip(scissorSettings->fScissorRect, clearToInside);
+
+ // walk through each clip element and perform its set op
+ // with the existing clip.
+ for (int c = start; c < count; ++c) {
+ GrPathFill fill;
+ bool fillInverted;
+ // enabled at bottom of loop
+ drawState->disableState(GrGpu::kModifyStencilClip_StateBit);
+
+ bool canRenderDirectToStencil; // can the clip element be drawn
+ // directly to the stencil buffer
+ // with a non-inverted fill rule
+ // without extra passes to
+ // resolve in/out status.
+
+ GrPathRenderer* pr = NULL;
+ const GrPath* clipPath = NULL;
+ if (kRect_ClipType == clipCopy.getElementType(c)) {
+ canRenderDirectToStencil = true;
+ fill = kEvenOdd_PathFill;
+ fillInverted = false;
+ // there is no point in intersecting a screen filling
+ // rectangle.
+ if (kIntersect_SetOp == clipCopy.getOp(c) &&
+ clipCopy.getRect(c).contains(rtRect)) {
+ continue;
+ }
+ } else {
+ fill = clipCopy.getPathFill(c);
+ fillInverted = GrIsFillInverted(fill);
+ fill = GrNonInvertedFill(fill);
+ clipPath = &clipCopy.getPath(c);
+ pr = this->getClipPathRenderer(gpu, *clipPath, fill);
+ if (NULL == pr) {
+ fClipMaskInStencil = false;
+ gpu->setClip(clipCopy); // restore to the original
+ return false;
}
+ canRenderDirectToStencil =
+ !pr->requiresStencilPass(*clipPath, fill, gpu);
+ }
- GrSetOp op = (c == start) ? startOp : clip.getOp(c);
- int passes;
- GrStencilSettings stencilSettings[GrStencilSettings::kMaxStencilClipPasses];
-
- bool canDrawDirectToClip; // Given the renderer, the element,
- // fill rule, and set operation can
- // we render the element directly to
- // stencil bit used for clipping.
- canDrawDirectToClip =
- GrStencilSettings::GetClipPasses(op,
- canRenderDirectToStencil,
- clipBit,
- fillInverted,
- &passes, stencilSettings);
-
- // draw the element to the client stencil bits if necessary
- if (!canDrawDirectToClip) {
- GR_STATIC_CONST_SAME_STENCIL(gDrawToStencil,
- kIncClamp_StencilOp,
- kIncClamp_StencilOp,
- kAlways_StencilFunc,
- 0xffff,
- 0x0000,
- 0xffff);
- SET_RANDOM_COLOR
- if (kRect_ClipType == clip.getElementType(c)) {
+ GrSetOp op = (c == start) ? startOp : clipCopy.getOp(c);
+ int passes;
+ GrStencilSettings stencilSettings[GrStencilSettings::kMaxStencilClipPasses];
+
+ bool canDrawDirectToClip; // Given the renderer, the element,
+ // fill rule, and set operation can
+ // we render the element directly to
+ // stencil bit used for clipping.
+ canDrawDirectToClip =
+ GrStencilSettings::GetClipPasses(op,
+ canRenderDirectToStencil,
+ clipBit,
+ fillInverted,
+ &passes, stencilSettings);
+
+ // draw the element to the client stencil bits if necessary
+ if (!canDrawDirectToClip) {
+ GR_STATIC_CONST_SAME_STENCIL(gDrawToStencil,
+ kIncClamp_StencilOp,
+ kIncClamp_StencilOp,
+ kAlways_StencilFunc,
+ 0xffff,
+ 0x0000,
+ 0xffff);
+ SET_RANDOM_COLOR
+ if (kRect_ClipType == clipCopy.getElementType(c)) {
+ *drawState->stencil() = gDrawToStencil;
+ gpu->drawSimpleRect(clipCopy.getRect(c), NULL, 0);
+ } else {
+ if (canRenderDirectToStencil) {
*drawState->stencil() = gDrawToStencil;
- this->drawSimpleRect(clip.getRect(c), NULL, 0);
+ pr->drawPath(*clipPath, fill, NULL, gpu, 0, false);
} else {
- if (canRenderDirectToStencil) {
- *drawState->stencil() = gDrawToStencil;
- pr->drawPath(*clipPath, fill, NULL, this, 0, false);
- } else {
- pr->drawPathToStencil(*clipPath, fill, this);
- }
+ pr->drawPathToStencil(*clipPath, fill, gpu);
}
}
+ }
- // now we modify the clip bit by rendering either the clip
- // element directly or a bounding rect of the entire clip.
- drawState->enableState(kModifyStencilClip_StateBit);
- for (int p = 0; p < passes; ++p) {
- *drawState->stencil() = stencilSettings[p];
- if (canDrawDirectToClip) {
- if (kRect_ClipType == clip.getElementType(c)) {
- SET_RANDOM_COLOR
- this->drawSimpleRect(clip.getRect(c), NULL, 0);
- } else {
- SET_RANDOM_COLOR
- pr->drawPath(*clipPath, fill, NULL, this, 0, false);
- }
+ // now we modify the clip bit by rendering either the clip
+ // element directly or a bounding rect of the entire clip.
+ drawState->enableState(GrGpu::kModifyStencilClip_StateBit);
+ for (int p = 0; p < passes; ++p) {
+ *drawState->stencil() = stencilSettings[p];
+ if (canDrawDirectToClip) {
+ if (kRect_ClipType == clipCopy.getElementType(c)) {
+ SET_RANDOM_COLOR
+ gpu->drawSimpleRect(clipCopy.getRect(c), NULL, 0);
} else {
SET_RANDOM_COLOR
- this->drawSimpleRect(bounds, NULL, 0);
+ pr->drawPath(*clipPath, fill, NULL, gpu, 0, false);
}
+ } else {
+ SET_RANDOM_COLOR
+ gpu->drawSimpleRect(bounds, NULL, 0);
}
}
- // restore clip
- fClip = clip;
- // recusive draws would have disabled this since they drew with
- // the clip bounds as clip.
- fClipInStencil = true;
}
+ // restore clip
+ gpu->setClip(clipCopy);
+ // recusive draws would have disabled this since they drew with
+ // the clip bounds as clip.
+ fClipMaskInStencil = true;
+ }
+
+ return true;
+}
+
+bool GrGpu::setupClipAndFlushState(GrPrimitiveType type) {
+
+ ScissoringSettings scissoringSettings;
+
+ if (!fClipMaskManager.createClipMask(this, fClip, &scissoringSettings)) {
+ return false;
}
// Must flush the scissor after graphics state
if (!this->flushGraphicsState(type)) {
return false;
}
- this->flushScissor(r);
+
+ scissoringSettings.setupScissoring(this);
return true;
}
-GrPathRenderer* GrGpu::getClipPathRenderer(const GrPath& path,
- GrPathFill fill) {
+GrPathRenderer* GrClipMaskManager::getClipPathRenderer(GrGpu* gpu,
+ const GrPath& path,
+ GrPathFill fill) {
if (NULL == fPathRendererChain) {
fPathRendererChain =
- new GrPathRendererChain(this->getContext(),
+ new GrPathRendererChain(gpu->getContext(),
GrPathRendererChain::kNonAAOnly_UsageFlag);
}
- return fPathRendererChain->getPathRenderer(path, fill, this, false);
+ return fPathRendererChain->getPathRenderer(path, fill, gpu, false);
}
@@ -982,3 +1029,19 @@ void GrGpu::printStats() const {
}
}
+
+////////////////////////////////////////////////////////////////////////////////
+void ScissoringSettings::setupScissoring(GrGpu* gpu) {
+ if (!fEnableScissoring) {
+ gpu->disableScissor();
+ return;
+ }
+
+ gpu->enableScissoring(fScissorRect);
+}
+
+
+void GrClipMaskManager::freeResources() {
+ // in case path renderer has any GrResources, start from scratch
+ GrSafeSetNull(fPathRendererChain);
+}
diff --git a/src/gpu/GrGpu.h b/src/gpu/GrGpu.h
index 4a986b17ab..7bba3558a0 100644
--- a/src/gpu/GrGpu.h
+++ b/src/gpu/GrGpu.h
@@ -51,6 +51,66 @@ struct GrGpuStats {
uint32_t fRenderTargetCreateCnt;
};
+/**
+ * Scissoring needs special handling during stencil clip mask creation
+ * since the creation process re-entrantly invokes setupClipAndFlushState.
+ * During this process the call stack is used to keep
+ * track of (and apply to the GPU) the current scissor settings.
+ */
+struct ScissoringSettings {
+ bool fEnableScissoring;
+ GrIRect fScissorRect;
+
+ void setupScissoring(GrGpu* gpu);
+};
+
+/**
+ * The clip mask creator handles the generation of the clip mask. If anti
+ * aliasing is requested it will (in the future) generate a single channel
+ * (8bit) mask. If no anti aliasing is requested it will generate a 1-bit
+ * mask in the stencil buffer. In the non anti-aliasing case, if the clip
+ * mask can be represented as a rectangle then scissoring is used. In all
+ * cases scissoring is used to bound the range of the clip mask.
+ */
+class GrClipMaskManager {
+public:
+ GrClipMaskManager()
+ : fClipMaskInStencil(false)
+ , fPathRendererChain(NULL) {
+ }
+
+ bool createClipMask(GrGpu* gpu,
+ const GrClip& clip,
+ ScissoringSettings* scissorSettings);
+
+ void freeResources();
+
+ bool isClipInStencil() const { return fClipMaskInStencil; }
+
+ void resetMask() {
+ fClipMaskInStencil = false;
+ }
+
+protected:
+private:
+ bool fClipMaskInStencil; // is the clip mask in the stencil buffer?
+
+ // must be instantiated after GrGpu object has been given its owning
+ // GrContext ptr. (GrGpu is constructed first then handed off to GrContext).
+ GrPathRendererChain* fPathRendererChain;
+
+ bool createStencilClipMask(GrGpu* gpu,
+ const GrClip& clip,
+ const GrRect& bounds,
+ ScissoringSettings* scissorSettings);
+
+ // determines the path renderer used to draw a clip path element.
+ GrPathRenderer* getClipPathRenderer(GrGpu* gpu,
+ const SkPath& path,
+ GrPathFill fill);
+
+};
+
class GrGpu : public GrDrawTarget {
public:
@@ -341,7 +401,14 @@ public:
return fConfigRenderSupport[config];
}
-protected:
+ virtual void enableScissoring(const GrIRect& rect) = 0;
+ virtual void disableScissor() = 0;
+
+ // GrGpu subclass sets clip bit in the stencil buffer. The subclass is
+ // free to clear the remaining bits to zero if masked clears are more
+ // expensive than clearing all bits.
+ virtual void clearStencilClip(const GrIRect& rect, bool insideClip) = 0;
+
enum PrivateDrawStateStateBits {
kFirstBit = (GrDrawState::kLastPublicStateBit << 1),
@@ -350,10 +417,7 @@ protected:
// clipping.
};
- // keep track of whether we are using stencil clipping (as opposed to
- // scissor).
- bool fClipInStencil;
-
+protected:
// prepares clip flushes gpu state before a draw
bool setupClipAndFlushState(GrPrimitiveType type);
@@ -374,6 +438,8 @@ protected:
GrGpuStats fStats;
+ GrClipMaskManager fClipMaskManager;
+
struct GeometryPoolState {
const GrVertexBuffer* fPoolVertexBuffer;
int fPoolStartVertex;
@@ -485,14 +551,6 @@ protected:
// returns false if current state is unsupported.
virtual bool flushGraphicsState(GrPrimitiveType type) = 0;
- // Sets the scissor rect, or disables if rect is NULL.
- virtual void flushScissor(const GrIRect* rect) = 0;
-
- // GrGpu subclass sets clip bit in the stencil buffer. The subclass is
- // free to clear the remaining bits to zero if masked clears are more
- // expensive than clearing all bits.
- virtual void clearStencilClip(const GrIRect& rect, bool insideClip) = 0;
-
// clears the entire stencil buffer to 0
virtual void clearStencil() = 0;
@@ -521,10 +579,6 @@ private:
mutable GrVertexBuffer* fUnitSquareVertexBuffer; // mutable so it can be
// created on-demand
- // must be instantiated after GrGpu object has been given its owning
- // GrContext ptr. (GrGpu is constructed first then handed off to GrContext).
- GrPathRendererChain* fPathRendererChain;
-
bool fContextIsDirty;
GrResource* fResourceHead;
@@ -546,9 +600,6 @@ private:
void prepareVertexPool();
void prepareIndexPool();
- // determines the path renderer used to draw a clip path element.
- GrPathRenderer* getClipPathRenderer(const SkPath& path, GrPathFill fill);
-
void resetContext() {
this->onResetContext();
++fResetTimestamp;
diff --git a/src/gpu/GrStencil.h b/src/gpu/GrStencil.h
index 143e52509a..39700fef00 100644
--- a/src/gpu/GrStencil.h
+++ b/src/gpu/GrStencil.h
@@ -289,7 +289,8 @@ public:
}
private:
- friend class GrGpu;
+ friend class GrClipMaskManager;
+
enum {
kMaxStencilClipPasses = 2 // maximum number of passes to add a clip
// element to the stencil buffer.
diff --git a/src/gpu/gl/GrGpuGL.cpp b/src/gpu/gl/GrGpuGL.cpp
index 9114a0e9cf..a17f7d7446 100644
--- a/src/gpu/gl/GrGpuGL.cpp
+++ b/src/gpu/gl/GrGpuGL.cpp
@@ -516,13 +516,16 @@ void GrGpuGL::onResetContext() {
}
fHWBounds.fScissorRect.invalidate();
- fHWBounds.fScissorEnabled = false;
- GL_CALL(Disable(GR_GL_SCISSOR_TEST));
+ this->disableScissor();
+
fHWBounds.fViewportRect.invalidate();
fHWDrawState.stencil()->invalidate();
fHWStencilClip = false;
- fClipInStencil = false;
+
+ // TODO: I believe this should actually go in GrGpu::onResetContext
+ // rather than here
+ fClipMaskManager.resetMask();
fHWGeometryState.fIndexBuffer = NULL;
fHWGeometryState.fVertexBuffer = NULL;
@@ -1311,7 +1314,7 @@ GrIndexBuffer* GrGpuGL::onCreateIndexBuffer(uint32_t size, bool dynamic) {
return NULL;
}
-void GrGpuGL::flushScissor(const GrIRect* rect) {
+void GrGpuGL::enableScissoring(const GrIRect& rect) {
const GrDrawState& drawState = this->getDrawState();
const GrGLRenderTarget* rt =
static_cast<const GrGLRenderTarget*>(drawState.getRenderTarget());
@@ -1320,28 +1323,28 @@ void GrGpuGL::flushScissor(const GrIRect* rect) {
const GrGLIRect& vp = rt->getViewport();
GrGLIRect scissor;
- if (NULL != rect) {
- scissor.setRelativeTo(vp, rect->fLeft, rect->fTop,
- rect->width(), rect->height());
- if (scissor.contains(vp)) {
- rect = NULL;
- }
+ scissor.setRelativeTo(vp, rect.fLeft, rect.fTop,
+ rect.width(), rect.height());
+ if (scissor.contains(vp)) {
+ disableScissor();
+ return;
}
- if (NULL != rect) {
- if (fHWBounds.fScissorRect != scissor) {
- scissor.pushToGLScissor(this->glInterface());
- fHWBounds.fScissorRect = scissor;
- }
- if (!fHWBounds.fScissorEnabled) {
- GL_CALL(Enable(GR_GL_SCISSOR_TEST));
- fHWBounds.fScissorEnabled = true;
- }
- } else {
- if (fHWBounds.fScissorEnabled) {
- GL_CALL(Disable(GR_GL_SCISSOR_TEST));
- fHWBounds.fScissorEnabled = false;
- }
+ if (fHWBounds.fScissorRect != scissor) {
+ scissor.pushToGLScissor(this->glInterface());
+ fHWBounds.fScissorRect = scissor;
+ }
+ if (!fHWBounds.fScissorEnabled) {
+ GL_CALL(Enable(GR_GL_SCISSOR_TEST));
+ fHWBounds.fScissorEnabled = true;
+ }
+}
+
+void GrGpuGL::disableScissor() {
+ if (fHWBounds.fScissorEnabled) {
+ GL_CALL(Disable(GR_GL_SCISSOR_TEST));
+ fHWBounds.fScissorEnabled = false;
+// fHWBounds.fScissorRect.invalidate();
}
}
@@ -1363,7 +1366,10 @@ void GrGpuGL::onClear(const GrIRect* rect, GrColor color) {
}
}
this->flushRenderTarget(rect);
- this->flushScissor(rect);
+ if (NULL != rect)
+ this->enableScissoring(*rect);
+ else
+ this->disableScissor();
GrGLfloat r, g, b, a;
static const GrGLfloat scale255 = 1.f / 255.f;
@@ -1389,10 +1395,8 @@ void GrGpuGL::clearStencil() {
this->flushRenderTarget(&GrIRect::EmptyIRect());
- if (fHWBounds.fScissorEnabled) {
- GL_CALL(Disable(GR_GL_SCISSOR_TEST));
- fHWBounds.fScissorEnabled = false;
- }
+ this->disableScissor();
+
GL_CALL(StencilMask(0xffffffff));
GL_CALL(ClearStencil(0));
GL_CALL(Clear(GR_GL_STENCIL_BUFFER_BIT));
@@ -1426,7 +1430,7 @@ void GrGpuGL::clearStencilClip(const GrIRect& rect, bool insideClip) {
value = 0;
}
this->flushRenderTarget(&GrIRect::EmptyIRect());
- this->flushScissor(&rect);
+ this->enableScissoring(rect);
GL_CALL(StencilMask(clipStencilMask));
GL_CALL(ClearStencil(value));
GL_CALL(Clear(GR_GL_STENCIL_BUFFER_BIT));
@@ -1733,18 +1737,23 @@ void GrGpuGL::onResolveRenderTarget(GrRenderTarget* target) {
if (GrGLCaps::kAppleES_MSFBOType == this->glCaps().msFBOType()) {
// Apple's extension uses the scissor as the blit bounds.
+#if 1
GL_CALL(Enable(GR_GL_SCISSOR_TEST));
GL_CALL(Scissor(r.fLeft, r.fBottom,
r.fWidth, r.fHeight));
GL_CALL(ResolveMultisampleFramebuffer());
fHWBounds.fScissorRect.invalidate();
fHWBounds.fScissorEnabled = true;
+#else
+ this->enableScissoring(dirtyRect);
+ GL_CALL(ResolveMultisampleFramebuffer());
+#endif
} else {
if (GrGLCaps::kDesktopARB_MSFBOType != this->glCaps().msFBOType()) {
// this respects the scissor during the blit, so disable it.
GrAssert(GrGLCaps::kDesktopEXT_MSFBOType ==
this->glCaps().msFBOType());
- this->flushScissor(NULL);
+ this->disableScissor();
}
int right = r.fLeft + r.fWidth;
int top = r.fBottom + r.fHeight;
@@ -1803,7 +1812,7 @@ void GrGpuGL::flushStencil() {
// use stencil for clipping if clipping is enabled and the clip
// has been written into the stencil.
- bool stencilClip = fClipInStencil && drawState.isClipState();
+ bool stencilClip = fClipMaskManager.isClipInStencil() && drawState.isClipState();
bool drawClipToStencil =
drawState.isStateFlagEnabled(kModifyStencilClip_StateBit);
bool stencilChange = (fHWDrawState.getStencil() != *settings) ||
diff --git a/src/gpu/gl/GrGpuGL.h b/src/gpu/gl/GrGpuGL.h
index 928b50e876..77b300a9ea 100644
--- a/src/gpu/gl/GrGpuGL.h
+++ b/src/gpu/gl/GrGpuGL.h
@@ -140,7 +140,9 @@ protected:
virtual void onGpuDrawNonIndexed(GrPrimitiveType type,
uint32_t vertexCount,
uint32_t numVertices);
- virtual void flushScissor(const GrIRect* rect);
+ virtual void enableScissoring(const GrIRect& rect);
+ virtual void disableScissor();
+
virtual void clearStencil();
virtual void clearStencilClip(const GrIRect& rect, bool insideClip);
virtual int getMaxEdges() const;