GrClipMaskManager.cpp revision 9ce30e1cd19ad813091aa9876fceb416fb781352
11e945b7e708c633d4aed937ebfce57d52ba21d83robertphillips@google.com/* 21e945b7e708c633d4aed937ebfce57d52ba21d83robertphillips@google.com * Copyright 2012 Google Inc. 31e945b7e708c633d4aed937ebfce57d52ba21d83robertphillips@google.com * 41e945b7e708c633d4aed937ebfce57d52ba21d83robertphillips@google.com * Use of this source code is governed by a BSD-style license that can be 51e945b7e708c633d4aed937ebfce57d52ba21d83robertphillips@google.com * found in the LICENSE file. 61e945b7e708c633d4aed937ebfce57d52ba21d83robertphillips@google.com */ 71e945b7e708c633d4aed937ebfce57d52ba21d83robertphillips@google.com 81e945b7e708c633d4aed937ebfce57d52ba21d83robertphillips@google.com#include "GrClipMaskManager.h" 9c26d94fd7dc0b00cd6d0e42d28285f4a38aff021bsalomon@google.com#include "GrAAConvexPathRenderer.h" 10c26d94fd7dc0b00cd6d0e42d28285f4a38aff021bsalomon@google.com#include "GrAAHairLinePathRenderer.h" 11bfe2b9d3a290d0153b82617cd6b65a4814fe89e3jvanverth@google.com#include "GrAARectRenderer.h" 12c26d94fd7dc0b00cd6d0e42d28285f4a38aff021bsalomon@google.com#include "GrDrawTargetCaps.h" 13c26d94fd7dc0b00cd6d0e42d28285f4a38aff021bsalomon@google.com#include "GrPaint.h" 14c26d94fd7dc0b00cd6d0e42d28285f4a38aff021bsalomon@google.com#include "GrPathRenderer.h" 151e945b7e708c633d4aed937ebfce57d52ba21d83robertphillips@google.com#include "GrRenderTarget.h" 166bc1b5fab8554a9cb643277b4867965dd4535cd6bsalomon#include "GrRenderTargetPriv.h" 171e945b7e708c633d4aed937ebfce57d52ba21d83robertphillips@google.com#include "GrStencilBuffer.h" 18c26d94fd7dc0b00cd6d0e42d28285f4a38aff021bsalomon@google.com#include "GrSWMaskHelper.h" 193a0cfeb96185934c0a36f1313f21b96c57ca6341joshualitt#include "SkRasterClip.h" 203a0cfeb96185934c0a36f1313f21b96c57ca6341joshualitt#include "SkStrokeRec.h" 213a0cfeb96185934c0a36f1313f21b96c57ca6341joshualitt#include "SkTLazy.h" 22a58fe35fdae3481cf43062f7032820c320c3d163joshualitt#include "effects/GrConvexPolyEffect.h" 239513143efa734bef0c1a0c7f945022572dbc8518egdaniel#include "effects/GrPorterDuffXferProcessor.h" 24a58fe35fdae3481cf43062f7032820c320c3d163joshualitt#include "effects/GrRRectEffect.h" 259513143efa734bef0c1a0c7f945022572dbc8518egdaniel#include "effects/GrTextureDomain.h" 26c6b3e48cb3a22d83ba3f4b9a614a5a35b05958a0bsalomon@google.com 278182fa0cac76e7e6d583aebba060229230516887bsalomon@google.comtypedef SkClipStack::Element Element; 2851a6286c241c1dc750d263ed9676079c898148b0bsalomon@google.com 2951a6286c241c1dc750d263ed9676079c898148b0bsalomon@google.com//////////////////////////////////////////////////////////////////////////////// 30e79f320ed6c5ec9f6164ba84be1ff586532e6517robertphillips@google.comnamespace { 31fbfcd5602128ec010c82cb733c9cdc0a3254f9f3rmistry@google.com// set up the draw state to enable the aa clipping mask. Besides setting up the 3208283afc265f1153834256fc1012519813ba6b73bsalomon@google.com// stage matrix this also alters the vertex layout 33642429e27c6439abff4121f0cba30a7832b4744ajoshualittvoid setup_drawstate_aaclip(GrPipelineBuilder* pipelineBuilder, 34642429e27c6439abff4121f0cba30a7832b4744ajoshualitt GrTexture* result, 356be6f7cb66b277e7b1ce13d09b635fb8e09a2f68bsalomon GrPipelineBuilder::AutoRestoreFragmentProcessors* arfp, 36642429e27c6439abff4121f0cba30a7832b4744ajoshualitt const SkIRect &devBound) { 376be6f7cb66b277e7b1ce13d09b635fb8e09a2f68bsalomon SkASSERT(pipelineBuilder && arfp); 386be6f7cb66b277e7b1ce13d09b635fb8e09a2f68bsalomon arfp->set(pipelineBuilder); 39a72eef322c686954cdffa849dc26d8133b802f1drobertphillips@google.com 40b9086a026844e4cfd08b219e49ce3f12294cba98bsalomon@google.com SkMatrix mat; 41309d4d590964fbf7443c5bc892c132faa61a9abbbsalomon // We use device coords to compute the texture coordinates. We set our matrix to be a 42309d4d590964fbf7443c5bc892c132faa61a9abbbsalomon // translation to the devBound, and then a scaling matrix to normalized coords. 43a72eef322c686954cdffa849dc26d8133b802f1drobertphillips@google.com mat.setIDiv(result->width(), result->height()); 44fbfcd5602128ec010c82cb733c9cdc0a3254f9f3rmistry@google.com mat.preTranslate(SkIntToScalar(-devBound.fLeft), 457b11289b4e4d117bbcee6d2460b057d0fcf6e437robertphillips@google.com SkIntToScalar(-devBound.fTop)); 46a72eef322c686954cdffa849dc26d8133b802f1drobertphillips@google.com 477b7cdd147f5528865238e5ed98c79e6d319fde9bbsalomon@google.com SkIRect domainTexels = SkIRect::MakeWH(devBound.width(), devBound.height()); 484c2443e36fdc6c095b17e90baa4a2f26a6f00b08bsalomon@google.com // This could be a long-lived effect that is cached with the alpha-mask. 498dd688b7569df569a672a8a67b2db86a9d376cfcegdaniel pipelineBuilder->addCoverageProcessor( 50eb6879f50a5564eeb981ec5616b55bf685eb76fcbsalomon@google.com GrTextureDomainEffect::Create(result, 517b7cdd147f5528865238e5ed98c79e6d319fde9bbsalomon@google.com mat, 52907fbd53c5e5dd4cbde7b72f9242b51febd7ef95commit-bot@chromium.org GrTextureDomain::MakeTexelDomain(result, domainTexels), 53907fbd53c5e5dd4cbde7b72f9242b51febd7ef95commit-bot@chromium.org GrTextureDomain::kDecal_Mode, 54b86add1ad37776818e1f730359ec587c9fdbff5fhumper@google.com GrTextureParams::kNone_FilterMode, 55309d4d590964fbf7443c5bc892c132faa61a9abbbsalomon kDevice_GrCoordSet))->unref(); 56a72eef322c686954cdffa849dc26d8133b802f1drobertphillips@google.com} 57a72eef322c686954cdffa849dc26d8133b802f1drobertphillips@google.com 58e79f320ed6c5ec9f6164ba84be1ff586532e6517robertphillips@google.combool path_needs_SW_renderer(GrContext* context, 599853ccef19c200be93a6211f32589fa82a53067cjoshualitt const GrDrawTarget* gpu, 608dd688b7569df569a672a8a67b2db86a9d376cfcegdaniel const GrPipelineBuilder* pipelineBuilder, 618059eb9f6e24ed609393fbda4ad71edea03ac258joshualitt const SkMatrix& viewMatrix, 62e79f320ed6c5ec9f6164ba84be1ff586532e6517robertphillips@google.com const SkPath& origPath, 63e79f320ed6c5ec9f6164ba84be1ff586532e6517robertphillips@google.com const SkStrokeRec& stroke, 64e79f320ed6c5ec9f6164ba84be1ff586532e6517robertphillips@google.com bool doAA) { 65e79f320ed6c5ec9f6164ba84be1ff586532e6517robertphillips@google.com // the gpu alpha mask will draw the inverse paths as non-inverse to a temp buffer 66e79f320ed6c5ec9f6164ba84be1ff586532e6517robertphillips@google.com SkTCopyOnFirstWrite<SkPath> path(origPath); 67e79f320ed6c5ec9f6164ba84be1ff586532e6517robertphillips@google.com if (path->isInverseFillType()) { 68e79f320ed6c5ec9f6164ba84be1ff586532e6517robertphillips@google.com path.writable()->toggleInverseFillType(); 69e79f320ed6c5ec9f6164ba84be1ff586532e6517robertphillips@google.com } 70e79f320ed6c5ec9f6164ba84be1ff586532e6517robertphillips@google.com // last (false) parameter disallows use of the SW path renderer 7145a15f551b5b3c6c747d8eaf6466b7d3b76a8faebsalomon@google.com GrPathRendererChain::DrawType type = doAA ? 7245a15f551b5b3c6c747d8eaf6466b7d3b76a8faebsalomon@google.com GrPathRendererChain::kColorAntiAlias_DrawType : 7345a15f551b5b3c6c747d8eaf6466b7d3b76a8faebsalomon@google.com GrPathRendererChain::kColor_DrawType; 7445a15f551b5b3c6c747d8eaf6466b7d3b76a8faebsalomon@google.com 758dd688b7569df569a672a8a67b2db86a9d376cfcegdaniel return NULL == context->getPathRenderer(gpu, pipelineBuilder, viewMatrix, *path, stroke, 768dd688b7569df569a672a8a67b2db86a9d376cfcegdaniel false, type); 77e79f320ed6c5ec9f6164ba84be1ff586532e6517robertphillips@google.com} 786b70a7bd3328ea0a12be47b1a7f835c905f16147robertphillips@google.com} 796b70a7bd3328ea0a12be47b1a7f835c905f16147robertphillips@google.com 80fa66294c7705831808ce7772d4328fc626d45034robertphillips@google.com/* 81fa66294c7705831808ce7772d4328fc626d45034robertphillips@google.com * This method traverses the clip stack to see if the GrSoftwarePathRenderer 82fa66294c7705831808ce7772d4328fc626d45034robertphillips@google.com * will be used on any element. If so, it returns true to indicate that the 83fa66294c7705831808ce7772d4328fc626d45034robertphillips@google.com * entire clip should be rendered in SW and then uploaded en masse to the gpu. 84fa66294c7705831808ce7772d4328fc626d45034robertphillips@google.com */ 858dd688b7569df569a672a8a67b2db86a9d376cfcegdanielbool GrClipMaskManager::useSWOnlyPath(const GrPipelineBuilder* pipelineBuilder, 868059eb9f6e24ed609393fbda4ad71edea03ac258joshualitt const SkVector& clipToMaskOffset, 879853ccef19c200be93a6211f32589fa82a53067cjoshualitt const GrReducedClip::ElementList& elements) { 888a4fc40b02fa0a8300ade26863f4ddae69197d62robertphillips@google.com // TODO: generalize this function so that when 89fa66294c7705831808ce7772d4328fc626d45034robertphillips@google.com // a clip gets complex enough it can just be done in SW regardless 90fa66294c7705831808ce7772d4328fc626d45034robertphillips@google.com // of whether it would invoke the GrSoftwarePathRenderer. 915f74cf8c49701f514b69dc6f1a8b5c0ffd78af0asugoi@google.com SkStrokeRec stroke(SkStrokeRec::kFill_InitStyle); 92d21444aab7128c97f4e0eb5e9bf05111d5037292skia.committer@gmail.com 938059eb9f6e24ed609393fbda4ad71edea03ac258joshualitt // Set the matrix so that rendered clip elements are transformed to mask space from clip 948059eb9f6e24ed609393fbda4ad71edea03ac258joshualitt // space. 958059eb9f6e24ed609393fbda4ad71edea03ac258joshualitt SkMatrix translate; 968059eb9f6e24ed609393fbda4ad71edea03ac258joshualitt translate.setTranslate(clipToMaskOffset); 978059eb9f6e24ed609393fbda4ad71edea03ac258joshualitt 98bf54e49e30cdc92f9ce3f336cc48cf6b236ddeabtfarina for (GrReducedClip::ElementList::Iter iter(elements.headIter()); iter.get(); iter.next()) { 994c2443e36fdc6c095b17e90baa4a2f26a6f00b08bsalomon@google.com const Element* element = iter.get(); 100f69a11b5c5dc5ae02489dfe7ca6432d641b9f121robertphillips@google.com // rects can always be drawn directly w/o using the software path 101e5b2af955b7d06815ddd405659ad62a2a8355ca3commit-bot@chromium.org // Skip rrects once we're drawing them directly. 102e5b2af955b7d06815ddd405659ad62a2a8355ca3commit-bot@chromium.org if (Element::kRect_Type != element->getType()) { 103e5b2af955b7d06815ddd405659ad62a2a8355ca3commit-bot@chromium.org SkPath path; 104e5b2af955b7d06815ddd405659ad62a2a8355ca3commit-bot@chromium.org element->asPath(&path); 1058dd688b7569df569a672a8a67b2db86a9d376cfcegdaniel if (path_needs_SW_renderer(this->getContext(), fClipTarget, pipelineBuilder, translate, 1068059eb9f6e24ed609393fbda4ad71edea03ac258joshualitt path, stroke, element->isAA())) { 107e5b2af955b7d06815ddd405659ad62a2a8355ca3commit-bot@chromium.org return true; 108e5b2af955b7d06815ddd405659ad62a2a8355ca3commit-bot@chromium.org } 109fa66294c7705831808ce7772d4328fc626d45034robertphillips@google.com } 110fa66294c7705831808ce7772d4328fc626d45034robertphillips@google.com } 1114c2443e36fdc6c095b17e90baa4a2f26a6f00b08bsalomon@google.com return false; 112a72eef322c686954cdffa849dc26d8133b802f1drobertphillips@google.com} 113a72eef322c686954cdffa849dc26d8133b802f1drobertphillips@google.com 1148dd688b7569df569a672a8a67b2db86a9d376cfcegdanielbool GrClipMaskManager::installClipEffects(GrPipelineBuilder* pipelineBuilder, 1156be6f7cb66b277e7b1ce13d09b635fb8e09a2f68bsalomon GrPipelineBuilder::AutoRestoreFragmentProcessors* arfp, 1169853ccef19c200be93a6211f32589fa82a53067cjoshualitt const GrReducedClip::ElementList& elements, 117e5a041c0688ccb861cc85f8917338602864d8e5acommit-bot@chromium.org const SkVector& clipToRTOffset, 118217daa7ec592fc306edffb9fb2a3d8c7ebff8c2dmtklein const SkRect* drawBounds) { 119e5a041c0688ccb861cc85f8917338602864d8e5acommit-bot@chromium.org SkRect boundsInClipSpace; 12049f085dddff10473b6ebf832a974288300224e60bsalomon if (drawBounds) { 121e5a041c0688ccb861cc85f8917338602864d8e5acommit-bot@chromium.org boundsInClipSpace = *drawBounds; 122e5a041c0688ccb861cc85f8917338602864d8e5acommit-bot@chromium.org boundsInClipSpace.offset(-clipToRTOffset.fX, -clipToRTOffset.fY); 123e5a041c0688ccb861cc85f8917338602864d8e5acommit-bot@chromium.org } 124e5a041c0688ccb861cc85f8917338602864d8e5acommit-bot@chromium.org 1256be6f7cb66b277e7b1ce13d09b635fb8e09a2f68bsalomon arfp->set(pipelineBuilder); 1268dd688b7569df569a672a8a67b2db86a9d376cfcegdaniel GrRenderTarget* rt = pipelineBuilder->getRenderTarget(); 127bf54e49e30cdc92f9ce3f336cc48cf6b236ddeabtfarina GrReducedClip::ElementList::Iter iter(elements); 128e5a041c0688ccb861cc85f8917338602864d8e5acommit-bot@chromium.org bool failed = false; 12949f085dddff10473b6ebf832a974288300224e60bsalomon while (iter.get()) { 130e5a041c0688ccb861cc85f8917338602864d8e5acommit-bot@chromium.org SkRegion::Op op = iter.get()->getOp(); 131e5a041c0688ccb861cc85f8917338602864d8e5acommit-bot@chromium.org bool invert; 132e5a041c0688ccb861cc85f8917338602864d8e5acommit-bot@chromium.org bool skip = false; 133e5a041c0688ccb861cc85f8917338602864d8e5acommit-bot@chromium.org switch (op) { 134e5a041c0688ccb861cc85f8917338602864d8e5acommit-bot@chromium.org case SkRegion::kReplace_Op: 135e5a041c0688ccb861cc85f8917338602864d8e5acommit-bot@chromium.org SkASSERT(iter.get() == elements.head()); 136e5a041c0688ccb861cc85f8917338602864d8e5acommit-bot@chromium.org // Fallthrough, handled same as intersect. 137e5a041c0688ccb861cc85f8917338602864d8e5acommit-bot@chromium.org case SkRegion::kIntersect_Op: 138e5a041c0688ccb861cc85f8917338602864d8e5acommit-bot@chromium.org invert = false; 13949f085dddff10473b6ebf832a974288300224e60bsalomon if (drawBounds && iter.get()->contains(boundsInClipSpace)) { 140e5a041c0688ccb861cc85f8917338602864d8e5acommit-bot@chromium.org skip = true; 141e5a041c0688ccb861cc85f8917338602864d8e5acommit-bot@chromium.org } 142e5a041c0688ccb861cc85f8917338602864d8e5acommit-bot@chromium.org break; 143e5a041c0688ccb861cc85f8917338602864d8e5acommit-bot@chromium.org case SkRegion::kDifference_Op: 144e5a041c0688ccb861cc85f8917338602864d8e5acommit-bot@chromium.org invert = true; 145e5a041c0688ccb861cc85f8917338602864d8e5acommit-bot@chromium.org // We don't currently have a cheap test for whether a rect is fully outside an 146e5a041c0688ccb861cc85f8917338602864d8e5acommit-bot@chromium.org // element's primitive, so don't attempt to set skip. 147e5a041c0688ccb861cc85f8917338602864d8e5acommit-bot@chromium.org break; 148e5a041c0688ccb861cc85f8917338602864d8e5acommit-bot@chromium.org default: 149e5a041c0688ccb861cc85f8917338602864d8e5acommit-bot@chromium.org failed = true; 150e5a041c0688ccb861cc85f8917338602864d8e5acommit-bot@chromium.org break; 151e5a041c0688ccb861cc85f8917338602864d8e5acommit-bot@chromium.org } 152e5a041c0688ccb861cc85f8917338602864d8e5acommit-bot@chromium.org if (failed) { 153e5a041c0688ccb861cc85f8917338602864d8e5acommit-bot@chromium.org break; 154e5a041c0688ccb861cc85f8917338602864d8e5acommit-bot@chromium.org } 155e5a041c0688ccb861cc85f8917338602864d8e5acommit-bot@chromium.org 156e5a041c0688ccb861cc85f8917338602864d8e5acommit-bot@chromium.org if (!skip) { 157b0a8a377f832c59cee939ad721e1f87d378b7142joshualitt GrPrimitiveEdgeType edgeType; 158e85a32d4f8ce7fb9b6aaae89137dbf3766d833f2robertphillips if (iter.get()->isAA()) { 159e5a041c0688ccb861cc85f8917338602864d8e5acommit-bot@chromium.org if (rt->isMultisampled()) { 160217daa7ec592fc306edffb9fb2a3d8c7ebff8c2dmtklein // Coverage based AA clips don't place nicely with MSAA. 161e5a041c0688ccb861cc85f8917338602864d8e5acommit-bot@chromium.org failed = true; 162e5a041c0688ccb861cc85f8917338602864d8e5acommit-bot@chromium.org break; 163e5a041c0688ccb861cc85f8917338602864d8e5acommit-bot@chromium.org } 164b0a8a377f832c59cee939ad721e1f87d378b7142joshualitt edgeType = 165b0a8a377f832c59cee939ad721e1f87d378b7142joshualitt invert ? kInverseFillAA_GrProcessorEdgeType : kFillAA_GrProcessorEdgeType; 166e5a041c0688ccb861cc85f8917338602864d8e5acommit-bot@chromium.org } else { 167b0a8a377f832c59cee939ad721e1f87d378b7142joshualitt edgeType = 16896e02a8f3f356085073de4a3d897dcc4e0931455bsalomoninvert ? kInverseFillBW_GrProcessorEdgeType : kFillBW_GrProcessorEdgeType; 169e5a041c0688ccb861cc85f8917338602864d8e5acommit-bot@chromium.org } 170b0a8a377f832c59cee939ad721e1f87d378b7142joshualitt SkAutoTUnref<GrFragmentProcessor> fp; 171e5a041c0688ccb861cc85f8917338602864d8e5acommit-bot@chromium.org switch (iter.get()->getType()) { 172e5a041c0688ccb861cc85f8917338602864d8e5acommit-bot@chromium.org case SkClipStack::Element::kPath_Type: 173b0a8a377f832c59cee939ad721e1f87d378b7142joshualitt fp.reset(GrConvexPolyEffect::Create(edgeType, iter.get()->getPath(), 174642429e27c6439abff4121f0cba30a7832b4744ajoshualitt &clipToRTOffset)); 175e5a041c0688ccb861cc85f8917338602864d8e5acommit-bot@chromium.org break; 176e5a041c0688ccb861cc85f8917338602864d8e5acommit-bot@chromium.org case SkClipStack::Element::kRRect_Type: { 177e5a041c0688ccb861cc85f8917338602864d8e5acommit-bot@chromium.org SkRRect rrect = iter.get()->getRRect(); 178e5a041c0688ccb861cc85f8917338602864d8e5acommit-bot@chromium.org rrect.offset(clipToRTOffset.fX, clipToRTOffset.fY); 179b0a8a377f832c59cee939ad721e1f87d378b7142joshualitt fp.reset(GrRRectEffect::Create(edgeType, rrect)); 180e5a041c0688ccb861cc85f8917338602864d8e5acommit-bot@chromium.org break; 181e5a041c0688ccb861cc85f8917338602864d8e5acommit-bot@chromium.org } 182e5a041c0688ccb861cc85f8917338602864d8e5acommit-bot@chromium.org case SkClipStack::Element::kRect_Type: { 183e5a041c0688ccb861cc85f8917338602864d8e5acommit-bot@chromium.org SkRect rect = iter.get()->getRect(); 184e5a041c0688ccb861cc85f8917338602864d8e5acommit-bot@chromium.org rect.offset(clipToRTOffset.fX, clipToRTOffset.fY); 185b0a8a377f832c59cee939ad721e1f87d378b7142joshualitt fp.reset(GrConvexPolyEffect::Create(edgeType, rect)); 186e5a041c0688ccb861cc85f8917338602864d8e5acommit-bot@chromium.org break; 187e5a041c0688ccb861cc85f8917338602864d8e5acommit-bot@chromium.org } 188e5a041c0688ccb861cc85f8917338602864d8e5acommit-bot@chromium.org default: 189e5a041c0688ccb861cc85f8917338602864d8e5acommit-bot@chromium.org break; 190e5a041c0688ccb861cc85f8917338602864d8e5acommit-bot@chromium.org } 191b0a8a377f832c59cee939ad721e1f87d378b7142joshualitt if (fp) { 1928dd688b7569df569a672a8a67b2db86a9d376cfcegdaniel pipelineBuilder->addCoverageProcessor(fp); 193217daa7ec592fc306edffb9fb2a3d8c7ebff8c2dmtklein } else { 194e5a041c0688ccb861cc85f8917338602864d8e5acommit-bot@chromium.org failed = true; 195e5a041c0688ccb861cc85f8917338602864d8e5acommit-bot@chromium.org break; 196e5a041c0688ccb861cc85f8917338602864d8e5acommit-bot@chromium.org } 197e5a041c0688ccb861cc85f8917338602864d8e5acommit-bot@chromium.org } 198217daa7ec592fc306edffb9fb2a3d8c7ebff8c2dmtklein iter.next(); 199e5a041c0688ccb861cc85f8917338602864d8e5acommit-bot@chromium.org } 200e5a041c0688ccb861cc85f8917338602864d8e5acommit-bot@chromium.org 201e5a041c0688ccb861cc85f8917338602864d8e5acommit-bot@chromium.org if (failed) { 2026be6f7cb66b277e7b1ce13d09b635fb8e09a2f68bsalomon arfp->set(NULL); 203e5a041c0688ccb861cc85f8917338602864d8e5acommit-bot@chromium.org } 204e5a041c0688ccb861cc85f8917338602864d8e5acommit-bot@chromium.org return !failed; 205e5a041c0688ccb861cc85f8917338602864d8e5acommit-bot@chromium.org} 206e5a041c0688ccb861cc85f8917338602864d8e5acommit-bot@chromium.org 207f294b773f0b2b9f05eb45b52dd3cb4d97b96af06robertphillips@google.com//////////////////////////////////////////////////////////////////////////////// 2086b70a7bd3328ea0a12be47b1a7f835c905f16147robertphillips@google.com// sort out what kind of clip mask needs to be created: alpha, stencil, 2096b70a7bd3328ea0a12be47b1a7f835c905f16147robertphillips@google.com// scissor, or entirely software 2108dd688b7569df569a672a8a67b2db86a9d376cfcegdanielbool GrClipMaskManager::setupClipping(GrPipelineBuilder* pipelineBuilder, 2116be6f7cb66b277e7b1ce13d09b635fb8e09a2f68bsalomon GrPipelineBuilder::AutoRestoreFragmentProcessors* arfp, 2128dd688b7569df569a672a8a67b2db86a9d376cfcegdaniel GrPipelineBuilder::AutoRestoreStencil* ars, 2133e79124a69d4806f0a1a776090bff718e1b90970bsalomon GrScissorState* scissorState, 2149853ccef19c200be93a6211f32589fa82a53067cjoshualitt const SkRect* devBounds) { 215c8f7f47afaf8f9471e6d111655c5610a8bd210a2bsalomon@google.com fCurrClipMaskType = kNone_ClipMaskType; 2167a6184fdf717a1da0c6e1e37b942b17fdaa236d3joshualitt if (kRespectClip_StencilClipMode == fClipMode) { 2177a6184fdf717a1da0c6e1e37b942b17fdaa236d3joshualitt fClipMode = kIgnoreClip_StencilClipMode; 2187a6184fdf717a1da0c6e1e37b942b17fdaa236d3joshualitt } 219a320194e4242ef0e5e758aea896bfd52bcb3dac7bsalomon@google.com 220bf54e49e30cdc92f9ce3f336cc48cf6b236ddeabtfarina GrReducedClip::ElementList elements(16); 22171d7f7f002332b9904bf12eb3f1908883f99120ebrucedawson int32_t genID = 0; 22271d7f7f002332b9904bf12eb3f1908883f99120ebrucedawson GrReducedClip::InitialState initialState = GrReducedClip::kAllIn_InitialState; 2234c2443e36fdc6c095b17e90baa4a2f26a6f00b08bsalomon@google.com SkIRect clipSpaceIBounds; 22471d7f7f002332b9904bf12eb3f1908883f99120ebrucedawson bool requiresAA = false; 2258dd688b7569df569a672a8a67b2db86a9d376cfcegdaniel GrRenderTarget* rt = pipelineBuilder->getRenderTarget(); 2264c2443e36fdc6c095b17e90baa4a2f26a6f00b08bsalomon@google.com 2271e945b7e708c633d4aed937ebfce57d52ba21d83robertphillips@google.com // GrDrawTarget should have filtered this for us 22849f085dddff10473b6ebf832a974288300224e60bsalomon SkASSERT(rt); 2291e945b7e708c633d4aed937ebfce57d52ba21d83robertphillips@google.com 23044701df5ce572ac3cccec785cf52103d3d5d14a5joshualitt SkIRect clipSpaceRTIBounds = SkIRect::MakeWH(rt->width(), rt->height()); 23144701df5ce572ac3cccec785cf52103d3d5d14a5joshualitt const GrClip& clip = pipelineBuilder->clip(); 23296e02a8f3f356085073de4a3d897dcc4e0931455bsalomon if (clip.isWideOpen(clipSpaceRTIBounds)) { 2338dd688b7569df569a672a8a67b2db86a9d376cfcegdaniel this->setPipelineBuilderStencil(pipelineBuilder, ars); 2344c2443e36fdc6c095b17e90baa4a2f26a6f00b08bsalomon@google.com return true; 235a320194e4242ef0e5e758aea896bfd52bcb3dac7bsalomon@google.com } 236a320194e4242ef0e5e758aea896bfd52bcb3dac7bsalomon@google.com 23796e02a8f3f356085073de4a3d897dcc4e0931455bsalomon // The clip mask manager always draws with a single IRect so we special case that logic here 23896e02a8f3f356085073de4a3d897dcc4e0931455bsalomon // Image filters just use a rect, so we also special case that logic 23996e02a8f3f356085073de4a3d897dcc4e0931455bsalomon switch (clip.clipType()) { 24096e02a8f3f356085073de4a3d897dcc4e0931455bsalomon case GrClip::kWideOpen_ClipType: 24196e02a8f3f356085073de4a3d897dcc4e0931455bsalomon SkFAIL("Should have caught this with clip.isWideOpen()"); 24296e02a8f3f356085073de4a3d897dcc4e0931455bsalomon return true; 2439ce30e1cd19ad813091aa9876fceb416fb781352bsalomon case GrClip::kIRect_ClipType: { 2449ce30e1cd19ad813091aa9876fceb416fb781352bsalomon SkIRect scissor = clip.irect(); 2459ce30e1cd19ad813091aa9876fceb416fb781352bsalomon if (scissor.intersect(clipSpaceRTIBounds)) { 2469ce30e1cd19ad813091aa9876fceb416fb781352bsalomon scissorState->set(scissor); 2479ce30e1cd19ad813091aa9876fceb416fb781352bsalomon this->setPipelineBuilderStencil(pipelineBuilder, ars); 2489ce30e1cd19ad813091aa9876fceb416fb781352bsalomon return true; 2499ce30e1cd19ad813091aa9876fceb416fb781352bsalomon } 2509ce30e1cd19ad813091aa9876fceb416fb781352bsalomon return false; 2519ce30e1cd19ad813091aa9876fceb416fb781352bsalomon } 25296e02a8f3f356085073de4a3d897dcc4e0931455bsalomon case GrClip::kClipStack_ClipType: { 25396e02a8f3f356085073de4a3d897dcc4e0931455bsalomon clipSpaceRTIBounds.offset(clip.origin()); 25496e02a8f3f356085073de4a3d897dcc4e0931455bsalomon GrReducedClip::ReduceClipStack(*clip.clipStack(), 25596e02a8f3f356085073de4a3d897dcc4e0931455bsalomon clipSpaceRTIBounds, 25696e02a8f3f356085073de4a3d897dcc4e0931455bsalomon &elements, 25796e02a8f3f356085073de4a3d897dcc4e0931455bsalomon &genID, 25896e02a8f3f356085073de4a3d897dcc4e0931455bsalomon &initialState, 25996e02a8f3f356085073de4a3d897dcc4e0931455bsalomon &clipSpaceIBounds, 26096e02a8f3f356085073de4a3d897dcc4e0931455bsalomon &requiresAA); 26196e02a8f3f356085073de4a3d897dcc4e0931455bsalomon if (elements.isEmpty()) { 26296e02a8f3f356085073de4a3d897dcc4e0931455bsalomon if (GrReducedClip::kAllIn_InitialState == initialState) { 26396e02a8f3f356085073de4a3d897dcc4e0931455bsalomon if (clipSpaceIBounds == clipSpaceRTIBounds) { 26496e02a8f3f356085073de4a3d897dcc4e0931455bsalomon this->setPipelineBuilderStencil(pipelineBuilder, ars); 26596e02a8f3f356085073de4a3d897dcc4e0931455bsalomon return true; 26696e02a8f3f356085073de4a3d897dcc4e0931455bsalomon } 26796e02a8f3f356085073de4a3d897dcc4e0931455bsalomon } else { 26896e02a8f3f356085073de4a3d897dcc4e0931455bsalomon return false; 26996e02a8f3f356085073de4a3d897dcc4e0931455bsalomon } 27096e02a8f3f356085073de4a3d897dcc4e0931455bsalomon } 27196e02a8f3f356085073de4a3d897dcc4e0931455bsalomon } break; 27296e02a8f3f356085073de4a3d897dcc4e0931455bsalomon } 27396e02a8f3f356085073de4a3d897dcc4e0931455bsalomon 274e5a041c0688ccb861cc85f8917338602864d8e5acommit-bot@chromium.org // An element count of 4 was chosen because of the common pattern in Blink of: 275e5a041c0688ccb861cc85f8917338602864d8e5acommit-bot@chromium.org // isect RR 276e5a041c0688ccb861cc85f8917338602864d8e5acommit-bot@chromium.org // diff RR 277e5a041c0688ccb861cc85f8917338602864d8e5acommit-bot@chromium.org // isect convex_poly 278e5a041c0688ccb861cc85f8917338602864d8e5acommit-bot@chromium.org // isect convex_poly 279e5a041c0688ccb861cc85f8917338602864d8e5acommit-bot@chromium.org // when drawing rounded div borders. This could probably be tuned based on a 280e5a041c0688ccb861cc85f8917338602864d8e5acommit-bot@chromium.org // configuration's relative costs of switching RTs to generate a mask vs 281e5a041c0688ccb861cc85f8917338602864d8e5acommit-bot@chromium.org // longer shaders. 282e5a041c0688ccb861cc85f8917338602864d8e5acommit-bot@chromium.org if (elements.count() <= 4) { 28344701df5ce572ac3cccec785cf52103d3d5d14a5joshualitt SkVector clipToRTOffset = { SkIntToScalar(-clip.origin().fX), 28444701df5ce572ac3cccec785cf52103d3d5d14a5joshualitt SkIntToScalar(-clip.origin().fY) }; 285e5a041c0688ccb861cc85f8917338602864d8e5acommit-bot@chromium.org if (elements.isEmpty() || 28655f0b18ee079b1517f43c08c70f91e1a21928d23bsalomon (requiresAA && this->installClipEffects(pipelineBuilder, arfp, elements, clipToRTOffset, 28755f0b18ee079b1517f43c08c70f91e1a21928d23bsalomon devBounds))) { 288217daa7ec592fc306edffb9fb2a3d8c7ebff8c2dmtklein SkIRect scissorSpaceIBounds(clipSpaceIBounds); 28944701df5ce572ac3cccec785cf52103d3d5d14a5joshualitt scissorSpaceIBounds.offset(-clip.origin()); 290217daa7ec592fc306edffb9fb2a3d8c7ebff8c2dmtklein if (NULL == devBounds || 291217daa7ec592fc306edffb9fb2a3d8c7ebff8c2dmtklein !SkRect::Make(scissorSpaceIBounds).contains(*devBounds)) { 29277b1307c1f5dac019575a6d431d5ce657370c4fbjoshualitt scissorState->set(scissorSpaceIBounds); 293e5a041c0688ccb861cc85f8917338602864d8e5acommit-bot@chromium.org } 2948dd688b7569df569a672a8a67b2db86a9d376cfcegdaniel this->setPipelineBuilderStencil(pipelineBuilder, ars); 29565ee5f424cb4dabd453268902c00086605d77c1dcommit-bot@chromium.org return true; 29665ee5f424cb4dabd453268902c00086605d77c1dcommit-bot@chromium.org } 29765ee5f424cb4dabd453268902c00086605d77c1dcommit-bot@chromium.org } 298d3066bd9b4a37cf4a39e7df7e1432f3df10dbc67bsalomon@google.com 299a3e5c63ab0264332169df4583a8a7da186fb4e66robertphillips@google.com // If MSAA is enabled we can do everything in the stencil buffer. 3004c2443e36fdc6c095b17e90baa4a2f26a6f00b08bsalomon@google.com if (0 == rt->numSamples() && requiresAA) { 3016b70a7bd3328ea0a12be47b1a7f835c905f16147robertphillips@google.com GrTexture* result = NULL; 302a3e5c63ab0264332169df4583a8a7da186fb4e66robertphillips@google.com 3038059eb9f6e24ed609393fbda4ad71edea03ac258joshualitt // The top-left of the mask corresponds to the top-left corner of the bounds. 3048059eb9f6e24ed609393fbda4ad71edea03ac258joshualitt SkVector clipToMaskOffset = { 3058059eb9f6e24ed609393fbda4ad71edea03ac258joshualitt SkIntToScalar(-clipSpaceIBounds.fLeft), 3068059eb9f6e24ed609393fbda4ad71edea03ac258joshualitt SkIntToScalar(-clipSpaceIBounds.fTop) 3078059eb9f6e24ed609393fbda4ad71edea03ac258joshualitt }; 3088059eb9f6e24ed609393fbda4ad71edea03ac258joshualitt 3098dd688b7569df569a672a8a67b2db86a9d376cfcegdaniel if (this->useSWOnlyPath(pipelineBuilder, clipToMaskOffset, elements)) { 3104c2443e36fdc6c095b17e90baa4a2f26a6f00b08bsalomon@google.com // The clip geometry is complex enough that it will be more efficient to create it 3114c2443e36fdc6c095b17e90baa4a2f26a6f00b08bsalomon@google.com // entirely in software 3124c2443e36fdc6c095b17e90baa4a2f26a6f00b08bsalomon@google.com result = this->createSoftwareClipMask(genID, 3134c2443e36fdc6c095b17e90baa4a2f26a6f00b08bsalomon@google.com initialState, 3144c2443e36fdc6c095b17e90baa4a2f26a6f00b08bsalomon@google.com elements, 3158059eb9f6e24ed609393fbda4ad71edea03ac258joshualitt clipToMaskOffset, 3164c2443e36fdc6c095b17e90baa4a2f26a6f00b08bsalomon@google.com clipSpaceIBounds); 3174c2443e36fdc6c095b17e90baa4a2f26a6f00b08bsalomon@google.com } else { 3184c2443e36fdc6c095b17e90baa4a2f26a6f00b08bsalomon@google.com result = this->createAlphaClipMask(genID, 3194c2443e36fdc6c095b17e90baa4a2f26a6f00b08bsalomon@google.com initialState, 3204c2443e36fdc6c095b17e90baa4a2f26a6f00b08bsalomon@google.com elements, 3218059eb9f6e24ed609393fbda4ad71edea03ac258joshualitt clipToMaskOffset, 3224c2443e36fdc6c095b17e90baa4a2f26a6f00b08bsalomon@google.com clipSpaceIBounds); 3234c2443e36fdc6c095b17e90baa4a2f26a6f00b08bsalomon@google.com } 3246b70a7bd3328ea0a12be47b1a7f835c905f16147robertphillips@google.com 32549f085dddff10473b6ebf832a974288300224e60bsalomon if (result) { 3266be6f7cb66b277e7b1ce13d09b635fb8e09a2f68bsalomon arfp->set(pipelineBuilder); 3274c2443e36fdc6c095b17e90baa4a2f26a6f00b08bsalomon@google.com // The mask's top left coord should be pinned to the rounded-out top left corner of 3284c2443e36fdc6c095b17e90baa4a2f26a6f00b08bsalomon@google.com // clipSpace bounds. We determine the mask's position WRT to the render target here. 3294c2443e36fdc6c095b17e90baa4a2f26a6f00b08bsalomon@google.com SkIRect rtSpaceMaskBounds = clipSpaceIBounds; 33044701df5ce572ac3cccec785cf52103d3d5d14a5joshualitt rtSpaceMaskBounds.offset(-clip.origin()); 3316be6f7cb66b277e7b1ce13d09b635fb8e09a2f68bsalomon setup_drawstate_aaclip(pipelineBuilder, result, arfp, rtSpaceMaskBounds); 3328dd688b7569df569a672a8a67b2db86a9d376cfcegdaniel this->setPipelineBuilderStencil(pipelineBuilder, ars); 333f294b773f0b2b9f05eb45b52dd3cb4d97b96af06robertphillips@google.com return true; 334f294b773f0b2b9f05eb45b52dd3cb4d97b96af06robertphillips@google.com } 3354c2443e36fdc6c095b17e90baa4a2f26a6f00b08bsalomon@google.com // if alpha clip mask creation fails fall through to the non-AA code paths 336f294b773f0b2b9f05eb45b52dd3cb4d97b96af06robertphillips@google.com } 337f294b773f0b2b9f05eb45b52dd3cb4d97b96af06robertphillips@google.com 3384c2443e36fdc6c095b17e90baa4a2f26a6f00b08bsalomon@google.com // Either a hard (stencil buffer) clip was explicitly requested or an anti-aliased clip couldn't 3394c2443e36fdc6c095b17e90baa4a2f26a6f00b08bsalomon@google.com // be created. In either case, free up the texture in the anti-aliased mask cache. 3404c2443e36fdc6c095b17e90baa4a2f26a6f00b08bsalomon@google.com // TODO: this may require more investigation. Ganesh performs a lot of utility draws (e.g., 3414c2443e36fdc6c095b17e90baa4a2f26a6f00b08bsalomon@google.com // clears, InOrderDrawBuffer playbacks) that hit the stencil buffer path. These may be 3424c2443e36fdc6c095b17e90baa4a2f26a6f00b08bsalomon@google.com // "incorrectly" clearing the AA cache. 3435acc0e36d987dff3172fd45a14b66c52a51d49e4robertphillips@google.com fAACache.reset(); 3445acc0e36d987dff3172fd45a14b66c52a51d49e4robertphillips@google.com 3451e945b7e708c633d4aed937ebfce57d52ba21d83robertphillips@google.com // use the stencil clip if we can't represent the clip as a rectangle. 34644701df5ce572ac3cccec785cf52103d3d5d14a5joshualitt SkIPoint clipSpaceToStencilSpaceOffset = -clip.origin(); 3479853ccef19c200be93a6211f32589fa82a53067cjoshualitt this->createStencilClipMask(rt, 3489853ccef19c200be93a6211f32589fa82a53067cjoshualitt genID, 349d3e5842db0cb169e10d6da1e62c94ba5cf182bb4commit-bot@chromium.org initialState, 3504c2443e36fdc6c095b17e90baa4a2f26a6f00b08bsalomon@google.com elements, 3514c2443e36fdc6c095b17e90baa4a2f26a6f00b08bsalomon@google.com clipSpaceIBounds, 3524c2443e36fdc6c095b17e90baa4a2f26a6f00b08bsalomon@google.com clipSpaceToStencilSpaceOffset); 3534c2443e36fdc6c095b17e90baa4a2f26a6f00b08bsalomon@google.com 3544c2443e36fdc6c095b17e90baa4a2f26a6f00b08bsalomon@google.com // This must occur after createStencilClipMask. That function may change the scissor. Also, it 3554c2443e36fdc6c095b17e90baa4a2f26a6f00b08bsalomon@google.com // only guarantees that the stencil mask is correct within the bounds it was passed, so we must 3564c2443e36fdc6c095b17e90baa4a2f26a6f00b08bsalomon@google.com // use both stencil and scissor test to the bounds for the final draw. 3574c2443e36fdc6c095b17e90baa4a2f26a6f00b08bsalomon@google.com SkIRect scissorSpaceIBounds(clipSpaceIBounds); 3584c2443e36fdc6c095b17e90baa4a2f26a6f00b08bsalomon@google.com scissorSpaceIBounds.offset(clipSpaceToStencilSpaceOffset); 35977b1307c1f5dac019575a6d431d5ce657370c4fbjoshualitt scissorState->set(scissorSpaceIBounds); 3608dd688b7569df569a672a8a67b2db86a9d376cfcegdaniel this->setPipelineBuilderStencil(pipelineBuilder, ars); 3611e945b7e708c633d4aed937ebfce57d52ba21d83robertphillips@google.com return true; 3621e945b7e708c633d4aed937ebfce57d52ba21d83robertphillips@google.com} 3631e945b7e708c633d4aed937ebfce57d52ba21d83robertphillips@google.com 3641e945b7e708c633d4aed937ebfce57d52ba21d83robertphillips@google.comnamespace { 365f294b773f0b2b9f05eb45b52dd3cb4d97b96af06robertphillips@google.com//////////////////////////////////////////////////////////////////////////////// 3668dd688b7569df569a672a8a67b2db86a9d376cfcegdaniel// Set a coverage drawing XPF on the pipelineBuilder for the given op and invertCoverage mode 3678dd688b7569df569a672a8a67b2db86a9d376cfcegdanielvoid set_coverage_drawing_xpf(SkRegion::Op op, bool invertCoverage, 3688dd688b7569df569a672a8a67b2db86a9d376cfcegdaniel GrPipelineBuilder* pipelineBuilder) { 3698750924a1470e8215b2a344155259b93062d3fa2egdaniel SkASSERT(op <= SkRegion::kLastOp); 3708dd688b7569df569a672a8a67b2db86a9d376cfcegdaniel pipelineBuilder->setCoverageSetOpXPFactory(op, invertCoverage); 371f294b773f0b2b9f05eb45b52dd3cb4d97b96af06robertphillips@google.com} 37272176b2d38db005863a54e3dd6657bbabd068bb6robertphillips@google.com} 373f294b773f0b2b9f05eb45b52dd3cb4d97b96af06robertphillips@google.com 374f294b773f0b2b9f05eb45b52dd3cb4d97b96af06robertphillips@google.com//////////////////////////////////////////////////////////////////////////////// 3758dd688b7569df569a672a8a67b2db86a9d376cfcegdanielbool GrClipMaskManager::drawElement(GrPipelineBuilder* pipelineBuilder, 3768059eb9f6e24ed609393fbda4ad71edea03ac258joshualitt const SkMatrix& viewMatrix, 3779853ccef19c200be93a6211f32589fa82a53067cjoshualitt GrTexture* target, 378e79f320ed6c5ec9f6164ba84be1ff586532e6517robertphillips@google.com const SkClipStack::Element* element, 379e79f320ed6c5ec9f6164ba84be1ff586532e6517robertphillips@google.com GrPathRenderer* pr) { 3809853ccef19c200be93a6211f32589fa82a53067cjoshualitt GrDrawTarget::AutoGeometryPush agp(fClipTarget); 381f294b773f0b2b9f05eb45b52dd3cb4d97b96af06robertphillips@google.com 3828dd688b7569df569a672a8a67b2db86a9d376cfcegdaniel pipelineBuilder->setRenderTarget(target->asRenderTarget()); 383f294b773f0b2b9f05eb45b52dd3cb4d97b96af06robertphillips@google.com 3848750924a1470e8215b2a344155259b93062d3fa2egdaniel // The color we use to draw does not matter since we will always be using a GrCoverageSetOpXP 3858750924a1470e8215b2a344155259b93062d3fa2egdaniel // which ignores color. 3868750924a1470e8215b2a344155259b93062d3fa2egdaniel GrColor color = GrColor_WHITE; 3878750924a1470e8215b2a344155259b93062d3fa2egdaniel 388e5b2af955b7d06815ddd405659ad62a2a8355ca3commit-bot@chromium.org // TODO: Draw rrects directly here. 3898182fa0cac76e7e6d583aebba060229230516887bsalomon@google.com switch (element->getType()) { 390e5b2af955b7d06815ddd405659ad62a2a8355ca3commit-bot@chromium.org case Element::kEmpty_Type: 391e5b2af955b7d06815ddd405659ad62a2a8355ca3commit-bot@chromium.org SkDEBUGFAIL("Should never get here with an empty element."); 392e5b2af955b7d06815ddd405659ad62a2a8355ca3commit-bot@chromium.org break; 3938182fa0cac76e7e6d583aebba060229230516887bsalomon@google.com case Element::kRect_Type: 394b0a8a377f832c59cee939ad721e1f87d378b7142joshualitt // TODO: Do rects directly to the accumulator using a aa-rect GrProcessor that covers 395b0a8a377f832c59cee939ad721e1f87d378b7142joshualitt // the entire mask bounds and writes 0 outside the rect. 3968182fa0cac76e7e6d583aebba060229230516887bsalomon@google.com if (element->isAA()) { 3978059eb9f6e24ed609393fbda4ad71edea03ac258joshualitt SkRect devRect = element->getRect(); 3988059eb9f6e24ed609393fbda4ad71edea03ac258joshualitt viewMatrix.mapRect(&devRect); 399329bf4862e9d5e05363c2b071d8ca475a0ef1952joshualitt this->getContext()->getAARectRenderer()->fillAARect(fClipTarget, 4008dd688b7569df569a672a8a67b2db86a9d376cfcegdaniel pipelineBuilder, 4012e3b3e369d79e78f7635d4c20e83a47ab571bdf2joshualitt color, 4028059eb9f6e24ed609393fbda4ad71edea03ac258joshualitt viewMatrix, 403a58fe35fdae3481cf43062f7032820c320c3d163joshualitt element->getRect(), 4048059eb9f6e24ed609393fbda4ad71edea03ac258joshualitt devRect); 4058182fa0cac76e7e6d583aebba060229230516887bsalomon@google.com } else { 4068dd688b7569df569a672a8a67b2db86a9d376cfcegdaniel fClipTarget->drawSimpleRect(pipelineBuilder, color, viewMatrix, element->getRect()); 4078182fa0cac76e7e6d583aebba060229230516887bsalomon@google.com } 4088182fa0cac76e7e6d583aebba060229230516887bsalomon@google.com return true; 409e5b2af955b7d06815ddd405659ad62a2a8355ca3commit-bot@chromium.org default: { 410e5b2af955b7d06815ddd405659ad62a2a8355ca3commit-bot@chromium.org SkPath path; 411e5b2af955b7d06815ddd405659ad62a2a8355ca3commit-bot@chromium.org element->asPath(&path); 412b3eb687f8a89eb1eacd1afb4016401eb392f66abjvanverth path.setIsVolatile(true); 413e5b2af955b7d06815ddd405659ad62a2a8355ca3commit-bot@chromium.org if (path.isInverseFillType()) { 414e5b2af955b7d06815ddd405659ad62a2a8355ca3commit-bot@chromium.org path.toggleInverseFillType(); 415e79f320ed6c5ec9f6164ba84be1ff586532e6517robertphillips@google.com } 4165f74cf8c49701f514b69dc6f1a8b5c0ffd78af0asugoi@google.com SkStrokeRec stroke(SkStrokeRec::kFill_InitStyle); 417e79f320ed6c5ec9f6164ba84be1ff586532e6517robertphillips@google.com if (NULL == pr) { 418e79f320ed6c5ec9f6164ba84be1ff586532e6517robertphillips@google.com GrPathRendererChain::DrawType type; 419e79f320ed6c5ec9f6164ba84be1ff586532e6517robertphillips@google.com type = element->isAA() ? GrPathRendererChain::kColorAntiAlias_DrawType : 420e79f320ed6c5ec9f6164ba84be1ff586532e6517robertphillips@google.com GrPathRendererChain::kColor_DrawType; 4218dd688b7569df569a672a8a67b2db86a9d376cfcegdaniel pr = this->getContext()->getPathRenderer(fClipTarget, pipelineBuilder, viewMatrix, 4228dd688b7569df569a672a8a67b2db86a9d376cfcegdaniel path, stroke, false, type); 423e79f320ed6c5ec9f6164ba84be1ff586532e6517robertphillips@google.com } 424e79f320ed6c5ec9f6164ba84be1ff586532e6517robertphillips@google.com if (NULL == pr) { 4254c2443e36fdc6c095b17e90baa4a2f26a6f00b08bsalomon@google.com return false; 4264c2443e36fdc6c095b17e90baa4a2f26a6f00b08bsalomon@google.com } 4279853ccef19c200be93a6211f32589fa82a53067cjoshualitt 4288dd688b7569df569a672a8a67b2db86a9d376cfcegdaniel pr->drawPath(fClipTarget, pipelineBuilder, color, viewMatrix, path, stroke, 4298dd688b7569df569a672a8a67b2db86a9d376cfcegdaniel element->isAA()); 4304c2443e36fdc6c095b17e90baa4a2f26a6f00b08bsalomon@google.com break; 4314c2443e36fdc6c095b17e90baa4a2f26a6f00b08bsalomon@google.com } 432f294b773f0b2b9f05eb45b52dd3cb4d97b96af06robertphillips@google.com } 433f294b773f0b2b9f05eb45b52dd3cb4d97b96af06robertphillips@google.com return true; 434f294b773f0b2b9f05eb45b52dd3cb4d97b96af06robertphillips@google.com} 435f294b773f0b2b9f05eb45b52dd3cb4d97b96af06robertphillips@google.com 4368dd688b7569df569a672a8a67b2db86a9d376cfcegdanielbool GrClipMaskManager::canStencilAndDrawElement(GrPipelineBuilder* pipelineBuilder, 4379853ccef19c200be93a6211f32589fa82a53067cjoshualitt GrTexture* target, 4389853ccef19c200be93a6211f32589fa82a53067cjoshualitt GrPathRenderer** pr, 4399853ccef19c200be93a6211f32589fa82a53067cjoshualitt const SkClipStack::Element* element) { 4408dd688b7569df569a672a8a67b2db86a9d376cfcegdaniel pipelineBuilder->setRenderTarget(target->asRenderTarget()); 441b68addd39f3e7183facc70374a133e7a6fb603c5bsalomon@google.com 442e5b2af955b7d06815ddd405659ad62a2a8355ca3commit-bot@chromium.org if (Element::kRect_Type == element->getType()) { 443e5b2af955b7d06815ddd405659ad62a2a8355ca3commit-bot@chromium.org return true; 444e5b2af955b7d06815ddd405659ad62a2a8355ca3commit-bot@chromium.org } else { 445e5b2af955b7d06815ddd405659ad62a2a8355ca3commit-bot@chromium.org // We shouldn't get here with an empty clip element. 446e5b2af955b7d06815ddd405659ad62a2a8355ca3commit-bot@chromium.org SkASSERT(Element::kEmpty_Type != element->getType()); 447e5b2af955b7d06815ddd405659ad62a2a8355ca3commit-bot@chromium.org SkPath path; 448e5b2af955b7d06815ddd405659ad62a2a8355ca3commit-bot@chromium.org element->asPath(&path); 449e5b2af955b7d06815ddd405659ad62a2a8355ca3commit-bot@chromium.org if (path.isInverseFillType()) { 450e5b2af955b7d06815ddd405659ad62a2a8355ca3commit-bot@chromium.org path.toggleInverseFillType(); 451b68addd39f3e7183facc70374a133e7a6fb603c5bsalomon@google.com } 452e5b2af955b7d06815ddd405659ad62a2a8355ca3commit-bot@chromium.org SkStrokeRec stroke(SkStrokeRec::kFill_InitStyle); 453e5b2af955b7d06815ddd405659ad62a2a8355ca3commit-bot@chromium.org GrPathRendererChain::DrawType type = element->isAA() ? 454e5b2af955b7d06815ddd405659ad62a2a8355ca3commit-bot@chromium.org GrPathRendererChain::kStencilAndColorAntiAlias_DrawType : 455e5b2af955b7d06815ddd405659ad62a2a8355ca3commit-bot@chromium.org GrPathRendererChain::kStencilAndColor_DrawType; 4568dd688b7569df569a672a8a67b2db86a9d376cfcegdaniel *pr = this->getContext()->getPathRenderer(fClipTarget, pipelineBuilder, SkMatrix::I(), path, 4578059eb9f6e24ed609393fbda4ad71edea03ac258joshualitt stroke, false, type); 45849f085dddff10473b6ebf832a974288300224e60bsalomon return SkToBool(*pr); 459b68addd39f3e7183facc70374a133e7a6fb603c5bsalomon@google.com } 460b68addd39f3e7183facc70374a133e7a6fb603c5bsalomon@google.com} 461b68addd39f3e7183facc70374a133e7a6fb603c5bsalomon@google.com 4628dd688b7569df569a672a8a67b2db86a9d376cfcegdanielvoid GrClipMaskManager::mergeMask(GrPipelineBuilder* pipelineBuilder, 4639853ccef19c200be93a6211f32589fa82a53067cjoshualitt GrTexture* dstMask, 4647b7cdd147f5528865238e5ed98c79e6d319fde9bbsalomon@google.com GrTexture* srcMask, 4657b7cdd147f5528865238e5ed98c79e6d319fde9bbsalomon@google.com SkRegion::Op op, 466fd03d4a829efe2d77a712fd991927c55f59a2ffecommit-bot@chromium.org const SkIRect& dstBound, 467fd03d4a829efe2d77a712fd991927c55f59a2ffecommit-bot@chromium.org const SkIRect& srcBound) { 4688dd688b7569df569a672a8a67b2db86a9d376cfcegdaniel pipelineBuilder->setRenderTarget(dstMask->asRenderTarget()); 469f294b773f0b2b9f05eb45b52dd3cb4d97b96af06robertphillips@google.com 4708750924a1470e8215b2a344155259b93062d3fa2egdaniel // We want to invert the coverage here 4718dd688b7569df569a672a8a67b2db86a9d376cfcegdaniel set_coverage_drawing_xpf(op, false, pipelineBuilder); 47272b2e6fff3f54c6aa80a98eab4c73f02a8cd450dskia.committer@gmail.com 473b9086a026844e4cfd08b219e49ce3f12294cba98bsalomon@google.com SkMatrix sampleM; 4747b7cdd147f5528865238e5ed98c79e6d319fde9bbsalomon@google.com sampleM.setIDiv(srcMask->width(), srcMask->height()); 475956b310f13c7412c035406c658ff16ca85eac656skia.committer@gmail.com 4768dd688b7569df569a672a8a67b2db86a9d376cfcegdaniel pipelineBuilder->addCoverageProcessor( 4777b7cdd147f5528865238e5ed98c79e6d319fde9bbsalomon@google.com GrTextureDomainEffect::Create(srcMask, 4787b7cdd147f5528865238e5ed98c79e6d319fde9bbsalomon@google.com sampleM, 479907fbd53c5e5dd4cbde7b72f9242b51febd7ef95commit-bot@chromium.org GrTextureDomain::MakeTexelDomain(srcMask, srcBound), 480907fbd53c5e5dd4cbde7b72f9242b51febd7ef95commit-bot@chromium.org GrTextureDomain::kDecal_Mode, 481b86add1ad37776818e1f730359ec587c9fdbff5fhumper@google.com GrTextureParams::kNone_FilterMode))->unref(); 4828750924a1470e8215b2a344155259b93062d3fa2egdaniel // The color passed in here does not matter since the coverageSetOpXP won't read it. 48344701df5ce572ac3cccec785cf52103d3d5d14a5joshualitt fClipTarget->drawSimpleRect(pipelineBuilder, 48444701df5ce572ac3cccec785cf52103d3d5d14a5joshualitt GrColor_WHITE, 48544701df5ce572ac3cccec785cf52103d3d5d14a5joshualitt SkMatrix::I(), 4868dd688b7569df569a672a8a67b2db86a9d376cfcegdaniel SkRect::Make(dstBound)); 487f294b773f0b2b9f05eb45b52dd3cb4d97b96af06robertphillips@google.com} 488f294b773f0b2b9f05eb45b52dd3cb4d97b96af06robertphillips@google.com 489427cf28861867c0ea9aafca3a23878ec4068ad99bsalomonGrTexture* GrClipMaskManager::createTempMask(int width, int height) { 490f2703d83da3ab2ae18b45231fd4f11e16cce3184bsalomon GrSurfaceDesc desc; 4913f490a0c0170feb8b53c220d6c5331c23aeb3f23bsalomon desc.fFlags = kRenderTarget_GrSurfaceFlag; 4924c2443e36fdc6c095b17e90baa4a2f26a6f00b08bsalomon@google.com desc.fWidth = width; 4934c2443e36fdc6c095b17e90baa4a2f26a6f00b08bsalomon@google.com desc.fHeight = height; 49451d1f7e3a4305e517586dc158a0329bbaa8896aabsalomon if (this->getContext()->isConfigRenderable(kAlpha_8_GrPixelConfig, false)) { 49551d1f7e3a4305e517586dc158a0329bbaa8896aabsalomon desc.fConfig = kAlpha_8_GrPixelConfig; 49651d1f7e3a4305e517586dc158a0329bbaa8896aabsalomon } else { 49751d1f7e3a4305e517586dc158a0329bbaa8896aabsalomon desc.fConfig = kRGBA_8888_GrPixelConfig; 49851d1f7e3a4305e517586dc158a0329bbaa8896aabsalomon } 4996b70a7bd3328ea0a12be47b1a7f835c905f16147robertphillips@google.com 500329bf4862e9d5e05363c2b071d8ca475a0ef1952joshualitt return this->getContext()->refScratchTexture(desc, GrContext::kApprox_ScratchTexMatch); 5016d62df404bf420bedff4d7b5edd061740a673d44robertphillips@google.com} 5026d62df404bf420bedff4d7b5edd061740a673d44robertphillips@google.com 5036b70a7bd3328ea0a12be47b1a7f835c905f16147robertphillips@google.com//////////////////////////////////////////////////////////////////////////////// 504ad1dc589cef8aebf7e14672ffdaa31c6d399675dkrajcevski// Return the texture currently in the cache if it exists. Otherwise, return NULL 505ad1dc589cef8aebf7e14672ffdaa31c6d399675dkrajcevskiGrTexture* GrClipMaskManager::getCachedMaskTexture(int32_t elementsGenID, 506ad1dc589cef8aebf7e14672ffdaa31c6d399675dkrajcevski const SkIRect& clipSpaceIBounds) { 507d3e5842db0cb169e10d6da1e62c94ba5cf182bb4commit-bot@chromium.org bool cached = fAACache.canReuse(elementsGenID, clipSpaceIBounds); 5084c2443e36fdc6c095b17e90baa4a2f26a6f00b08bsalomon@google.com if (!cached) { 509ad1dc589cef8aebf7e14672ffdaa31c6d399675dkrajcevski return NULL; 510ad1dc589cef8aebf7e14672ffdaa31c6d399675dkrajcevski } 5114c2443e36fdc6c095b17e90baa4a2f26a6f00b08bsalomon@google.com 512ad1dc589cef8aebf7e14672ffdaa31c6d399675dkrajcevski return fAACache.getLastMask(); 513ad1dc589cef8aebf7e14672ffdaa31c6d399675dkrajcevski} 514f294b773f0b2b9f05eb45b52dd3cb4d97b96af06robertphillips@google.com 515ad1dc589cef8aebf7e14672ffdaa31c6d399675dkrajcevski//////////////////////////////////////////////////////////////////////////////// 516ad1dc589cef8aebf7e14672ffdaa31c6d399675dkrajcevski// Allocate a texture in the texture cache. This function returns the texture 517ad1dc589cef8aebf7e14672ffdaa31c6d399675dkrajcevski// allocated (or NULL on error). 518ad1dc589cef8aebf7e14672ffdaa31c6d399675dkrajcevskiGrTexture* GrClipMaskManager::allocMaskTexture(int32_t elementsGenID, 519ad1dc589cef8aebf7e14672ffdaa31c6d399675dkrajcevski const SkIRect& clipSpaceIBounds, 520ad1dc589cef8aebf7e14672ffdaa31c6d399675dkrajcevski bool willUpload) { 521ad1dc589cef8aebf7e14672ffdaa31c6d399675dkrajcevski // Since we are setting up the cache we should free up the 522ad1dc589cef8aebf7e14672ffdaa31c6d399675dkrajcevski // currently cached mask so it can be reused. 523ad1dc589cef8aebf7e14672ffdaa31c6d399675dkrajcevski fAACache.reset(); 524a72eef322c686954cdffa849dc26d8133b802f1drobertphillips@google.com 525f2703d83da3ab2ae18b45231fd4f11e16cce3184bsalomon GrSurfaceDesc desc; 526f2703d83da3ab2ae18b45231fd4f11e16cce3184bsalomon desc.fFlags = willUpload ? kNone_GrSurfaceFlags : kRenderTarget_GrSurfaceFlag; 527ad1dc589cef8aebf7e14672ffdaa31c6d399675dkrajcevski desc.fWidth = clipSpaceIBounds.width(); 528ad1dc589cef8aebf7e14672ffdaa31c6d399675dkrajcevski desc.fHeight = clipSpaceIBounds.height(); 529ad1dc589cef8aebf7e14672ffdaa31c6d399675dkrajcevski desc.fConfig = kRGBA_8888_GrPixelConfig; 530ad1dc589cef8aebf7e14672ffdaa31c6d399675dkrajcevski if (willUpload || this->getContext()->isConfigRenderable(kAlpha_8_GrPixelConfig, false)) { 531ad1dc589cef8aebf7e14672ffdaa31c6d399675dkrajcevski // We would always like A8 but it isn't supported on all platforms 532ad1dc589cef8aebf7e14672ffdaa31c6d399675dkrajcevski desc.fConfig = kAlpha_8_GrPixelConfig; 5338fff356c8505f2ac78e1fc9dc17c1192e3a608e4robertphillips@google.com } 5348fff356c8505f2ac78e1fc9dc17c1192e3a608e4robertphillips@google.com 535ad1dc589cef8aebf7e14672ffdaa31c6d399675dkrajcevski fAACache.acquireMask(elementsGenID, desc, clipSpaceIBounds); 536ad1dc589cef8aebf7e14672ffdaa31c6d399675dkrajcevski return fAACache.getLastMask(); 5376b70a7bd3328ea0a12be47b1a7f835c905f16147robertphillips@google.com} 538f294b773f0b2b9f05eb45b52dd3cb4d97b96af06robertphillips@google.com 5396b70a7bd3328ea0a12be47b1a7f835c905f16147robertphillips@google.com//////////////////////////////////////////////////////////////////////////////// 5406b70a7bd3328ea0a12be47b1a7f835c905f16147robertphillips@google.com// Create a 8-bit clip mask in alpha 541d3e5842db0cb169e10d6da1e62c94ba5cf182bb4commit-bot@chromium.orgGrTexture* GrClipMaskManager::createAlphaClipMask(int32_t elementsGenID, 542bf54e49e30cdc92f9ce3f336cc48cf6b236ddeabtfarina GrReducedClip::InitialState initialState, 543bf54e49e30cdc92f9ce3f336cc48cf6b236ddeabtfarina const GrReducedClip::ElementList& elements, 5448059eb9f6e24ed609393fbda4ad71edea03ac258joshualitt const SkVector& clipToMaskOffset, 5454c2443e36fdc6c095b17e90baa4a2f26a6f00b08bsalomon@google.com const SkIRect& clipSpaceIBounds) { 546f6de475e5cbd143f348ff7738919e397b7fe7f57tfarina@chromium.org SkASSERT(kNone_ClipMaskType == fCurrClipMaskType); 547c8f7f47afaf8f9471e6d111655c5610a8bd210a2bsalomon@google.com 548ad1dc589cef8aebf7e14672ffdaa31c6d399675dkrajcevski // First, check for cached texture 549ad1dc589cef8aebf7e14672ffdaa31c6d399675dkrajcevski GrTexture* result = this->getCachedMaskTexture(elementsGenID, clipSpaceIBounds); 55049f085dddff10473b6ebf832a974288300224e60bsalomon if (result) { 551c8f7f47afaf8f9471e6d111655c5610a8bd210a2bsalomon@google.com fCurrClipMaskType = kAlpha_ClipMaskType; 5524c2443e36fdc6c095b17e90baa4a2f26a6f00b08bsalomon@google.com return result; 5536b70a7bd3328ea0a12be47b1a7f835c905f16147robertphillips@google.com } 554f294b773f0b2b9f05eb45b52dd3cb4d97b96af06robertphillips@google.com 555ad1dc589cef8aebf7e14672ffdaa31c6d399675dkrajcevski // There's no texture in the cache. Let's try to allocate it then. 556ad1dc589cef8aebf7e14672ffdaa31c6d399675dkrajcevski result = this->allocMaskTexture(elementsGenID, clipSpaceIBounds, false); 5574c2443e36fdc6c095b17e90baa4a2f26a6f00b08bsalomon@google.com if (NULL == result) { 558f105b109264f71dfb0bfd9977e6a5dd0a5a12f57robertphillips@google.com fAACache.reset(); 5594c2443e36fdc6c095b17e90baa4a2f26a6f00b08bsalomon@google.com return NULL; 560f294b773f0b2b9f05eb45b52dd3cb4d97b96af06robertphillips@google.com } 561f294b773f0b2b9f05eb45b52dd3cb4d97b96af06robertphillips@google.com 5628059eb9f6e24ed609393fbda4ad71edea03ac258joshualitt // Set the matrix so that rendered clip elements are transformed to mask space from clip 5638059eb9f6e24ed609393fbda4ad71edea03ac258joshualitt // space. 5648059eb9f6e24ed609393fbda4ad71edea03ac258joshualitt SkMatrix translate; 5658059eb9f6e24ed609393fbda4ad71edea03ac258joshualitt translate.setTranslate(clipToMaskOffset); 5668059eb9f6e24ed609393fbda4ad71edea03ac258joshualitt 5674c2443e36fdc6c095b17e90baa4a2f26a6f00b08bsalomon@google.com // The texture may be larger than necessary, this rect represents the part of the texture 5684c2443e36fdc6c095b17e90baa4a2f26a6f00b08bsalomon@google.com // we populate with a rasterization of the clip. 5694c2443e36fdc6c095b17e90baa4a2f26a6f00b08bsalomon@google.com SkIRect maskSpaceIBounds = SkIRect::MakeWH(clipSpaceIBounds.width(), clipSpaceIBounds.height()); 570f294b773f0b2b9f05eb45b52dd3cb4d97b96af06robertphillips@google.com 5717b7cdd147f5528865238e5ed98c79e6d319fde9bbsalomon@google.com // The scratch texture that we are drawing into can be substantially larger than the mask. Only 5727b7cdd147f5528865238e5ed98c79e6d319fde9bbsalomon@google.com // clear the part that we care about. 573329bf4862e9d5e05363c2b071d8ca475a0ef1952joshualitt fClipTarget->clear(&maskSpaceIBounds, 574329bf4862e9d5e05363c2b071d8ca475a0ef1952joshualitt GrReducedClip::kAllIn_InitialState == initialState ? 0xffffffff : 0x00000000, 575329bf4862e9d5e05363c2b071d8ca475a0ef1952joshualitt true, 576329bf4862e9d5e05363c2b071d8ca475a0ef1952joshualitt result->asRenderTarget()); 577d9f7503e0cb0c4db856f53b4bdeec1332db6f296skia.committer@gmail.com 578b68addd39f3e7183facc70374a133e7a6fb603c5bsalomon@google.com // When we use the stencil in the below loop it is important to have this clip installed. 579b68addd39f3e7183facc70374a133e7a6fb603c5bsalomon@google.com // The second pass that zeros the stencil buffer renders the rect maskSpaceIBounds so the first 580b68addd39f3e7183facc70374a133e7a6fb603c5bsalomon@google.com // pass must not set values outside of this bounds or stencil values outside the rect won't be 581b68addd39f3e7183facc70374a133e7a6fb603c5bsalomon@google.com // cleared. 58244701df5ce572ac3cccec785cf52103d3d5d14a5joshualitt GrClip clip(maskSpaceIBounds); 583427cf28861867c0ea9aafca3a23878ec4068ad99bsalomon SkAutoTUnref<GrTexture> temp; 5849853ccef19c200be93a6211f32589fa82a53067cjoshualitt 585f294b773f0b2b9f05eb45b52dd3cb4d97b96af06robertphillips@google.com // walk through each clip element and perform its set op 586bf54e49e30cdc92f9ce3f336cc48cf6b236ddeabtfarina for (GrReducedClip::ElementList::Iter iter = elements.headIter(); iter.get(); iter.next()) { 5874c2443e36fdc6c095b17e90baa4a2f26a6f00b08bsalomon@google.com const Element* element = iter.get(); 5888182fa0cac76e7e6d583aebba060229230516887bsalomon@google.com SkRegion::Op op = element->getOp(); 589b68addd39f3e7183facc70374a133e7a6fb603c5bsalomon@google.com bool invert = element->isInverseFilled(); 590b68addd39f3e7183facc70374a133e7a6fb603c5bsalomon@google.com if (invert || SkRegion::kIntersect_Op == op || SkRegion::kReverseDifference_Op == op) { 5918dd688b7569df569a672a8a67b2db86a9d376cfcegdaniel GrPipelineBuilder pipelineBuilder; 5929853ccef19c200be93a6211f32589fa82a53067cjoshualitt 59344701df5ce572ac3cccec785cf52103d3d5d14a5joshualitt pipelineBuilder.setClip(clip); 594e79f320ed6c5ec9f6164ba84be1ff586532e6517robertphillips@google.com GrPathRenderer* pr = NULL; 5958dd688b7569df569a672a8a67b2db86a9d376cfcegdaniel bool useTemp = !this->canStencilAndDrawElement(&pipelineBuilder, result, &pr, element); 596b68addd39f3e7183facc70374a133e7a6fb603c5bsalomon@google.com GrTexture* dst; 5974c2443e36fdc6c095b17e90baa4a2f26a6f00b08bsalomon@google.com // This is the bounds of the clip element in the space of the alpha-mask. The temporary 5987b7cdd147f5528865238e5ed98c79e6d319fde9bbsalomon@google.com // mask buffer can be substantially larger than the actually clip stack element. We 5997b7cdd147f5528865238e5ed98c79e6d319fde9bbsalomon@google.com // touch the minimum number of pixels necessary and use decal mode to combine it with 600b68addd39f3e7183facc70374a133e7a6fb603c5bsalomon@google.com // the accumulator. 601fd03d4a829efe2d77a712fd991927c55f59a2ffecommit-bot@chromium.org SkIRect maskSpaceElementIBounds; 602b68addd39f3e7183facc70374a133e7a6fb603c5bsalomon@google.com 603b68addd39f3e7183facc70374a133e7a6fb603c5bsalomon@google.com if (useTemp) { 604b68addd39f3e7183facc70374a133e7a6fb603c5bsalomon@google.com if (invert) { 605b68addd39f3e7183facc70374a133e7a6fb603c5bsalomon@google.com maskSpaceElementIBounds = maskSpaceIBounds; 606b68addd39f3e7183facc70374a133e7a6fb603c5bsalomon@google.com } else { 607fd03d4a829efe2d77a712fd991927c55f59a2ffecommit-bot@chromium.org SkRect elementBounds = element->getBounds(); 608b68addd39f3e7183facc70374a133e7a6fb603c5bsalomon@google.com elementBounds.offset(clipToMaskOffset); 609b68addd39f3e7183facc70374a133e7a6fb603c5bsalomon@google.com elementBounds.roundOut(&maskSpaceElementIBounds); 610b68addd39f3e7183facc70374a133e7a6fb603c5bsalomon@google.com } 611b68addd39f3e7183facc70374a133e7a6fb603c5bsalomon@google.com 612427cf28861867c0ea9aafca3a23878ec4068ad99bsalomon if (!temp) { 613427cf28861867c0ea9aafca3a23878ec4068ad99bsalomon temp.reset(this->createTempMask(maskSpaceIBounds.fRight, 614427cf28861867c0ea9aafca3a23878ec4068ad99bsalomon maskSpaceIBounds.fBottom)); 615427cf28861867c0ea9aafca3a23878ec4068ad99bsalomon if (!temp) { 616427cf28861867c0ea9aafca3a23878ec4068ad99bsalomon fAACache.reset(); 617427cf28861867c0ea9aafca3a23878ec4068ad99bsalomon return NULL; 618427cf28861867c0ea9aafca3a23878ec4068ad99bsalomon } 619a7aedfec9e28db36c97e49f11f2bc2e0eb624c30skia.committer@gmail.com } 620427cf28861867c0ea9aafca3a23878ec4068ad99bsalomon dst = temp; 621b68addd39f3e7183facc70374a133e7a6fb603c5bsalomon@google.com // clear the temp target and set blend to replace 622329bf4862e9d5e05363c2b071d8ca475a0ef1952joshualitt fClipTarget->clear(&maskSpaceElementIBounds, 6239853ccef19c200be93a6211f32589fa82a53067cjoshualitt invert ? 0xffffffff : 0x00000000, 6249853ccef19c200be93a6211f32589fa82a53067cjoshualitt true, 6259853ccef19c200be93a6211f32589fa82a53067cjoshualitt dst->asRenderTarget()); 6268dd688b7569df569a672a8a67b2db86a9d376cfcegdaniel set_coverage_drawing_xpf(SkRegion::kReplace_Op, invert, &pipelineBuilder); 6274c2443e36fdc6c095b17e90baa4a2f26a6f00b08bsalomon@google.com } else { 628b68addd39f3e7183facc70374a133e7a6fb603c5bsalomon@google.com // draw directly into the result with the stencil set to make the pixels affected 629b68addd39f3e7183facc70374a133e7a6fb603c5bsalomon@google.com // by the clip shape be non-zero. 630b68addd39f3e7183facc70374a133e7a6fb603c5bsalomon@google.com dst = result; 631b68addd39f3e7183facc70374a133e7a6fb603c5bsalomon@google.com GR_STATIC_CONST_SAME_STENCIL(kStencilInElement, 632b68addd39f3e7183facc70374a133e7a6fb603c5bsalomon@google.com kReplace_StencilOp, 633b68addd39f3e7183facc70374a133e7a6fb603c5bsalomon@google.com kReplace_StencilOp, 634b68addd39f3e7183facc70374a133e7a6fb603c5bsalomon@google.com kAlways_StencilFunc, 635b68addd39f3e7183facc70374a133e7a6fb603c5bsalomon@google.com 0xffff, 636b68addd39f3e7183facc70374a133e7a6fb603c5bsalomon@google.com 0xffff, 637b68addd39f3e7183facc70374a133e7a6fb603c5bsalomon@google.com 0xffff); 6388dd688b7569df569a672a8a67b2db86a9d376cfcegdaniel pipelineBuilder.setStencil(kStencilInElement); 6398dd688b7569df569a672a8a67b2db86a9d376cfcegdaniel set_coverage_drawing_xpf(op, invert, &pipelineBuilder); 6404c2443e36fdc6c095b17e90baa4a2f26a6f00b08bsalomon@google.com } 6417b7cdd147f5528865238e5ed98c79e6d319fde9bbsalomon@google.com 6428dd688b7569df569a672a8a67b2db86a9d376cfcegdaniel if (!this->drawElement(&pipelineBuilder, translate, dst, element, pr)) { 643e79f320ed6c5ec9f6164ba84be1ff586532e6517robertphillips@google.com fAACache.reset(); 644e79f320ed6c5ec9f6164ba84be1ff586532e6517robertphillips@google.com return NULL; 6454c2443e36fdc6c095b17e90baa4a2f26a6f00b08bsalomon@google.com } 646f294b773f0b2b9f05eb45b52dd3cb4d97b96af06robertphillips@google.com 647b68addd39f3e7183facc70374a133e7a6fb603c5bsalomon@google.com if (useTemp) { 6488dd688b7569df569a672a8a67b2db86a9d376cfcegdaniel GrPipelineBuilder backgroundPipelineBuilder; 6498dd688b7569df569a672a8a67b2db86a9d376cfcegdaniel backgroundPipelineBuilder.setRenderTarget(result->asRenderTarget()); 6508fc6c2d82c1f30ff82274334c01f0799def6a609joshualitt 651b68addd39f3e7183facc70374a133e7a6fb603c5bsalomon@google.com // Now draw into the accumulator using the real operation and the temp buffer as a 652b68addd39f3e7183facc70374a133e7a6fb603c5bsalomon@google.com // texture 6538dd688b7569df569a672a8a67b2db86a9d376cfcegdaniel this->mergeMask(&backgroundPipelineBuilder, 6549853ccef19c200be93a6211f32589fa82a53067cjoshualitt result, 655427cf28861867c0ea9aafca3a23878ec4068ad99bsalomon temp, 656b68addd39f3e7183facc70374a133e7a6fb603c5bsalomon@google.com op, 657b68addd39f3e7183facc70374a133e7a6fb603c5bsalomon@google.com maskSpaceIBounds, 658b68addd39f3e7183facc70374a133e7a6fb603c5bsalomon@google.com maskSpaceElementIBounds); 659b68addd39f3e7183facc70374a133e7a6fb603c5bsalomon@google.com } else { 6608dd688b7569df569a672a8a67b2db86a9d376cfcegdaniel GrPipelineBuilder backgroundPipelineBuilder; 6618dd688b7569df569a672a8a67b2db86a9d376cfcegdaniel backgroundPipelineBuilder.setRenderTarget(result->asRenderTarget()); 6628fc6c2d82c1f30ff82274334c01f0799def6a609joshualitt 6638dd688b7569df569a672a8a67b2db86a9d376cfcegdaniel set_coverage_drawing_xpf(op, !invert, &backgroundPipelineBuilder); 664b68addd39f3e7183facc70374a133e7a6fb603c5bsalomon@google.com // Draw to the exterior pixels (those with a zero stencil value). 665b68addd39f3e7183facc70374a133e7a6fb603c5bsalomon@google.com GR_STATIC_CONST_SAME_STENCIL(kDrawOutsideElement, 666b68addd39f3e7183facc70374a133e7a6fb603c5bsalomon@google.com kZero_StencilOp, 667b68addd39f3e7183facc70374a133e7a6fb603c5bsalomon@google.com kZero_StencilOp, 668b68addd39f3e7183facc70374a133e7a6fb603c5bsalomon@google.com kEqual_StencilFunc, 669b68addd39f3e7183facc70374a133e7a6fb603c5bsalomon@google.com 0xffff, 670b68addd39f3e7183facc70374a133e7a6fb603c5bsalomon@google.com 0x0000, 671b68addd39f3e7183facc70374a133e7a6fb603c5bsalomon@google.com 0xffff); 6728dd688b7569df569a672a8a67b2db86a9d376cfcegdaniel backgroundPipelineBuilder.setStencil(kDrawOutsideElement); 6738750924a1470e8215b2a344155259b93062d3fa2egdaniel // The color passed in here does not matter since the coverageSetOpXP won't read it. 6748dd688b7569df569a672a8a67b2db86a9d376cfcegdaniel fClipTarget->drawSimpleRect(&backgroundPipelineBuilder, GrColor_WHITE, translate, 6758059eb9f6e24ed609393fbda4ad71edea03ac258joshualitt clipSpaceIBounds); 676b68addd39f3e7183facc70374a133e7a6fb603c5bsalomon@google.com } 677f294b773f0b2b9f05eb45b52dd3cb4d97b96af06robertphillips@google.com } else { 6788dd688b7569df569a672a8a67b2db86a9d376cfcegdaniel GrPipelineBuilder pipelineBuilder; 6799853ccef19c200be93a6211f32589fa82a53067cjoshualitt 680e79f320ed6c5ec9f6164ba84be1ff586532e6517robertphillips@google.com // all the remaining ops can just be directly draw into the accumulation buffer 6818dd688b7569df569a672a8a67b2db86a9d376cfcegdaniel set_coverage_drawing_xpf(op, false, &pipelineBuilder); 6828750924a1470e8215b2a344155259b93062d3fa2egdaniel // The color passed in here does not matter since the coverageSetOpXP won't read it. 6838dd688b7569df569a672a8a67b2db86a9d376cfcegdaniel this->drawElement(&pipelineBuilder, translate, result, element); 684f294b773f0b2b9f05eb45b52dd3cb4d97b96af06robertphillips@google.com } 685f294b773f0b2b9f05eb45b52dd3cb4d97b96af06robertphillips@google.com } 686f294b773f0b2b9f05eb45b52dd3cb4d97b96af06robertphillips@google.com 687c8f7f47afaf8f9471e6d111655c5610a8bd210a2bsalomon@google.com fCurrClipMaskType = kAlpha_ClipMaskType; 6884c2443e36fdc6c095b17e90baa4a2f26a6f00b08bsalomon@google.com return result; 6891e945b7e708c633d4aed937ebfce57d52ba21d83robertphillips@google.com} 6901e945b7e708c633d4aed937ebfce57d52ba21d83robertphillips@google.com 691f294b773f0b2b9f05eb45b52dd3cb4d97b96af06robertphillips@google.com//////////////////////////////////////////////////////////////////////////////// 692fbfcd5602128ec010c82cb733c9cdc0a3254f9f3rmistry@google.com// Create a 1-bit clip mask in the stencil buffer. 'devClipBounds' are in device 693f8d904a7eed435b9de68fd2eef6d7f3c59fcc9ccrobertphillips@google.com// (as opposed to canvas) coordinates 6949853ccef19c200be93a6211f32589fa82a53067cjoshualittbool GrClipMaskManager::createStencilClipMask(GrRenderTarget* rt, 6959853ccef19c200be93a6211f32589fa82a53067cjoshualitt int32_t elementsGenID, 696bf54e49e30cdc92f9ce3f336cc48cf6b236ddeabtfarina GrReducedClip::InitialState initialState, 697bf54e49e30cdc92f9ce3f336cc48cf6b236ddeabtfarina const GrReducedClip::ElementList& elements, 6984c2443e36fdc6c095b17e90baa4a2f26a6f00b08bsalomon@google.com const SkIRect& clipSpaceIBounds, 6994c2443e36fdc6c095b17e90baa4a2f26a6f00b08bsalomon@google.com const SkIPoint& clipSpaceToStencilOffset) { 700f6de475e5cbd143f348ff7738919e397b7fe7f57tfarina@chromium.org SkASSERT(kNone_ClipMaskType == fCurrClipMaskType); 70149f085dddff10473b6ebf832a974288300224e60bsalomon SkASSERT(rt); 7021e945b7e708c633d4aed937ebfce57d52ba21d83robertphillips@google.com 7036bc1b5fab8554a9cb643277b4867965dd4535cd6bsalomon GrStencilBuffer* stencilBuffer = rt->renderTargetPriv().attachStencilBuffer(); 7041e945b7e708c633d4aed937ebfce57d52ba21d83robertphillips@google.com if (NULL == stencilBuffer) { 7051e945b7e708c633d4aed937ebfce57d52ba21d83robertphillips@google.com return false; 7061e945b7e708c633d4aed937ebfce57d52ba21d83robertphillips@google.com } 7071e945b7e708c633d4aed937ebfce57d52ba21d83robertphillips@google.com 708d3e5842db0cb169e10d6da1e62c94ba5cf182bb4commit-bot@chromium.org if (stencilBuffer->mustRenderClip(elementsGenID, clipSpaceIBounds, clipSpaceToStencilOffset)) { 709d3e5842db0cb169e10d6da1e62c94ba5cf182bb4commit-bot@chromium.org stencilBuffer->setLastClip(elementsGenID, clipSpaceIBounds, clipSpaceToStencilOffset); 710137f1347abaf0bb6a945e91c2f6cb49f0ee69bc3bsalomon@google.com // Set the matrix so that rendered clip elements are transformed from clip to stencil space. 711137f1347abaf0bb6a945e91c2f6cb49f0ee69bc3bsalomon@google.com SkVector translate = { 712137f1347abaf0bb6a945e91c2f6cb49f0ee69bc3bsalomon@google.com SkIntToScalar(clipSpaceToStencilOffset.fX), 713137f1347abaf0bb6a945e91c2f6cb49f0ee69bc3bsalomon@google.com SkIntToScalar(clipSpaceToStencilOffset.fY) 714137f1347abaf0bb6a945e91c2f6cb49f0ee69bc3bsalomon@google.com }; 7158059eb9f6e24ed609393fbda4ad71edea03ac258joshualitt SkMatrix viewMatrix; 7168059eb9f6e24ed609393fbda4ad71edea03ac258joshualitt viewMatrix.setTranslate(translate); 7171e945b7e708c633d4aed937ebfce57d52ba21d83robertphillips@google.com 7189f13174da5295e88d447f29740318003b9cec9c3bsalomon@google.com // We set the current clip to the bounds so that our recursive draws are scissored to them. 7199f13174da5295e88d447f29740318003b9cec9c3bsalomon@google.com SkIRect stencilSpaceIBounds(clipSpaceIBounds); 7209f13174da5295e88d447f29740318003b9cec9c3bsalomon@google.com stencilSpaceIBounds.offset(clipSpaceToStencilOffset); 72144701df5ce572ac3cccec785cf52103d3d5d14a5joshualitt GrClip clip(stencilSpaceIBounds); 7221e945b7e708c633d4aed937ebfce57d52ba21d83robertphillips@google.com 7231e945b7e708c633d4aed937ebfce57d52ba21d83robertphillips@google.com int clipBit = stencilBuffer->bits(); 7244c2443e36fdc6c095b17e90baa4a2f26a6f00b08bsalomon@google.com SkASSERT((clipBit <= 16) && "Ganesh only handles 16b or smaller stencil buffers"); 7251e945b7e708c633d4aed937ebfce57d52ba21d83robertphillips@google.com clipBit = (1 << (clipBit-1)); 7261e945b7e708c633d4aed937ebfce57d52ba21d83robertphillips@google.com 727329bf4862e9d5e05363c2b071d8ca475a0ef1952joshualitt fClipTarget->clearStencilClip(stencilSpaceIBounds, 728329bf4862e9d5e05363c2b071d8ca475a0ef1952joshualitt GrReducedClip::kAllIn_InitialState == initialState, 729329bf4862e9d5e05363c2b071d8ca475a0ef1952joshualitt rt); 7301e945b7e708c633d4aed937ebfce57d52ba21d83robertphillips@google.com 7311e945b7e708c633d4aed937ebfce57d52ba21d83robertphillips@google.com // walk through each clip element and perform its set op 7321e945b7e708c633d4aed937ebfce57d52ba21d83robertphillips@google.com // with the existing clip. 733bf54e49e30cdc92f9ce3f336cc48cf6b236ddeabtfarina for (GrReducedClip::ElementList::Iter iter(elements.headIter()); iter.get(); iter.next()) { 7344c2443e36fdc6c095b17e90baa4a2f26a6f00b08bsalomon@google.com const Element* element = iter.get(); 7359853ccef19c200be93a6211f32589fa82a53067cjoshualitt 7368dd688b7569df569a672a8a67b2db86a9d376cfcegdaniel GrPipelineBuilder pipelineBuilder; 73744701df5ce572ac3cccec785cf52103d3d5d14a5joshualitt pipelineBuilder.setClip(clip); 7388dd688b7569df569a672a8a67b2db86a9d376cfcegdaniel pipelineBuilder.setRenderTarget(rt); 739080e673b10ac607305f140ddb245e140ccde40c6egdaniel 7408dd688b7569df569a672a8a67b2db86a9d376cfcegdaniel pipelineBuilder.setDisableColorXPFactory(); 7419853ccef19c200be93a6211f32589fa82a53067cjoshualitt 742ded4f4b163f5aa19c22c871178c55ecb34623846bsalomon@google.com // if the target is MSAA then we want MSAA enabled when the clip is soft 743ded4f4b163f5aa19c22c871178c55ecb34623846bsalomon@google.com if (rt->isMultisampled()) { 7448dd688b7569df569a672a8a67b2db86a9d376cfcegdaniel pipelineBuilder.setState(GrPipelineBuilder::kHWAntialias_StateBit, element->isAA()); 745ded4f4b163f5aa19c22c871178c55ecb34623846bsalomon@google.com } 7461e945b7e708c633d4aed937ebfce57d52ba21d83robertphillips@google.com 7479853ccef19c200be93a6211f32589fa82a53067cjoshualitt bool fillInverted = false; 7489853ccef19c200be93a6211f32589fa82a53067cjoshualitt // enabled at bottom of loop 7499853ccef19c200be93a6211f32589fa82a53067cjoshualitt fClipMode = kIgnoreClip_StencilClipMode; 7509853ccef19c200be93a6211f32589fa82a53067cjoshualitt 75145a15f551b5b3c6c747d8eaf6466b7d3b76a8faebsalomon@google.com // This will be used to determine whether the clip shape can be rendered into the 75245a15f551b5b3c6c747d8eaf6466b7d3b76a8faebsalomon@google.com // stencil with arbitrary stencil settings. 75345a15f551b5b3c6c747d8eaf6466b7d3b76a8faebsalomon@google.com GrPathRenderer::StencilSupport stencilSupport; 7541e945b7e708c633d4aed937ebfce57d52ba21d83robertphillips@google.com 7555f74cf8c49701f514b69dc6f1a8b5c0ffd78af0asugoi@google.com SkStrokeRec stroke(SkStrokeRec::kFill_InitStyle); 7568182fa0cac76e7e6d583aebba060229230516887bsalomon@google.com SkRegion::Op op = element->getOp(); 757f294b773f0b2b9f05eb45b52dd3cb4d97b96af06robertphillips@google.com 758e79f320ed6c5ec9f6164ba84be1ff586532e6517robertphillips@google.com GrPathRenderer* pr = NULL; 759e5b2af955b7d06815ddd405659ad62a2a8355ca3commit-bot@chromium.org SkPath clipPath; 7608182fa0cac76e7e6d583aebba060229230516887bsalomon@google.com if (Element::kRect_Type == element->getType()) { 76145a15f551b5b3c6c747d8eaf6466b7d3b76a8faebsalomon@google.com stencilSupport = GrPathRenderer::kNoRestriction_StencilSupport; 7621e945b7e708c633d4aed937ebfce57d52ba21d83robertphillips@google.com fillInverted = false; 7638afae61a57f87e4a50578effce6c428031499301tomhudson@google.com } else { 764e5b2af955b7d06815ddd405659ad62a2a8355ca3commit-bot@chromium.org element->asPath(&clipPath); 765e5b2af955b7d06815ddd405659ad62a2a8355ca3commit-bot@chromium.org fillInverted = clipPath.isInverseFillType(); 766e79f320ed6c5ec9f6164ba84be1ff586532e6517robertphillips@google.com if (fillInverted) { 767e5b2af955b7d06815ddd405659ad62a2a8355ca3commit-bot@chromium.org clipPath.toggleInverseFillType(); 768e79f320ed6c5ec9f6164ba84be1ff586532e6517robertphillips@google.com } 7699853ccef19c200be93a6211f32589fa82a53067cjoshualitt pr = this->getContext()->getPathRenderer(fClipTarget, 7708dd688b7569df569a672a8a67b2db86a9d376cfcegdaniel &pipelineBuilder, 7718059eb9f6e24ed609393fbda4ad71edea03ac258joshualitt viewMatrix, 7729853ccef19c200be93a6211f32589fa82a53067cjoshualitt clipPath, 77345a15f551b5b3c6c747d8eaf6466b7d3b76a8faebsalomon@google.com stroke, 77445a15f551b5b3c6c747d8eaf6466b7d3b76a8faebsalomon@google.com false, 77545a15f551b5b3c6c747d8eaf6466b7d3b76a8faebsalomon@google.com GrPathRendererChain::kStencilOnly_DrawType, 776e79f320ed6c5ec9f6164ba84be1ff586532e6517robertphillips@google.com &stencilSupport); 777e79f320ed6c5ec9f6164ba84be1ff586532e6517robertphillips@google.com if (NULL == pr) { 7781e945b7e708c633d4aed937ebfce57d52ba21d83robertphillips@google.com return false; 7791e945b7e708c633d4aed937ebfce57d52ba21d83robertphillips@google.com } 7801e945b7e708c633d4aed937ebfce57d52ba21d83robertphillips@google.com } 7811e945b7e708c633d4aed937ebfce57d52ba21d83robertphillips@google.com 7821e945b7e708c633d4aed937ebfce57d52ba21d83robertphillips@google.com int passes; 7831e945b7e708c633d4aed937ebfce57d52ba21d83robertphillips@google.com GrStencilSettings stencilSettings[GrStencilSettings::kMaxStencilClipPasses]; 7841e945b7e708c633d4aed937ebfce57d52ba21d83robertphillips@google.com 78545a15f551b5b3c6c747d8eaf6466b7d3b76a8faebsalomon@google.com bool canRenderDirectToStencil = 78645a15f551b5b3c6c747d8eaf6466b7d3b76a8faebsalomon@google.com GrPathRenderer::kNoRestriction_StencilSupport == stencilSupport; 7871e945b7e708c633d4aed937ebfce57d52ba21d83robertphillips@google.com bool canDrawDirectToClip; // Given the renderer, the element, 7884c2443e36fdc6c095b17e90baa4a2f26a6f00b08bsalomon@google.com // fill rule, and set operation can 7894c2443e36fdc6c095b17e90baa4a2f26a6f00b08bsalomon@google.com // we render the element directly to 7904c2443e36fdc6c095b17e90baa4a2f26a6f00b08bsalomon@google.com // stencil bit used for clipping. 7914c2443e36fdc6c095b17e90baa4a2f26a6f00b08bsalomon@google.com canDrawDirectToClip = GrStencilSettings::GetClipPasses(op, 7924c2443e36fdc6c095b17e90baa4a2f26a6f00b08bsalomon@google.com canRenderDirectToStencil, 7934c2443e36fdc6c095b17e90baa4a2f26a6f00b08bsalomon@google.com clipBit, 7944c2443e36fdc6c095b17e90baa4a2f26a6f00b08bsalomon@google.com fillInverted, 7954c2443e36fdc6c095b17e90baa4a2f26a6f00b08bsalomon@google.com &passes, 7964c2443e36fdc6c095b17e90baa4a2f26a6f00b08bsalomon@google.com stencilSettings); 7971e945b7e708c633d4aed937ebfce57d52ba21d83robertphillips@google.com 7981e945b7e708c633d4aed937ebfce57d52ba21d83robertphillips@google.com // draw the element to the client stencil bits if necessary 7991e945b7e708c633d4aed937ebfce57d52ba21d83robertphillips@google.com if (!canDrawDirectToClip) { 8001e945b7e708c633d4aed937ebfce57d52ba21d83robertphillips@google.com GR_STATIC_CONST_SAME_STENCIL(gDrawToStencil, 8014c2443e36fdc6c095b17e90baa4a2f26a6f00b08bsalomon@google.com kIncClamp_StencilOp, 8024c2443e36fdc6c095b17e90baa4a2f26a6f00b08bsalomon@google.com kIncClamp_StencilOp, 8034c2443e36fdc6c095b17e90baa4a2f26a6f00b08bsalomon@google.com kAlways_StencilFunc, 8044c2443e36fdc6c095b17e90baa4a2f26a6f00b08bsalomon@google.com 0xffff, 8054c2443e36fdc6c095b17e90baa4a2f26a6f00b08bsalomon@google.com 0x0000, 8064c2443e36fdc6c095b17e90baa4a2f26a6f00b08bsalomon@google.com 0xffff); 8078182fa0cac76e7e6d583aebba060229230516887bsalomon@google.com if (Element::kRect_Type == element->getType()) { 8088dd688b7569df569a672a8a67b2db86a9d376cfcegdaniel *pipelineBuilder.stencil() = gDrawToStencil; 80944701df5ce572ac3cccec785cf52103d3d5d14a5joshualitt fClipTarget->drawSimpleRect(&pipelineBuilder, 81044701df5ce572ac3cccec785cf52103d3d5d14a5joshualitt GrColor_WHITE, 81144701df5ce572ac3cccec785cf52103d3d5d14a5joshualitt viewMatrix, 8128059eb9f6e24ed609393fbda4ad71edea03ac258joshualitt element->getRect()); 8131e945b7e708c633d4aed937ebfce57d52ba21d83robertphillips@google.com } else { 814e5b2af955b7d06815ddd405659ad62a2a8355ca3commit-bot@chromium.org if (!clipPath.isEmpty()) { 8159853ccef19c200be93a6211f32589fa82a53067cjoshualitt GrDrawTarget::AutoGeometryPush agp(fClipTarget); 81619dd017a6256be636ccb550752bb563c4e7caeb5commit-bot@chromium.org if (canRenderDirectToStencil) { 8178dd688b7569df569a672a8a67b2db86a9d376cfcegdaniel *pipelineBuilder.stencil() = gDrawToStencil; 81844701df5ce572ac3cccec785cf52103d3d5d14a5joshualitt pr->drawPath(fClipTarget, &pipelineBuilder, GrColor_WHITE, 81944701df5ce572ac3cccec785cf52103d3d5d14a5joshualitt viewMatrix, clipPath, stroke, false); 82019dd017a6256be636ccb550752bb563c4e7caeb5commit-bot@chromium.org } else { 82144701df5ce572ac3cccec785cf52103d3d5d14a5joshualitt pr->stencilPath(fClipTarget, &pipelineBuilder, viewMatrix, 82244701df5ce572ac3cccec785cf52103d3d5d14a5joshualitt clipPath, stroke); 82319dd017a6256be636ccb550752bb563c4e7caeb5commit-bot@chromium.org } 8241e945b7e708c633d4aed937ebfce57d52ba21d83robertphillips@google.com } 8251e945b7e708c633d4aed937ebfce57d52ba21d83robertphillips@google.com } 8261e945b7e708c633d4aed937ebfce57d52ba21d83robertphillips@google.com } 8271e945b7e708c633d4aed937ebfce57d52ba21d83robertphillips@google.com 8281e945b7e708c633d4aed937ebfce57d52ba21d83robertphillips@google.com // now we modify the clip bit by rendering either the clip 8291e945b7e708c633d4aed937ebfce57d52ba21d83robertphillips@google.com // element directly or a bounding rect of the entire clip. 8307a6184fdf717a1da0c6e1e37b942b17fdaa236d3joshualitt fClipMode = kModifyClip_StencilClipMode; 8311e945b7e708c633d4aed937ebfce57d52ba21d83robertphillips@google.com for (int p = 0; p < passes; ++p) { 8328dd688b7569df569a672a8a67b2db86a9d376cfcegdaniel GrPipelineBuilder pipelineBuilderCopy(pipelineBuilder); 8338dd688b7569df569a672a8a67b2db86a9d376cfcegdaniel *pipelineBuilderCopy.stencil() = stencilSettings[p]; 8349853ccef19c200be93a6211f32589fa82a53067cjoshualitt 8351e945b7e708c633d4aed937ebfce57d52ba21d83robertphillips@google.com if (canDrawDirectToClip) { 8368182fa0cac76e7e6d583aebba060229230516887bsalomon@google.com if (Element::kRect_Type == element->getType()) { 83744701df5ce572ac3cccec785cf52103d3d5d14a5joshualitt fClipTarget->drawSimpleRect(&pipelineBuilderCopy, 83844701df5ce572ac3cccec785cf52103d3d5d14a5joshualitt GrColor_WHITE, 83944701df5ce572ac3cccec785cf52103d3d5d14a5joshualitt viewMatrix, 8402e3b3e369d79e78f7635d4c20e83a47ab571bdf2joshualitt element->getRect()); 8411e945b7e708c633d4aed937ebfce57d52ba21d83robertphillips@google.com } else { 8429853ccef19c200be93a6211f32589fa82a53067cjoshualitt GrDrawTarget::AutoGeometryPush agp(fClipTarget); 84344701df5ce572ac3cccec785cf52103d3d5d14a5joshualitt pr->drawPath(fClipTarget, &pipelineBuilderCopy, GrColor_WHITE, 84444701df5ce572ac3cccec785cf52103d3d5d14a5joshualitt viewMatrix, clipPath, stroke, false); 8451e945b7e708c633d4aed937ebfce57d52ba21d83robertphillips@google.com } 8461e945b7e708c633d4aed937ebfce57d52ba21d83robertphillips@google.com } else { 8474c2443e36fdc6c095b17e90baa4a2f26a6f00b08bsalomon@google.com // The view matrix is setup to do clip space -> stencil space translation, so 8484c2443e36fdc6c095b17e90baa4a2f26a6f00b08bsalomon@google.com // draw rect in clip space. 84944701df5ce572ac3cccec785cf52103d3d5d14a5joshualitt fClipTarget->drawSimpleRect(&pipelineBuilderCopy, 85044701df5ce572ac3cccec785cf52103d3d5d14a5joshualitt GrColor_WHITE, 85144701df5ce572ac3cccec785cf52103d3d5d14a5joshualitt viewMatrix, 8522e3b3e369d79e78f7635d4c20e83a47ab571bdf2joshualitt SkRect::Make(clipSpaceIBounds)); 8531e945b7e708c633d4aed937ebfce57d52ba21d83robertphillips@google.com } 8541e945b7e708c633d4aed937ebfce57d52ba21d83robertphillips@google.com } 8551e945b7e708c633d4aed937ebfce57d52ba21d83robertphillips@google.com } 8561e945b7e708c633d4aed937ebfce57d52ba21d83robertphillips@google.com } 857c8f7f47afaf8f9471e6d111655c5610a8bd210a2bsalomon@google.com // set this last because recursive draws may overwrite it back to kNone. 858f6de475e5cbd143f348ff7738919e397b7fe7f57tfarina@chromium.org SkASSERT(kNone_ClipMaskType == fCurrClipMaskType); 859c8f7f47afaf8f9471e6d111655c5610a8bd210a2bsalomon@google.com fCurrClipMaskType = kStencil_ClipMaskType; 8607a6184fdf717a1da0c6e1e37b942b17fdaa236d3joshualitt fClipMode = kRespectClip_StencilClipMode; 8611e945b7e708c633d4aed937ebfce57d52ba21d83robertphillips@google.com return true; 8621e945b7e708c633d4aed937ebfce57d52ba21d83robertphillips@google.com} 8631e945b7e708c633d4aed937ebfce57d52ba21d83robertphillips@google.com 864411dad0630913fc07f2412b4be17acfbfd914fbcbsalomon@google.com// mapping of clip-respecting stencil funcs to normal stencil funcs 865411dad0630913fc07f2412b4be17acfbfd914fbcbsalomon@google.com// mapping depends on whether stencil-clipping is in effect. 866fbfcd5602128ec010c82cb733c9cdc0a3254f9f3rmistry@google.comstatic const GrStencilFunc 867411dad0630913fc07f2412b4be17acfbfd914fbcbsalomon@google.com gSpecialToBasicStencilFunc[2][kClipStencilFuncCount] = { 868411dad0630913fc07f2412b4be17acfbfd914fbcbsalomon@google.com {// Stencil-Clipping is DISABLED, we are effectively always inside the clip 869411dad0630913fc07f2412b4be17acfbfd914fbcbsalomon@google.com // In the Clip Funcs 870411dad0630913fc07f2412b4be17acfbfd914fbcbsalomon@google.com kAlways_StencilFunc, // kAlwaysIfInClip_StencilFunc 871411dad0630913fc07f2412b4be17acfbfd914fbcbsalomon@google.com kEqual_StencilFunc, // kEqualIfInClip_StencilFunc 872411dad0630913fc07f2412b4be17acfbfd914fbcbsalomon@google.com kLess_StencilFunc, // kLessIfInClip_StencilFunc 873411dad0630913fc07f2412b4be17acfbfd914fbcbsalomon@google.com kLEqual_StencilFunc, // kLEqualIfInClip_StencilFunc 874411dad0630913fc07f2412b4be17acfbfd914fbcbsalomon@google.com // Special in the clip func that forces user's ref to be 0. 875411dad0630913fc07f2412b4be17acfbfd914fbcbsalomon@google.com kNotEqual_StencilFunc, // kNonZeroIfInClip_StencilFunc 876411dad0630913fc07f2412b4be17acfbfd914fbcbsalomon@google.com // make ref 0 and do normal nequal. 877411dad0630913fc07f2412b4be17acfbfd914fbcbsalomon@google.com }, 878411dad0630913fc07f2412b4be17acfbfd914fbcbsalomon@google.com {// Stencil-Clipping is ENABLED 879411dad0630913fc07f2412b4be17acfbfd914fbcbsalomon@google.com // In the Clip Funcs 880411dad0630913fc07f2412b4be17acfbfd914fbcbsalomon@google.com kEqual_StencilFunc, // kAlwaysIfInClip_StencilFunc 881411dad0630913fc07f2412b4be17acfbfd914fbcbsalomon@google.com // eq stencil clip bit, mask 882411dad0630913fc07f2412b4be17acfbfd914fbcbsalomon@google.com // out user bits. 883411dad0630913fc07f2412b4be17acfbfd914fbcbsalomon@google.com 884411dad0630913fc07f2412b4be17acfbfd914fbcbsalomon@google.com kEqual_StencilFunc, // kEqualIfInClip_StencilFunc 885411dad0630913fc07f2412b4be17acfbfd914fbcbsalomon@google.com // add stencil bit to mask and ref 886411dad0630913fc07f2412b4be17acfbfd914fbcbsalomon@google.com 887411dad0630913fc07f2412b4be17acfbfd914fbcbsalomon@google.com kLess_StencilFunc, // kLessIfInClip_StencilFunc 888411dad0630913fc07f2412b4be17acfbfd914fbcbsalomon@google.com kLEqual_StencilFunc, // kLEqualIfInClip_StencilFunc 889411dad0630913fc07f2412b4be17acfbfd914fbcbsalomon@google.com // for both of these we can add 890411dad0630913fc07f2412b4be17acfbfd914fbcbsalomon@google.com // the clip bit to the mask and 891411dad0630913fc07f2412b4be17acfbfd914fbcbsalomon@google.com // ref and compare as normal 892411dad0630913fc07f2412b4be17acfbfd914fbcbsalomon@google.com // Special in the clip func that forces user's ref to be 0. 893411dad0630913fc07f2412b4be17acfbfd914fbcbsalomon@google.com kLess_StencilFunc, // kNonZeroIfInClip_StencilFunc 894411dad0630913fc07f2412b4be17acfbfd914fbcbsalomon@google.com // make ref have only the clip bit set 895411dad0630913fc07f2412b4be17acfbfd914fbcbsalomon@google.com // and make comparison be less 896411dad0630913fc07f2412b4be17acfbfd914fbcbsalomon@google.com // 10..0 < 1..user_bits.. 897411dad0630913fc07f2412b4be17acfbfd914fbcbsalomon@google.com } 898411dad0630913fc07f2412b4be17acfbfd914fbcbsalomon@google.com}; 899411dad0630913fc07f2412b4be17acfbfd914fbcbsalomon@google.com 900a320194e4242ef0e5e758aea896bfd52bcb3dac7bsalomon@google.comnamespace { 901a320194e4242ef0e5e758aea896bfd52bcb3dac7bsalomon@google.com// Sets the settings to clip against the stencil buffer clip while ignoring the 902a320194e4242ef0e5e758aea896bfd52bcb3dac7bsalomon@google.com// client bits. 903a320194e4242ef0e5e758aea896bfd52bcb3dac7bsalomon@google.comconst GrStencilSettings& basic_apply_stencil_clip_settings() { 904a320194e4242ef0e5e758aea896bfd52bcb3dac7bsalomon@google.com // stencil settings to use when clip is in stencil 905a320194e4242ef0e5e758aea896bfd52bcb3dac7bsalomon@google.com GR_STATIC_CONST_SAME_STENCIL_STRUCT(gSettings, 906a320194e4242ef0e5e758aea896bfd52bcb3dac7bsalomon@google.com kKeep_StencilOp, 907a320194e4242ef0e5e758aea896bfd52bcb3dac7bsalomon@google.com kKeep_StencilOp, 908a320194e4242ef0e5e758aea896bfd52bcb3dac7bsalomon@google.com kAlwaysIfInClip_StencilFunc, 909a320194e4242ef0e5e758aea896bfd52bcb3dac7bsalomon@google.com 0x0000, 910a320194e4242ef0e5e758aea896bfd52bcb3dac7bsalomon@google.com 0x0000, 911fbfcd5602128ec010c82cb733c9cdc0a3254f9f3rmistry@google.com 0x0000); 912a320194e4242ef0e5e758aea896bfd52bcb3dac7bsalomon@google.com return *GR_CONST_STENCIL_SETTINGS_PTR_FROM_STRUCT_PTR(&gSettings); 913a320194e4242ef0e5e758aea896bfd52bcb3dac7bsalomon@google.com} 914a320194e4242ef0e5e758aea896bfd52bcb3dac7bsalomon@google.com} 915a320194e4242ef0e5e758aea896bfd52bcb3dac7bsalomon@google.com 9168dd688b7569df569a672a8a67b2db86a9d376cfcegdanielvoid GrClipMaskManager::setPipelineBuilderStencil(GrPipelineBuilder* pipelineBuilder, 9178dd688b7569df569a672a8a67b2db86a9d376cfcegdaniel GrPipelineBuilder::AutoRestoreStencil* ars) { 918a320194e4242ef0e5e758aea896bfd52bcb3dac7bsalomon@google.com // We make two copies of the StencilSettings here (except in the early 919a320194e4242ef0e5e758aea896bfd52bcb3dac7bsalomon@google.com // exit scenario. One copy from draw state to the stack var. Then another 920a320194e4242ef0e5e758aea896bfd52bcb3dac7bsalomon@google.com // from the stack var to the gpu. We could make this class hold a ptr to 921a320194e4242ef0e5e758aea896bfd52bcb3dac7bsalomon@google.com // GrGpu's fStencilSettings and eliminate the stack copy here. 922a320194e4242ef0e5e758aea896bfd52bcb3dac7bsalomon@google.com 923a320194e4242ef0e5e758aea896bfd52bcb3dac7bsalomon@google.com // use stencil for clipping if clipping is enabled and the clip 924a320194e4242ef0e5e758aea896bfd52bcb3dac7bsalomon@google.com // has been written into the stencil. 925a320194e4242ef0e5e758aea896bfd52bcb3dac7bsalomon@google.com GrStencilSettings settings; 9269853ccef19c200be93a6211f32589fa82a53067cjoshualitt 927a320194e4242ef0e5e758aea896bfd52bcb3dac7bsalomon@google.com // The GrGpu client may not be using the stencil buffer but we may need to 928a320194e4242ef0e5e758aea896bfd52bcb3dac7bsalomon@google.com // enable it in order to respect a stencil clip. 9298dd688b7569df569a672a8a67b2db86a9d376cfcegdaniel if (pipelineBuilder->getStencil().isDisabled()) { 9307a6184fdf717a1da0c6e1e37b942b17fdaa236d3joshualitt if (GrClipMaskManager::kRespectClip_StencilClipMode == fClipMode) { 931a320194e4242ef0e5e758aea896bfd52bcb3dac7bsalomon@google.com settings = basic_apply_stencil_clip_settings(); 932a320194e4242ef0e5e758aea896bfd52bcb3dac7bsalomon@google.com } else { 933a320194e4242ef0e5e758aea896bfd52bcb3dac7bsalomon@google.com return; 934a320194e4242ef0e5e758aea896bfd52bcb3dac7bsalomon@google.com } 935a320194e4242ef0e5e758aea896bfd52bcb3dac7bsalomon@google.com } else { 9368dd688b7569df569a672a8a67b2db86a9d376cfcegdaniel settings = pipelineBuilder->getStencil(); 937a320194e4242ef0e5e758aea896bfd52bcb3dac7bsalomon@google.com } 938a320194e4242ef0e5e758aea896bfd52bcb3dac7bsalomon@google.com 939a320194e4242ef0e5e758aea896bfd52bcb3dac7bsalomon@google.com int stencilBits = 0; 9406bc1b5fab8554a9cb643277b4867965dd4535cd6bsalomon GrRenderTarget* rt = pipelineBuilder->getRenderTarget(); 9416bc1b5fab8554a9cb643277b4867965dd4535cd6bsalomon GrStencilBuffer* stencilBuffer = rt->renderTargetPriv().attachStencilBuffer(); 94249f085dddff10473b6ebf832a974288300224e60bsalomon if (stencilBuffer) { 943a320194e4242ef0e5e758aea896bfd52bcb3dac7bsalomon@google.com stencilBits = stencilBuffer->bits(); 944a320194e4242ef0e5e758aea896bfd52bcb3dac7bsalomon@google.com } 945a320194e4242ef0e5e758aea896bfd52bcb3dac7bsalomon@google.com 946329bf4862e9d5e05363c2b071d8ca475a0ef1952joshualitt SkASSERT(fClipTarget->caps()->stencilWrapOpsSupport() || !settings.usesWrapOp()); 947329bf4862e9d5e05363c2b071d8ca475a0ef1952joshualitt SkASSERT(fClipTarget->caps()->twoSidedStencilSupport() || !settings.isTwoSided()); 9487a6184fdf717a1da0c6e1e37b942b17fdaa236d3joshualitt this->adjustStencilParams(&settings, fClipMode, stencilBits); 9498dd688b7569df569a672a8a67b2db86a9d376cfcegdaniel ars->set(pipelineBuilder); 9508dd688b7569df569a672a8a67b2db86a9d376cfcegdaniel pipelineBuilder->setStencil(settings); 951a320194e4242ef0e5e758aea896bfd52bcb3dac7bsalomon@google.com} 952a320194e4242ef0e5e758aea896bfd52bcb3dac7bsalomon@google.com 953a320194e4242ef0e5e758aea896bfd52bcb3dac7bsalomon@google.comvoid GrClipMaskManager::adjustStencilParams(GrStencilSettings* settings, 954a320194e4242ef0e5e758aea896bfd52bcb3dac7bsalomon@google.com StencilClipMode mode, 955a320194e4242ef0e5e758aea896bfd52bcb3dac7bsalomon@google.com int stencilBitCnt) { 956f6de475e5cbd143f348ff7738919e397b7fe7f57tfarina@chromium.org SkASSERT(stencilBitCnt > 0); 957411dad0630913fc07f2412b4be17acfbfd914fbcbsalomon@google.com 958411dad0630913fc07f2412b4be17acfbfd914fbcbsalomon@google.com if (kModifyClip_StencilClipMode == mode) { 959a320194e4242ef0e5e758aea896bfd52bcb3dac7bsalomon@google.com // We assume that this clip manager itself is drawing to the GrGpu and 960a320194e4242ef0e5e758aea896bfd52bcb3dac7bsalomon@google.com // has already setup the correct values. 961a320194e4242ef0e5e758aea896bfd52bcb3dac7bsalomon@google.com return; 962411dad0630913fc07f2412b4be17acfbfd914fbcbsalomon@google.com } 963a320194e4242ef0e5e758aea896bfd52bcb3dac7bsalomon@google.com 964411dad0630913fc07f2412b4be17acfbfd914fbcbsalomon@google.com unsigned int clipBit = (1 << (stencilBitCnt - 1)); 965411dad0630913fc07f2412b4be17acfbfd914fbcbsalomon@google.com unsigned int userBits = clipBit - 1; 966411dad0630913fc07f2412b4be17acfbfd914fbcbsalomon@google.com 967a320194e4242ef0e5e758aea896bfd52bcb3dac7bsalomon@google.com GrStencilSettings::Face face = GrStencilSettings::kFront_Face; 968329bf4862e9d5e05363c2b071d8ca475a0ef1952joshualitt bool twoSided = fClipTarget->caps()->twoSidedStencilSupport(); 969a320194e4242ef0e5e758aea896bfd52bcb3dac7bsalomon@google.com 970a320194e4242ef0e5e758aea896bfd52bcb3dac7bsalomon@google.com bool finished = false; 971a320194e4242ef0e5e758aea896bfd52bcb3dac7bsalomon@google.com while (!finished) { 972a320194e4242ef0e5e758aea896bfd52bcb3dac7bsalomon@google.com GrStencilFunc func = settings->func(face); 973a320194e4242ef0e5e758aea896bfd52bcb3dac7bsalomon@google.com uint16_t writeMask = settings->writeMask(face); 974a320194e4242ef0e5e758aea896bfd52bcb3dac7bsalomon@google.com uint16_t funcMask = settings->funcMask(face); 975a320194e4242ef0e5e758aea896bfd52bcb3dac7bsalomon@google.com uint16_t funcRef = settings->funcRef(face); 976a320194e4242ef0e5e758aea896bfd52bcb3dac7bsalomon@google.com 977f6de475e5cbd143f348ff7738919e397b7fe7f57tfarina@chromium.org SkASSERT((unsigned) func < kStencilFuncCount); 978a320194e4242ef0e5e758aea896bfd52bcb3dac7bsalomon@google.com 979a320194e4242ef0e5e758aea896bfd52bcb3dac7bsalomon@google.com writeMask &= userBits; 980a320194e4242ef0e5e758aea896bfd52bcb3dac7bsalomon@google.com 981a320194e4242ef0e5e758aea896bfd52bcb3dac7bsalomon@google.com if (func >= kBasicStencilFuncCount) { 982a320194e4242ef0e5e758aea896bfd52bcb3dac7bsalomon@google.com int respectClip = kRespectClip_StencilClipMode == mode; 983a320194e4242ef0e5e758aea896bfd52bcb3dac7bsalomon@google.com if (respectClip) { 984a320194e4242ef0e5e758aea896bfd52bcb3dac7bsalomon@google.com // The GrGpu class should have checked this 985f6de475e5cbd143f348ff7738919e397b7fe7f57tfarina@chromium.org SkASSERT(this->isClipInStencil()); 986a320194e4242ef0e5e758aea896bfd52bcb3dac7bsalomon@google.com switch (func) { 987a320194e4242ef0e5e758aea896bfd52bcb3dac7bsalomon@google.com case kAlwaysIfInClip_StencilFunc: 988a320194e4242ef0e5e758aea896bfd52bcb3dac7bsalomon@google.com funcMask = clipBit; 989a320194e4242ef0e5e758aea896bfd52bcb3dac7bsalomon@google.com funcRef = clipBit; 990a320194e4242ef0e5e758aea896bfd52bcb3dac7bsalomon@google.com break; 991a320194e4242ef0e5e758aea896bfd52bcb3dac7bsalomon@google.com case kEqualIfInClip_StencilFunc: 992a320194e4242ef0e5e758aea896bfd52bcb3dac7bsalomon@google.com case kLessIfInClip_StencilFunc: 993a320194e4242ef0e5e758aea896bfd52bcb3dac7bsalomon@google.com case kLEqualIfInClip_StencilFunc: 994a320194e4242ef0e5e758aea896bfd52bcb3dac7bsalomon@google.com funcMask = (funcMask & userBits) | clipBit; 995a320194e4242ef0e5e758aea896bfd52bcb3dac7bsalomon@google.com funcRef = (funcRef & userBits) | clipBit; 996a320194e4242ef0e5e758aea896bfd52bcb3dac7bsalomon@google.com break; 997a320194e4242ef0e5e758aea896bfd52bcb3dac7bsalomon@google.com case kNonZeroIfInClip_StencilFunc: 998a320194e4242ef0e5e758aea896bfd52bcb3dac7bsalomon@google.com funcMask = (funcMask & userBits) | clipBit; 999a320194e4242ef0e5e758aea896bfd52bcb3dac7bsalomon@google.com funcRef = clipBit; 1000a320194e4242ef0e5e758aea896bfd52bcb3dac7bsalomon@google.com break; 1001a320194e4242ef0e5e758aea896bfd52bcb3dac7bsalomon@google.com default: 100288cb22b6b4816c7a9ca6c5b795965b4606f9eb7bcommit-bot@chromium.org SkFAIL("Unknown stencil func"); 1003a320194e4242ef0e5e758aea896bfd52bcb3dac7bsalomon@google.com } 1004a320194e4242ef0e5e758aea896bfd52bcb3dac7bsalomon@google.com } else { 1005a320194e4242ef0e5e758aea896bfd52bcb3dac7bsalomon@google.com funcMask &= userBits; 1006a320194e4242ef0e5e758aea896bfd52bcb3dac7bsalomon@google.com funcRef &= userBits; 1007411dad0630913fc07f2412b4be17acfbfd914fbcbsalomon@google.com } 1008fbfcd5602128ec010c82cb733c9cdc0a3254f9f3rmistry@google.com const GrStencilFunc* table = 1009a320194e4242ef0e5e758aea896bfd52bcb3dac7bsalomon@google.com gSpecialToBasicStencilFunc[respectClip]; 1010a320194e4242ef0e5e758aea896bfd52bcb3dac7bsalomon@google.com func = table[func - kBasicStencilFuncCount]; 1011f6de475e5cbd143f348ff7738919e397b7fe7f57tfarina@chromium.org SkASSERT(func >= 0 && func < kBasicStencilFuncCount); 1012411dad0630913fc07f2412b4be17acfbfd914fbcbsalomon@google.com } else { 1013a320194e4242ef0e5e758aea896bfd52bcb3dac7bsalomon@google.com funcMask &= userBits; 1014a320194e4242ef0e5e758aea896bfd52bcb3dac7bsalomon@google.com funcRef &= userBits; 1015411dad0630913fc07f2412b4be17acfbfd914fbcbsalomon@google.com } 1016a320194e4242ef0e5e758aea896bfd52bcb3dac7bsalomon@google.com 1017a320194e4242ef0e5e758aea896bfd52bcb3dac7bsalomon@google.com settings->setFunc(face, func); 1018a320194e4242ef0e5e758aea896bfd52bcb3dac7bsalomon@google.com settings->setWriteMask(face, writeMask); 1019a320194e4242ef0e5e758aea896bfd52bcb3dac7bsalomon@google.com settings->setFuncMask(face, funcMask); 1020a320194e4242ef0e5e758aea896bfd52bcb3dac7bsalomon@google.com settings->setFuncRef(face, funcRef); 1021a320194e4242ef0e5e758aea896bfd52bcb3dac7bsalomon@google.com 1022a320194e4242ef0e5e758aea896bfd52bcb3dac7bsalomon@google.com if (GrStencilSettings::kFront_Face == face) { 1023a320194e4242ef0e5e758aea896bfd52bcb3dac7bsalomon@google.com face = GrStencilSettings::kBack_Face; 1024a320194e4242ef0e5e758aea896bfd52bcb3dac7bsalomon@google.com finished = !twoSided; 1025a320194e4242ef0e5e758aea896bfd52bcb3dac7bsalomon@google.com } else { 1026a320194e4242ef0e5e758aea896bfd52bcb3dac7bsalomon@google.com finished = true; 1027a320194e4242ef0e5e758aea896bfd52bcb3dac7bsalomon@google.com } 1028a320194e4242ef0e5e758aea896bfd52bcb3dac7bsalomon@google.com } 1029a320194e4242ef0e5e758aea896bfd52bcb3dac7bsalomon@google.com if (!twoSided) { 1030a320194e4242ef0e5e758aea896bfd52bcb3dac7bsalomon@google.com settings->copyFrontSettingsToBack(); 1031411dad0630913fc07f2412b4be17acfbfd914fbcbsalomon@google.com } 1032411dad0630913fc07f2412b4be17acfbfd914fbcbsalomon@google.com} 1033411dad0630913fc07f2412b4be17acfbfd914fbcbsalomon@google.com 1034411dad0630913fc07f2412b4be17acfbfd914fbcbsalomon@google.com//////////////////////////////////////////////////////////////////////////////// 1035d3e5842db0cb169e10d6da1e62c94ba5cf182bb4commit-bot@chromium.orgGrTexture* GrClipMaskManager::createSoftwareClipMask(int32_t elementsGenID, 10364c2443e36fdc6c095b17e90baa4a2f26a6f00b08bsalomon@google.com GrReducedClip::InitialState initialState, 10374c2443e36fdc6c095b17e90baa4a2f26a6f00b08bsalomon@google.com const GrReducedClip::ElementList& elements, 10388059eb9f6e24ed609393fbda4ad71edea03ac258joshualitt const SkVector& clipToMaskOffset, 10394c2443e36fdc6c095b17e90baa4a2f26a6f00b08bsalomon@google.com const SkIRect& clipSpaceIBounds) { 1040f6de475e5cbd143f348ff7738919e397b7fe7f57tfarina@chromium.org SkASSERT(kNone_ClipMaskType == fCurrClipMaskType); 10416b70a7bd3328ea0a12be47b1a7f835c905f16147robertphillips@google.com 1042ad1dc589cef8aebf7e14672ffdaa31c6d399675dkrajcevski GrTexture* result = this->getCachedMaskTexture(elementsGenID, clipSpaceIBounds); 104349f085dddff10473b6ebf832a974288300224e60bsalomon if (result) { 10444c2443e36fdc6c095b17e90baa4a2f26a6f00b08bsalomon@google.com return result; 10456b70a7bd3328ea0a12be47b1a7f835c905f16147robertphillips@google.com } 10466b70a7bd3328ea0a12be47b1a7f835c905f16147robertphillips@google.com 10474c2443e36fdc6c095b17e90baa4a2f26a6f00b08bsalomon@google.com // The mask texture may be larger than necessary. We round out the clip space bounds and pin 10484c2443e36fdc6c095b17e90baa4a2f26a6f00b08bsalomon@google.com // the top left corner of the resulting rect to the top left of the texture. 10494c2443e36fdc6c095b17e90baa4a2f26a6f00b08bsalomon@google.com SkIRect maskSpaceIBounds = SkIRect::MakeWH(clipSpaceIBounds.width(), clipSpaceIBounds.height()); 10504c2443e36fdc6c095b17e90baa4a2f26a6f00b08bsalomon@google.com 10512c75681e36b33fcafc5665d7012bbd4fc6647d83robertphillips@google.com GrSWMaskHelper helper(this->getContext()); 10526b70a7bd3328ea0a12be47b1a7f835c905f16147robertphillips@google.com 10538059eb9f6e24ed609393fbda4ad71edea03ac258joshualitt // Set the matrix so that rendered clip elements are transformed to mask space from clip 10548059eb9f6e24ed609393fbda4ad71edea03ac258joshualitt // space. 10558059eb9f6e24ed609393fbda4ad71edea03ac258joshualitt SkMatrix translate; 10568059eb9f6e24ed609393fbda4ad71edea03ac258joshualitt translate.setTranslate(clipToMaskOffset); 10574c2443e36fdc6c095b17e90baa4a2f26a6f00b08bsalomon@google.com 10588059eb9f6e24ed609393fbda4ad71edea03ac258joshualitt helper.init(maskSpaceIBounds, &translate, false); 1059bf54e49e30cdc92f9ce3f336cc48cf6b236ddeabtfarina helper.clear(GrReducedClip::kAllIn_InitialState == initialState ? 0xFF : 0x00); 10605f74cf8c49701f514b69dc6f1a8b5c0ffd78af0asugoi@google.com SkStrokeRec stroke(SkStrokeRec::kFill_InitStyle); 106112b4e27ae1a29460e91a59f38122483e1faec697sugoi@google.com 1062bf54e49e30cdc92f9ce3f336cc48cf6b236ddeabtfarina for (GrReducedClip::ElementList::Iter iter(elements.headIter()) ; iter.get(); iter.next()) { 10634c2443e36fdc6c095b17e90baa4a2f26a6f00b08bsalomon@google.com const Element* element = iter.get(); 10648182fa0cac76e7e6d583aebba060229230516887bsalomon@google.com SkRegion::Op op = element->getOp(); 1065fa66294c7705831808ce7772d4328fc626d45034robertphillips@google.com 10664c2443e36fdc6c095b17e90baa4a2f26a6f00b08bsalomon@google.com if (SkRegion::kIntersect_Op == op || SkRegion::kReverseDifference_Op == op) { 10674c2443e36fdc6c095b17e90baa4a2f26a6f00b08bsalomon@google.com // Intersect and reverse difference require modifying pixels outside of the geometry 10684c2443e36fdc6c095b17e90baa4a2f26a6f00b08bsalomon@google.com // that is being "drawn". In both cases we erase all the pixels outside of the geometry 10694c2443e36fdc6c095b17e90baa4a2f26a6f00b08bsalomon@google.com // but leave the pixels inside the geometry alone. For reverse difference we invert all 10704c2443e36fdc6c095b17e90baa4a2f26a6f00b08bsalomon@google.com // the pixels before clearing the ones outside the geometry. 1071fa66294c7705831808ce7772d4328fc626d45034robertphillips@google.com if (SkRegion::kReverseDifference_Op == op) { 10724469938e92d779dff05e745559e67907bbf21e78reed@google.com SkRect temp = SkRect::Make(clipSpaceIBounds); 1073fa66294c7705831808ce7772d4328fc626d45034robertphillips@google.com // invert the entire scene 1074366f1c6a09f63c76e78145cb08028f66062f31fdrobertphillips@google.com helper.draw(temp, SkRegion::kXOR_Op, false, 0xFF); 1075fa66294c7705831808ce7772d4328fc626d45034robertphillips@google.com } 10765c056399259bb7ec06ff1eb8ce904001b363276ccommit-bot@chromium.org SkPath clipPath; 10775c056399259bb7ec06ff1eb8ce904001b363276ccommit-bot@chromium.org element->asPath(&clipPath); 10785c056399259bb7ec06ff1eb8ce904001b363276ccommit-bot@chromium.org clipPath.toggleInverseFillType(); 10795c056399259bb7ec06ff1eb8ce904001b363276ccommit-bot@chromium.org helper.draw(clipPath, stroke, SkRegion::kReplace_Op, element->isAA(), 0x00); 1080fa66294c7705831808ce7772d4328fc626d45034robertphillips@google.com continue; 1081fa66294c7705831808ce7772d4328fc626d45034robertphillips@google.com } 1082fa66294c7705831808ce7772d4328fc626d45034robertphillips@google.com 1083fa66294c7705831808ce7772d4328fc626d45034robertphillips@google.com // The other ops (union, xor, diff) only affect pixels inside 1084fa66294c7705831808ce7772d4328fc626d45034robertphillips@google.com // the geometry so they can just be drawn normally 10858182fa0cac76e7e6d583aebba060229230516887bsalomon@google.com if (Element::kRect_Type == element->getType()) { 10868182fa0cac76e7e6d583aebba060229230516887bsalomon@google.com helper.draw(element->getRect(), op, element->isAA(), 0xFF); 10878182fa0cac76e7e6d583aebba060229230516887bsalomon@google.com } else { 10885c056399259bb7ec06ff1eb8ce904001b363276ccommit-bot@chromium.org SkPath path; 10895c056399259bb7ec06ff1eb8ce904001b363276ccommit-bot@chromium.org element->asPath(&path); 10905c056399259bb7ec06ff1eb8ce904001b363276ccommit-bot@chromium.org helper.draw(path, stroke, op, element->isAA(), 0xFF); 10916b70a7bd3328ea0a12be47b1a7f835c905f16147robertphillips@google.com } 10926b70a7bd3328ea0a12be47b1a7f835c905f16147robertphillips@google.com } 10936b70a7bd3328ea0a12be47b1a7f835c905f16147robertphillips@google.com 1094ad1dc589cef8aebf7e14672ffdaa31c6d399675dkrajcevski // Allocate clip mask texture 1095ad1dc589cef8aebf7e14672ffdaa31c6d399675dkrajcevski result = this->allocMaskTexture(elementsGenID, clipSpaceIBounds, true); 1096ad1dc589cef8aebf7e14672ffdaa31c6d399675dkrajcevski if (NULL == result) { 1097ad1dc589cef8aebf7e14672ffdaa31c6d399675dkrajcevski fAACache.reset(); 1098ad1dc589cef8aebf7e14672ffdaa31c6d399675dkrajcevski return NULL; 1099ad1dc589cef8aebf7e14672ffdaa31c6d399675dkrajcevski } 1100d92cf2ebbfbb9d737ea4a551e64ffccb08376875robertphillips@google.com helper.toTexture(result); 11016b70a7bd3328ea0a12be47b1a7f835c905f16147robertphillips@google.com 1102c8f7f47afaf8f9471e6d111655c5610a8bd210a2bsalomon@google.com fCurrClipMaskType = kAlpha_ClipMaskType; 11034c2443e36fdc6c095b17e90baa4a2f26a6f00b08bsalomon@google.com return result; 11046b70a7bd3328ea0a12be47b1a7f835c905f16147robertphillips@google.com} 11056b70a7bd3328ea0a12be47b1a7f835c905f16147robertphillips@google.com 1106f294b773f0b2b9f05eb45b52dd3cb4d97b96af06robertphillips@google.com//////////////////////////////////////////////////////////////////////////////// 1107c8dc1f74b6cdda9a43a638292a608c59c1d72d80bsalomonvoid GrClipMaskManager::purgeResources() { 1108c8dc1f74b6cdda9a43a638292a608c59c1d72d80bsalomon fAACache.purgeResources(); 11091e945b7e708c633d4aed937ebfce57d52ba21d83robertphillips@google.com} 11106e4e65066a7c0dbc9bfbfe4b8f5d49c3d8a79b59bsalomon@google.com 1111329bf4862e9d5e05363c2b071d8ca475a0ef1952joshualittvoid GrClipMaskManager::setClipTarget(GrClipTarget* clipTarget) { 1112329bf4862e9d5e05363c2b071d8ca475a0ef1952joshualitt fClipTarget = clipTarget; 1113329bf4862e9d5e05363c2b071d8ca475a0ef1952joshualitt fAACache.setContext(clipTarget->getContext()); 11146e4e65066a7c0dbc9bfbfe4b8f5d49c3d8a79b59bsalomon@google.com} 1115c4dc0ad8e252a7e30d19b47d3d0d9f2c69faf854commit-bot@chromium.org 11169853ccef19c200be93a6211f32589fa82a53067cjoshualittvoid GrClipMaskManager::adjustPathStencilParams(const GrStencilBuffer* stencilBuffer, 11179853ccef19c200be93a6211f32589fa82a53067cjoshualitt GrStencilSettings* settings) { 111849f085dddff10473b6ebf832a974288300224e60bsalomon if (stencilBuffer) { 11199853ccef19c200be93a6211f32589fa82a53067cjoshualitt int stencilBits = stencilBuffer->bits(); 11207a6184fdf717a1da0c6e1e37b942b17fdaa236d3joshualitt this->adjustStencilParams(settings, fClipMode, stencilBits); 1121c4dc0ad8e252a7e30d19b47d3d0d9f2c69faf854commit-bot@chromium.org } 1122c4dc0ad8e252a7e30d19b47d3d0d9f2c69faf854commit-bot@chromium.org} 1123