diff options
-rw-r--r-- | src/gpu/GrGpu.cpp | 387 | ||||
-rw-r--r-- | src/gpu/GrGpu.h | 91 | ||||
-rw-r--r-- | src/gpu/GrStencil.h | 3 | ||||
-rw-r--r-- | src/gpu/gl/GrGpuGL.cpp | 73 | ||||
-rw-r--r-- | src/gpu/gl/GrGpuGL.h | 4 |
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; |