1321f62ca78984b4e78d0f2c014af46327cf7331crobertphillips@google.com 2321f62ca78984b4e78d0f2c014af46327cf7331crobertphillips@google.com/* 3321f62ca78984b4e78d0f2c014af46327cf7331crobertphillips@google.com * Copyright 2012 Google Inc. 4321f62ca78984b4e78d0f2c014af46327cf7331crobertphillips@google.com * 5321f62ca78984b4e78d0f2c014af46327cf7331crobertphillips@google.com * Use of this source code is governed by a BSD-style license that can be 6321f62ca78984b4e78d0f2c014af46327cf7331crobertphillips@google.com * found in the LICENSE file. 7321f62ca78984b4e78d0f2c014af46327cf7331crobertphillips@google.com */ 8321f62ca78984b4e78d0f2c014af46327cf7331crobertphillips@google.com 9321f62ca78984b4e78d0f2c014af46327cf7331crobertphillips@google.com#include "GrClipMaskManager.h" 10516b4c312ba95ab60863c325482ee6c36618f706bsalomon@google.com#include "GrAAConvexPathRenderer.h" 11516b4c312ba95ab60863c325482ee6c36618f706bsalomon@google.com#include "GrAAHairLinePathRenderer.h" 12516b4c312ba95ab60863c325482ee6c36618f706bsalomon@google.com#include "GrDrawTargetCaps.h" 13321f62ca78984b4e78d0f2c014af46327cf7331crobertphillips@google.com#include "GrGpu.h" 14516b4c312ba95ab60863c325482ee6c36618f706bsalomon@google.com#include "GrPaint.h" 15516b4c312ba95ab60863c325482ee6c36618f706bsalomon@google.com#include "GrPathRenderer.h" 16321f62ca78984b4e78d0f2c014af46327cf7331crobertphillips@google.com#include "GrRenderTarget.h" 17321f62ca78984b4e78d0f2c014af46327cf7331crobertphillips@google.com#include "GrStencilBuffer.h" 18516b4c312ba95ab60863c325482ee6c36618f706bsalomon@google.com#include "GrSWMaskHelper.h" 19516b4c312ba95ab60863c325482ee6c36618f706bsalomon@google.com#include "effects/GrTextureDomainEffect.h" 202e2671b7977fa3f1fb0b1353abae74dc3d0ddf42robertphillips@google.com#include "SkRasterClip.h" 215c2ee5c5d8f8593d40a2a9ffd9ca834653ee6af1sugoi@google.com#include "SkStrokeRec.h" 2231997dacc509386a68fbd000d979801268f36767bsalomon@google.com#include "SkTLazy.h" 2331997dacc509386a68fbd000d979801268f36767bsalomon@google.com 248646bb70e6e5805a32e008f4d5e13e8c511872bbrobertphillips@google.com#define GR_AA_CLIP 1 25b59d0a5438a70249b58c51a35980c1930b5078b5robertphillips@google.com 267830e470d00cdeb468ebf34525bc9f3f0c731014bsalomon@google.comtypedef SkClipStack::Element Element; 2715634ca6ad93fd47a3d8a0d3e78fc18527886328bsalomon@google.com 28e6aa2fce1b318c69ecf03324d19f93168e86feb6bsalomon@google.comusing namespace GrReducedClip; 29e6aa2fce1b318c69ecf03324d19f93168e86feb6bsalomon@google.com 3015634ca6ad93fd47a3d8a0d3e78fc18527886328bsalomon@google.com//////////////////////////////////////////////////////////////////////////////// 31b59d0a5438a70249b58c51a35980c1930b5078b5robertphillips@google.comnamespace { 32935e9f4fafdfc64130e6be9ea2bb30e3bafd852armistry@google.com// set up the draw state to enable the aa clipping mask. Besides setting up the 337879945fc341357322f2a19d9a927ff2e6bae4d9bsalomon@google.com// stage matrix this also alters the vertex layout 34935e9f4fafdfc64130e6be9ea2bb30e3bafd852armistry@google.comvoid setup_drawstate_aaclip(GrGpu* gpu, 35935e9f4fafdfc64130e6be9ea2bb30e3bafd852armistry@google.com GrTexture* result, 36a8cbc57c2d74f8024d149370377bd7dcbd8d204ccommit-bot@chromium.org const SkIRect &devBound) { 37b59d0a5438a70249b58c51a35980c1930b5078b5robertphillips@google.com GrDrawState* drawState = gpu->drawState(); 38b59d0a5438a70249b58c51a35980c1930b5078b5robertphillips@google.com GrAssert(drawState); 39b59d0a5438a70249b58c51a35980c1930b5078b5robertphillips@google.com 40a4e2f5beb2d73243c15ab871f013d2ba29e8fea3bsalomon@google.com SkMatrix mat; 418bc9236bf27d711cc7fe5cd618b02d29d7c59881bsalomon@google.com // We want to use device coords to compute the texture coordinates. We set our matrix to be 428bc9236bf27d711cc7fe5cd618b02d29d7c59881bsalomon@google.com // equal to the view matrix followed by an offset to the devBound, and then a scaling matrix to 438bc9236bf27d711cc7fe5cd618b02d29d7c59881bsalomon@google.com // normalized coords. We apply this matrix to the vertex positions rather than local coords. 44b59d0a5438a70249b58c51a35980c1930b5078b5robertphillips@google.com mat.setIDiv(result->width(), result->height()); 45935e9f4fafdfc64130e6be9ea2bb30e3bafd852armistry@google.com mat.preTranslate(SkIntToScalar(-devBound.fLeft), 46b6b643945182d1df391fdd11e2e788af8445914frobertphillips@google.com SkIntToScalar(-devBound.fTop)); 47b59d0a5438a70249b58c51a35980c1930b5078b5robertphillips@google.com mat.preConcat(drawState->getViewMatrix()); 48b59d0a5438a70249b58c51a35980c1930b5078b5robertphillips@google.com 49746496832ab4c5f603dbb7efa12a68f3b08bed8dbsalomon@google.com SkIRect domainTexels = SkIRect::MakeWH(devBound.width(), devBound.height()); 50e6aa2fce1b318c69ecf03324d19f93168e86feb6bsalomon@google.com // This could be a long-lived effect that is cached with the alpha-mask. 51860912a0affd82bc6b30ad9006658df856ca1d17bsalomon@google.com drawState->addCoverageEffect( 52860912a0affd82bc6b30ad9006658df856ca1d17bsalomon@google.com GrTextureDomainEffect::Create(result, 53746496832ab4c5f603dbb7efa12a68f3b08bed8dbsalomon@google.com mat, 54746496832ab4c5f603dbb7efa12a68f3b08bed8dbsalomon@google.com GrTextureDomainEffect::MakeTexelDomain(result, domainTexels), 558bc9236bf27d711cc7fe5cd618b02d29d7c59881bsalomon@google.com GrTextureDomainEffect::kDecal_WrapMode, 5629ba4805e88962ad40e3ca79c9a768e073f52badhumper@google.com GrTextureParams::kNone_FilterMode, 578bc9236bf27d711cc7fe5cd618b02d29d7c59881bsalomon@google.com GrEffect::kPosition_CoordsType))->unref(); 58b59d0a5438a70249b58c51a35980c1930b5078b5robertphillips@google.com} 59b59d0a5438a70249b58c51a35980c1930b5078b5robertphillips@google.com 60e9f225e140a696bfbf2900459f9c58691f50b6d6robertphillips@google.combool path_needs_SW_renderer(GrContext* context, 6162310c0ce7ef008e106b483e568fcfa03fb04e66bsalomon@google.com GrGpu* gpu, 6231997dacc509386a68fbd000d979801268f36767bsalomon@google.com const SkPath& origPath, 635c2ee5c5d8f8593d40a2a9ffd9ca834653ee6af1sugoi@google.com const SkStrokeRec& stroke, 6462310c0ce7ef008e106b483e568fcfa03fb04e66bsalomon@google.com bool doAA) { 6531997dacc509386a68fbd000d979801268f36767bsalomon@google.com // the gpu alpha mask will draw the inverse paths as non-inverse to a temp buffer 6631997dacc509386a68fbd000d979801268f36767bsalomon@google.com SkTCopyOnFirstWrite<SkPath> path(origPath); 6731997dacc509386a68fbd000d979801268f36767bsalomon@google.com if (path->isInverseFillType()) { 6831997dacc509386a68fbd000d979801268f36767bsalomon@google.com path.writable()->toggleInverseFillType(); 6931997dacc509386a68fbd000d979801268f36767bsalomon@google.com } 70e9f225e140a696bfbf2900459f9c58691f50b6d6robertphillips@google.com // last (false) parameter disallows use of the SW path renderer 710afd9ef7f06395f1bbbe9a18d8fcfa181d5f6bb0bsalomon@google.com GrPathRendererChain::DrawType type = doAA ? 720afd9ef7f06395f1bbbe9a18d8fcfa181d5f6bb0bsalomon@google.com GrPathRendererChain::kColorAntiAlias_DrawType : 730afd9ef7f06395f1bbbe9a18d8fcfa181d5f6bb0bsalomon@google.com GrPathRendererChain::kColor_DrawType; 740afd9ef7f06395f1bbbe9a18d8fcfa181d5f6bb0bsalomon@google.com 750afd9ef7f06395f1bbbe9a18d8fcfa181d5f6bb0bsalomon@google.com return NULL == context->getPathRenderer(*path, stroke, gpu, false, type); 767d0c7447d2cdde3e89f1db67e1519b81dd21cde1robertphillips@google.com} 777d0c7447d2cdde3e89f1db67e1519b81dd21cde1robertphillips@google.com 782e2671b7977fa3f1fb0b1353abae74dc3d0ddf42robertphillips@google.com} 792e2671b7977fa3f1fb0b1353abae74dc3d0ddf42robertphillips@google.com 804cc75e380b63fe8ce4823bc7902ebf6b0ca377darobertphillips@google.com/* 814cc75e380b63fe8ce4823bc7902ebf6b0ca377darobertphillips@google.com * This method traverses the clip stack to see if the GrSoftwarePathRenderer 824cc75e380b63fe8ce4823bc7902ebf6b0ca377darobertphillips@google.com * will be used on any element. If so, it returns true to indicate that the 834cc75e380b63fe8ce4823bc7902ebf6b0ca377darobertphillips@google.com * entire clip should be rendered in SW and then uploaded en masse to the gpu. 844cc75e380b63fe8ce4823bc7902ebf6b0ca377darobertphillips@google.com */ 85e6aa2fce1b318c69ecf03324d19f93168e86feb6bsalomon@google.combool GrClipMaskManager::useSWOnlyPath(const ElementList& elements) { 86211117a567bc16d558b39acc71d9335a8eca914arobertphillips@google.com 87e9f225e140a696bfbf2900459f9c58691f50b6d6robertphillips@google.com // TODO: generalize this function so that when 884cc75e380b63fe8ce4823bc7902ebf6b0ca377darobertphillips@google.com // a clip gets complex enough it can just be done in SW regardless 894cc75e380b63fe8ce4823bc7902ebf6b0ca377darobertphillips@google.com // of whether it would invoke the GrSoftwarePathRenderer. 905c2ee5c5d8f8593d40a2a9ffd9ca834653ee6af1sugoi@google.com SkStrokeRec stroke(SkStrokeRec::kFill_InitStyle); 91f4e6e352876ae31b68064b03bfadef08d29912acskia.committer@gmail.com 92e6aa2fce1b318c69ecf03324d19f93168e86feb6bsalomon@google.com for (ElementList::Iter iter(elements.headIter()); iter.get(); iter.next()) { 93e6aa2fce1b318c69ecf03324d19f93168e86feb6bsalomon@google.com const Element* element = iter.get(); 946e46fa2ba101bd88b2400b56b9001d27b9a00b48robertphillips@google.com // rects can always be drawn directly w/o using the software path 956e46fa2ba101bd88b2400b56b9001d27b9a00b48robertphillips@google.com // so only paths need to be checked 967830e470d00cdeb468ebf34525bc9f3f0c731014bsalomon@google.com if (Element::kPath_Type == element->getType() && 97935e9f4fafdfc64130e6be9ea2bb30e3bafd852armistry@google.com path_needs_SW_renderer(this->getContext(), fGpu, 987830e470d00cdeb468ebf34525bc9f3f0c731014bsalomon@google.com element->getPath(), 99290bf0ae34af76a4350a5df76ce02feb93d68196sugoi@google.com stroke, 1007830e470d00cdeb468ebf34525bc9f3f0c731014bsalomon@google.com element->isAA())) { 101e6aa2fce1b318c69ecf03324d19f93168e86feb6bsalomon@google.com return true; 1024cc75e380b63fe8ce4823bc7902ebf6b0ca377darobertphillips@google.com } 1034cc75e380b63fe8ce4823bc7902ebf6b0ca377darobertphillips@google.com } 104e6aa2fce1b318c69ecf03324d19f93168e86feb6bsalomon@google.com return false; 105b59d0a5438a70249b58c51a35980c1930b5078b5robertphillips@google.com} 106b59d0a5438a70249b58c51a35980c1930b5078b5robertphillips@google.com 107fcf86a350bf9d8cdaff79d69bc8f3fecd019817brobertphillips@google.com//////////////////////////////////////////////////////////////////////////////// 1082e2671b7977fa3f1fb0b1353abae74dc3d0ddf42robertphillips@google.com// sort out what kind of clip mask needs to be created: alpha, stencil, 1092e2671b7977fa3f1fb0b1353abae74dc3d0ddf42robertphillips@google.com// scissor, or entirely software 110860912a0affd82bc6b30ad9006658df856ca1d17bsalomon@google.combool GrClipMaskManager::setupClipping(const GrClipData* clipDataIn, 111860912a0affd82bc6b30ad9006658df856ca1d17bsalomon@google.com GrDrawState::AutoRestoreEffects* are) { 1120c4165f59a09574d521de66abeb3cc3101b04bd6bsalomon@google.com fCurrClipMaskType = kNone_ClipMaskType; 11385d47bf8e929c8eca60ce0fc5bda1f64481d5ef1bsalomon@google.com 114e6aa2fce1b318c69ecf03324d19f93168e86feb6bsalomon@google.com ElementList elements(16); 115e6aa2fce1b318c69ecf03324d19f93168e86feb6bsalomon@google.com InitialState initialState; 116e6aa2fce1b318c69ecf03324d19f93168e86feb6bsalomon@google.com SkIRect clipSpaceIBounds; 117e6aa2fce1b318c69ecf03324d19f93168e86feb6bsalomon@google.com bool requiresAA; 118e6aa2fce1b318c69ecf03324d19f93168e86feb6bsalomon@google.com bool isRect = false; 119e6aa2fce1b318c69ecf03324d19f93168e86feb6bsalomon@google.com 12062310c0ce7ef008e106b483e568fcfa03fb04e66bsalomon@google.com GrDrawState* drawState = fGpu->drawState(); 121321f62ca78984b4e78d0f2c014af46327cf7331crobertphillips@google.com 122e6aa2fce1b318c69ecf03324d19f93168e86feb6bsalomon@google.com const GrRenderTarget* rt = drawState->getRenderTarget(); 123321f62ca78984b4e78d0f2c014af46327cf7331crobertphillips@google.com // GrDrawTarget should have filtered this for us 124321f62ca78984b4e78d0f2c014af46327cf7331crobertphillips@google.com GrAssert(NULL != rt); 125321f62ca78984b4e78d0f2c014af46327cf7331crobertphillips@google.com 126e6aa2fce1b318c69ecf03324d19f93168e86feb6bsalomon@google.com bool ignoreClip = !drawState->isClipState() || clipDataIn->fClipStack->isWideOpen(); 127e6aa2fce1b318c69ecf03324d19f93168e86feb6bsalomon@google.com 128e6aa2fce1b318c69ecf03324d19f93168e86feb6bsalomon@google.com if (!ignoreClip) { 129e6aa2fce1b318c69ecf03324d19f93168e86feb6bsalomon@google.com SkIRect clipSpaceRTIBounds = SkIRect::MakeWH(rt->width(), rt->height()); 130e6aa2fce1b318c69ecf03324d19f93168e86feb6bsalomon@google.com clipSpaceRTIBounds.offset(clipDataIn->fOrigin); 131e6aa2fce1b318c69ecf03324d19f93168e86feb6bsalomon@google.com ReduceClipStack(*clipDataIn->fClipStack, 132e6aa2fce1b318c69ecf03324d19f93168e86feb6bsalomon@google.com clipSpaceRTIBounds, 133e6aa2fce1b318c69ecf03324d19f93168e86feb6bsalomon@google.com &elements, 134e6aa2fce1b318c69ecf03324d19f93168e86feb6bsalomon@google.com &initialState, 135e6aa2fce1b318c69ecf03324d19f93168e86feb6bsalomon@google.com &clipSpaceIBounds, 136e6aa2fce1b318c69ecf03324d19f93168e86feb6bsalomon@google.com &requiresAA); 137e6aa2fce1b318c69ecf03324d19f93168e86feb6bsalomon@google.com if (elements.isEmpty()) { 138e6aa2fce1b318c69ecf03324d19f93168e86feb6bsalomon@google.com if (kAllIn_InitialState == initialState) { 139e6aa2fce1b318c69ecf03324d19f93168e86feb6bsalomon@google.com ignoreClip = clipSpaceIBounds == clipSpaceRTIBounds; 140e6aa2fce1b318c69ecf03324d19f93168e86feb6bsalomon@google.com isRect = true; 141e6aa2fce1b318c69ecf03324d19f93168e86feb6bsalomon@google.com } else { 142e6aa2fce1b318c69ecf03324d19f93168e86feb6bsalomon@google.com return false; 143e6aa2fce1b318c69ecf03324d19f93168e86feb6bsalomon@google.com } 144e6aa2fce1b318c69ecf03324d19f93168e86feb6bsalomon@google.com } 145e6aa2fce1b318c69ecf03324d19f93168e86feb6bsalomon@google.com } 14615e7ae449c45978bc7ed7aba427369e4f78bc6derobertphillips@google.com 147e6aa2fce1b318c69ecf03324d19f93168e86feb6bsalomon@google.com if (ignoreClip) { 148e6aa2fce1b318c69ecf03324d19f93168e86feb6bsalomon@google.com fGpu->disableScissor(); 149e6aa2fce1b318c69ecf03324d19f93168e86feb6bsalomon@google.com this->setGpuStencil(); 150e6aa2fce1b318c69ecf03324d19f93168e86feb6bsalomon@google.com return true; 15185d47bf8e929c8eca60ce0fc5bda1f64481d5ef1bsalomon@google.com } 15285d47bf8e929c8eca60ce0fc5bda1f64481d5ef1bsalomon@google.com 153e6aa2fce1b318c69ecf03324d19f93168e86feb6bsalomon@google.com#if GR_AA_CLIP 154e6aa2fce1b318c69ecf03324d19f93168e86feb6bsalomon@google.com // TODO: catch isRect && requiresAA and use clip planes if available rather than a mask. 155ac6e6ad8d9d2ca6018773a8b507ecd774efd4cdfrobertphillips@google.com 156211117a567bc16d558b39acc71d9335a8eca914arobertphillips@google.com // If MSAA is enabled we can do everything in the stencil buffer. 157e6aa2fce1b318c69ecf03324d19f93168e86feb6bsalomon@google.com if (0 == rt->numSamples() && requiresAA) { 158e6aa2fce1b318c69ecf03324d19f93168e86feb6bsalomon@google.com int32_t genID = clipDataIn->fClipStack->getTopmostGenID(); 1592e2671b7977fa3f1fb0b1353abae74dc3d0ddf42robertphillips@google.com GrTexture* result = NULL; 160211117a567bc16d558b39acc71d9335a8eca914arobertphillips@google.com 161e6aa2fce1b318c69ecf03324d19f93168e86feb6bsalomon@google.com if (this->useSWOnlyPath(elements)) { 162e6aa2fce1b318c69ecf03324d19f93168e86feb6bsalomon@google.com // The clip geometry is complex enough that it will be more efficient to create it 163e6aa2fce1b318c69ecf03324d19f93168e86feb6bsalomon@google.com // entirely in software 164e6aa2fce1b318c69ecf03324d19f93168e86feb6bsalomon@google.com result = this->createSoftwareClipMask(genID, 165e6aa2fce1b318c69ecf03324d19f93168e86feb6bsalomon@google.com initialState, 166e6aa2fce1b318c69ecf03324d19f93168e86feb6bsalomon@google.com elements, 167e6aa2fce1b318c69ecf03324d19f93168e86feb6bsalomon@google.com clipSpaceIBounds); 168e6aa2fce1b318c69ecf03324d19f93168e86feb6bsalomon@google.com } else { 169e6aa2fce1b318c69ecf03324d19f93168e86feb6bsalomon@google.com result = this->createAlphaClipMask(genID, 170e6aa2fce1b318c69ecf03324d19f93168e86feb6bsalomon@google.com initialState, 171e6aa2fce1b318c69ecf03324d19f93168e86feb6bsalomon@google.com elements, 172e6aa2fce1b318c69ecf03324d19f93168e86feb6bsalomon@google.com clipSpaceIBounds); 173e6aa2fce1b318c69ecf03324d19f93168e86feb6bsalomon@google.com } 1742e2671b7977fa3f1fb0b1353abae74dc3d0ddf42robertphillips@google.com 175e6aa2fce1b318c69ecf03324d19f93168e86feb6bsalomon@google.com if (NULL != result) { 176e6aa2fce1b318c69ecf03324d19f93168e86feb6bsalomon@google.com // The mask's top left coord should be pinned to the rounded-out top left corner of 177e6aa2fce1b318c69ecf03324d19f93168e86feb6bsalomon@google.com // clipSpace bounds. We determine the mask's position WRT to the render target here. 178e6aa2fce1b318c69ecf03324d19f93168e86feb6bsalomon@google.com SkIRect rtSpaceMaskBounds = clipSpaceIBounds; 179e6aa2fce1b318c69ecf03324d19f93168e86feb6bsalomon@google.com rtSpaceMaskBounds.offset(-clipDataIn->fOrigin); 180860912a0affd82bc6b30ad9006658df856ca1d17bsalomon@google.com are->set(fGpu->drawState()); 181e6aa2fce1b318c69ecf03324d19f93168e86feb6bsalomon@google.com setup_drawstate_aaclip(fGpu, result, rtSpaceMaskBounds); 18285d47bf8e929c8eca60ce0fc5bda1f64481d5ef1bsalomon@google.com fGpu->disableScissor(); 18385d47bf8e929c8eca60ce0fc5bda1f64481d5ef1bsalomon@google.com this->setGpuStencil(); 184fcf86a350bf9d8cdaff79d69bc8f3fecd019817brobertphillips@google.com return true; 185fcf86a350bf9d8cdaff79d69bc8f3fecd019817brobertphillips@google.com } 186e6aa2fce1b318c69ecf03324d19f93168e86feb6bsalomon@google.com // if alpha clip mask creation fails fall through to the non-AA code paths 187fcf86a350bf9d8cdaff79d69bc8f3fecd019817brobertphillips@google.com } 188fcf86a350bf9d8cdaff79d69bc8f3fecd019817brobertphillips@google.com#endif // GR_AA_CLIP 189fcf86a350bf9d8cdaff79d69bc8f3fecd019817brobertphillips@google.com 190e6aa2fce1b318c69ecf03324d19f93168e86feb6bsalomon@google.com // Either a hard (stencil buffer) clip was explicitly requested or an anti-aliased clip couldn't 191e6aa2fce1b318c69ecf03324d19f93168e86feb6bsalomon@google.com // be created. In either case, free up the texture in the anti-aliased mask cache. 192e6aa2fce1b318c69ecf03324d19f93168e86feb6bsalomon@google.com // TODO: this may require more investigation. Ganesh performs a lot of utility draws (e.g., 193e6aa2fce1b318c69ecf03324d19f93168e86feb6bsalomon@google.com // clears, InOrderDrawBuffer playbacks) that hit the stencil buffer path. These may be 194e6aa2fce1b318c69ecf03324d19f93168e86feb6bsalomon@google.com // "incorrectly" clearing the AA cache. 1957ee019c963ed4a2c9eb3d1c8490ba1ee246e0b1arobertphillips@google.com fAACache.reset(); 1967ee019c963ed4a2c9eb3d1c8490ba1ee246e0b1arobertphillips@google.com 19785d47bf8e929c8eca60ce0fc5bda1f64481d5ef1bsalomon@google.com // If the clip is a rectangle then just set the scissor. Otherwise, create 19885d47bf8e929c8eca60ce0fc5bda1f64481d5ef1bsalomon@google.com // a stencil mask. 199e6aa2fce1b318c69ecf03324d19f93168e86feb6bsalomon@google.com if (isRect) { 200e6aa2fce1b318c69ecf03324d19f93168e86feb6bsalomon@google.com SkIRect clipRect = clipSpaceIBounds; 201e6aa2fce1b318c69ecf03324d19f93168e86feb6bsalomon@google.com clipRect.offset(-clipDataIn->fOrigin); 202e6aa2fce1b318c69ecf03324d19f93168e86feb6bsalomon@google.com fGpu->enableScissor(clipRect); 20385d47bf8e929c8eca60ce0fc5bda1f64481d5ef1bsalomon@google.com this->setGpuStencil(); 20485d47bf8e929c8eca60ce0fc5bda1f64481d5ef1bsalomon@google.com return true; 205321f62ca78984b4e78d0f2c014af46327cf7331crobertphillips@google.com } 206321f62ca78984b4e78d0f2c014af46327cf7331crobertphillips@google.com 207321f62ca78984b4e78d0f2c014af46327cf7331crobertphillips@google.com // use the stencil clip if we can't represent the clip as a rectangle. 208e6aa2fce1b318c69ecf03324d19f93168e86feb6bsalomon@google.com SkIPoint clipSpaceToStencilSpaceOffset = -clipDataIn->fOrigin; 209e6aa2fce1b318c69ecf03324d19f93168e86feb6bsalomon@google.com this->createStencilClipMask(initialState, 210e6aa2fce1b318c69ecf03324d19f93168e86feb6bsalomon@google.com elements, 211e6aa2fce1b318c69ecf03324d19f93168e86feb6bsalomon@google.com clipSpaceIBounds, 212e6aa2fce1b318c69ecf03324d19f93168e86feb6bsalomon@google.com clipSpaceToStencilSpaceOffset); 213e6aa2fce1b318c69ecf03324d19f93168e86feb6bsalomon@google.com 214e6aa2fce1b318c69ecf03324d19f93168e86feb6bsalomon@google.com // This must occur after createStencilClipMask. That function may change the scissor. Also, it 215e6aa2fce1b318c69ecf03324d19f93168e86feb6bsalomon@google.com // only guarantees that the stencil mask is correct within the bounds it was passed, so we must 216e6aa2fce1b318c69ecf03324d19f93168e86feb6bsalomon@google.com // use both stencil and scissor test to the bounds for the final draw. 217e6aa2fce1b318c69ecf03324d19f93168e86feb6bsalomon@google.com SkIRect scissorSpaceIBounds(clipSpaceIBounds); 218e6aa2fce1b318c69ecf03324d19f93168e86feb6bsalomon@google.com scissorSpaceIBounds.offset(clipSpaceToStencilSpaceOffset); 219e6aa2fce1b318c69ecf03324d19f93168e86feb6bsalomon@google.com fGpu->enableScissor(scissorSpaceIBounds); 22085d47bf8e929c8eca60ce0fc5bda1f64481d5ef1bsalomon@google.com this->setGpuStencil(); 221321f62ca78984b4e78d0f2c014af46327cf7331crobertphillips@google.com return true; 222321f62ca78984b4e78d0f2c014af46327cf7331crobertphillips@google.com} 223321f62ca78984b4e78d0f2c014af46327cf7331crobertphillips@google.com 224321f62ca78984b4e78d0f2c014af46327cf7331crobertphillips@google.com#define VISUALIZE_COMPLEX_CLIP 0 225321f62ca78984b4e78d0f2c014af46327cf7331crobertphillips@google.com 226321f62ca78984b4e78d0f2c014af46327cf7331crobertphillips@google.com#if VISUALIZE_COMPLEX_CLIP 227a842e014d45c092cca5e8ca81fac7ed48634703ctfarina@chromium.org #include "SkRandom.h" 228a842e014d45c092cca5e8ca81fac7ed48634703ctfarina@chromium.org SkRandom gRandom; 229321f62ca78984b4e78d0f2c014af46327cf7331crobertphillips@google.com #define SET_RANDOM_COLOR drawState->setColor(0xff000000 | gRandom.nextU()); 230321f62ca78984b4e78d0f2c014af46327cf7331crobertphillips@google.com#else 231321f62ca78984b4e78d0f2c014af46327cf7331crobertphillips@google.com #define SET_RANDOM_COLOR 232321f62ca78984b4e78d0f2c014af46327cf7331crobertphillips@google.com#endif 233321f62ca78984b4e78d0f2c014af46327cf7331crobertphillips@google.com 234321f62ca78984b4e78d0f2c014af46327cf7331crobertphillips@google.comnamespace { 235fcf86a350bf9d8cdaff79d69bc8f3fecd019817brobertphillips@google.com 236fcf86a350bf9d8cdaff79d69bc8f3fecd019817brobertphillips@google.com//////////////////////////////////////////////////////////////////////////////// 237935e9f4fafdfc64130e6be9ea2bb30e3bafd852armistry@google.com// set up the OpenGL blend function to perform the specified 238935e9f4fafdfc64130e6be9ea2bb30e3bafd852armistry@google.com// boolean operation for alpha clip mask creation 2392e2671b7977fa3f1fb0b1353abae74dc3d0ddf42robertphillips@google.comvoid setup_boolean_blendcoeffs(GrDrawState* drawState, SkRegion::Op op) { 240fcf86a350bf9d8cdaff79d69bc8f3fecd019817brobertphillips@google.com 241fcf86a350bf9d8cdaff79d69bc8f3fecd019817brobertphillips@google.com switch (op) { 242fcf86a350bf9d8cdaff79d69bc8f3fecd019817brobertphillips@google.com case SkRegion::kReplace_Op: 2437de94cd88f290887d0c09549902c9f3890265ff2bsalomon@google.com drawState->setBlendFunc(kOne_GrBlendCoeff, kZero_GrBlendCoeff); 244fcf86a350bf9d8cdaff79d69bc8f3fecd019817brobertphillips@google.com break; 245fcf86a350bf9d8cdaff79d69bc8f3fecd019817brobertphillips@google.com case SkRegion::kIntersect_Op: 2467de94cd88f290887d0c09549902c9f3890265ff2bsalomon@google.com drawState->setBlendFunc(kDC_GrBlendCoeff, kZero_GrBlendCoeff); 247fcf86a350bf9d8cdaff79d69bc8f3fecd019817brobertphillips@google.com break; 248fcf86a350bf9d8cdaff79d69bc8f3fecd019817brobertphillips@google.com case SkRegion::kUnion_Op: 2497de94cd88f290887d0c09549902c9f3890265ff2bsalomon@google.com drawState->setBlendFunc(kOne_GrBlendCoeff, kISC_GrBlendCoeff); 250fcf86a350bf9d8cdaff79d69bc8f3fecd019817brobertphillips@google.com break; 251fcf86a350bf9d8cdaff79d69bc8f3fecd019817brobertphillips@google.com case SkRegion::kXOR_Op: 2527de94cd88f290887d0c09549902c9f3890265ff2bsalomon@google.com drawState->setBlendFunc(kIDC_GrBlendCoeff, kISC_GrBlendCoeff); 253fcf86a350bf9d8cdaff79d69bc8f3fecd019817brobertphillips@google.com break; 254fcf86a350bf9d8cdaff79d69bc8f3fecd019817brobertphillips@google.com case SkRegion::kDifference_Op: 2557de94cd88f290887d0c09549902c9f3890265ff2bsalomon@google.com drawState->setBlendFunc(kZero_GrBlendCoeff, kISC_GrBlendCoeff); 256fcf86a350bf9d8cdaff79d69bc8f3fecd019817brobertphillips@google.com break; 257fcf86a350bf9d8cdaff79d69bc8f3fecd019817brobertphillips@google.com case SkRegion::kReverseDifference_Op: 2587de94cd88f290887d0c09549902c9f3890265ff2bsalomon@google.com drawState->setBlendFunc(kIDC_GrBlendCoeff, kZero_GrBlendCoeff); 259fcf86a350bf9d8cdaff79d69bc8f3fecd019817brobertphillips@google.com break; 260fcf86a350bf9d8cdaff79d69bc8f3fecd019817brobertphillips@google.com default: 261fcf86a350bf9d8cdaff79d69bc8f3fecd019817brobertphillips@google.com GrAssert(false); 262fcf86a350bf9d8cdaff79d69bc8f3fecd019817brobertphillips@google.com break; 263fcf86a350bf9d8cdaff79d69bc8f3fecd019817brobertphillips@google.com } 264fcf86a350bf9d8cdaff79d69bc8f3fecd019817brobertphillips@google.com} 265fcf86a350bf9d8cdaff79d69bc8f3fecd019817brobertphillips@google.com 266a1a88ae20406b1cc7eae3d64bc1788d92eaf3816robertphillips@google.com} 267fcf86a350bf9d8cdaff79d69bc8f3fecd019817brobertphillips@google.com 268fcf86a350bf9d8cdaff79d69bc8f3fecd019817brobertphillips@google.com//////////////////////////////////////////////////////////////////////////////// 269bf2c6afceebb56969edeedda8114b172165a2982bsalomon@google.combool GrClipMaskManager::drawElement(GrTexture* target, 270bf2c6afceebb56969edeedda8114b172165a2982bsalomon@google.com const SkClipStack::Element* element, 271bf2c6afceebb56969edeedda8114b172165a2982bsalomon@google.com GrPathRenderer* pr) { 27262310c0ce7ef008e106b483e568fcfa03fb04e66bsalomon@google.com GrDrawState* drawState = fGpu->drawState(); 273fcf86a350bf9d8cdaff79d69bc8f3fecd019817brobertphillips@google.com 274fcf86a350bf9d8cdaff79d69bc8f3fecd019817brobertphillips@google.com drawState->setRenderTarget(target->asRenderTarget()); 275fcf86a350bf9d8cdaff79d69bc8f3fecd019817brobertphillips@google.com 2767830e470d00cdeb468ebf34525bc9f3f0c731014bsalomon@google.com switch (element->getType()) { 2777830e470d00cdeb468ebf34525bc9f3f0c731014bsalomon@google.com case Element::kRect_Type: 278e6aa2fce1b318c69ecf03324d19f93168e86feb6bsalomon@google.com // TODO: Do rects directly to the accumulator using a aa-rect GrEffect that covers the 279e6aa2fce1b318c69ecf03324d19f93168e86feb6bsalomon@google.com // entire mask bounds and writes 0 outside the rect. 2807830e470d00cdeb468ebf34525bc9f3f0c731014bsalomon@google.com if (element->isAA()) { 281bfaf011e7439431680ac6929f7a48c30e4fdaf89bsalomon@google.com getContext()->getAARectRenderer()->fillAARect(fGpu, 282bfaf011e7439431680ac6929f7a48c30e4fdaf89bsalomon@google.com fGpu, 283bfaf011e7439431680ac6929f7a48c30e4fdaf89bsalomon@google.com element->getRect(), 284b94d10665366901ae9fda0c98d75ffbbd71ff8c4robertphillips@google.com SkMatrix::I(), 2850d4d39654e55999edb3ef20aa4acbe681045d8e5robertphillips@google.com element->getRect(), 286bfaf011e7439431680ac6929f7a48c30e4fdaf89bsalomon@google.com false); 2877830e470d00cdeb468ebf34525bc9f3f0c731014bsalomon@google.com } else { 2887830e470d00cdeb468ebf34525bc9f3f0c731014bsalomon@google.com fGpu->drawSimpleRect(element->getRect(), NULL); 2897830e470d00cdeb468ebf34525bc9f3f0c731014bsalomon@google.com } 2907830e470d00cdeb468ebf34525bc9f3f0c731014bsalomon@google.com return true; 291e6aa2fce1b318c69ecf03324d19f93168e86feb6bsalomon@google.com case Element::kPath_Type: { 29231997dacc509386a68fbd000d979801268f36767bsalomon@google.com SkTCopyOnFirstWrite<SkPath> path(element->getPath()); 29331997dacc509386a68fbd000d979801268f36767bsalomon@google.com if (path->isInverseFillType()) { 29431997dacc509386a68fbd000d979801268f36767bsalomon@google.com path.writable()->toggleInverseFillType(); 29531997dacc509386a68fbd000d979801268f36767bsalomon@google.com } 2965c2ee5c5d8f8593d40a2a9ffd9ca834653ee6af1sugoi@google.com SkStrokeRec stroke(SkStrokeRec::kFill_InitStyle); 297bf2c6afceebb56969edeedda8114b172165a2982bsalomon@google.com if (NULL == pr) { 298bf2c6afceebb56969edeedda8114b172165a2982bsalomon@google.com GrPathRendererChain::DrawType type; 299bf2c6afceebb56969edeedda8114b172165a2982bsalomon@google.com type = element->isAA() ? GrPathRendererChain::kColorAntiAlias_DrawType : 300bf2c6afceebb56969edeedda8114b172165a2982bsalomon@google.com GrPathRendererChain::kColor_DrawType; 301bf2c6afceebb56969edeedda8114b172165a2982bsalomon@google.com pr = this->getContext()->getPathRenderer(*path, stroke, fGpu, false, type); 302bf2c6afceebb56969edeedda8114b172165a2982bsalomon@google.com } 303e6aa2fce1b318c69ecf03324d19f93168e86feb6bsalomon@google.com if (NULL == pr) { 304e6aa2fce1b318c69ecf03324d19f93168e86feb6bsalomon@google.com return false; 305e6aa2fce1b318c69ecf03324d19f93168e86feb6bsalomon@google.com } 306e6aa2fce1b318c69ecf03324d19f93168e86feb6bsalomon@google.com pr->drawPath(element->getPath(), stroke, fGpu, element->isAA()); 307e6aa2fce1b318c69ecf03324d19f93168e86feb6bsalomon@google.com break; 308e6aa2fce1b318c69ecf03324d19f93168e86feb6bsalomon@google.com } 3097830e470d00cdeb468ebf34525bc9f3f0c731014bsalomon@google.com default: 3107830e470d00cdeb468ebf34525bc9f3f0c731014bsalomon@google.com // something is wrong if we're trying to draw an empty element. 3117830e470d00cdeb468ebf34525bc9f3f0c731014bsalomon@google.com GrCrash("Unexpected element type"); 3127830e470d00cdeb468ebf34525bc9f3f0c731014bsalomon@google.com return false; 313fcf86a350bf9d8cdaff79d69bc8f3fecd019817brobertphillips@google.com } 314fcf86a350bf9d8cdaff79d69bc8f3fecd019817brobertphillips@google.com return true; 315fcf86a350bf9d8cdaff79d69bc8f3fecd019817brobertphillips@google.com} 316fcf86a350bf9d8cdaff79d69bc8f3fecd019817brobertphillips@google.com 317bf2c6afceebb56969edeedda8114b172165a2982bsalomon@google.combool GrClipMaskManager::canStencilAndDrawElement(GrTexture* target, 318bf2c6afceebb56969edeedda8114b172165a2982bsalomon@google.com const SkClipStack::Element* element, 319bf2c6afceebb56969edeedda8114b172165a2982bsalomon@google.com GrPathRenderer** pr) { 320bf2c6afceebb56969edeedda8114b172165a2982bsalomon@google.com GrDrawState* drawState = fGpu->drawState(); 321bf2c6afceebb56969edeedda8114b172165a2982bsalomon@google.com drawState->setRenderTarget(target->asRenderTarget()); 322bf2c6afceebb56969edeedda8114b172165a2982bsalomon@google.com 323bf2c6afceebb56969edeedda8114b172165a2982bsalomon@google.com switch (element->getType()) { 324bf2c6afceebb56969edeedda8114b172165a2982bsalomon@google.com case Element::kRect_Type: 325bf2c6afceebb56969edeedda8114b172165a2982bsalomon@google.com return true; 326bf2c6afceebb56969edeedda8114b172165a2982bsalomon@google.com case Element::kPath_Type: { 327bf2c6afceebb56969edeedda8114b172165a2982bsalomon@google.com SkTCopyOnFirstWrite<SkPath> path(element->getPath()); 328bf2c6afceebb56969edeedda8114b172165a2982bsalomon@google.com if (path->isInverseFillType()) { 329bf2c6afceebb56969edeedda8114b172165a2982bsalomon@google.com path.writable()->toggleInverseFillType(); 330bf2c6afceebb56969edeedda8114b172165a2982bsalomon@google.com } 3315c2ee5c5d8f8593d40a2a9ffd9ca834653ee6af1sugoi@google.com SkStrokeRec stroke(SkStrokeRec::kFill_InitStyle); 332bf2c6afceebb56969edeedda8114b172165a2982bsalomon@google.com GrPathRendererChain::DrawType type = element->isAA() ? 333bf2c6afceebb56969edeedda8114b172165a2982bsalomon@google.com GrPathRendererChain::kStencilAndColorAntiAlias_DrawType : 334bf2c6afceebb56969edeedda8114b172165a2982bsalomon@google.com GrPathRendererChain::kStencilAndColor_DrawType; 335bf2c6afceebb56969edeedda8114b172165a2982bsalomon@google.com *pr = this->getContext()->getPathRenderer(*path, stroke, fGpu, false, type); 336bf2c6afceebb56969edeedda8114b172165a2982bsalomon@google.com return NULL != *pr; 337bf2c6afceebb56969edeedda8114b172165a2982bsalomon@google.com } 338bf2c6afceebb56969edeedda8114b172165a2982bsalomon@google.com default: 339bf2c6afceebb56969edeedda8114b172165a2982bsalomon@google.com // something is wrong if we're trying to draw an empty element. 340bf2c6afceebb56969edeedda8114b172165a2982bsalomon@google.com GrCrash("Unexpected element type"); 341bf2c6afceebb56969edeedda8114b172165a2982bsalomon@google.com return false; 342bf2c6afceebb56969edeedda8114b172165a2982bsalomon@google.com } 343bf2c6afceebb56969edeedda8114b172165a2982bsalomon@google.com} 344bf2c6afceebb56969edeedda8114b172165a2982bsalomon@google.com 345746496832ab4c5f603dbb7efa12a68f3b08bed8dbsalomon@google.comvoid GrClipMaskManager::mergeMask(GrTexture* dstMask, 346746496832ab4c5f603dbb7efa12a68f3b08bed8dbsalomon@google.com GrTexture* srcMask, 347746496832ab4c5f603dbb7efa12a68f3b08bed8dbsalomon@google.com SkRegion::Op op, 348a8cbc57c2d74f8024d149370377bd7dcbd8d204ccommit-bot@chromium.org const SkIRect& dstBound, 349a8cbc57c2d74f8024d149370377bd7dcbd8d204ccommit-bot@chromium.org const SkIRect& srcBound) { 350fbf9f30e11f6dfae9203b152092125fe9b47adb8bsalomon@google.com GrDrawState::AutoViewMatrixRestore avmr; 35162310c0ce7ef008e106b483e568fcfa03fb04e66bsalomon@google.com GrDrawState* drawState = fGpu->drawState(); 352fbf9f30e11f6dfae9203b152092125fe9b47adb8bsalomon@google.com SkAssertResult(avmr.setIdentity(drawState)); 353860912a0affd82bc6b30ad9006658df856ca1d17bsalomon@google.com GrDrawState::AutoRestoreEffects are(drawState); 354fcf86a350bf9d8cdaff79d69bc8f3fecd019817brobertphillips@google.com 355746496832ab4c5f603dbb7efa12a68f3b08bed8dbsalomon@google.com drawState->setRenderTarget(dstMask->asRenderTarget()); 356fcf86a350bf9d8cdaff79d69bc8f3fecd019817brobertphillips@google.com 357746496832ab4c5f603dbb7efa12a68f3b08bed8dbsalomon@google.com setup_boolean_blendcoeffs(drawState, op); 35834b845f26af9ca8e747ae2439c5c9abb28388f4eskia.committer@gmail.com 359a4e2f5beb2d73243c15ab871f013d2ba29e8fea3bsalomon@google.com SkMatrix sampleM; 360746496832ab4c5f603dbb7efa12a68f3b08bed8dbsalomon@google.com sampleM.setIDiv(srcMask->width(), srcMask->height()); 36137d2c1133a35ca9ef444823d7f1a6a79b3f7871fskia.committer@gmail.com 362860912a0affd82bc6b30ad9006658df856ca1d17bsalomon@google.com drawState->addColorEffect( 363746496832ab4c5f603dbb7efa12a68f3b08bed8dbsalomon@google.com GrTextureDomainEffect::Create(srcMask, 364746496832ab4c5f603dbb7efa12a68f3b08bed8dbsalomon@google.com sampleM, 365746496832ab4c5f603dbb7efa12a68f3b08bed8dbsalomon@google.com GrTextureDomainEffect::MakeTexelDomain(srcMask, srcBound), 3668bc9236bf27d711cc7fe5cd618b02d29d7c59881bsalomon@google.com GrTextureDomainEffect::kDecal_WrapMode, 36729ba4805e88962ad40e3ca79c9a768e073f52badhumper@google.com GrTextureParams::kNone_FilterMode))->unref(); 368746496832ab4c5f603dbb7efa12a68f3b08bed8dbsalomon@google.com fGpu->drawSimpleRect(SkRect::MakeFromIRect(dstBound), NULL); 369fcf86a350bf9d8cdaff79d69bc8f3fecd019817brobertphillips@google.com} 370fcf86a350bf9d8cdaff79d69bc8f3fecd019817brobertphillips@google.com 371bb3e02c86c0bc10ad2f064718166c19809fac440robertphillips@google.com// get a texture to act as a temporary buffer for AA clip boolean operations 372bb3e02c86c0bc10ad2f064718166c19809fac440robertphillips@google.com// TODO: given the expense of createTexture we may want to just cache this too 373e6aa2fce1b318c69ecf03324d19f93168e86feb6bsalomon@google.comvoid GrClipMaskManager::getTemp(int width, int height, GrAutoScratchTexture* temp) { 3740fe76ba222e76bf6610aa99f7f605d25da059cd3robertphillips@google.com if (NULL != temp->texture()) { 375bb3e02c86c0bc10ad2f064718166c19809fac440robertphillips@google.com // we've already allocated the temp texture 376bb3e02c86c0bc10ad2f064718166c19809fac440robertphillips@google.com return; 377bb3e02c86c0bc10ad2f064718166c19809fac440robertphillips@google.com } 378bb3e02c86c0bc10ad2f064718166c19809fac440robertphillips@google.com 379c937ae9bcbf6bdb6fe7f6b4cdb518a684fb5f1barobertphillips@google.com GrTextureDesc desc; 380c937ae9bcbf6bdb6fe7f6b4cdb518a684fb5f1barobertphillips@google.com desc.fFlags = kRenderTarget_GrTextureFlagBit|kNoStencil_GrTextureFlagBit; 381e6aa2fce1b318c69ecf03324d19f93168e86feb6bsalomon@google.com desc.fWidth = width; 382e6aa2fce1b318c69ecf03324d19f93168e86feb6bsalomon@google.com desc.fHeight = height; 383c937ae9bcbf6bdb6fe7f6b4cdb518a684fb5f1barobertphillips@google.com desc.fConfig = kAlpha_8_GrPixelConfig; 3842e2671b7977fa3f1fb0b1353abae74dc3d0ddf42robertphillips@google.com 385a21adf42a7140b5420b400e1b03cbebb92b357f1robertphillips@google.com temp->set(this->getContext(), desc); 386bb3e02c86c0bc10ad2f064718166c19809fac440robertphillips@google.com} 387bb3e02c86c0bc10ad2f064718166c19809fac440robertphillips@google.com 3882e2671b7977fa3f1fb0b1353abae74dc3d0ddf42robertphillips@google.com//////////////////////////////////////////////////////////////////////////////// 389e6aa2fce1b318c69ecf03324d19f93168e86feb6bsalomon@google.com// Handles caching & allocation (if needed) of a clip alpha-mask texture for both the sw-upload 390e6aa2fce1b318c69ecf03324d19f93168e86feb6bsalomon@google.com// or gpu-rendered cases. Returns true if there is no more work to be done (i.e., we got a cache 391e6aa2fce1b318c69ecf03324d19f93168e86feb6bsalomon@google.com// hit) 392e6aa2fce1b318c69ecf03324d19f93168e86feb6bsalomon@google.combool GrClipMaskManager::getMaskTexture(int32_t clipStackGenID, 393e6aa2fce1b318c69ecf03324d19f93168e86feb6bsalomon@google.com const SkIRect& clipSpaceIBounds, 394e6aa2fce1b318c69ecf03324d19f93168e86feb6bsalomon@google.com GrTexture** result) { 395e6aa2fce1b318c69ecf03324d19f93168e86feb6bsalomon@google.com bool cached = fAACache.canReuse(clipStackGenID, clipSpaceIBounds); 396e6aa2fce1b318c69ecf03324d19f93168e86feb6bsalomon@google.com if (!cached) { 397e6aa2fce1b318c69ecf03324d19f93168e86feb6bsalomon@google.com 398e6aa2fce1b318c69ecf03324d19f93168e86feb6bsalomon@google.com // There isn't a suitable entry in the cache so we create a new texture to store the mask. 399e6aa2fce1b318c69ecf03324d19f93168e86feb6bsalomon@google.com // Since we are setting up the cache we know the last lookup was a miss. Free up the 400e6aa2fce1b318c69ecf03324d19f93168e86feb6bsalomon@google.com // currently cached mask so it can be reused. 401e6aa2fce1b318c69ecf03324d19f93168e86feb6bsalomon@google.com fAACache.reset(); 402fcf86a350bf9d8cdaff79d69bc8f3fecd019817brobertphillips@google.com 403e6aa2fce1b318c69ecf03324d19f93168e86feb6bsalomon@google.com GrTextureDesc desc; 404bf2c6afceebb56969edeedda8114b172165a2982bsalomon@google.com desc.fFlags = kRenderTarget_GrTextureFlagBit; 405e6aa2fce1b318c69ecf03324d19f93168e86feb6bsalomon@google.com desc.fWidth = clipSpaceIBounds.width(); 406e6aa2fce1b318c69ecf03324d19f93168e86feb6bsalomon@google.com desc.fHeight = clipSpaceIBounds.height(); 407ccc9cf9a1f76a236d9e30725646933afa0b72e57robertphillips@google.com desc.fConfig = kRGBA_8888_GrPixelConfig; 408ccc9cf9a1f76a236d9e30725646933afa0b72e57robertphillips@google.com if (this->getContext()->isConfigRenderable(kAlpha_8_GrPixelConfig)) { 409ccc9cf9a1f76a236d9e30725646933afa0b72e57robertphillips@google.com // We would always like A8 but it isn't supported on all platforms 410ccc9cf9a1f76a236d9e30725646933afa0b72e57robertphillips@google.com desc.fConfig = kAlpha_8_GrPixelConfig; 411ccc9cf9a1f76a236d9e30725646933afa0b72e57robertphillips@google.com } 412b59d0a5438a70249b58c51a35980c1930b5078b5robertphillips@google.com 413e6aa2fce1b318c69ecf03324d19f93168e86feb6bsalomon@google.com fAACache.acquireMask(clipStackGenID, desc, clipSpaceIBounds); 414d787b85db007288b95757d7098a4f213bc60de63robertphillips@google.com } 415d787b85db007288b95757d7098a4f213bc60de63robertphillips@google.com 416e6aa2fce1b318c69ecf03324d19f93168e86feb6bsalomon@google.com *result = fAACache.getLastMask(); 417e6aa2fce1b318c69ecf03324d19f93168e86feb6bsalomon@google.com return cached; 4182e2671b7977fa3f1fb0b1353abae74dc3d0ddf42robertphillips@google.com} 419fcf86a350bf9d8cdaff79d69bc8f3fecd019817brobertphillips@google.com 4202e2671b7977fa3f1fb0b1353abae74dc3d0ddf42robertphillips@google.com//////////////////////////////////////////////////////////////////////////////// 4212e2671b7977fa3f1fb0b1353abae74dc3d0ddf42robertphillips@google.com// Create a 8-bit clip mask in alpha 422e6aa2fce1b318c69ecf03324d19f93168e86feb6bsalomon@google.comGrTexture* GrClipMaskManager::createAlphaClipMask(int32_t clipStackGenID, 423e6aa2fce1b318c69ecf03324d19f93168e86feb6bsalomon@google.com InitialState initialState, 424e6aa2fce1b318c69ecf03324d19f93168e86feb6bsalomon@google.com const ElementList& elements, 425e6aa2fce1b318c69ecf03324d19f93168e86feb6bsalomon@google.com const SkIRect& clipSpaceIBounds) { 4260c4165f59a09574d521de66abeb3cc3101b04bd6bsalomon@google.com GrAssert(kNone_ClipMaskType == fCurrClipMaskType); 4270c4165f59a09574d521de66abeb3cc3101b04bd6bsalomon@google.com 428e6aa2fce1b318c69ecf03324d19f93168e86feb6bsalomon@google.com GrTexture* result; 429e6aa2fce1b318c69ecf03324d19f93168e86feb6bsalomon@google.com if (this->getMaskTexture(clipStackGenID, clipSpaceIBounds, &result)) { 4300c4165f59a09574d521de66abeb3cc3101b04bd6bsalomon@google.com fCurrClipMaskType = kAlpha_ClipMaskType; 431e6aa2fce1b318c69ecf03324d19f93168e86feb6bsalomon@google.com return result; 4322e2671b7977fa3f1fb0b1353abae74dc3d0ddf42robertphillips@google.com } 433fcf86a350bf9d8cdaff79d69bc8f3fecd019817brobertphillips@google.com 434e6aa2fce1b318c69ecf03324d19f93168e86feb6bsalomon@google.com if (NULL == result) { 4350fe76ba222e76bf6610aa99f7f605d25da059cd3robertphillips@google.com fAACache.reset(); 436e6aa2fce1b318c69ecf03324d19f93168e86feb6bsalomon@google.com return NULL; 437fcf86a350bf9d8cdaff79d69bc8f3fecd019817brobertphillips@google.com } 438fcf86a350bf9d8cdaff79d69bc8f3fecd019817brobertphillips@google.com 439e6aa2fce1b318c69ecf03324d19f93168e86feb6bsalomon@google.com // The top-left of the mask corresponds to the top-left corner of the bounds. 440746496832ab4c5f603dbb7efa12a68f3b08bed8dbsalomon@google.com SkVector clipToMaskOffset = { 441e6aa2fce1b318c69ecf03324d19f93168e86feb6bsalomon@google.com SkIntToScalar(-clipSpaceIBounds.fLeft), 442e6aa2fce1b318c69ecf03324d19f93168e86feb6bsalomon@google.com SkIntToScalar(-clipSpaceIBounds.fTop) 443746496832ab4c5f603dbb7efa12a68f3b08bed8dbsalomon@google.com }; 444e6aa2fce1b318c69ecf03324d19f93168e86feb6bsalomon@google.com // The texture may be larger than necessary, this rect represents the part of the texture 445e6aa2fce1b318c69ecf03324d19f93168e86feb6bsalomon@google.com // we populate with a rasterization of the clip. 446e6aa2fce1b318c69ecf03324d19f93168e86feb6bsalomon@google.com SkIRect maskSpaceIBounds = SkIRect::MakeWH(clipSpaceIBounds.width(), clipSpaceIBounds.height()); 447fcf86a350bf9d8cdaff79d69bc8f3fecd019817brobertphillips@google.com 448fbf9f30e11f6dfae9203b152092125fe9b47adb8bsalomon@google.com // Set the matrix so that rendered clip elements are transformed to mask space from clip space. 449fbf9f30e11f6dfae9203b152092125fe9b47adb8bsalomon@google.com SkMatrix translate; 450fbf9f30e11f6dfae9203b152092125fe9b47adb8bsalomon@google.com translate.setTranslate(clipToMaskOffset); 451fbf9f30e11f6dfae9203b152092125fe9b47adb8bsalomon@google.com GrDrawTarget::AutoGeometryAndStatePush agasp(fGpu, GrDrawTarget::kReset_ASRInit, &translate); 452fbf9f30e11f6dfae9203b152092125fe9b47adb8bsalomon@google.com 453fbf9f30e11f6dfae9203b152092125fe9b47adb8bsalomon@google.com GrDrawState* drawState = fGpu->drawState(); 454fbf9f30e11f6dfae9203b152092125fe9b47adb8bsalomon@google.com 455bfaf011e7439431680ac6929f7a48c30e4fdaf89bsalomon@google.com // We're drawing a coverage mask and want coverage to be run through the blend function. 456bfaf011e7439431680ac6929f7a48c30e4fdaf89bsalomon@google.com drawState->enableState(GrDrawState::kCoverageDrawing_StateBit); 457bfaf011e7439431680ac6929f7a48c30e4fdaf89bsalomon@google.com 458746496832ab4c5f603dbb7efa12a68f3b08bed8dbsalomon@google.com // The scratch texture that we are drawing into can be substantially larger than the mask. Only 459746496832ab4c5f603dbb7efa12a68f3b08bed8dbsalomon@google.com // clear the part that we care about. 460e6aa2fce1b318c69ecf03324d19f93168e86feb6bsalomon@google.com fGpu->clear(&maskSpaceIBounds, 461e6aa2fce1b318c69ecf03324d19f93168e86feb6bsalomon@google.com kAllIn_InitialState == initialState ? 0xffffffff : 0x00000000, 462e6aa2fce1b318c69ecf03324d19f93168e86feb6bsalomon@google.com result->asRenderTarget()); 46397a687296e1523295073a7181a3c550cba38d8f6skia.committer@gmail.com 464bf2c6afceebb56969edeedda8114b172165a2982bsalomon@google.com // When we use the stencil in the below loop it is important to have this clip installed. 465bf2c6afceebb56969edeedda8114b172165a2982bsalomon@google.com // The second pass that zeros the stencil buffer renders the rect maskSpaceIBounds so the first 466bf2c6afceebb56969edeedda8114b172165a2982bsalomon@google.com // pass must not set values outside of this bounds or stencil values outside the rect won't be 467bf2c6afceebb56969edeedda8114b172165a2982bsalomon@google.com // cleared. 468bf2c6afceebb56969edeedda8114b172165a2982bsalomon@google.com GrDrawTarget::AutoClipRestore acr(fGpu, maskSpaceIBounds); 469bf2c6afceebb56969edeedda8114b172165a2982bsalomon@google.com drawState->enableState(GrDrawState::kClip_StateBit); 470bf2c6afceebb56969edeedda8114b172165a2982bsalomon@google.com 4710fe76ba222e76bf6610aa99f7f605d25da059cd3robertphillips@google.com GrAutoScratchTexture temp; 472fcf86a350bf9d8cdaff79d69bc8f3fecd019817brobertphillips@google.com // walk through each clip element and perform its set op 473e6aa2fce1b318c69ecf03324d19f93168e86feb6bsalomon@google.com for (ElementList::Iter iter = elements.headIter(); iter.get(); iter.next()) { 474e6aa2fce1b318c69ecf03324d19f93168e86feb6bsalomon@google.com const Element* element = iter.get(); 4757830e470d00cdeb468ebf34525bc9f3f0c731014bsalomon@google.com SkRegion::Op op = element->getOp(); 476bf2c6afceebb56969edeedda8114b172165a2982bsalomon@google.com bool invert = element->isInverseFilled(); 477fcf86a350bf9d8cdaff79d69bc8f3fecd019817brobertphillips@google.com 478bf2c6afceebb56969edeedda8114b172165a2982bsalomon@google.com if (invert || SkRegion::kIntersect_Op == op || SkRegion::kReverseDifference_Op == op) { 479bf2c6afceebb56969edeedda8114b172165a2982bsalomon@google.com GrPathRenderer* pr = NULL; 480bf2c6afceebb56969edeedda8114b172165a2982bsalomon@google.com bool useTemp = !this->canStencilAndDrawElement(result, element, &pr); 481bf2c6afceebb56969edeedda8114b172165a2982bsalomon@google.com GrTexture* dst; 482e6aa2fce1b318c69ecf03324d19f93168e86feb6bsalomon@google.com // This is the bounds of the clip element in the space of the alpha-mask. The temporary 483746496832ab4c5f603dbb7efa12a68f3b08bed8dbsalomon@google.com // mask buffer can be substantially larger than the actually clip stack element. We 484746496832ab4c5f603dbb7efa12a68f3b08bed8dbsalomon@google.com // touch the minimum number of pixels necessary and use decal mode to combine it with 485bf2c6afceebb56969edeedda8114b172165a2982bsalomon@google.com // the accumulator. 486a8cbc57c2d74f8024d149370377bd7dcbd8d204ccommit-bot@chromium.org SkIRect maskSpaceElementIBounds; 487bf2c6afceebb56969edeedda8114b172165a2982bsalomon@google.com 488bf2c6afceebb56969edeedda8114b172165a2982bsalomon@google.com if (useTemp) { 489bf2c6afceebb56969edeedda8114b172165a2982bsalomon@google.com if (invert) { 490bf2c6afceebb56969edeedda8114b172165a2982bsalomon@google.com maskSpaceElementIBounds = maskSpaceIBounds; 491bf2c6afceebb56969edeedda8114b172165a2982bsalomon@google.com } else { 492a8cbc57c2d74f8024d149370377bd7dcbd8d204ccommit-bot@chromium.org SkRect elementBounds = element->getBounds(); 493bf2c6afceebb56969edeedda8114b172165a2982bsalomon@google.com elementBounds.offset(clipToMaskOffset); 494bf2c6afceebb56969edeedda8114b172165a2982bsalomon@google.com elementBounds.roundOut(&maskSpaceElementIBounds); 495bf2c6afceebb56969edeedda8114b172165a2982bsalomon@google.com } 496bf2c6afceebb56969edeedda8114b172165a2982bsalomon@google.com 497bf2c6afceebb56969edeedda8114b172165a2982bsalomon@google.com this->getTemp(maskSpaceIBounds.fRight, maskSpaceIBounds.fBottom, &temp); 498bf2c6afceebb56969edeedda8114b172165a2982bsalomon@google.com if (NULL == temp.texture()) { 499bf2c6afceebb56969edeedda8114b172165a2982bsalomon@google.com fAACache.reset(); 500bf2c6afceebb56969edeedda8114b172165a2982bsalomon@google.com return NULL; 501d98496744f026ccd603b12b461a79cda70129e77skia.committer@gmail.com } 502bf2c6afceebb56969edeedda8114b172165a2982bsalomon@google.com dst = temp.texture(); 503bf2c6afceebb56969edeedda8114b172165a2982bsalomon@google.com // clear the temp target and set blend to replace 504bf2c6afceebb56969edeedda8114b172165a2982bsalomon@google.com fGpu->clear(&maskSpaceElementIBounds, 505bf2c6afceebb56969edeedda8114b172165a2982bsalomon@google.com invert ? 0xffffffff : 0x00000000, 506bf2c6afceebb56969edeedda8114b172165a2982bsalomon@google.com dst->asRenderTarget()); 507bf2c6afceebb56969edeedda8114b172165a2982bsalomon@google.com setup_boolean_blendcoeffs(drawState, SkRegion::kReplace_Op); 508d98496744f026ccd603b12b461a79cda70129e77skia.committer@gmail.com 509e6aa2fce1b318c69ecf03324d19f93168e86feb6bsalomon@google.com } else { 510bf2c6afceebb56969edeedda8114b172165a2982bsalomon@google.com // draw directly into the result with the stencil set to make the pixels affected 511bf2c6afceebb56969edeedda8114b172165a2982bsalomon@google.com // by the clip shape be non-zero. 512bf2c6afceebb56969edeedda8114b172165a2982bsalomon@google.com dst = result; 513bf2c6afceebb56969edeedda8114b172165a2982bsalomon@google.com GR_STATIC_CONST_SAME_STENCIL(kStencilInElement, 514bf2c6afceebb56969edeedda8114b172165a2982bsalomon@google.com kReplace_StencilOp, 515bf2c6afceebb56969edeedda8114b172165a2982bsalomon@google.com kReplace_StencilOp, 516bf2c6afceebb56969edeedda8114b172165a2982bsalomon@google.com kAlways_StencilFunc, 517bf2c6afceebb56969edeedda8114b172165a2982bsalomon@google.com 0xffff, 518bf2c6afceebb56969edeedda8114b172165a2982bsalomon@google.com 0xffff, 519bf2c6afceebb56969edeedda8114b172165a2982bsalomon@google.com 0xffff); 520bf2c6afceebb56969edeedda8114b172165a2982bsalomon@google.com drawState->setStencil(kStencilInElement); 521d98496744f026ccd603b12b461a79cda70129e77skia.committer@gmail.com setup_boolean_blendcoeffs(drawState, op); 522e6aa2fce1b318c69ecf03324d19f93168e86feb6bsalomon@google.com } 523746496832ab4c5f603dbb7efa12a68f3b08bed8dbsalomon@google.com 52431997dacc509386a68fbd000d979801268f36767bsalomon@google.com drawState->setAlpha(invert ? 0x00 : 0xff); 52531997dacc509386a68fbd000d979801268f36767bsalomon@google.com 526bf2c6afceebb56969edeedda8114b172165a2982bsalomon@google.com if (!this->drawElement(dst, element, pr)) { 527e6aa2fce1b318c69ecf03324d19f93168e86feb6bsalomon@google.com fAACache.reset(); 528e6aa2fce1b318c69ecf03324d19f93168e86feb6bsalomon@google.com return NULL; 529e6aa2fce1b318c69ecf03324d19f93168e86feb6bsalomon@google.com } 530fcf86a350bf9d8cdaff79d69bc8f3fecd019817brobertphillips@google.com 531bf2c6afceebb56969edeedda8114b172165a2982bsalomon@google.com if (useTemp) { 532bf2c6afceebb56969edeedda8114b172165a2982bsalomon@google.com // Now draw into the accumulator using the real operation and the temp buffer as a 533bf2c6afceebb56969edeedda8114b172165a2982bsalomon@google.com // texture 534bf2c6afceebb56969edeedda8114b172165a2982bsalomon@google.com this->mergeMask(result, 535bf2c6afceebb56969edeedda8114b172165a2982bsalomon@google.com temp.texture(), 536bf2c6afceebb56969edeedda8114b172165a2982bsalomon@google.com op, 537bf2c6afceebb56969edeedda8114b172165a2982bsalomon@google.com maskSpaceIBounds, 538bf2c6afceebb56969edeedda8114b172165a2982bsalomon@google.com maskSpaceElementIBounds); 539bf2c6afceebb56969edeedda8114b172165a2982bsalomon@google.com } else { 540bf2c6afceebb56969edeedda8114b172165a2982bsalomon@google.com // Draw to the exterior pixels (those with a zero stencil value). 541bf2c6afceebb56969edeedda8114b172165a2982bsalomon@google.com drawState->setAlpha(invert ? 0xff : 0x00); 542bf2c6afceebb56969edeedda8114b172165a2982bsalomon@google.com GR_STATIC_CONST_SAME_STENCIL(kDrawOutsideElement, 543bf2c6afceebb56969edeedda8114b172165a2982bsalomon@google.com kZero_StencilOp, 544bf2c6afceebb56969edeedda8114b172165a2982bsalomon@google.com kZero_StencilOp, 545bf2c6afceebb56969edeedda8114b172165a2982bsalomon@google.com kEqual_StencilFunc, 546bf2c6afceebb56969edeedda8114b172165a2982bsalomon@google.com 0xffff, 547bf2c6afceebb56969edeedda8114b172165a2982bsalomon@google.com 0x0000, 548bf2c6afceebb56969edeedda8114b172165a2982bsalomon@google.com 0xffff); 549bf2c6afceebb56969edeedda8114b172165a2982bsalomon@google.com drawState->setStencil(kDrawOutsideElement); 550bf2c6afceebb56969edeedda8114b172165a2982bsalomon@google.com fGpu->drawSimpleRect(clipSpaceIBounds); 551bf2c6afceebb56969edeedda8114b172165a2982bsalomon@google.com drawState->disableStencil(); 552bf2c6afceebb56969edeedda8114b172165a2982bsalomon@google.com } 553fcf86a350bf9d8cdaff79d69bc8f3fecd019817brobertphillips@google.com } else { 55431997dacc509386a68fbd000d979801268f36767bsalomon@google.com // all the remaining ops can just be directly draw into the accumulation buffer 55531997dacc509386a68fbd000d979801268f36767bsalomon@google.com drawState->setAlpha(0xff); 5562e2671b7977fa3f1fb0b1353abae74dc3d0ddf42robertphillips@google.com setup_boolean_blendcoeffs(drawState, op); 557bf2c6afceebb56969edeedda8114b172165a2982bsalomon@google.com this->drawElement(result, element); 558fcf86a350bf9d8cdaff79d69bc8f3fecd019817brobertphillips@google.com } 559fcf86a350bf9d8cdaff79d69bc8f3fecd019817brobertphillips@google.com } 560fcf86a350bf9d8cdaff79d69bc8f3fecd019817brobertphillips@google.com 5610c4165f59a09574d521de66abeb3cc3101b04bd6bsalomon@google.com fCurrClipMaskType = kAlpha_ClipMaskType; 562e6aa2fce1b318c69ecf03324d19f93168e86feb6bsalomon@google.com return result; 563321f62ca78984b4e78d0f2c014af46327cf7331crobertphillips@google.com} 564321f62ca78984b4e78d0f2c014af46327cf7331crobertphillips@google.com 565fcf86a350bf9d8cdaff79d69bc8f3fecd019817brobertphillips@google.com//////////////////////////////////////////////////////////////////////////////// 566935e9f4fafdfc64130e6be9ea2bb30e3bafd852armistry@google.com// Create a 1-bit clip mask in the stencil buffer. 'devClipBounds' are in device 567784f40d04a98ffa1fe187474716844b17bceed3arobertphillips@google.com// (as opposed to canvas) coordinates 568e6aa2fce1b318c69ecf03324d19f93168e86feb6bsalomon@google.combool GrClipMaskManager::createStencilClipMask(InitialState initialState, 569e6aa2fce1b318c69ecf03324d19f93168e86feb6bsalomon@google.com const ElementList& elements, 570e6aa2fce1b318c69ecf03324d19f93168e86feb6bsalomon@google.com const SkIRect& clipSpaceIBounds, 571e6aa2fce1b318c69ecf03324d19f93168e86feb6bsalomon@google.com const SkIPoint& clipSpaceToStencilOffset) { 572321f62ca78984b4e78d0f2c014af46327cf7331crobertphillips@google.com 5730c4165f59a09574d521de66abeb3cc3101b04bd6bsalomon@google.com GrAssert(kNone_ClipMaskType == fCurrClipMaskType); 574321f62ca78984b4e78d0f2c014af46327cf7331crobertphillips@google.com 57562310c0ce7ef008e106b483e568fcfa03fb04e66bsalomon@google.com GrDrawState* drawState = fGpu->drawState(); 576321f62ca78984b4e78d0f2c014af46327cf7331crobertphillips@google.com GrAssert(drawState->isClipState()); 577321f62ca78984b4e78d0f2c014af46327cf7331crobertphillips@google.com 578321f62ca78984b4e78d0f2c014af46327cf7331crobertphillips@google.com GrRenderTarget* rt = drawState->getRenderTarget(); 579321f62ca78984b4e78d0f2c014af46327cf7331crobertphillips@google.com GrAssert(NULL != rt); 580321f62ca78984b4e78d0f2c014af46327cf7331crobertphillips@google.com 581321f62ca78984b4e78d0f2c014af46327cf7331crobertphillips@google.com // TODO: dynamically attach a SB when needed. 582321f62ca78984b4e78d0f2c014af46327cf7331crobertphillips@google.com GrStencilBuffer* stencilBuffer = rt->getStencilBuffer(); 583321f62ca78984b4e78d0f2c014af46327cf7331crobertphillips@google.com if (NULL == stencilBuffer) { 584321f62ca78984b4e78d0f2c014af46327cf7331crobertphillips@google.com return false; 585321f62ca78984b4e78d0f2c014af46327cf7331crobertphillips@google.com } 586e6aa2fce1b318c69ecf03324d19f93168e86feb6bsalomon@google.com int32_t genID = elements.tail()->getGenID(); 587321f62ca78984b4e78d0f2c014af46327cf7331crobertphillips@google.com 588e6aa2fce1b318c69ecf03324d19f93168e86feb6bsalomon@google.com if (stencilBuffer->mustRenderClip(genID, clipSpaceIBounds, clipSpaceToStencilOffset)) { 589321f62ca78984b4e78d0f2c014af46327cf7331crobertphillips@google.com 590e6aa2fce1b318c69ecf03324d19f93168e86feb6bsalomon@google.com stencilBuffer->setLastClip(genID, clipSpaceIBounds, clipSpaceToStencilOffset); 591321f62ca78984b4e78d0f2c014af46327cf7331crobertphillips@google.com 592fbf9f30e11f6dfae9203b152092125fe9b47adb8bsalomon@google.com // Set the matrix so that rendered clip elements are transformed from clip to stencil space. 593fbf9f30e11f6dfae9203b152092125fe9b47adb8bsalomon@google.com SkVector translate = { 594fbf9f30e11f6dfae9203b152092125fe9b47adb8bsalomon@google.com SkIntToScalar(clipSpaceToStencilOffset.fX), 595fbf9f30e11f6dfae9203b152092125fe9b47adb8bsalomon@google.com SkIntToScalar(clipSpaceToStencilOffset.fY) 596fbf9f30e11f6dfae9203b152092125fe9b47adb8bsalomon@google.com }; 597fbf9f30e11f6dfae9203b152092125fe9b47adb8bsalomon@google.com SkMatrix matrix; 598fbf9f30e11f6dfae9203b152092125fe9b47adb8bsalomon@google.com matrix.setTranslate(translate); 599fbf9f30e11f6dfae9203b152092125fe9b47adb8bsalomon@google.com GrDrawTarget::AutoGeometryAndStatePush agasp(fGpu, GrDrawTarget::kReset_ASRInit, &matrix); 60062310c0ce7ef008e106b483e568fcfa03fb04e66bsalomon@google.com drawState = fGpu->drawState(); 601fbf9f30e11f6dfae9203b152092125fe9b47adb8bsalomon@google.com 602321f62ca78984b4e78d0f2c014af46327cf7331crobertphillips@google.com drawState->setRenderTarget(rt); 603321f62ca78984b4e78d0f2c014af46327cf7331crobertphillips@google.com 6043e084cbcaddfd2f130479a9a8e4e82626f5ce524bsalomon@google.com // We set the current clip to the bounds so that our recursive draws are scissored to them. 6053e084cbcaddfd2f130479a9a8e4e82626f5ce524bsalomon@google.com SkIRect stencilSpaceIBounds(clipSpaceIBounds); 6063e084cbcaddfd2f130479a9a8e4e82626f5ce524bsalomon@google.com stencilSpaceIBounds.offset(clipSpaceToStencilOffset); 6073e084cbcaddfd2f130479a9a8e4e82626f5ce524bsalomon@google.com GrDrawTarget::AutoClipRestore acr(fGpu, stencilSpaceIBounds); 6083e084cbcaddfd2f130479a9a8e4e82626f5ce524bsalomon@google.com drawState->enableState(GrDrawState::kClip_StateBit); 6093e084cbcaddfd2f130479a9a8e4e82626f5ce524bsalomon@google.com 610321f62ca78984b4e78d0f2c014af46327cf7331crobertphillips@google.com#if !VISUALIZE_COMPLEX_CLIP 611321f62ca78984b4e78d0f2c014af46327cf7331crobertphillips@google.com drawState->enableState(GrDrawState::kNoColorWrites_StateBit); 612321f62ca78984b4e78d0f2c014af46327cf7331crobertphillips@google.com#endif 613321f62ca78984b4e78d0f2c014af46327cf7331crobertphillips@google.com 614321f62ca78984b4e78d0f2c014af46327cf7331crobertphillips@google.com int clipBit = stencilBuffer->bits(); 615e6aa2fce1b318c69ecf03324d19f93168e86feb6bsalomon@google.com SkASSERT((clipBit <= 16) && "Ganesh only handles 16b or smaller stencil buffers"); 616321f62ca78984b4e78d0f2c014af46327cf7331crobertphillips@google.com clipBit = (1 << (clipBit-1)); 617321f62ca78984b4e78d0f2c014af46327cf7331crobertphillips@google.com 618e6aa2fce1b318c69ecf03324d19f93168e86feb6bsalomon@google.com fGpu->clearStencilClip(stencilSpaceIBounds, kAllIn_InitialState == initialState); 619321f62ca78984b4e78d0f2c014af46327cf7331crobertphillips@google.com 620321f62ca78984b4e78d0f2c014af46327cf7331crobertphillips@google.com // walk through each clip element and perform its set op 621321f62ca78984b4e78d0f2c014af46327cf7331crobertphillips@google.com // with the existing clip. 622e6aa2fce1b318c69ecf03324d19f93168e86feb6bsalomon@google.com for (ElementList::Iter iter(elements.headIter()); NULL != iter.get(); iter.next()) { 623e6aa2fce1b318c69ecf03324d19f93168e86feb6bsalomon@google.com const Element* element = iter.get(); 624ebf86866ddd26b1a19eb94009407dcd19c276c72tomhudson@google.com bool fillInverted = false; 625321f62ca78984b4e78d0f2c014af46327cf7331crobertphillips@google.com // enabled at bottom of loop 626321f62ca78984b4e78d0f2c014af46327cf7331crobertphillips@google.com drawState->disableState(GrGpu::kModifyStencilClip_StateBit); 6278dc33d06f5759d2e587dbd266226fc0fe0c1562bbsalomon@google.com // if the target is MSAA then we want MSAA enabled when the clip is soft 6288dc33d06f5759d2e587dbd266226fc0fe0c1562bbsalomon@google.com if (rt->isMultisampled()) { 6297830e470d00cdeb468ebf34525bc9f3f0c731014bsalomon@google.com drawState->setState(GrDrawState::kHWAntialias_StateBit, element->isAA()); 6308dc33d06f5759d2e587dbd266226fc0fe0c1562bbsalomon@google.com } 631321f62ca78984b4e78d0f2c014af46327cf7331crobertphillips@google.com 6320afd9ef7f06395f1bbbe9a18d8fcfa181d5f6bb0bsalomon@google.com // This will be used to determine whether the clip shape can be rendered into the 6330afd9ef7f06395f1bbbe9a18d8fcfa181d5f6bb0bsalomon@google.com // stencil with arbitrary stencil settings. 6340afd9ef7f06395f1bbbe9a18d8fcfa181d5f6bb0bsalomon@google.com GrPathRenderer::StencilSupport stencilSupport; 635321f62ca78984b4e78d0f2c014af46327cf7331crobertphillips@google.com 6365c2ee5c5d8f8593d40a2a9ffd9ca834653ee6af1sugoi@google.com SkStrokeRec stroke(SkStrokeRec::kFill_InitStyle); 637290bf0ae34af76a4350a5df76ce02feb93d68196sugoi@google.com 6387830e470d00cdeb468ebf34525bc9f3f0c731014bsalomon@google.com SkRegion::Op op = element->getOp(); 639fcf86a350bf9d8cdaff79d69bc8f3fecd019817brobertphillips@google.com 640321f62ca78984b4e78d0f2c014af46327cf7331crobertphillips@google.com GrPathRenderer* pr = NULL; 6410afd9ef7f06395f1bbbe9a18d8fcfa181d5f6bb0bsalomon@google.com SkTCopyOnFirstWrite<SkPath> clipPath; 6427830e470d00cdeb468ebf34525bc9f3f0c731014bsalomon@google.com if (Element::kRect_Type == element->getType()) { 6430afd9ef7f06395f1bbbe9a18d8fcfa181d5f6bb0bsalomon@google.com stencilSupport = GrPathRenderer::kNoRestriction_StencilSupport; 644321f62ca78984b4e78d0f2c014af46327cf7331crobertphillips@google.com fillInverted = false; 645ebf86866ddd26b1a19eb94009407dcd19c276c72tomhudson@google.com } else { 6467830e470d00cdeb468ebf34525bc9f3f0c731014bsalomon@google.com GrAssert(Element::kPath_Type == element->getType()); 6470afd9ef7f06395f1bbbe9a18d8fcfa181d5f6bb0bsalomon@google.com clipPath.init(element->getPath()); 6480afd9ef7f06395f1bbbe9a18d8fcfa181d5f6bb0bsalomon@google.com fillInverted = clipPath->isInverseFillType(); 6490afd9ef7f06395f1bbbe9a18d8fcfa181d5f6bb0bsalomon@google.com if (fillInverted) { 6500afd9ef7f06395f1bbbe9a18d8fcfa181d5f6bb0bsalomon@google.com clipPath.writable()->toggleInverseFillType(); 6510afd9ef7f06395f1bbbe9a18d8fcfa181d5f6bb0bsalomon@google.com } 6520afd9ef7f06395f1bbbe9a18d8fcfa181d5f6bb0bsalomon@google.com pr = this->getContext()->getPathRenderer(*clipPath, 6530afd9ef7f06395f1bbbe9a18d8fcfa181d5f6bb0bsalomon@google.com stroke, 6540afd9ef7f06395f1bbbe9a18d8fcfa181d5f6bb0bsalomon@google.com fGpu, 6550afd9ef7f06395f1bbbe9a18d8fcfa181d5f6bb0bsalomon@google.com false, 6560afd9ef7f06395f1bbbe9a18d8fcfa181d5f6bb0bsalomon@google.com GrPathRendererChain::kStencilOnly_DrawType, 6570afd9ef7f06395f1bbbe9a18d8fcfa181d5f6bb0bsalomon@google.com &stencilSupport); 658321f62ca78984b4e78d0f2c014af46327cf7331crobertphillips@google.com if (NULL == pr) { 659321f62ca78984b4e78d0f2c014af46327cf7331crobertphillips@google.com return false; 660321f62ca78984b4e78d0f2c014af46327cf7331crobertphillips@google.com } 661321f62ca78984b4e78d0f2c014af46327cf7331crobertphillips@google.com } 662321f62ca78984b4e78d0f2c014af46327cf7331crobertphillips@google.com 663321f62ca78984b4e78d0f2c014af46327cf7331crobertphillips@google.com int passes; 664321f62ca78984b4e78d0f2c014af46327cf7331crobertphillips@google.com GrStencilSettings stencilSettings[GrStencilSettings::kMaxStencilClipPasses]; 665321f62ca78984b4e78d0f2c014af46327cf7331crobertphillips@google.com 6660afd9ef7f06395f1bbbe9a18d8fcfa181d5f6bb0bsalomon@google.com bool canRenderDirectToStencil = 6670afd9ef7f06395f1bbbe9a18d8fcfa181d5f6bb0bsalomon@google.com GrPathRenderer::kNoRestriction_StencilSupport == stencilSupport; 668321f62ca78984b4e78d0f2c014af46327cf7331crobertphillips@google.com bool canDrawDirectToClip; // Given the renderer, the element, 669e6aa2fce1b318c69ecf03324d19f93168e86feb6bsalomon@google.com // fill rule, and set operation can 670e6aa2fce1b318c69ecf03324d19f93168e86feb6bsalomon@google.com // we render the element directly to 671e6aa2fce1b318c69ecf03324d19f93168e86feb6bsalomon@google.com // stencil bit used for clipping. 672e6aa2fce1b318c69ecf03324d19f93168e86feb6bsalomon@google.com canDrawDirectToClip = GrStencilSettings::GetClipPasses(op, 673e6aa2fce1b318c69ecf03324d19f93168e86feb6bsalomon@google.com canRenderDirectToStencil, 674e6aa2fce1b318c69ecf03324d19f93168e86feb6bsalomon@google.com clipBit, 675e6aa2fce1b318c69ecf03324d19f93168e86feb6bsalomon@google.com fillInverted, 676e6aa2fce1b318c69ecf03324d19f93168e86feb6bsalomon@google.com &passes, 677e6aa2fce1b318c69ecf03324d19f93168e86feb6bsalomon@google.com stencilSettings); 678321f62ca78984b4e78d0f2c014af46327cf7331crobertphillips@google.com 679321f62ca78984b4e78d0f2c014af46327cf7331crobertphillips@google.com // draw the element to the client stencil bits if necessary 680321f62ca78984b4e78d0f2c014af46327cf7331crobertphillips@google.com if (!canDrawDirectToClip) { 681321f62ca78984b4e78d0f2c014af46327cf7331crobertphillips@google.com GR_STATIC_CONST_SAME_STENCIL(gDrawToStencil, 682e6aa2fce1b318c69ecf03324d19f93168e86feb6bsalomon@google.com kIncClamp_StencilOp, 683e6aa2fce1b318c69ecf03324d19f93168e86feb6bsalomon@google.com kIncClamp_StencilOp, 684e6aa2fce1b318c69ecf03324d19f93168e86feb6bsalomon@google.com kAlways_StencilFunc, 685e6aa2fce1b318c69ecf03324d19f93168e86feb6bsalomon@google.com 0xffff, 686e6aa2fce1b318c69ecf03324d19f93168e86feb6bsalomon@google.com 0x0000, 687e6aa2fce1b318c69ecf03324d19f93168e86feb6bsalomon@google.com 0xffff); 688321f62ca78984b4e78d0f2c014af46327cf7331crobertphillips@google.com SET_RANDOM_COLOR 6897830e470d00cdeb468ebf34525bc9f3f0c731014bsalomon@google.com if (Element::kRect_Type == element->getType()) { 690321f62ca78984b4e78d0f2c014af46327cf7331crobertphillips@google.com *drawState->stencil() = gDrawToStencil; 6917830e470d00cdeb468ebf34525bc9f3f0c731014bsalomon@google.com fGpu->drawSimpleRect(element->getRect(), NULL); 692321f62ca78984b4e78d0f2c014af46327cf7331crobertphillips@google.com } else { 6937830e470d00cdeb468ebf34525bc9f3f0c731014bsalomon@google.com GrAssert(Element::kPath_Type == element->getType()); 6944d077f56281afad5309f6b9ff951bb9d0b9f6f72commit-bot@chromium.org if (!clipPath->isEmpty()) { 6954d077f56281afad5309f6b9ff951bb9d0b9f6f72commit-bot@chromium.org if (canRenderDirectToStencil) { 6964d077f56281afad5309f6b9ff951bb9d0b9f6f72commit-bot@chromium.org *drawState->stencil() = gDrawToStencil; 6974d077f56281afad5309f6b9ff951bb9d0b9f6f72commit-bot@chromium.org pr->drawPath(*clipPath, stroke, fGpu, false); 6984d077f56281afad5309f6b9ff951bb9d0b9f6f72commit-bot@chromium.org } else { 6994d077f56281afad5309f6b9ff951bb9d0b9f6f72commit-bot@chromium.org pr->stencilPath(*clipPath, stroke, fGpu); 7004d077f56281afad5309f6b9ff951bb9d0b9f6f72commit-bot@chromium.org } 701321f62ca78984b4e78d0f2c014af46327cf7331crobertphillips@google.com } 702321f62ca78984b4e78d0f2c014af46327cf7331crobertphillips@google.com } 703321f62ca78984b4e78d0f2c014af46327cf7331crobertphillips@google.com } 704321f62ca78984b4e78d0f2c014af46327cf7331crobertphillips@google.com 705321f62ca78984b4e78d0f2c014af46327cf7331crobertphillips@google.com // now we modify the clip bit by rendering either the clip 706321f62ca78984b4e78d0f2c014af46327cf7331crobertphillips@google.com // element directly or a bounding rect of the entire clip. 707321f62ca78984b4e78d0f2c014af46327cf7331crobertphillips@google.com drawState->enableState(GrGpu::kModifyStencilClip_StateBit); 708321f62ca78984b4e78d0f2c014af46327cf7331crobertphillips@google.com for (int p = 0; p < passes; ++p) { 709321f62ca78984b4e78d0f2c014af46327cf7331crobertphillips@google.com *drawState->stencil() = stencilSettings[p]; 710321f62ca78984b4e78d0f2c014af46327cf7331crobertphillips@google.com if (canDrawDirectToClip) { 7117830e470d00cdeb468ebf34525bc9f3f0c731014bsalomon@google.com if (Element::kRect_Type == element->getType()) { 712321f62ca78984b4e78d0f2c014af46327cf7331crobertphillips@google.com SET_RANDOM_COLOR 7137830e470d00cdeb468ebf34525bc9f3f0c731014bsalomon@google.com fGpu->drawSimpleRect(element->getRect(), NULL); 714321f62ca78984b4e78d0f2c014af46327cf7331crobertphillips@google.com } else { 7157830e470d00cdeb468ebf34525bc9f3f0c731014bsalomon@google.com GrAssert(Element::kPath_Type == element->getType()); 716321f62ca78984b4e78d0f2c014af46327cf7331crobertphillips@google.com SET_RANDOM_COLOR 7170afd9ef7f06395f1bbbe9a18d8fcfa181d5f6bb0bsalomon@google.com pr->drawPath(*clipPath, stroke, fGpu, false); 718321f62ca78984b4e78d0f2c014af46327cf7331crobertphillips@google.com } 719321f62ca78984b4e78d0f2c014af46327cf7331crobertphillips@google.com } else { 720321f62ca78984b4e78d0f2c014af46327cf7331crobertphillips@google.com SET_RANDOM_COLOR 721e6aa2fce1b318c69ecf03324d19f93168e86feb6bsalomon@google.com // The view matrix is setup to do clip space -> stencil space translation, so 722e6aa2fce1b318c69ecf03324d19f93168e86feb6bsalomon@google.com // draw rect in clip space. 723e6aa2fce1b318c69ecf03324d19f93168e86feb6bsalomon@google.com fGpu->drawSimpleRect(SkRect::MakeFromIRect(clipSpaceIBounds), NULL); 724321f62ca78984b4e78d0f2c014af46327cf7331crobertphillips@google.com } 725321f62ca78984b4e78d0f2c014af46327cf7331crobertphillips@google.com } 726321f62ca78984b4e78d0f2c014af46327cf7331crobertphillips@google.com } 727321f62ca78984b4e78d0f2c014af46327cf7331crobertphillips@google.com } 7280c4165f59a09574d521de66abeb3cc3101b04bd6bsalomon@google.com // set this last because recursive draws may overwrite it back to kNone. 7290c4165f59a09574d521de66abeb3cc3101b04bd6bsalomon@google.com GrAssert(kNone_ClipMaskType == fCurrClipMaskType); 7300c4165f59a09574d521de66abeb3cc3101b04bd6bsalomon@google.com fCurrClipMaskType = kStencil_ClipMaskType; 731321f62ca78984b4e78d0f2c014af46327cf7331crobertphillips@google.com return true; 732321f62ca78984b4e78d0f2c014af46327cf7331crobertphillips@google.com} 733321f62ca78984b4e78d0f2c014af46327cf7331crobertphillips@google.com 734784f40d04a98ffa1fe187474716844b17bceed3arobertphillips@google.com 7357d9fe5f786cc56c653bbcc99ea2a632d3b920f80bsalomon@google.com// mapping of clip-respecting stencil funcs to normal stencil funcs 7367d9fe5f786cc56c653bbcc99ea2a632d3b920f80bsalomon@google.com// mapping depends on whether stencil-clipping is in effect. 737935e9f4fafdfc64130e6be9ea2bb30e3bafd852armistry@google.comstatic const GrStencilFunc 7387d9fe5f786cc56c653bbcc99ea2a632d3b920f80bsalomon@google.com gSpecialToBasicStencilFunc[2][kClipStencilFuncCount] = { 7397d9fe5f786cc56c653bbcc99ea2a632d3b920f80bsalomon@google.com {// Stencil-Clipping is DISABLED, we are effectively always inside the clip 7407d9fe5f786cc56c653bbcc99ea2a632d3b920f80bsalomon@google.com // In the Clip Funcs 7417d9fe5f786cc56c653bbcc99ea2a632d3b920f80bsalomon@google.com kAlways_StencilFunc, // kAlwaysIfInClip_StencilFunc 7427d9fe5f786cc56c653bbcc99ea2a632d3b920f80bsalomon@google.com kEqual_StencilFunc, // kEqualIfInClip_StencilFunc 7437d9fe5f786cc56c653bbcc99ea2a632d3b920f80bsalomon@google.com kLess_StencilFunc, // kLessIfInClip_StencilFunc 7447d9fe5f786cc56c653bbcc99ea2a632d3b920f80bsalomon@google.com kLEqual_StencilFunc, // kLEqualIfInClip_StencilFunc 7457d9fe5f786cc56c653bbcc99ea2a632d3b920f80bsalomon@google.com // Special in the clip func that forces user's ref to be 0. 7467d9fe5f786cc56c653bbcc99ea2a632d3b920f80bsalomon@google.com kNotEqual_StencilFunc, // kNonZeroIfInClip_StencilFunc 7477d9fe5f786cc56c653bbcc99ea2a632d3b920f80bsalomon@google.com // make ref 0 and do normal nequal. 7487d9fe5f786cc56c653bbcc99ea2a632d3b920f80bsalomon@google.com }, 7497d9fe5f786cc56c653bbcc99ea2a632d3b920f80bsalomon@google.com {// Stencil-Clipping is ENABLED 7507d9fe5f786cc56c653bbcc99ea2a632d3b920f80bsalomon@google.com // In the Clip Funcs 7517d9fe5f786cc56c653bbcc99ea2a632d3b920f80bsalomon@google.com kEqual_StencilFunc, // kAlwaysIfInClip_StencilFunc 7527d9fe5f786cc56c653bbcc99ea2a632d3b920f80bsalomon@google.com // eq stencil clip bit, mask 7537d9fe5f786cc56c653bbcc99ea2a632d3b920f80bsalomon@google.com // out user bits. 7547d9fe5f786cc56c653bbcc99ea2a632d3b920f80bsalomon@google.com 7557d9fe5f786cc56c653bbcc99ea2a632d3b920f80bsalomon@google.com kEqual_StencilFunc, // kEqualIfInClip_StencilFunc 7567d9fe5f786cc56c653bbcc99ea2a632d3b920f80bsalomon@google.com // add stencil bit to mask and ref 7577d9fe5f786cc56c653bbcc99ea2a632d3b920f80bsalomon@google.com 7587d9fe5f786cc56c653bbcc99ea2a632d3b920f80bsalomon@google.com kLess_StencilFunc, // kLessIfInClip_StencilFunc 7597d9fe5f786cc56c653bbcc99ea2a632d3b920f80bsalomon@google.com kLEqual_StencilFunc, // kLEqualIfInClip_StencilFunc 7607d9fe5f786cc56c653bbcc99ea2a632d3b920f80bsalomon@google.com // for both of these we can add 7617d9fe5f786cc56c653bbcc99ea2a632d3b920f80bsalomon@google.com // the clip bit to the mask and 7627d9fe5f786cc56c653bbcc99ea2a632d3b920f80bsalomon@google.com // ref and compare as normal 7637d9fe5f786cc56c653bbcc99ea2a632d3b920f80bsalomon@google.com // Special in the clip func that forces user's ref to be 0. 7647d9fe5f786cc56c653bbcc99ea2a632d3b920f80bsalomon@google.com kLess_StencilFunc, // kNonZeroIfInClip_StencilFunc 7657d9fe5f786cc56c653bbcc99ea2a632d3b920f80bsalomon@google.com // make ref have only the clip bit set 7667d9fe5f786cc56c653bbcc99ea2a632d3b920f80bsalomon@google.com // and make comparison be less 7677d9fe5f786cc56c653bbcc99ea2a632d3b920f80bsalomon@google.com // 10..0 < 1..user_bits.. 7687d9fe5f786cc56c653bbcc99ea2a632d3b920f80bsalomon@google.com } 7697d9fe5f786cc56c653bbcc99ea2a632d3b920f80bsalomon@google.com}; 7707d9fe5f786cc56c653bbcc99ea2a632d3b920f80bsalomon@google.com 77185d47bf8e929c8eca60ce0fc5bda1f64481d5ef1bsalomon@google.comnamespace { 77285d47bf8e929c8eca60ce0fc5bda1f64481d5ef1bsalomon@google.com// Sets the settings to clip against the stencil buffer clip while ignoring the 77385d47bf8e929c8eca60ce0fc5bda1f64481d5ef1bsalomon@google.com// client bits. 77485d47bf8e929c8eca60ce0fc5bda1f64481d5ef1bsalomon@google.comconst GrStencilSettings& basic_apply_stencil_clip_settings() { 77585d47bf8e929c8eca60ce0fc5bda1f64481d5ef1bsalomon@google.com // stencil settings to use when clip is in stencil 77685d47bf8e929c8eca60ce0fc5bda1f64481d5ef1bsalomon@google.com GR_STATIC_CONST_SAME_STENCIL_STRUCT(gSettings, 77785d47bf8e929c8eca60ce0fc5bda1f64481d5ef1bsalomon@google.com kKeep_StencilOp, 77885d47bf8e929c8eca60ce0fc5bda1f64481d5ef1bsalomon@google.com kKeep_StencilOp, 77985d47bf8e929c8eca60ce0fc5bda1f64481d5ef1bsalomon@google.com kAlwaysIfInClip_StencilFunc, 78085d47bf8e929c8eca60ce0fc5bda1f64481d5ef1bsalomon@google.com 0x0000, 78185d47bf8e929c8eca60ce0fc5bda1f64481d5ef1bsalomon@google.com 0x0000, 782935e9f4fafdfc64130e6be9ea2bb30e3bafd852armistry@google.com 0x0000); 78385d47bf8e929c8eca60ce0fc5bda1f64481d5ef1bsalomon@google.com return *GR_CONST_STENCIL_SETTINGS_PTR_FROM_STRUCT_PTR(&gSettings); 78485d47bf8e929c8eca60ce0fc5bda1f64481d5ef1bsalomon@google.com} 78585d47bf8e929c8eca60ce0fc5bda1f64481d5ef1bsalomon@google.com} 78685d47bf8e929c8eca60ce0fc5bda1f64481d5ef1bsalomon@google.com 78785d47bf8e929c8eca60ce0fc5bda1f64481d5ef1bsalomon@google.comvoid GrClipMaskManager::setGpuStencil() { 78885d47bf8e929c8eca60ce0fc5bda1f64481d5ef1bsalomon@google.com // We make two copies of the StencilSettings here (except in the early 78985d47bf8e929c8eca60ce0fc5bda1f64481d5ef1bsalomon@google.com // exit scenario. One copy from draw state to the stack var. Then another 79085d47bf8e929c8eca60ce0fc5bda1f64481d5ef1bsalomon@google.com // from the stack var to the gpu. We could make this class hold a ptr to 79185d47bf8e929c8eca60ce0fc5bda1f64481d5ef1bsalomon@google.com // GrGpu's fStencilSettings and eliminate the stack copy here. 79285d47bf8e929c8eca60ce0fc5bda1f64481d5ef1bsalomon@google.com 79385d47bf8e929c8eca60ce0fc5bda1f64481d5ef1bsalomon@google.com const GrDrawState& drawState = fGpu->getDrawState(); 79485d47bf8e929c8eca60ce0fc5bda1f64481d5ef1bsalomon@google.com 79585d47bf8e929c8eca60ce0fc5bda1f64481d5ef1bsalomon@google.com // use stencil for clipping if clipping is enabled and the clip 79685d47bf8e929c8eca60ce0fc5bda1f64481d5ef1bsalomon@google.com // has been written into the stencil. 79785d47bf8e929c8eca60ce0fc5bda1f64481d5ef1bsalomon@google.com GrClipMaskManager::StencilClipMode clipMode; 79885d47bf8e929c8eca60ce0fc5bda1f64481d5ef1bsalomon@google.com if (this->isClipInStencil() && drawState.isClipState()) { 79985d47bf8e929c8eca60ce0fc5bda1f64481d5ef1bsalomon@google.com clipMode = GrClipMaskManager::kRespectClip_StencilClipMode; 80085d47bf8e929c8eca60ce0fc5bda1f64481d5ef1bsalomon@google.com // We can't be modifying the clip and respecting it at the same time. 80185d47bf8e929c8eca60ce0fc5bda1f64481d5ef1bsalomon@google.com GrAssert(!drawState.isStateFlagEnabled( 80285d47bf8e929c8eca60ce0fc5bda1f64481d5ef1bsalomon@google.com GrGpu::kModifyStencilClip_StateBit)); 80385d47bf8e929c8eca60ce0fc5bda1f64481d5ef1bsalomon@google.com } else if (drawState.isStateFlagEnabled( 80485d47bf8e929c8eca60ce0fc5bda1f64481d5ef1bsalomon@google.com GrGpu::kModifyStencilClip_StateBit)) { 80585d47bf8e929c8eca60ce0fc5bda1f64481d5ef1bsalomon@google.com clipMode = GrClipMaskManager::kModifyClip_StencilClipMode; 80685d47bf8e929c8eca60ce0fc5bda1f64481d5ef1bsalomon@google.com } else { 80785d47bf8e929c8eca60ce0fc5bda1f64481d5ef1bsalomon@google.com clipMode = GrClipMaskManager::kIgnoreClip_StencilClipMode; 80885d47bf8e929c8eca60ce0fc5bda1f64481d5ef1bsalomon@google.com } 80985d47bf8e929c8eca60ce0fc5bda1f64481d5ef1bsalomon@google.com 81085d47bf8e929c8eca60ce0fc5bda1f64481d5ef1bsalomon@google.com GrStencilSettings settings; 81185d47bf8e929c8eca60ce0fc5bda1f64481d5ef1bsalomon@google.com // The GrGpu client may not be using the stencil buffer but we may need to 81285d47bf8e929c8eca60ce0fc5bda1f64481d5ef1bsalomon@google.com // enable it in order to respect a stencil clip. 81385d47bf8e929c8eca60ce0fc5bda1f64481d5ef1bsalomon@google.com if (drawState.getStencil().isDisabled()) { 81485d47bf8e929c8eca60ce0fc5bda1f64481d5ef1bsalomon@google.com if (GrClipMaskManager::kRespectClip_StencilClipMode == clipMode) { 81585d47bf8e929c8eca60ce0fc5bda1f64481d5ef1bsalomon@google.com settings = basic_apply_stencil_clip_settings(); 81685d47bf8e929c8eca60ce0fc5bda1f64481d5ef1bsalomon@google.com } else { 81785d47bf8e929c8eca60ce0fc5bda1f64481d5ef1bsalomon@google.com fGpu->disableStencil(); 81885d47bf8e929c8eca60ce0fc5bda1f64481d5ef1bsalomon@google.com return; 81985d47bf8e929c8eca60ce0fc5bda1f64481d5ef1bsalomon@google.com } 82085d47bf8e929c8eca60ce0fc5bda1f64481d5ef1bsalomon@google.com } else { 82185d47bf8e929c8eca60ce0fc5bda1f64481d5ef1bsalomon@google.com settings = drawState.getStencil(); 82285d47bf8e929c8eca60ce0fc5bda1f64481d5ef1bsalomon@google.com } 82385d47bf8e929c8eca60ce0fc5bda1f64481d5ef1bsalomon@google.com 82485d47bf8e929c8eca60ce0fc5bda1f64481d5ef1bsalomon@google.com // TODO: dynamically attach a stencil buffer 82585d47bf8e929c8eca60ce0fc5bda1f64481d5ef1bsalomon@google.com int stencilBits = 0; 826935e9f4fafdfc64130e6be9ea2bb30e3bafd852armistry@google.com GrStencilBuffer* stencilBuffer = 82785d47bf8e929c8eca60ce0fc5bda1f64481d5ef1bsalomon@google.com drawState.getRenderTarget()->getStencilBuffer(); 82885d47bf8e929c8eca60ce0fc5bda1f64481d5ef1bsalomon@google.com if (NULL != stencilBuffer) { 82985d47bf8e929c8eca60ce0fc5bda1f64481d5ef1bsalomon@google.com stencilBits = stencilBuffer->bits(); 83085d47bf8e929c8eca60ce0fc5bda1f64481d5ef1bsalomon@google.com } 83185d47bf8e929c8eca60ce0fc5bda1f64481d5ef1bsalomon@google.com 83259831d70980761e3d9403a122c46e996a5d32543bsalomon@google.com GrAssert(fGpu->caps()->stencilWrapOpsSupport() || !settings.usesWrapOp()); 83359831d70980761e3d9403a122c46e996a5d32543bsalomon@google.com GrAssert(fGpu->caps()->twoSidedStencilSupport() || !settings.isTwoSided()); 83485d47bf8e929c8eca60ce0fc5bda1f64481d5ef1bsalomon@google.com this->adjustStencilParams(&settings, clipMode, stencilBits); 83585d47bf8e929c8eca60ce0fc5bda1f64481d5ef1bsalomon@google.com fGpu->setStencilSettings(settings); 83685d47bf8e929c8eca60ce0fc5bda1f64481d5ef1bsalomon@google.com} 83785d47bf8e929c8eca60ce0fc5bda1f64481d5ef1bsalomon@google.com 83885d47bf8e929c8eca60ce0fc5bda1f64481d5ef1bsalomon@google.comvoid GrClipMaskManager::adjustStencilParams(GrStencilSettings* settings, 83985d47bf8e929c8eca60ce0fc5bda1f64481d5ef1bsalomon@google.com StencilClipMode mode, 84085d47bf8e929c8eca60ce0fc5bda1f64481d5ef1bsalomon@google.com int stencilBitCnt) { 8417d9fe5f786cc56c653bbcc99ea2a632d3b920f80bsalomon@google.com GrAssert(stencilBitCnt > 0); 8427d9fe5f786cc56c653bbcc99ea2a632d3b920f80bsalomon@google.com 8437d9fe5f786cc56c653bbcc99ea2a632d3b920f80bsalomon@google.com if (kModifyClip_StencilClipMode == mode) { 84485d47bf8e929c8eca60ce0fc5bda1f64481d5ef1bsalomon@google.com // We assume that this clip manager itself is drawing to the GrGpu and 84585d47bf8e929c8eca60ce0fc5bda1f64481d5ef1bsalomon@google.com // has already setup the correct values. 84685d47bf8e929c8eca60ce0fc5bda1f64481d5ef1bsalomon@google.com return; 8477d9fe5f786cc56c653bbcc99ea2a632d3b920f80bsalomon@google.com } 84885d47bf8e929c8eca60ce0fc5bda1f64481d5ef1bsalomon@google.com 8497d9fe5f786cc56c653bbcc99ea2a632d3b920f80bsalomon@google.com unsigned int clipBit = (1 << (stencilBitCnt - 1)); 8507d9fe5f786cc56c653bbcc99ea2a632d3b920f80bsalomon@google.com unsigned int userBits = clipBit - 1; 8517d9fe5f786cc56c653bbcc99ea2a632d3b920f80bsalomon@google.com 85285d47bf8e929c8eca60ce0fc5bda1f64481d5ef1bsalomon@google.com GrStencilSettings::Face face = GrStencilSettings::kFront_Face; 85359831d70980761e3d9403a122c46e996a5d32543bsalomon@google.com bool twoSided = fGpu->caps()->twoSidedStencilSupport(); 85485d47bf8e929c8eca60ce0fc5bda1f64481d5ef1bsalomon@google.com 85585d47bf8e929c8eca60ce0fc5bda1f64481d5ef1bsalomon@google.com bool finished = false; 85685d47bf8e929c8eca60ce0fc5bda1f64481d5ef1bsalomon@google.com while (!finished) { 85785d47bf8e929c8eca60ce0fc5bda1f64481d5ef1bsalomon@google.com GrStencilFunc func = settings->func(face); 85885d47bf8e929c8eca60ce0fc5bda1f64481d5ef1bsalomon@google.com uint16_t writeMask = settings->writeMask(face); 85985d47bf8e929c8eca60ce0fc5bda1f64481d5ef1bsalomon@google.com uint16_t funcMask = settings->funcMask(face); 86085d47bf8e929c8eca60ce0fc5bda1f64481d5ef1bsalomon@google.com uint16_t funcRef = settings->funcRef(face); 86185d47bf8e929c8eca60ce0fc5bda1f64481d5ef1bsalomon@google.com 86285d47bf8e929c8eca60ce0fc5bda1f64481d5ef1bsalomon@google.com GrAssert((unsigned) func < kStencilFuncCount); 86385d47bf8e929c8eca60ce0fc5bda1f64481d5ef1bsalomon@google.com 86485d47bf8e929c8eca60ce0fc5bda1f64481d5ef1bsalomon@google.com writeMask &= userBits; 86585d47bf8e929c8eca60ce0fc5bda1f64481d5ef1bsalomon@google.com 86685d47bf8e929c8eca60ce0fc5bda1f64481d5ef1bsalomon@google.com if (func >= kBasicStencilFuncCount) { 86785d47bf8e929c8eca60ce0fc5bda1f64481d5ef1bsalomon@google.com int respectClip = kRespectClip_StencilClipMode == mode; 86885d47bf8e929c8eca60ce0fc5bda1f64481d5ef1bsalomon@google.com if (respectClip) { 86985d47bf8e929c8eca60ce0fc5bda1f64481d5ef1bsalomon@google.com // The GrGpu class should have checked this 87085d47bf8e929c8eca60ce0fc5bda1f64481d5ef1bsalomon@google.com GrAssert(this->isClipInStencil()); 87185d47bf8e929c8eca60ce0fc5bda1f64481d5ef1bsalomon@google.com switch (func) { 87285d47bf8e929c8eca60ce0fc5bda1f64481d5ef1bsalomon@google.com case kAlwaysIfInClip_StencilFunc: 87385d47bf8e929c8eca60ce0fc5bda1f64481d5ef1bsalomon@google.com funcMask = clipBit; 87485d47bf8e929c8eca60ce0fc5bda1f64481d5ef1bsalomon@google.com funcRef = clipBit; 87585d47bf8e929c8eca60ce0fc5bda1f64481d5ef1bsalomon@google.com break; 87685d47bf8e929c8eca60ce0fc5bda1f64481d5ef1bsalomon@google.com case kEqualIfInClip_StencilFunc: 87785d47bf8e929c8eca60ce0fc5bda1f64481d5ef1bsalomon@google.com case kLessIfInClip_StencilFunc: 87885d47bf8e929c8eca60ce0fc5bda1f64481d5ef1bsalomon@google.com case kLEqualIfInClip_StencilFunc: 87985d47bf8e929c8eca60ce0fc5bda1f64481d5ef1bsalomon@google.com funcMask = (funcMask & userBits) | clipBit; 88085d47bf8e929c8eca60ce0fc5bda1f64481d5ef1bsalomon@google.com funcRef = (funcRef & userBits) | clipBit; 88185d47bf8e929c8eca60ce0fc5bda1f64481d5ef1bsalomon@google.com break; 88285d47bf8e929c8eca60ce0fc5bda1f64481d5ef1bsalomon@google.com case kNonZeroIfInClip_StencilFunc: 88385d47bf8e929c8eca60ce0fc5bda1f64481d5ef1bsalomon@google.com funcMask = (funcMask & userBits) | clipBit; 88485d47bf8e929c8eca60ce0fc5bda1f64481d5ef1bsalomon@google.com funcRef = clipBit; 88585d47bf8e929c8eca60ce0fc5bda1f64481d5ef1bsalomon@google.com break; 88685d47bf8e929c8eca60ce0fc5bda1f64481d5ef1bsalomon@google.com default: 88785d47bf8e929c8eca60ce0fc5bda1f64481d5ef1bsalomon@google.com GrCrash("Unknown stencil func"); 88885d47bf8e929c8eca60ce0fc5bda1f64481d5ef1bsalomon@google.com } 88985d47bf8e929c8eca60ce0fc5bda1f64481d5ef1bsalomon@google.com } else { 89085d47bf8e929c8eca60ce0fc5bda1f64481d5ef1bsalomon@google.com funcMask &= userBits; 89185d47bf8e929c8eca60ce0fc5bda1f64481d5ef1bsalomon@google.com funcRef &= userBits; 8927d9fe5f786cc56c653bbcc99ea2a632d3b920f80bsalomon@google.com } 893935e9f4fafdfc64130e6be9ea2bb30e3bafd852armistry@google.com const GrStencilFunc* table = 89485d47bf8e929c8eca60ce0fc5bda1f64481d5ef1bsalomon@google.com gSpecialToBasicStencilFunc[respectClip]; 89585d47bf8e929c8eca60ce0fc5bda1f64481d5ef1bsalomon@google.com func = table[func - kBasicStencilFuncCount]; 89685d47bf8e929c8eca60ce0fc5bda1f64481d5ef1bsalomon@google.com GrAssert(func >= 0 && func < kBasicStencilFuncCount); 8977d9fe5f786cc56c653bbcc99ea2a632d3b920f80bsalomon@google.com } else { 89885d47bf8e929c8eca60ce0fc5bda1f64481d5ef1bsalomon@google.com funcMask &= userBits; 89985d47bf8e929c8eca60ce0fc5bda1f64481d5ef1bsalomon@google.com funcRef &= userBits; 9007d9fe5f786cc56c653bbcc99ea2a632d3b920f80bsalomon@google.com } 90185d47bf8e929c8eca60ce0fc5bda1f64481d5ef1bsalomon@google.com 90285d47bf8e929c8eca60ce0fc5bda1f64481d5ef1bsalomon@google.com settings->setFunc(face, func); 90385d47bf8e929c8eca60ce0fc5bda1f64481d5ef1bsalomon@google.com settings->setWriteMask(face, writeMask); 90485d47bf8e929c8eca60ce0fc5bda1f64481d5ef1bsalomon@google.com settings->setFuncMask(face, funcMask); 90585d47bf8e929c8eca60ce0fc5bda1f64481d5ef1bsalomon@google.com settings->setFuncRef(face, funcRef); 90685d47bf8e929c8eca60ce0fc5bda1f64481d5ef1bsalomon@google.com 90785d47bf8e929c8eca60ce0fc5bda1f64481d5ef1bsalomon@google.com if (GrStencilSettings::kFront_Face == face) { 90885d47bf8e929c8eca60ce0fc5bda1f64481d5ef1bsalomon@google.com face = GrStencilSettings::kBack_Face; 90985d47bf8e929c8eca60ce0fc5bda1f64481d5ef1bsalomon@google.com finished = !twoSided; 91085d47bf8e929c8eca60ce0fc5bda1f64481d5ef1bsalomon@google.com } else { 91185d47bf8e929c8eca60ce0fc5bda1f64481d5ef1bsalomon@google.com finished = true; 91285d47bf8e929c8eca60ce0fc5bda1f64481d5ef1bsalomon@google.com } 91385d47bf8e929c8eca60ce0fc5bda1f64481d5ef1bsalomon@google.com } 91485d47bf8e929c8eca60ce0fc5bda1f64481d5ef1bsalomon@google.com if (!twoSided) { 91585d47bf8e929c8eca60ce0fc5bda1f64481d5ef1bsalomon@google.com settings->copyFrontSettingsToBack(); 9167d9fe5f786cc56c653bbcc99ea2a632d3b920f80bsalomon@google.com } 9177d9fe5f786cc56c653bbcc99ea2a632d3b920f80bsalomon@google.com} 9187d9fe5f786cc56c653bbcc99ea2a632d3b920f80bsalomon@google.com 9197d9fe5f786cc56c653bbcc99ea2a632d3b920f80bsalomon@google.com//////////////////////////////////////////////////////////////////////////////// 920e6aa2fce1b318c69ecf03324d19f93168e86feb6bsalomon@google.comGrTexture* GrClipMaskManager::createSoftwareClipMask(int32_t clipStackGenID, 921e6aa2fce1b318c69ecf03324d19f93168e86feb6bsalomon@google.com GrReducedClip::InitialState initialState, 922e6aa2fce1b318c69ecf03324d19f93168e86feb6bsalomon@google.com const GrReducedClip::ElementList& elements, 923e6aa2fce1b318c69ecf03324d19f93168e86feb6bsalomon@google.com const SkIRect& clipSpaceIBounds) { 9240c4165f59a09574d521de66abeb3cc3101b04bd6bsalomon@google.com GrAssert(kNone_ClipMaskType == fCurrClipMaskType); 9252e2671b7977fa3f1fb0b1353abae74dc3d0ddf42robertphillips@google.com 926e6aa2fce1b318c69ecf03324d19f93168e86feb6bsalomon@google.com GrTexture* result; 927e6aa2fce1b318c69ecf03324d19f93168e86feb6bsalomon@google.com if (this->getMaskTexture(clipStackGenID, clipSpaceIBounds, &result)) { 928e6aa2fce1b318c69ecf03324d19f93168e86feb6bsalomon@google.com return result; 9292e2671b7977fa3f1fb0b1353abae74dc3d0ddf42robertphillips@google.com } 9302e2671b7977fa3f1fb0b1353abae74dc3d0ddf42robertphillips@google.com 931e6aa2fce1b318c69ecf03324d19f93168e86feb6bsalomon@google.com if (NULL == result) { 9320fe76ba222e76bf6610aa99f7f605d25da059cd3robertphillips@google.com fAACache.reset(); 933e6aa2fce1b318c69ecf03324d19f93168e86feb6bsalomon@google.com return NULL; 9342e2671b7977fa3f1fb0b1353abae74dc3d0ddf42robertphillips@google.com } 9352e2671b7977fa3f1fb0b1353abae74dc3d0ddf42robertphillips@google.com 936e6aa2fce1b318c69ecf03324d19f93168e86feb6bsalomon@google.com // The mask texture may be larger than necessary. We round out the clip space bounds and pin 937e6aa2fce1b318c69ecf03324d19f93168e86feb6bsalomon@google.com // the top left corner of the resulting rect to the top left of the texture. 938e6aa2fce1b318c69ecf03324d19f93168e86feb6bsalomon@google.com SkIRect maskSpaceIBounds = SkIRect::MakeWH(clipSpaceIBounds.width(), clipSpaceIBounds.height()); 939e6aa2fce1b318c69ecf03324d19f93168e86feb6bsalomon@google.com 940a21adf42a7140b5420b400e1b03cbebb92b357f1robertphillips@google.com GrSWMaskHelper helper(this->getContext()); 9412e2671b7977fa3f1fb0b1353abae74dc3d0ddf42robertphillips@google.com 942a4e2f5beb2d73243c15ab871f013d2ba29e8fea3bsalomon@google.com SkMatrix matrix; 943e6aa2fce1b318c69ecf03324d19f93168e86feb6bsalomon@google.com matrix.setTranslate(SkIntToScalar(-clipSpaceIBounds.fLeft), 944e6aa2fce1b318c69ecf03324d19f93168e86feb6bsalomon@google.com SkIntToScalar(-clipSpaceIBounds.fTop)); 945e6aa2fce1b318c69ecf03324d19f93168e86feb6bsalomon@google.com helper.init(maskSpaceIBounds, &matrix); 946e6aa2fce1b318c69ecf03324d19f93168e86feb6bsalomon@google.com 947e6aa2fce1b318c69ecf03324d19f93168e86feb6bsalomon@google.com helper.clear(kAllIn_InitialState == initialState ? 0xFF : 0x00); 9484cc75e380b63fe8ce4823bc7902ebf6b0ca377darobertphillips@google.com 9495c2ee5c5d8f8593d40a2a9ffd9ca834653ee6af1sugoi@google.com SkStrokeRec stroke(SkStrokeRec::kFill_InitStyle); 950290bf0ae34af76a4350a5df76ce02feb93d68196sugoi@google.com 951e6aa2fce1b318c69ecf03324d19f93168e86feb6bsalomon@google.com for (ElementList::Iter iter(elements.headIter()) ; NULL != iter.get(); iter.next()) { 9524cc75e380b63fe8ce4823bc7902ebf6b0ca377darobertphillips@google.com 953e6aa2fce1b318c69ecf03324d19f93168e86feb6bsalomon@google.com const Element* element = iter.get(); 9547830e470d00cdeb468ebf34525bc9f3f0c731014bsalomon@google.com SkRegion::Op op = element->getOp(); 9554cc75e380b63fe8ce4823bc7902ebf6b0ca377darobertphillips@google.com 956e6aa2fce1b318c69ecf03324d19f93168e86feb6bsalomon@google.com if (SkRegion::kIntersect_Op == op || SkRegion::kReverseDifference_Op == op) { 957e6aa2fce1b318c69ecf03324d19f93168e86feb6bsalomon@google.com // Intersect and reverse difference require modifying pixels outside of the geometry 958e6aa2fce1b318c69ecf03324d19f93168e86feb6bsalomon@google.com // that is being "drawn". In both cases we erase all the pixels outside of the geometry 959e6aa2fce1b318c69ecf03324d19f93168e86feb6bsalomon@google.com // but leave the pixels inside the geometry alone. For reverse difference we invert all 960e6aa2fce1b318c69ecf03324d19f93168e86feb6bsalomon@google.com // the pixels before clearing the ones outside the geometry. 9614cc75e380b63fe8ce4823bc7902ebf6b0ca377darobertphillips@google.com if (SkRegion::kReverseDifference_Op == op) { 962e6aa2fce1b318c69ecf03324d19f93168e86feb6bsalomon@google.com SkRect temp = SkRect::MakeFromIRect(clipSpaceIBounds); 9634cc75e380b63fe8ce4823bc7902ebf6b0ca377darobertphillips@google.com // invert the entire scene 964eeb064d9572cc6a9859260de155096c43c0a2116robertphillips@google.com helper.draw(temp, SkRegion::kXOR_Op, false, 0xFF); 9654cc75e380b63fe8ce4823bc7902ebf6b0ca377darobertphillips@google.com } 9664cc75e380b63fe8ce4823bc7902ebf6b0ca377darobertphillips@google.com 9677830e470d00cdeb468ebf34525bc9f3f0c731014bsalomon@google.com if (Element::kRect_Type == element->getType()) { 9684cc75e380b63fe8ce4823bc7902ebf6b0ca377darobertphillips@google.com // convert the rect to a path so we can invert the fill 9694cc75e380b63fe8ce4823bc7902ebf6b0ca377darobertphillips@google.com SkPath temp; 9707830e470d00cdeb468ebf34525bc9f3f0c731014bsalomon@google.com temp.addRect(element->getRect()); 971290bf0ae34af76a4350a5df76ce02feb93d68196sugoi@google.com temp.setFillType(SkPath::kInverseEvenOdd_FillType); 9724cc75e380b63fe8ce4823bc7902ebf6b0ca377darobertphillips@google.com 973290bf0ae34af76a4350a5df76ce02feb93d68196sugoi@google.com helper.draw(temp, stroke, SkRegion::kReplace_Op, 974290bf0ae34af76a4350a5df76ce02feb93d68196sugoi@google.com element->isAA(), 975eeb064d9572cc6a9859260de155096c43c0a2116robertphillips@google.com 0x00); 9767830e470d00cdeb468ebf34525bc9f3f0c731014bsalomon@google.com } else { 9777830e470d00cdeb468ebf34525bc9f3f0c731014bsalomon@google.com GrAssert(Element::kPath_Type == element->getType()); 978290bf0ae34af76a4350a5df76ce02feb93d68196sugoi@google.com SkPath clipPath = element->getPath(); 979290bf0ae34af76a4350a5df76ce02feb93d68196sugoi@google.com clipPath.toggleInverseFillType(); 980f4e6e352876ae31b68064b03bfadef08d29912acskia.committer@gmail.com helper.draw(clipPath, stroke, 9814cc75e380b63fe8ce4823bc7902ebf6b0ca377darobertphillips@google.com SkRegion::kReplace_Op, 9827830e470d00cdeb468ebf34525bc9f3f0c731014bsalomon@google.com element->isAA(), 983eeb064d9572cc6a9859260de155096c43c0a2116robertphillips@google.com 0x00); 9844cc75e380b63fe8ce4823bc7902ebf6b0ca377darobertphillips@google.com } 9854cc75e380b63fe8ce4823bc7902ebf6b0ca377darobertphillips@google.com 9864cc75e380b63fe8ce4823bc7902ebf6b0ca377darobertphillips@google.com continue; 9874cc75e380b63fe8ce4823bc7902ebf6b0ca377darobertphillips@google.com } 9884cc75e380b63fe8ce4823bc7902ebf6b0ca377darobertphillips@google.com 9894cc75e380b63fe8ce4823bc7902ebf6b0ca377darobertphillips@google.com // The other ops (union, xor, diff) only affect pixels inside 9904cc75e380b63fe8ce4823bc7902ebf6b0ca377darobertphillips@google.com // the geometry so they can just be drawn normally 9917830e470d00cdeb468ebf34525bc9f3f0c731014bsalomon@google.com if (Element::kRect_Type == element->getType()) { 9927830e470d00cdeb468ebf34525bc9f3f0c731014bsalomon@google.com helper.draw(element->getRect(), op, element->isAA(), 0xFF); 9937830e470d00cdeb468ebf34525bc9f3f0c731014bsalomon@google.com } else { 9947830e470d00cdeb468ebf34525bc9f3f0c731014bsalomon@google.com GrAssert(Element::kPath_Type == element->getType()); 995290bf0ae34af76a4350a5df76ce02feb93d68196sugoi@google.com helper.draw(element->getPath(), stroke, op, element->isAA(), 0xFF); 9962e2671b7977fa3f1fb0b1353abae74dc3d0ddf42robertphillips@google.com } 9972e2671b7977fa3f1fb0b1353abae74dc3d0ddf42robertphillips@google.com } 9982e2671b7977fa3f1fb0b1353abae74dc3d0ddf42robertphillips@google.com 999746a86a379880a9eb62d344f6d42d90930f6c017robertphillips@google.com helper.toTexture(result); 10002e2671b7977fa3f1fb0b1353abae74dc3d0ddf42robertphillips@google.com 10010c4165f59a09574d521de66abeb3cc3101b04bd6bsalomon@google.com fCurrClipMaskType = kAlpha_ClipMaskType; 1002e6aa2fce1b318c69ecf03324d19f93168e86feb6bsalomon@google.com return result; 10032e2671b7977fa3f1fb0b1353abae74dc3d0ddf42robertphillips@google.com} 10042e2671b7977fa3f1fb0b1353abae74dc3d0ddf42robertphillips@google.com 1005fcf86a350bf9d8cdaff79d69bc8f3fecd019817brobertphillips@google.com//////////////////////////////////////////////////////////////////////////////// 10060fe76ba222e76bf6610aa99f7f605d25da059cd3robertphillips@google.comvoid GrClipMaskManager::releaseResources() { 10070fe76ba222e76bf6610aa99f7f605d25da059cd3robertphillips@google.com fAACache.releaseResources(); 1008321f62ca78984b4e78d0f2c014af46327cf7331crobertphillips@google.com} 10090ad5bd91fd7dc876326ee0832ca8f7947dc1cc24bsalomon@google.com 10100ad5bd91fd7dc876326ee0832ca8f7947dc1cc24bsalomon@google.comvoid GrClipMaskManager::setGpu(GrGpu* gpu) { 10110ad5bd91fd7dc876326ee0832ca8f7947dc1cc24bsalomon@google.com fGpu = gpu; 10120ad5bd91fd7dc876326ee0832ca8f7947dc1cc24bsalomon@google.com fAACache.setContext(gpu->getContext()); 10130ad5bd91fd7dc876326ee0832ca8f7947dc1cc24bsalomon@google.com} 1014