michael@0: /* michael@0: * Copyright 2012 Google Inc. michael@0: * michael@0: * Use of this source code is governed by a BSD-style license that can be michael@0: * found in the LICENSE file. michael@0: */ michael@0: michael@0: #ifndef GrClipMaskManager_DEFINED michael@0: #define GrClipMaskManager_DEFINED michael@0: michael@0: #include "GrClipMaskCache.h" michael@0: #include "GrContext.h" michael@0: #include "GrDrawState.h" michael@0: #include "GrReducedClip.h" michael@0: #include "GrStencil.h" michael@0: #include "GrTexture.h" michael@0: michael@0: #include "SkClipStack.h" michael@0: #include "SkDeque.h" michael@0: #include "SkPath.h" michael@0: #include "SkRefCnt.h" michael@0: #include "SkTLList.h" michael@0: #include "SkTypes.h" michael@0: michael@0: class GrGpu; michael@0: class GrPathRenderer; michael@0: class GrPathRendererChain; michael@0: class GrTexture; michael@0: class SkPath; michael@0: michael@0: /** michael@0: * The clip mask creator handles the generation of the clip mask. If anti michael@0: * aliasing is requested it will (in the future) generate a single channel michael@0: * (8bit) mask. If no anti aliasing is requested it will generate a 1-bit michael@0: * mask in the stencil buffer. In the non anti-aliasing case, if the clip michael@0: * mask can be represented as a rectangle then scissoring is used. In all michael@0: * cases scissoring is used to bound the range of the clip mask. michael@0: */ michael@0: class GrClipMaskManager : public SkNoncopyable { michael@0: public: michael@0: GrClipMaskManager() michael@0: : fGpu(NULL) michael@0: , fCurrClipMaskType(kNone_ClipMaskType) { michael@0: } michael@0: michael@0: /** michael@0: * Creates a clip mask if necessary as a stencil buffer or alpha texture michael@0: * and sets the GrGpu's scissor and stencil state. If the return is false michael@0: * then the draw can be skipped. The AutoRestoreEffects is initialized by michael@0: * the manager when it must install additional effects to implement the michael@0: * clip. devBounds is optional but can help optimize clipping. michael@0: */ michael@0: bool setupClipping(const GrClipData* clipDataIn, GrDrawState::AutoRestoreEffects*, michael@0: const SkRect* devBounds); michael@0: michael@0: void releaseResources(); michael@0: michael@0: bool isClipInStencil() const { michael@0: return kStencil_ClipMaskType == fCurrClipMaskType; michael@0: } michael@0: bool isClipInAlpha() const { michael@0: return kAlpha_ClipMaskType == fCurrClipMaskType; michael@0: } michael@0: michael@0: void invalidateStencilMask() { michael@0: if (kStencil_ClipMaskType == fCurrClipMaskType) { michael@0: fCurrClipMaskType = kNone_ClipMaskType; michael@0: } michael@0: } michael@0: michael@0: GrContext* getContext() { michael@0: return fAACache.getContext(); michael@0: } michael@0: michael@0: void setGpu(GrGpu* gpu); michael@0: michael@0: void adjustPathStencilParams(GrStencilSettings* settings); michael@0: private: michael@0: /** michael@0: * Informs the helper function adjustStencilParams() about how the stencil michael@0: * buffer clip is being used. michael@0: */ michael@0: enum StencilClipMode { michael@0: // Draw to the clip bit of the stencil buffer michael@0: kModifyClip_StencilClipMode, michael@0: // Clip against the existing representation of the clip in the high bit michael@0: // of the stencil buffer. michael@0: kRespectClip_StencilClipMode, michael@0: // Neither writing to nor clipping against the clip bit. michael@0: kIgnoreClip_StencilClipMode, michael@0: }; michael@0: michael@0: GrGpu* fGpu; michael@0: michael@0: /** michael@0: * We may represent the clip as a mask in the stencil buffer or as an alpha michael@0: * texture. It may be neither because the scissor rect suffices or we michael@0: * haven't yet examined the clip. michael@0: */ michael@0: enum ClipMaskType { michael@0: kNone_ClipMaskType, michael@0: kStencil_ClipMaskType, michael@0: kAlpha_ClipMaskType, michael@0: } fCurrClipMaskType; michael@0: michael@0: GrClipMaskCache fAACache; // cache for the AA path michael@0: michael@0: // Attempts to install a series of coverage effects to implement the clip. Return indicates michael@0: // whether the element list was successfully converted to effects. michael@0: bool installClipEffects(const GrReducedClip::ElementList&, michael@0: GrDrawState::AutoRestoreEffects*, michael@0: const SkVector& clipOffset, michael@0: const SkRect* devBounds); michael@0: michael@0: // Draws the clip into the stencil buffer michael@0: bool createStencilClipMask(int32_t elementsGenID, michael@0: GrReducedClip::InitialState initialState, michael@0: const GrReducedClip::ElementList& elements, michael@0: const SkIRect& clipSpaceIBounds, michael@0: const SkIPoint& clipSpaceToStencilOffset); michael@0: // Creates an alpha mask of the clip. The mask is a rasterization of elements through the michael@0: // rect specified by clipSpaceIBounds. michael@0: GrTexture* createAlphaClipMask(int32_t elementsGenID, michael@0: GrReducedClip::InitialState initialState, michael@0: const GrReducedClip::ElementList& elements, michael@0: const SkIRect& clipSpaceIBounds); michael@0: // Similar to createAlphaClipMask but it rasterizes in SW and uploads to the result texture. michael@0: GrTexture* createSoftwareClipMask(int32_t elementsGenID, michael@0: GrReducedClip::InitialState initialState, michael@0: const GrReducedClip::ElementList& elements, michael@0: const SkIRect& clipSpaceIBounds); michael@0: michael@0: // Gets a texture to use for the clip mask. If true is returned then a cached mask was found michael@0: // that already contains the rasterization of the clip stack, otherwise an uninitialized texture michael@0: // is returned. 'willUpload' is set when the alpha mask needs to be uploaded from the CPU. michael@0: bool getMaskTexture(int32_t elementsGenID, michael@0: const SkIRect& clipSpaceIBounds, michael@0: GrTexture** result, michael@0: bool willUpload); michael@0: michael@0: bool useSWOnlyPath(const GrReducedClip::ElementList& elements); michael@0: michael@0: // Draws a clip element into the target alpha mask. The caller should have already setup the michael@0: // desired blend operation. Optionally if the caller already selected a path renderer it can michael@0: // be passed. Otherwise the function will select one if the element is a path. michael@0: bool drawElement(GrTexture* target, const SkClipStack::Element*, GrPathRenderer* = NULL); michael@0: michael@0: // Determines whether it is possible to draw the element to both the stencil buffer and the michael@0: // alpha mask simultaneously. If so and the element is a path a compatible path renderer is michael@0: // also returned. michael@0: bool canStencilAndDrawElement(GrTexture* target, const SkClipStack::Element*, GrPathRenderer**); michael@0: michael@0: void mergeMask(GrTexture* dstMask, michael@0: GrTexture* srcMask, michael@0: SkRegion::Op op, michael@0: const SkIRect& dstBound, michael@0: const SkIRect& srcBound); michael@0: michael@0: void getTemp(int width, int height, GrAutoScratchTexture* temp); michael@0: michael@0: void setupCache(const SkClipStack& clip, michael@0: const SkIRect& bounds); michael@0: michael@0: /** michael@0: * Called prior to return control back the GrGpu in setupClipping. It michael@0: * updates the GrGpu with stencil settings that account stencil-based michael@0: * clipping. michael@0: */ michael@0: void setGpuStencil(); michael@0: michael@0: /** michael@0: * Adjusts the stencil settings to account for interaction with stencil michael@0: * clipping. michael@0: */ michael@0: void adjustStencilParams(GrStencilSettings* settings, michael@0: StencilClipMode mode, michael@0: int stencilBitCnt); michael@0: michael@0: typedef SkNoncopyable INHERITED; michael@0: }; michael@0: michael@0: #endif // GrClipMaskManager_DEFINED