GrClipMaskManager.cpp revision 9853ccef19c200be93a6211f32589fa82a53067c
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" 161e945b7e708c633d4aed937ebfce57d52ba21d83robertphillips@google.com#include "GrStencilBuffer.h" 17c26d94fd7dc0b00cd6d0e42d28285f4a38aff021bsalomon@google.com#include "GrSWMaskHelper.h" 183a0cfeb96185934c0a36f1313f21b96c57ca6341joshualitt#include "SkRasterClip.h" 193a0cfeb96185934c0a36f1313f21b96c57ca6341joshualitt#include "SkStrokeRec.h" 203a0cfeb96185934c0a36f1313f21b96c57ca6341joshualitt#include "SkTLazy.h" 21a58fe35fdae3481cf43062f7032820c320c3d163joshualitt#include "effects/GrTextureDomain.h" 22a58fe35fdae3481cf43062f7032820c320c3d163joshualitt#include "effects/GrConvexPolyEffect.h" 23a58fe35fdae3481cf43062f7032820c320c3d163joshualitt#include "effects/GrRRectEffect.h" 24c6b3e48cb3a22d83ba3f4b9a614a5a35b05958a0bsalomon@google.com 25ba998f2ddc5a904376bfdb118976868b9ee2b6e8robertphillips@google.com#define GR_AA_CLIP 1 268182fa0cac76e7e6d583aebba060229230516887bsalomon@google.comtypedef SkClipStack::Element Element; 2751a6286c241c1dc750d263ed9676079c898148b0bsalomon@google.com 2851a6286c241c1dc750d263ed9676079c898148b0bsalomon@google.com//////////////////////////////////////////////////////////////////////////////// 29e79f320ed6c5ec9f6164ba84be1ff586532e6517robertphillips@google.comnamespace { 30fbfcd5602128ec010c82cb733c9cdc0a3254f9f3rmistry@google.com// set up the draw state to enable the aa clipping mask. Besides setting up the 3108283afc265f1153834256fc1012519813ba6b73bsalomon@google.com// stage matrix this also alters the vertex layout 329853ccef19c200be93a6211f32589fa82a53067cjoshualittvoid setup_drawstate_aaclip(const SkIRect &devBound, 339853ccef19c200be93a6211f32589fa82a53067cjoshualitt GrDrawState* drawState, 349853ccef19c200be93a6211f32589fa82a53067cjoshualitt GrTexture* result) { 35f6de475e5cbd143f348ff7738919e397b7fe7f57tfarina@chromium.org SkASSERT(drawState); 36a72eef322c686954cdffa849dc26d8133b802f1drobertphillips@google.com 37b9086a026844e4cfd08b219e49ce3f12294cba98bsalomon@google.com SkMatrix mat; 38c78188896e28a4ae49e406a7422b345ae177dafebsalomon@google.com // We want to use device coords to compute the texture coordinates. We set our matrix to be 39c78188896e28a4ae49e406a7422b345ae177dafebsalomon@google.com // equal to the view matrix followed by an offset to the devBound, and then a scaling matrix to 40c78188896e28a4ae49e406a7422b345ae177dafebsalomon@google.com // normalized coords. We apply this matrix to the vertex positions rather than local coords. 41a72eef322c686954cdffa849dc26d8133b802f1drobertphillips@google.com mat.setIDiv(result->width(), result->height()); 42fbfcd5602128ec010c82cb733c9cdc0a3254f9f3rmistry@google.com mat.preTranslate(SkIntToScalar(-devBound.fLeft), 437b11289b4e4d117bbcee6d2460b057d0fcf6e437robertphillips@google.com SkIntToScalar(-devBound.fTop)); 44a72eef322c686954cdffa849dc26d8133b802f1drobertphillips@google.com mat.preConcat(drawState->getViewMatrix()); 45a72eef322c686954cdffa849dc26d8133b802f1drobertphillips@google.com 467b7cdd147f5528865238e5ed98c79e6d319fde9bbsalomon@google.com SkIRect domainTexels = SkIRect::MakeWH(devBound.width(), devBound.height()); 474c2443e36fdc6c095b17e90baa4a2f26a6f00b08bsalomon@google.com // This could be a long-lived effect that is cached with the alpha-mask. 48b0a8a377f832c59cee939ad721e1f87d378b7142joshualitt drawState->addCoverageProcessor( 49eb6879f50a5564eeb981ec5616b55bf685eb76fcbsalomon@google.com GrTextureDomainEffect::Create(result, 507b7cdd147f5528865238e5ed98c79e6d319fde9bbsalomon@google.com mat, 51907fbd53c5e5dd4cbde7b72f9242b51febd7ef95commit-bot@chromium.org GrTextureDomain::MakeTexelDomain(result, domainTexels), 52907fbd53c5e5dd4cbde7b72f9242b51febd7ef95commit-bot@chromium.org GrTextureDomain::kDecal_Mode, 53b86add1ad37776818e1f730359ec587c9fdbff5fhumper@google.com GrTextureParams::kNone_FilterMode, 5477af6805e5faea1e2a5c0220098aec9082f3a6e5bsalomon@google.com kPosition_GrCoordSet))->unref(); 55a72eef322c686954cdffa849dc26d8133b802f1drobertphillips@google.com} 56a72eef322c686954cdffa849dc26d8133b802f1drobertphillips@google.com 57e79f320ed6c5ec9f6164ba84be1ff586532e6517robertphillips@google.combool path_needs_SW_renderer(GrContext* context, 589853ccef19c200be93a6211f32589fa82a53067cjoshualitt const GrDrawTarget* gpu, 599853ccef19c200be93a6211f32589fa82a53067cjoshualitt const GrDrawState* drawState, 60e79f320ed6c5ec9f6164ba84be1ff586532e6517robertphillips@google.com const SkPath& origPath, 61e79f320ed6c5ec9f6164ba84be1ff586532e6517robertphillips@google.com const SkStrokeRec& stroke, 62e79f320ed6c5ec9f6164ba84be1ff586532e6517robertphillips@google.com bool doAA) { 63e79f320ed6c5ec9f6164ba84be1ff586532e6517robertphillips@google.com // the gpu alpha mask will draw the inverse paths as non-inverse to a temp buffer 64e79f320ed6c5ec9f6164ba84be1ff586532e6517robertphillips@google.com SkTCopyOnFirstWrite<SkPath> path(origPath); 65e79f320ed6c5ec9f6164ba84be1ff586532e6517robertphillips@google.com if (path->isInverseFillType()) { 66e79f320ed6c5ec9f6164ba84be1ff586532e6517robertphillips@google.com path.writable()->toggleInverseFillType(); 67e79f320ed6c5ec9f6164ba84be1ff586532e6517robertphillips@google.com } 68e79f320ed6c5ec9f6164ba84be1ff586532e6517robertphillips@google.com // last (false) parameter disallows use of the SW path renderer 6945a15f551b5b3c6c747d8eaf6466b7d3b76a8faebsalomon@google.com GrPathRendererChain::DrawType type = doAA ? 7045a15f551b5b3c6c747d8eaf6466b7d3b76a8faebsalomon@google.com GrPathRendererChain::kColorAntiAlias_DrawType : 7145a15f551b5b3c6c747d8eaf6466b7d3b76a8faebsalomon@google.com GrPathRendererChain::kColor_DrawType; 7245a15f551b5b3c6c747d8eaf6466b7d3b76a8faebsalomon@google.com 739853ccef19c200be93a6211f32589fa82a53067cjoshualitt return NULL == context->getPathRenderer(gpu, drawState, *path, stroke, false, type); 74e79f320ed6c5ec9f6164ba84be1ff586532e6517robertphillips@google.com} 756b70a7bd3328ea0a12be47b1a7f835c905f16147robertphillips@google.com} 766b70a7bd3328ea0a12be47b1a7f835c905f16147robertphillips@google.com 77fa66294c7705831808ce7772d4328fc626d45034robertphillips@google.com/* 78fa66294c7705831808ce7772d4328fc626d45034robertphillips@google.com * This method traverses the clip stack to see if the GrSoftwarePathRenderer 79fa66294c7705831808ce7772d4328fc626d45034robertphillips@google.com * will be used on any element. If so, it returns true to indicate that the 80fa66294c7705831808ce7772d4328fc626d45034robertphillips@google.com * entire clip should be rendered in SW and then uploaded en masse to the gpu. 81fa66294c7705831808ce7772d4328fc626d45034robertphillips@google.com */ 829853ccef19c200be93a6211f32589fa82a53067cjoshualittbool GrClipMaskManager::useSWOnlyPath(const GrDrawState* drawState, 839853ccef19c200be93a6211f32589fa82a53067cjoshualitt const GrReducedClip::ElementList& elements) { 848a4fc40b02fa0a8300ade26863f4ddae69197d62robertphillips@google.com // TODO: generalize this function so that when 85fa66294c7705831808ce7772d4328fc626d45034robertphillips@google.com // a clip gets complex enough it can just be done in SW regardless 86fa66294c7705831808ce7772d4328fc626d45034robertphillips@google.com // of whether it would invoke the GrSoftwarePathRenderer. 875f74cf8c49701f514b69dc6f1a8b5c0ffd78af0asugoi@google.com SkStrokeRec stroke(SkStrokeRec::kFill_InitStyle); 88d21444aab7128c97f4e0eb5e9bf05111d5037292skia.committer@gmail.com 89bf54e49e30cdc92f9ce3f336cc48cf6b236ddeabtfarina for (GrReducedClip::ElementList::Iter iter(elements.headIter()); iter.get(); iter.next()) { 904c2443e36fdc6c095b17e90baa4a2f26a6f00b08bsalomon@google.com const Element* element = iter.get(); 91f69a11b5c5dc5ae02489dfe7ca6432d641b9f121robertphillips@google.com // rects can always be drawn directly w/o using the software path 92e5b2af955b7d06815ddd405659ad62a2a8355ca3commit-bot@chromium.org // Skip rrects once we're drawing them directly. 93e5b2af955b7d06815ddd405659ad62a2a8355ca3commit-bot@chromium.org if (Element::kRect_Type != element->getType()) { 94e5b2af955b7d06815ddd405659ad62a2a8355ca3commit-bot@chromium.org SkPath path; 95e5b2af955b7d06815ddd405659ad62a2a8355ca3commit-bot@chromium.org element->asPath(&path); 969853ccef19c200be93a6211f32589fa82a53067cjoshualitt if (path_needs_SW_renderer(this->getContext(), fClipTarget, drawState, path, stroke, 97329bf4862e9d5e05363c2b071d8ca475a0ef1952joshualitt element->isAA())) { 98e5b2af955b7d06815ddd405659ad62a2a8355ca3commit-bot@chromium.org return true; 99e5b2af955b7d06815ddd405659ad62a2a8355ca3commit-bot@chromium.org } 100fa66294c7705831808ce7772d4328fc626d45034robertphillips@google.com } 101fa66294c7705831808ce7772d4328fc626d45034robertphillips@google.com } 1024c2443e36fdc6c095b17e90baa4a2f26a6f00b08bsalomon@google.com return false; 103a72eef322c686954cdffa849dc26d8133b802f1drobertphillips@google.com} 104a72eef322c686954cdffa849dc26d8133b802f1drobertphillips@google.com 1059853ccef19c200be93a6211f32589fa82a53067cjoshualittbool GrClipMaskManager::installClipEffects(GrDrawState* drawState, 106e5a041c0688ccb861cc85f8917338602864d8e5acommit-bot@chromium.org GrDrawState::AutoRestoreEffects* are, 1079853ccef19c200be93a6211f32589fa82a53067cjoshualitt const GrReducedClip::ElementList& elements, 108e5a041c0688ccb861cc85f8917338602864d8e5acommit-bot@chromium.org const SkVector& clipToRTOffset, 109217daa7ec592fc306edffb9fb2a3d8c7ebff8c2dmtklein const SkRect* drawBounds) { 110e5a041c0688ccb861cc85f8917338602864d8e5acommit-bot@chromium.org SkRect boundsInClipSpace; 11149f085dddff10473b6ebf832a974288300224e60bsalomon if (drawBounds) { 112e5a041c0688ccb861cc85f8917338602864d8e5acommit-bot@chromium.org boundsInClipSpace = *drawBounds; 113e5a041c0688ccb861cc85f8917338602864d8e5acommit-bot@chromium.org boundsInClipSpace.offset(-clipToRTOffset.fX, -clipToRTOffset.fY); 114e5a041c0688ccb861cc85f8917338602864d8e5acommit-bot@chromium.org } 115e5a041c0688ccb861cc85f8917338602864d8e5acommit-bot@chromium.org 116e5a041c0688ccb861cc85f8917338602864d8e5acommit-bot@chromium.org are->set(drawState); 117e5a041c0688ccb861cc85f8917338602864d8e5acommit-bot@chromium.org GrRenderTarget* rt = drawState->getRenderTarget(); 118bf54e49e30cdc92f9ce3f336cc48cf6b236ddeabtfarina GrReducedClip::ElementList::Iter iter(elements); 119e5a041c0688ccb861cc85f8917338602864d8e5acommit-bot@chromium.org bool failed = false; 12049f085dddff10473b6ebf832a974288300224e60bsalomon while (iter.get()) { 121e5a041c0688ccb861cc85f8917338602864d8e5acommit-bot@chromium.org SkRegion::Op op = iter.get()->getOp(); 122e5a041c0688ccb861cc85f8917338602864d8e5acommit-bot@chromium.org bool invert; 123e5a041c0688ccb861cc85f8917338602864d8e5acommit-bot@chromium.org bool skip = false; 124e5a041c0688ccb861cc85f8917338602864d8e5acommit-bot@chromium.org switch (op) { 125e5a041c0688ccb861cc85f8917338602864d8e5acommit-bot@chromium.org case SkRegion::kReplace_Op: 126e5a041c0688ccb861cc85f8917338602864d8e5acommit-bot@chromium.org SkASSERT(iter.get() == elements.head()); 127e5a041c0688ccb861cc85f8917338602864d8e5acommit-bot@chromium.org // Fallthrough, handled same as intersect. 128e5a041c0688ccb861cc85f8917338602864d8e5acommit-bot@chromium.org case SkRegion::kIntersect_Op: 129e5a041c0688ccb861cc85f8917338602864d8e5acommit-bot@chromium.org invert = false; 13049f085dddff10473b6ebf832a974288300224e60bsalomon if (drawBounds && iter.get()->contains(boundsInClipSpace)) { 131e5a041c0688ccb861cc85f8917338602864d8e5acommit-bot@chromium.org skip = true; 132e5a041c0688ccb861cc85f8917338602864d8e5acommit-bot@chromium.org } 133e5a041c0688ccb861cc85f8917338602864d8e5acommit-bot@chromium.org break; 134e5a041c0688ccb861cc85f8917338602864d8e5acommit-bot@chromium.org case SkRegion::kDifference_Op: 135e5a041c0688ccb861cc85f8917338602864d8e5acommit-bot@chromium.org invert = true; 136e5a041c0688ccb861cc85f8917338602864d8e5acommit-bot@chromium.org // We don't currently have a cheap test for whether a rect is fully outside an 137e5a041c0688ccb861cc85f8917338602864d8e5acommit-bot@chromium.org // element's primitive, so don't attempt to set skip. 138e5a041c0688ccb861cc85f8917338602864d8e5acommit-bot@chromium.org break; 139e5a041c0688ccb861cc85f8917338602864d8e5acommit-bot@chromium.org default: 140e5a041c0688ccb861cc85f8917338602864d8e5acommit-bot@chromium.org failed = true; 141e5a041c0688ccb861cc85f8917338602864d8e5acommit-bot@chromium.org break; 142e5a041c0688ccb861cc85f8917338602864d8e5acommit-bot@chromium.org } 143e5a041c0688ccb861cc85f8917338602864d8e5acommit-bot@chromium.org if (failed) { 144e5a041c0688ccb861cc85f8917338602864d8e5acommit-bot@chromium.org break; 145e5a041c0688ccb861cc85f8917338602864d8e5acommit-bot@chromium.org } 146e5a041c0688ccb861cc85f8917338602864d8e5acommit-bot@chromium.org 147e5a041c0688ccb861cc85f8917338602864d8e5acommit-bot@chromium.org if (!skip) { 148b0a8a377f832c59cee939ad721e1f87d378b7142joshualitt GrPrimitiveEdgeType edgeType; 149e5a041c0688ccb861cc85f8917338602864d8e5acommit-bot@chromium.org if (GR_AA_CLIP && iter.get()->isAA()) { 150e5a041c0688ccb861cc85f8917338602864d8e5acommit-bot@chromium.org if (rt->isMultisampled()) { 151217daa7ec592fc306edffb9fb2a3d8c7ebff8c2dmtklein // Coverage based AA clips don't place nicely with MSAA. 152e5a041c0688ccb861cc85f8917338602864d8e5acommit-bot@chromium.org failed = true; 153e5a041c0688ccb861cc85f8917338602864d8e5acommit-bot@chromium.org break; 154e5a041c0688ccb861cc85f8917338602864d8e5acommit-bot@chromium.org } 155b0a8a377f832c59cee939ad721e1f87d378b7142joshualitt edgeType = 156b0a8a377f832c59cee939ad721e1f87d378b7142joshualitt invert ? kInverseFillAA_GrProcessorEdgeType : kFillAA_GrProcessorEdgeType; 157e5a041c0688ccb861cc85f8917338602864d8e5acommit-bot@chromium.org } else { 158b0a8a377f832c59cee939ad721e1f87d378b7142joshualitt edgeType = 159b0a8a377f832c59cee939ad721e1f87d378b7142joshualitt invert ? kInverseFillBW_GrProcessorEdgeType : kFillBW_GrProcessorEdgeType; 160e5a041c0688ccb861cc85f8917338602864d8e5acommit-bot@chromium.org } 161b0a8a377f832c59cee939ad721e1f87d378b7142joshualitt SkAutoTUnref<GrFragmentProcessor> fp; 162e5a041c0688ccb861cc85f8917338602864d8e5acommit-bot@chromium.org switch (iter.get()->getType()) { 163e5a041c0688ccb861cc85f8917338602864d8e5acommit-bot@chromium.org case SkClipStack::Element::kPath_Type: 164b0a8a377f832c59cee939ad721e1f87d378b7142joshualitt fp.reset(GrConvexPolyEffect::Create(edgeType, iter.get()->getPath(), 165e5a041c0688ccb861cc85f8917338602864d8e5acommit-bot@chromium.org &clipToRTOffset)); 166e5a041c0688ccb861cc85f8917338602864d8e5acommit-bot@chromium.org break; 167e5a041c0688ccb861cc85f8917338602864d8e5acommit-bot@chromium.org case SkClipStack::Element::kRRect_Type: { 168e5a041c0688ccb861cc85f8917338602864d8e5acommit-bot@chromium.org SkRRect rrect = iter.get()->getRRect(); 169e5a041c0688ccb861cc85f8917338602864d8e5acommit-bot@chromium.org rrect.offset(clipToRTOffset.fX, clipToRTOffset.fY); 170b0a8a377f832c59cee939ad721e1f87d378b7142joshualitt fp.reset(GrRRectEffect::Create(edgeType, rrect)); 171e5a041c0688ccb861cc85f8917338602864d8e5acommit-bot@chromium.org break; 172e5a041c0688ccb861cc85f8917338602864d8e5acommit-bot@chromium.org } 173e5a041c0688ccb861cc85f8917338602864d8e5acommit-bot@chromium.org case SkClipStack::Element::kRect_Type: { 174e5a041c0688ccb861cc85f8917338602864d8e5acommit-bot@chromium.org SkRect rect = iter.get()->getRect(); 175e5a041c0688ccb861cc85f8917338602864d8e5acommit-bot@chromium.org rect.offset(clipToRTOffset.fX, clipToRTOffset.fY); 176b0a8a377f832c59cee939ad721e1f87d378b7142joshualitt fp.reset(GrConvexPolyEffect::Create(edgeType, rect)); 177e5a041c0688ccb861cc85f8917338602864d8e5acommit-bot@chromium.org break; 178e5a041c0688ccb861cc85f8917338602864d8e5acommit-bot@chromium.org } 179e5a041c0688ccb861cc85f8917338602864d8e5acommit-bot@chromium.org default: 180e5a041c0688ccb861cc85f8917338602864d8e5acommit-bot@chromium.org break; 181e5a041c0688ccb861cc85f8917338602864d8e5acommit-bot@chromium.org } 182b0a8a377f832c59cee939ad721e1f87d378b7142joshualitt if (fp) { 1839853ccef19c200be93a6211f32589fa82a53067cjoshualitt drawState->addCoverageProcessor(fp); 184217daa7ec592fc306edffb9fb2a3d8c7ebff8c2dmtklein } else { 185e5a041c0688ccb861cc85f8917338602864d8e5acommit-bot@chromium.org failed = true; 186e5a041c0688ccb861cc85f8917338602864d8e5acommit-bot@chromium.org break; 187e5a041c0688ccb861cc85f8917338602864d8e5acommit-bot@chromium.org } 188e5a041c0688ccb861cc85f8917338602864d8e5acommit-bot@chromium.org } 189217daa7ec592fc306edffb9fb2a3d8c7ebff8c2dmtklein iter.next(); 190e5a041c0688ccb861cc85f8917338602864d8e5acommit-bot@chromium.org } 191e5a041c0688ccb861cc85f8917338602864d8e5acommit-bot@chromium.org 192e5a041c0688ccb861cc85f8917338602864d8e5acommit-bot@chromium.org if (failed) { 193e5a041c0688ccb861cc85f8917338602864d8e5acommit-bot@chromium.org are->set(NULL); 194e5a041c0688ccb861cc85f8917338602864d8e5acommit-bot@chromium.org } 195e5a041c0688ccb861cc85f8917338602864d8e5acommit-bot@chromium.org return !failed; 196e5a041c0688ccb861cc85f8917338602864d8e5acommit-bot@chromium.org} 197e5a041c0688ccb861cc85f8917338602864d8e5acommit-bot@chromium.org 198f294b773f0b2b9f05eb45b52dd3cb4d97b96af06robertphillips@google.com//////////////////////////////////////////////////////////////////////////////// 1996b70a7bd3328ea0a12be47b1a7f835c905f16147robertphillips@google.com// sort out what kind of clip mask needs to be created: alpha, stencil, 2006b70a7bd3328ea0a12be47b1a7f835c905f16147robertphillips@google.com// scissor, or entirely software 2019853ccef19c200be93a6211f32589fa82a53067cjoshualittbool GrClipMaskManager::setupClipping(GrDrawState* drawState, 2023ae0e6c2b213d45c370846a4d4182a6754ca493ecommit-bot@chromium.org GrDrawState::AutoRestoreEffects* are, 20377b1307c1f5dac019575a6d431d5ce657370c4fbjoshualitt GrDrawState::AutoRestoreStencil* ars, 2049853ccef19c200be93a6211f32589fa82a53067cjoshualitt ScissorState* scissorState, 2059853ccef19c200be93a6211f32589fa82a53067cjoshualitt const GrClipData* clipDataIn, 2069853ccef19c200be93a6211f32589fa82a53067cjoshualitt const SkRect* devBounds) { 207c8f7f47afaf8f9471e6d111655c5610a8bd210a2bsalomon@google.com fCurrClipMaskType = kNone_ClipMaskType; 2087a6184fdf717a1da0c6e1e37b942b17fdaa236d3joshualitt if (kRespectClip_StencilClipMode == fClipMode) { 2097a6184fdf717a1da0c6e1e37b942b17fdaa236d3joshualitt fClipMode = kIgnoreClip_StencilClipMode; 2107a6184fdf717a1da0c6e1e37b942b17fdaa236d3joshualitt } 211a320194e4242ef0e5e758aea896bfd52bcb3dac7bsalomon@google.com 212bf54e49e30cdc92f9ce3f336cc48cf6b236ddeabtfarina GrReducedClip::ElementList elements(16); 213d3e5842db0cb169e10d6da1e62c94ba5cf182bb4commit-bot@chromium.org int32_t genID; 214bf54e49e30cdc92f9ce3f336cc48cf6b236ddeabtfarina GrReducedClip::InitialState initialState; 2154c2443e36fdc6c095b17e90baa4a2f26a6f00b08bsalomon@google.com SkIRect clipSpaceIBounds; 2164c2443e36fdc6c095b17e90baa4a2f26a6f00b08bsalomon@google.com bool requiresAA; 2179853ccef19c200be93a6211f32589fa82a53067cjoshualitt GrRenderTarget* rt = drawState->getRenderTarget(); 2184c2443e36fdc6c095b17e90baa4a2f26a6f00b08bsalomon@google.com 2191e945b7e708c633d4aed937ebfce57d52ba21d83robertphillips@google.com // GrDrawTarget should have filtered this for us 22049f085dddff10473b6ebf832a974288300224e60bsalomon SkASSERT(rt); 2211e945b7e708c633d4aed937ebfce57d52ba21d83robertphillips@google.com 2224c2443e36fdc6c095b17e90baa4a2f26a6f00b08bsalomon@google.com bool ignoreClip = !drawState->isClipState() || clipDataIn->fClipStack->isWideOpen(); 2234c2443e36fdc6c095b17e90baa4a2f26a6f00b08bsalomon@google.com if (!ignoreClip) { 2244c2443e36fdc6c095b17e90baa4a2f26a6f00b08bsalomon@google.com SkIRect clipSpaceRTIBounds = SkIRect::MakeWH(rt->width(), rt->height()); 2254c2443e36fdc6c095b17e90baa4a2f26a6f00b08bsalomon@google.com clipSpaceRTIBounds.offset(clipDataIn->fOrigin); 226bf54e49e30cdc92f9ce3f336cc48cf6b236ddeabtfarina GrReducedClip::ReduceClipStack(*clipDataIn->fClipStack, 227bf54e49e30cdc92f9ce3f336cc48cf6b236ddeabtfarina clipSpaceRTIBounds, 228bf54e49e30cdc92f9ce3f336cc48cf6b236ddeabtfarina &elements, 229bf54e49e30cdc92f9ce3f336cc48cf6b236ddeabtfarina &genID, 230bf54e49e30cdc92f9ce3f336cc48cf6b236ddeabtfarina &initialState, 231bf54e49e30cdc92f9ce3f336cc48cf6b236ddeabtfarina &clipSpaceIBounds, 232bf54e49e30cdc92f9ce3f336cc48cf6b236ddeabtfarina &requiresAA); 2334c2443e36fdc6c095b17e90baa4a2f26a6f00b08bsalomon@google.com if (elements.isEmpty()) { 234bf54e49e30cdc92f9ce3f336cc48cf6b236ddeabtfarina if (GrReducedClip::kAllIn_InitialState == initialState) { 2354c2443e36fdc6c095b17e90baa4a2f26a6f00b08bsalomon@google.com ignoreClip = clipSpaceIBounds == clipSpaceRTIBounds; 2364c2443e36fdc6c095b17e90baa4a2f26a6f00b08bsalomon@google.com } else { 2374c2443e36fdc6c095b17e90baa4a2f26a6f00b08bsalomon@google.com return false; 2384c2443e36fdc6c095b17e90baa4a2f26a6f00b08bsalomon@google.com } 2394c2443e36fdc6c095b17e90baa4a2f26a6f00b08bsalomon@google.com } 2404c2443e36fdc6c095b17e90baa4a2f26a6f00b08bsalomon@google.com } 2413e11c0bd92fbd12f59080c3f9450201d6105db83robertphillips@google.com 2424c2443e36fdc6c095b17e90baa4a2f26a6f00b08bsalomon@google.com if (ignoreClip) { 2439853ccef19c200be93a6211f32589fa82a53067cjoshualitt this->setDrawStateStencil(drawState, ars); 2444c2443e36fdc6c095b17e90baa4a2f26a6f00b08bsalomon@google.com return true; 245a320194e4242ef0e5e758aea896bfd52bcb3dac7bsalomon@google.com } 246a320194e4242ef0e5e758aea896bfd52bcb3dac7bsalomon@google.com 247e5a041c0688ccb861cc85f8917338602864d8e5acommit-bot@chromium.org // An element count of 4 was chosen because of the common pattern in Blink of: 248e5a041c0688ccb861cc85f8917338602864d8e5acommit-bot@chromium.org // isect RR 249e5a041c0688ccb861cc85f8917338602864d8e5acommit-bot@chromium.org // diff RR 250e5a041c0688ccb861cc85f8917338602864d8e5acommit-bot@chromium.org // isect convex_poly 251e5a041c0688ccb861cc85f8917338602864d8e5acommit-bot@chromium.org // isect convex_poly 252e5a041c0688ccb861cc85f8917338602864d8e5acommit-bot@chromium.org // when drawing rounded div borders. This could probably be tuned based on a 253e5a041c0688ccb861cc85f8917338602864d8e5acommit-bot@chromium.org // configuration's relative costs of switching RTs to generate a mask vs 254e5a041c0688ccb861cc85f8917338602864d8e5acommit-bot@chromium.org // longer shaders. 255e5a041c0688ccb861cc85f8917338602864d8e5acommit-bot@chromium.org if (elements.count() <= 4) { 256e5a041c0688ccb861cc85f8917338602864d8e5acommit-bot@chromium.org SkVector clipToRTOffset = { SkIntToScalar(-clipDataIn->fOrigin.fX), 257b21fac156d9287d6c0cfd446d707c4c7be6fae6ecommit-bot@chromium.org SkIntToScalar(-clipDataIn->fOrigin.fY) }; 258e5a041c0688ccb861cc85f8917338602864d8e5acommit-bot@chromium.org if (elements.isEmpty() || 2599853ccef19c200be93a6211f32589fa82a53067cjoshualitt (requiresAA && this->installClipEffects(drawState, are, elements, clipToRTOffset, 2609853ccef19c200be93a6211f32589fa82a53067cjoshualitt devBounds))) { 261217daa7ec592fc306edffb9fb2a3d8c7ebff8c2dmtklein SkIRect scissorSpaceIBounds(clipSpaceIBounds); 262217daa7ec592fc306edffb9fb2a3d8c7ebff8c2dmtklein scissorSpaceIBounds.offset(-clipDataIn->fOrigin); 263217daa7ec592fc306edffb9fb2a3d8c7ebff8c2dmtklein if (NULL == devBounds || 264217daa7ec592fc306edffb9fb2a3d8c7ebff8c2dmtklein !SkRect::Make(scissorSpaceIBounds).contains(*devBounds)) { 26577b1307c1f5dac019575a6d431d5ce657370c4fbjoshualitt scissorState->set(scissorSpaceIBounds); 266e5a041c0688ccb861cc85f8917338602864d8e5acommit-bot@chromium.org } 2679853ccef19c200be93a6211f32589fa82a53067cjoshualitt this->setDrawStateStencil(drawState, ars); 26865ee5f424cb4dabd453268902c00086605d77c1dcommit-bot@chromium.org return true; 26965ee5f424cb4dabd453268902c00086605d77c1dcommit-bot@chromium.org } 27065ee5f424cb4dabd453268902c00086605d77c1dcommit-bot@chromium.org } 271d3066bd9b4a37cf4a39e7df7e1432f3df10dbc67bsalomon@google.com 27265ee5f424cb4dabd453268902c00086605d77c1dcommit-bot@chromium.org#if GR_AA_CLIP 273a3e5c63ab0264332169df4583a8a7da186fb4e66robertphillips@google.com // If MSAA is enabled we can do everything in the stencil buffer. 2744c2443e36fdc6c095b17e90baa4a2f26a6f00b08bsalomon@google.com if (0 == rt->numSamples() && requiresAA) { 2756b70a7bd3328ea0a12be47b1a7f835c905f16147robertphillips@google.com GrTexture* result = NULL; 276a3e5c63ab0264332169df4583a8a7da186fb4e66robertphillips@google.com 2779853ccef19c200be93a6211f32589fa82a53067cjoshualitt if (this->useSWOnlyPath(drawState, elements)) { 2784c2443e36fdc6c095b17e90baa4a2f26a6f00b08bsalomon@google.com // The clip geometry is complex enough that it will be more efficient to create it 2794c2443e36fdc6c095b17e90baa4a2f26a6f00b08bsalomon@google.com // entirely in software 2804c2443e36fdc6c095b17e90baa4a2f26a6f00b08bsalomon@google.com result = this->createSoftwareClipMask(genID, 2814c2443e36fdc6c095b17e90baa4a2f26a6f00b08bsalomon@google.com initialState, 2824c2443e36fdc6c095b17e90baa4a2f26a6f00b08bsalomon@google.com elements, 2834c2443e36fdc6c095b17e90baa4a2f26a6f00b08bsalomon@google.com clipSpaceIBounds); 2844c2443e36fdc6c095b17e90baa4a2f26a6f00b08bsalomon@google.com } else { 2854c2443e36fdc6c095b17e90baa4a2f26a6f00b08bsalomon@google.com result = this->createAlphaClipMask(genID, 2864c2443e36fdc6c095b17e90baa4a2f26a6f00b08bsalomon@google.com initialState, 2874c2443e36fdc6c095b17e90baa4a2f26a6f00b08bsalomon@google.com elements, 2884c2443e36fdc6c095b17e90baa4a2f26a6f00b08bsalomon@google.com clipSpaceIBounds); 2894c2443e36fdc6c095b17e90baa4a2f26a6f00b08bsalomon@google.com } 2906b70a7bd3328ea0a12be47b1a7f835c905f16147robertphillips@google.com 29149f085dddff10473b6ebf832a974288300224e60bsalomon if (result) { 2924c2443e36fdc6c095b17e90baa4a2f26a6f00b08bsalomon@google.com // The mask's top left coord should be pinned to the rounded-out top left corner of 2934c2443e36fdc6c095b17e90baa4a2f26a6f00b08bsalomon@google.com // clipSpace bounds. We determine the mask's position WRT to the render target here. 2944c2443e36fdc6c095b17e90baa4a2f26a6f00b08bsalomon@google.com SkIRect rtSpaceMaskBounds = clipSpaceIBounds; 2954c2443e36fdc6c095b17e90baa4a2f26a6f00b08bsalomon@google.com rtSpaceMaskBounds.offset(-clipDataIn->fOrigin); 2969853ccef19c200be93a6211f32589fa82a53067cjoshualitt setup_drawstate_aaclip(rtSpaceMaskBounds, drawState, result); 2979853ccef19c200be93a6211f32589fa82a53067cjoshualitt this->setDrawStateStencil(drawState, ars); 298f294b773f0b2b9f05eb45b52dd3cb4d97b96af06robertphillips@google.com return true; 299f294b773f0b2b9f05eb45b52dd3cb4d97b96af06robertphillips@google.com } 3004c2443e36fdc6c095b17e90baa4a2f26a6f00b08bsalomon@google.com // if alpha clip mask creation fails fall through to the non-AA code paths 301f294b773f0b2b9f05eb45b52dd3cb4d97b96af06robertphillips@google.com } 302f294b773f0b2b9f05eb45b52dd3cb4d97b96af06robertphillips@google.com#endif // GR_AA_CLIP 303f294b773f0b2b9f05eb45b52dd3cb4d97b96af06robertphillips@google.com 3044c2443e36fdc6c095b17e90baa4a2f26a6f00b08bsalomon@google.com // Either a hard (stencil buffer) clip was explicitly requested or an anti-aliased clip couldn't 3054c2443e36fdc6c095b17e90baa4a2f26a6f00b08bsalomon@google.com // be created. In either case, free up the texture in the anti-aliased mask cache. 3064c2443e36fdc6c095b17e90baa4a2f26a6f00b08bsalomon@google.com // TODO: this may require more investigation. Ganesh performs a lot of utility draws (e.g., 3074c2443e36fdc6c095b17e90baa4a2f26a6f00b08bsalomon@google.com // clears, InOrderDrawBuffer playbacks) that hit the stencil buffer path. These may be 3084c2443e36fdc6c095b17e90baa4a2f26a6f00b08bsalomon@google.com // "incorrectly" clearing the AA cache. 3095acc0e36d987dff3172fd45a14b66c52a51d49e4robertphillips@google.com fAACache.reset(); 3105acc0e36d987dff3172fd45a14b66c52a51d49e4robertphillips@google.com 3111e945b7e708c633d4aed937ebfce57d52ba21d83robertphillips@google.com // use the stencil clip if we can't represent the clip as a rectangle. 3124c2443e36fdc6c095b17e90baa4a2f26a6f00b08bsalomon@google.com SkIPoint clipSpaceToStencilSpaceOffset = -clipDataIn->fOrigin; 3139853ccef19c200be93a6211f32589fa82a53067cjoshualitt this->createStencilClipMask(rt, 3149853ccef19c200be93a6211f32589fa82a53067cjoshualitt genID, 315d3e5842db0cb169e10d6da1e62c94ba5cf182bb4commit-bot@chromium.org initialState, 3164c2443e36fdc6c095b17e90baa4a2f26a6f00b08bsalomon@google.com elements, 3174c2443e36fdc6c095b17e90baa4a2f26a6f00b08bsalomon@google.com clipSpaceIBounds, 3184c2443e36fdc6c095b17e90baa4a2f26a6f00b08bsalomon@google.com clipSpaceToStencilSpaceOffset); 3194c2443e36fdc6c095b17e90baa4a2f26a6f00b08bsalomon@google.com 3204c2443e36fdc6c095b17e90baa4a2f26a6f00b08bsalomon@google.com // This must occur after createStencilClipMask. That function may change the scissor. Also, it 3214c2443e36fdc6c095b17e90baa4a2f26a6f00b08bsalomon@google.com // only guarantees that the stencil mask is correct within the bounds it was passed, so we must 3224c2443e36fdc6c095b17e90baa4a2f26a6f00b08bsalomon@google.com // use both stencil and scissor test to the bounds for the final draw. 3234c2443e36fdc6c095b17e90baa4a2f26a6f00b08bsalomon@google.com SkIRect scissorSpaceIBounds(clipSpaceIBounds); 3244c2443e36fdc6c095b17e90baa4a2f26a6f00b08bsalomon@google.com scissorSpaceIBounds.offset(clipSpaceToStencilSpaceOffset); 32577b1307c1f5dac019575a6d431d5ce657370c4fbjoshualitt scissorState->set(scissorSpaceIBounds); 3269853ccef19c200be93a6211f32589fa82a53067cjoshualitt this->setDrawStateStencil(drawState, ars); 3271e945b7e708c633d4aed937ebfce57d52ba21d83robertphillips@google.com return true; 3281e945b7e708c633d4aed937ebfce57d52ba21d83robertphillips@google.com} 3291e945b7e708c633d4aed937ebfce57d52ba21d83robertphillips@google.com 3301e945b7e708c633d4aed937ebfce57d52ba21d83robertphillips@google.comnamespace { 331f294b773f0b2b9f05eb45b52dd3cb4d97b96af06robertphillips@google.com//////////////////////////////////////////////////////////////////////////////// 332fbfcd5602128ec010c82cb733c9cdc0a3254f9f3rmistry@google.com// set up the OpenGL blend function to perform the specified 333fbfcd5602128ec010c82cb733c9cdc0a3254f9f3rmistry@google.com// boolean operation for alpha clip mask creation 3349853ccef19c200be93a6211f32589fa82a53067cjoshualittvoid setup_boolean_blendcoeffs(SkRegion::Op op, GrDrawState* drawState) { 335f294b773f0b2b9f05eb45b52dd3cb4d97b96af06robertphillips@google.com switch (op) { 336f294b773f0b2b9f05eb45b52dd3cb4d97b96af06robertphillips@google.com case SkRegion::kReplace_Op: 33747059542e7aa153926377456a6c611e55c8e428cbsalomon@google.com drawState->setBlendFunc(kOne_GrBlendCoeff, kZero_GrBlendCoeff); 338f294b773f0b2b9f05eb45b52dd3cb4d97b96af06robertphillips@google.com break; 339f294b773f0b2b9f05eb45b52dd3cb4d97b96af06robertphillips@google.com case SkRegion::kIntersect_Op: 34047059542e7aa153926377456a6c611e55c8e428cbsalomon@google.com drawState->setBlendFunc(kDC_GrBlendCoeff, kZero_GrBlendCoeff); 341f294b773f0b2b9f05eb45b52dd3cb4d97b96af06robertphillips@google.com break; 342f294b773f0b2b9f05eb45b52dd3cb4d97b96af06robertphillips@google.com case SkRegion::kUnion_Op: 34347059542e7aa153926377456a6c611e55c8e428cbsalomon@google.com drawState->setBlendFunc(kOne_GrBlendCoeff, kISC_GrBlendCoeff); 344f294b773f0b2b9f05eb45b52dd3cb4d97b96af06robertphillips@google.com break; 345f294b773f0b2b9f05eb45b52dd3cb4d97b96af06robertphillips@google.com case SkRegion::kXOR_Op: 34647059542e7aa153926377456a6c611e55c8e428cbsalomon@google.com drawState->setBlendFunc(kIDC_GrBlendCoeff, kISC_GrBlendCoeff); 347f294b773f0b2b9f05eb45b52dd3cb4d97b96af06robertphillips@google.com break; 348f294b773f0b2b9f05eb45b52dd3cb4d97b96af06robertphillips@google.com case SkRegion::kDifference_Op: 34947059542e7aa153926377456a6c611e55c8e428cbsalomon@google.com drawState->setBlendFunc(kZero_GrBlendCoeff, kISC_GrBlendCoeff); 350f294b773f0b2b9f05eb45b52dd3cb4d97b96af06robertphillips@google.com break; 351f294b773f0b2b9f05eb45b52dd3cb4d97b96af06robertphillips@google.com case SkRegion::kReverseDifference_Op: 35247059542e7aa153926377456a6c611e55c8e428cbsalomon@google.com drawState->setBlendFunc(kIDC_GrBlendCoeff, kZero_GrBlendCoeff); 353f294b773f0b2b9f05eb45b52dd3cb4d97b96af06robertphillips@google.com break; 354f294b773f0b2b9f05eb45b52dd3cb4d97b96af06robertphillips@google.com default: 355f6de475e5cbd143f348ff7738919e397b7fe7f57tfarina@chromium.org SkASSERT(false); 356f294b773f0b2b9f05eb45b52dd3cb4d97b96af06robertphillips@google.com break; 357f294b773f0b2b9f05eb45b52dd3cb4d97b96af06robertphillips@google.com } 358f294b773f0b2b9f05eb45b52dd3cb4d97b96af06robertphillips@google.com} 35972176b2d38db005863a54e3dd6657bbabd068bb6robertphillips@google.com} 360f294b773f0b2b9f05eb45b52dd3cb4d97b96af06robertphillips@google.com 361f294b773f0b2b9f05eb45b52dd3cb4d97b96af06robertphillips@google.com//////////////////////////////////////////////////////////////////////////////// 3629853ccef19c200be93a6211f32589fa82a53067cjoshualittbool GrClipMaskManager::drawElement(GrDrawState* drawState, 3639853ccef19c200be93a6211f32589fa82a53067cjoshualitt GrTexture* target, 364e79f320ed6c5ec9f6164ba84be1ff586532e6517robertphillips@google.com const SkClipStack::Element* element, 365e79f320ed6c5ec9f6164ba84be1ff586532e6517robertphillips@google.com GrPathRenderer* pr) { 3669853ccef19c200be93a6211f32589fa82a53067cjoshualitt GrDrawTarget::AutoGeometryPush agp(fClipTarget); 367f294b773f0b2b9f05eb45b52dd3cb4d97b96af06robertphillips@google.com 368f294b773f0b2b9f05eb45b52dd3cb4d97b96af06robertphillips@google.com drawState->setRenderTarget(target->asRenderTarget()); 369f294b773f0b2b9f05eb45b52dd3cb4d97b96af06robertphillips@google.com 370e5b2af955b7d06815ddd405659ad62a2a8355ca3commit-bot@chromium.org // TODO: Draw rrects directly here. 3718182fa0cac76e7e6d583aebba060229230516887bsalomon@google.com switch (element->getType()) { 372e5b2af955b7d06815ddd405659ad62a2a8355ca3commit-bot@chromium.org case Element::kEmpty_Type: 373e5b2af955b7d06815ddd405659ad62a2a8355ca3commit-bot@chromium.org SkDEBUGFAIL("Should never get here with an empty element."); 374e5b2af955b7d06815ddd405659ad62a2a8355ca3commit-bot@chromium.org break; 3758182fa0cac76e7e6d583aebba060229230516887bsalomon@google.com case Element::kRect_Type: 376b0a8a377f832c59cee939ad721e1f87d378b7142joshualitt // TODO: Do rects directly to the accumulator using a aa-rect GrProcessor that covers 377b0a8a377f832c59cee939ad721e1f87d378b7142joshualitt // the entire mask bounds and writes 0 outside the rect. 3788182fa0cac76e7e6d583aebba060229230516887bsalomon@google.com if (element->isAA()) { 379329bf4862e9d5e05363c2b071d8ca475a0ef1952joshualitt this->getContext()->getAARectRenderer()->fillAARect(fClipTarget, 3809853ccef19c200be93a6211f32589fa82a53067cjoshualitt drawState, 381a58fe35fdae3481cf43062f7032820c320c3d163joshualitt element->getRect(), 382a58fe35fdae3481cf43062f7032820c320c3d163joshualitt SkMatrix::I(), 383a58fe35fdae3481cf43062f7032820c320c3d163joshualitt element->getRect()); 3848182fa0cac76e7e6d583aebba060229230516887bsalomon@google.com } else { 3859853ccef19c200be93a6211f32589fa82a53067cjoshualitt fClipTarget->drawSimpleRect(drawState, element->getRect()); 3868182fa0cac76e7e6d583aebba060229230516887bsalomon@google.com } 3878182fa0cac76e7e6d583aebba060229230516887bsalomon@google.com return true; 388e5b2af955b7d06815ddd405659ad62a2a8355ca3commit-bot@chromium.org default: { 389e5b2af955b7d06815ddd405659ad62a2a8355ca3commit-bot@chromium.org SkPath path; 390e5b2af955b7d06815ddd405659ad62a2a8355ca3commit-bot@chromium.org element->asPath(&path); 391b3eb687f8a89eb1eacd1afb4016401eb392f66abjvanverth path.setIsVolatile(true); 392e5b2af955b7d06815ddd405659ad62a2a8355ca3commit-bot@chromium.org if (path.isInverseFillType()) { 393e5b2af955b7d06815ddd405659ad62a2a8355ca3commit-bot@chromium.org path.toggleInverseFillType(); 394e79f320ed6c5ec9f6164ba84be1ff586532e6517robertphillips@google.com } 3955f74cf8c49701f514b69dc6f1a8b5c0ffd78af0asugoi@google.com SkStrokeRec stroke(SkStrokeRec::kFill_InitStyle); 396e79f320ed6c5ec9f6164ba84be1ff586532e6517robertphillips@google.com if (NULL == pr) { 397e79f320ed6c5ec9f6164ba84be1ff586532e6517robertphillips@google.com GrPathRendererChain::DrawType type; 398e79f320ed6c5ec9f6164ba84be1ff586532e6517robertphillips@google.com type = element->isAA() ? GrPathRendererChain::kColorAntiAlias_DrawType : 399e79f320ed6c5ec9f6164ba84be1ff586532e6517robertphillips@google.com GrPathRendererChain::kColor_DrawType; 4009853ccef19c200be93a6211f32589fa82a53067cjoshualitt pr = this->getContext()->getPathRenderer(fClipTarget, drawState, path, stroke, 4019853ccef19c200be93a6211f32589fa82a53067cjoshualitt false, type); 402e79f320ed6c5ec9f6164ba84be1ff586532e6517robertphillips@google.com } 403e79f320ed6c5ec9f6164ba84be1ff586532e6517robertphillips@google.com if (NULL == pr) { 4044c2443e36fdc6c095b17e90baa4a2f26a6f00b08bsalomon@google.com return false; 4054c2443e36fdc6c095b17e90baa4a2f26a6f00b08bsalomon@google.com } 4069853ccef19c200be93a6211f32589fa82a53067cjoshualitt 4079853ccef19c200be93a6211f32589fa82a53067cjoshualitt pr->drawPath(fClipTarget, drawState, path, stroke, element->isAA()); 4084c2443e36fdc6c095b17e90baa4a2f26a6f00b08bsalomon@google.com break; 4094c2443e36fdc6c095b17e90baa4a2f26a6f00b08bsalomon@google.com } 410f294b773f0b2b9f05eb45b52dd3cb4d97b96af06robertphillips@google.com } 411f294b773f0b2b9f05eb45b52dd3cb4d97b96af06robertphillips@google.com return true; 412f294b773f0b2b9f05eb45b52dd3cb4d97b96af06robertphillips@google.com} 413f294b773f0b2b9f05eb45b52dd3cb4d97b96af06robertphillips@google.com 4149853ccef19c200be93a6211f32589fa82a53067cjoshualittbool GrClipMaskManager::canStencilAndDrawElement(GrDrawState* drawState, 4159853ccef19c200be93a6211f32589fa82a53067cjoshualitt GrTexture* target, 4169853ccef19c200be93a6211f32589fa82a53067cjoshualitt GrPathRenderer** pr, 4179853ccef19c200be93a6211f32589fa82a53067cjoshualitt const SkClipStack::Element* element) { 418b68addd39f3e7183facc70374a133e7a6fb603c5bsalomon@google.com drawState->setRenderTarget(target->asRenderTarget()); 419b68addd39f3e7183facc70374a133e7a6fb603c5bsalomon@google.com 420e5b2af955b7d06815ddd405659ad62a2a8355ca3commit-bot@chromium.org if (Element::kRect_Type == element->getType()) { 421e5b2af955b7d06815ddd405659ad62a2a8355ca3commit-bot@chromium.org return true; 422e5b2af955b7d06815ddd405659ad62a2a8355ca3commit-bot@chromium.org } else { 423e5b2af955b7d06815ddd405659ad62a2a8355ca3commit-bot@chromium.org // We shouldn't get here with an empty clip element. 424e5b2af955b7d06815ddd405659ad62a2a8355ca3commit-bot@chromium.org SkASSERT(Element::kEmpty_Type != element->getType()); 425e5b2af955b7d06815ddd405659ad62a2a8355ca3commit-bot@chromium.org SkPath path; 426e5b2af955b7d06815ddd405659ad62a2a8355ca3commit-bot@chromium.org element->asPath(&path); 427e5b2af955b7d06815ddd405659ad62a2a8355ca3commit-bot@chromium.org if (path.isInverseFillType()) { 428e5b2af955b7d06815ddd405659ad62a2a8355ca3commit-bot@chromium.org path.toggleInverseFillType(); 429b68addd39f3e7183facc70374a133e7a6fb603c5bsalomon@google.com } 430e5b2af955b7d06815ddd405659ad62a2a8355ca3commit-bot@chromium.org SkStrokeRec stroke(SkStrokeRec::kFill_InitStyle); 431e5b2af955b7d06815ddd405659ad62a2a8355ca3commit-bot@chromium.org GrPathRendererChain::DrawType type = element->isAA() ? 432e5b2af955b7d06815ddd405659ad62a2a8355ca3commit-bot@chromium.org GrPathRendererChain::kStencilAndColorAntiAlias_DrawType : 433e5b2af955b7d06815ddd405659ad62a2a8355ca3commit-bot@chromium.org GrPathRendererChain::kStencilAndColor_DrawType; 4349853ccef19c200be93a6211f32589fa82a53067cjoshualitt *pr = this->getContext()->getPathRenderer(fClipTarget, drawState, path, stroke, false, 4359853ccef19c200be93a6211f32589fa82a53067cjoshualitt type); 43649f085dddff10473b6ebf832a974288300224e60bsalomon return SkToBool(*pr); 437b68addd39f3e7183facc70374a133e7a6fb603c5bsalomon@google.com } 438b68addd39f3e7183facc70374a133e7a6fb603c5bsalomon@google.com} 439b68addd39f3e7183facc70374a133e7a6fb603c5bsalomon@google.com 4409853ccef19c200be93a6211f32589fa82a53067cjoshualittvoid GrClipMaskManager::mergeMask(GrDrawState* drawState, 4419853ccef19c200be93a6211f32589fa82a53067cjoshualitt GrTexture* dstMask, 4427b7cdd147f5528865238e5ed98c79e6d319fde9bbsalomon@google.com GrTexture* srcMask, 4437b7cdd147f5528865238e5ed98c79e6d319fde9bbsalomon@google.com SkRegion::Op op, 444fd03d4a829efe2d77a712fd991927c55f59a2ffecommit-bot@chromium.org const SkIRect& dstBound, 445fd03d4a829efe2d77a712fd991927c55f59a2ffecommit-bot@chromium.org const SkIRect& srcBound) { 4469853ccef19c200be93a6211f32589fa82a53067cjoshualitt SkAssertResult(drawState->setIdentityViewMatrix()); 447f294b773f0b2b9f05eb45b52dd3cb4d97b96af06robertphillips@google.com 4487b7cdd147f5528865238e5ed98c79e6d319fde9bbsalomon@google.com drawState->setRenderTarget(dstMask->asRenderTarget()); 449f294b773f0b2b9f05eb45b52dd3cb4d97b96af06robertphillips@google.com 4509853ccef19c200be93a6211f32589fa82a53067cjoshualitt setup_boolean_blendcoeffs(op, drawState); 45172b2e6fff3f54c6aa80a98eab4c73f02a8cd450dskia.committer@gmail.com 452b9086a026844e4cfd08b219e49ce3f12294cba98bsalomon@google.com SkMatrix sampleM; 4537b7cdd147f5528865238e5ed98c79e6d319fde9bbsalomon@google.com sampleM.setIDiv(srcMask->width(), srcMask->height()); 454956b310f13c7412c035406c658ff16ca85eac656skia.committer@gmail.com 455b0a8a377f832c59cee939ad721e1f87d378b7142joshualitt drawState->addColorProcessor( 4567b7cdd147f5528865238e5ed98c79e6d319fde9bbsalomon@google.com GrTextureDomainEffect::Create(srcMask, 4577b7cdd147f5528865238e5ed98c79e6d319fde9bbsalomon@google.com sampleM, 458907fbd53c5e5dd4cbde7b72f9242b51febd7ef95commit-bot@chromium.org GrTextureDomain::MakeTexelDomain(srcMask, srcBound), 459907fbd53c5e5dd4cbde7b72f9242b51febd7ef95commit-bot@chromium.org GrTextureDomain::kDecal_Mode, 460b86add1ad37776818e1f730359ec587c9fdbff5fhumper@google.com GrTextureParams::kNone_FilterMode))->unref(); 4619853ccef19c200be93a6211f32589fa82a53067cjoshualitt fClipTarget->drawSimpleRect(drawState, SkRect::Make(dstBound)); 462f294b773f0b2b9f05eb45b52dd3cb4d97b96af06robertphillips@google.com} 463f294b773f0b2b9f05eb45b52dd3cb4d97b96af06robertphillips@google.com 464427cf28861867c0ea9aafca3a23878ec4068ad99bsalomonGrTexture* GrClipMaskManager::createTempMask(int width, int height) { 465f2703d83da3ab2ae18b45231fd4f11e16cce3184bsalomon GrSurfaceDesc desc; 466f2703d83da3ab2ae18b45231fd4f11e16cce3184bsalomon desc.fFlags = kRenderTarget_GrSurfaceFlag|kNoStencil_GrSurfaceFlag; 4674c2443e36fdc6c095b17e90baa4a2f26a6f00b08bsalomon@google.com desc.fWidth = width; 4684c2443e36fdc6c095b17e90baa4a2f26a6f00b08bsalomon@google.com desc.fHeight = height; 46975b3c9633cb9a594dab0ccf51dab1e694c149a18robertphillips@google.com desc.fConfig = kAlpha_8_GrPixelConfig; 4706b70a7bd3328ea0a12be47b1a7f835c905f16147robertphillips@google.com 471329bf4862e9d5e05363c2b071d8ca475a0ef1952joshualitt return this->getContext()->refScratchTexture(desc, GrContext::kApprox_ScratchTexMatch); 4726d62df404bf420bedff4d7b5edd061740a673d44robertphillips@google.com} 4736d62df404bf420bedff4d7b5edd061740a673d44robertphillips@google.com 4746b70a7bd3328ea0a12be47b1a7f835c905f16147robertphillips@google.com//////////////////////////////////////////////////////////////////////////////// 475ad1dc589cef8aebf7e14672ffdaa31c6d399675dkrajcevski// Return the texture currently in the cache if it exists. Otherwise, return NULL 476ad1dc589cef8aebf7e14672ffdaa31c6d399675dkrajcevskiGrTexture* GrClipMaskManager::getCachedMaskTexture(int32_t elementsGenID, 477ad1dc589cef8aebf7e14672ffdaa31c6d399675dkrajcevski const SkIRect& clipSpaceIBounds) { 478d3e5842db0cb169e10d6da1e62c94ba5cf182bb4commit-bot@chromium.org bool cached = fAACache.canReuse(elementsGenID, clipSpaceIBounds); 4794c2443e36fdc6c095b17e90baa4a2f26a6f00b08bsalomon@google.com if (!cached) { 480ad1dc589cef8aebf7e14672ffdaa31c6d399675dkrajcevski return NULL; 481ad1dc589cef8aebf7e14672ffdaa31c6d399675dkrajcevski } 4824c2443e36fdc6c095b17e90baa4a2f26a6f00b08bsalomon@google.com 483ad1dc589cef8aebf7e14672ffdaa31c6d399675dkrajcevski return fAACache.getLastMask(); 484ad1dc589cef8aebf7e14672ffdaa31c6d399675dkrajcevski} 485f294b773f0b2b9f05eb45b52dd3cb4d97b96af06robertphillips@google.com 486ad1dc589cef8aebf7e14672ffdaa31c6d399675dkrajcevski//////////////////////////////////////////////////////////////////////////////// 487ad1dc589cef8aebf7e14672ffdaa31c6d399675dkrajcevski// Allocate a texture in the texture cache. This function returns the texture 488ad1dc589cef8aebf7e14672ffdaa31c6d399675dkrajcevski// allocated (or NULL on error). 489ad1dc589cef8aebf7e14672ffdaa31c6d399675dkrajcevskiGrTexture* GrClipMaskManager::allocMaskTexture(int32_t elementsGenID, 490ad1dc589cef8aebf7e14672ffdaa31c6d399675dkrajcevski const SkIRect& clipSpaceIBounds, 491ad1dc589cef8aebf7e14672ffdaa31c6d399675dkrajcevski bool willUpload) { 492ad1dc589cef8aebf7e14672ffdaa31c6d399675dkrajcevski // Since we are setting up the cache we should free up the 493ad1dc589cef8aebf7e14672ffdaa31c6d399675dkrajcevski // currently cached mask so it can be reused. 494ad1dc589cef8aebf7e14672ffdaa31c6d399675dkrajcevski fAACache.reset(); 495a72eef322c686954cdffa849dc26d8133b802f1drobertphillips@google.com 496f2703d83da3ab2ae18b45231fd4f11e16cce3184bsalomon GrSurfaceDesc desc; 497f2703d83da3ab2ae18b45231fd4f11e16cce3184bsalomon desc.fFlags = willUpload ? kNone_GrSurfaceFlags : kRenderTarget_GrSurfaceFlag; 498ad1dc589cef8aebf7e14672ffdaa31c6d399675dkrajcevski desc.fWidth = clipSpaceIBounds.width(); 499ad1dc589cef8aebf7e14672ffdaa31c6d399675dkrajcevski desc.fHeight = clipSpaceIBounds.height(); 500ad1dc589cef8aebf7e14672ffdaa31c6d399675dkrajcevski desc.fConfig = kRGBA_8888_GrPixelConfig; 501ad1dc589cef8aebf7e14672ffdaa31c6d399675dkrajcevski if (willUpload || this->getContext()->isConfigRenderable(kAlpha_8_GrPixelConfig, false)) { 502ad1dc589cef8aebf7e14672ffdaa31c6d399675dkrajcevski // We would always like A8 but it isn't supported on all platforms 503ad1dc589cef8aebf7e14672ffdaa31c6d399675dkrajcevski desc.fConfig = kAlpha_8_GrPixelConfig; 5048fff356c8505f2ac78e1fc9dc17c1192e3a608e4robertphillips@google.com } 5058fff356c8505f2ac78e1fc9dc17c1192e3a608e4robertphillips@google.com 506ad1dc589cef8aebf7e14672ffdaa31c6d399675dkrajcevski fAACache.acquireMask(elementsGenID, desc, clipSpaceIBounds); 507ad1dc589cef8aebf7e14672ffdaa31c6d399675dkrajcevski return fAACache.getLastMask(); 5086b70a7bd3328ea0a12be47b1a7f835c905f16147robertphillips@google.com} 509f294b773f0b2b9f05eb45b52dd3cb4d97b96af06robertphillips@google.com 5106b70a7bd3328ea0a12be47b1a7f835c905f16147robertphillips@google.com//////////////////////////////////////////////////////////////////////////////// 5116b70a7bd3328ea0a12be47b1a7f835c905f16147robertphillips@google.com// Create a 8-bit clip mask in alpha 512d3e5842db0cb169e10d6da1e62c94ba5cf182bb4commit-bot@chromium.orgGrTexture* GrClipMaskManager::createAlphaClipMask(int32_t elementsGenID, 513bf54e49e30cdc92f9ce3f336cc48cf6b236ddeabtfarina GrReducedClip::InitialState initialState, 514bf54e49e30cdc92f9ce3f336cc48cf6b236ddeabtfarina const GrReducedClip::ElementList& elements, 5154c2443e36fdc6c095b17e90baa4a2f26a6f00b08bsalomon@google.com const SkIRect& clipSpaceIBounds) { 516f6de475e5cbd143f348ff7738919e397b7fe7f57tfarina@chromium.org SkASSERT(kNone_ClipMaskType == fCurrClipMaskType); 517c8f7f47afaf8f9471e6d111655c5610a8bd210a2bsalomon@google.com 518ad1dc589cef8aebf7e14672ffdaa31c6d399675dkrajcevski // First, check for cached texture 519ad1dc589cef8aebf7e14672ffdaa31c6d399675dkrajcevski GrTexture* result = this->getCachedMaskTexture(elementsGenID, clipSpaceIBounds); 52049f085dddff10473b6ebf832a974288300224e60bsalomon if (result) { 521c8f7f47afaf8f9471e6d111655c5610a8bd210a2bsalomon@google.com fCurrClipMaskType = kAlpha_ClipMaskType; 5224c2443e36fdc6c095b17e90baa4a2f26a6f00b08bsalomon@google.com return result; 5236b70a7bd3328ea0a12be47b1a7f835c905f16147robertphillips@google.com } 524f294b773f0b2b9f05eb45b52dd3cb4d97b96af06robertphillips@google.com 525ad1dc589cef8aebf7e14672ffdaa31c6d399675dkrajcevski // There's no texture in the cache. Let's try to allocate it then. 526ad1dc589cef8aebf7e14672ffdaa31c6d399675dkrajcevski result = this->allocMaskTexture(elementsGenID, clipSpaceIBounds, false); 5274c2443e36fdc6c095b17e90baa4a2f26a6f00b08bsalomon@google.com if (NULL == result) { 528f105b109264f71dfb0bfd9977e6a5dd0a5a12f57robertphillips@google.com fAACache.reset(); 5294c2443e36fdc6c095b17e90baa4a2f26a6f00b08bsalomon@google.com return NULL; 530f294b773f0b2b9f05eb45b52dd3cb4d97b96af06robertphillips@google.com } 531f294b773f0b2b9f05eb45b52dd3cb4d97b96af06robertphillips@google.com 5324c2443e36fdc6c095b17e90baa4a2f26a6f00b08bsalomon@google.com // The top-left of the mask corresponds to the top-left corner of the bounds. 5337b7cdd147f5528865238e5ed98c79e6d319fde9bbsalomon@google.com SkVector clipToMaskOffset = { 5344c2443e36fdc6c095b17e90baa4a2f26a6f00b08bsalomon@google.com SkIntToScalar(-clipSpaceIBounds.fLeft), 5354c2443e36fdc6c095b17e90baa4a2f26a6f00b08bsalomon@google.com SkIntToScalar(-clipSpaceIBounds.fTop) 5367b7cdd147f5528865238e5ed98c79e6d319fde9bbsalomon@google.com }; 5374c2443e36fdc6c095b17e90baa4a2f26a6f00b08bsalomon@google.com // The texture may be larger than necessary, this rect represents the part of the texture 5384c2443e36fdc6c095b17e90baa4a2f26a6f00b08bsalomon@google.com // we populate with a rasterization of the clip. 5394c2443e36fdc6c095b17e90baa4a2f26a6f00b08bsalomon@google.com SkIRect maskSpaceIBounds = SkIRect::MakeWH(clipSpaceIBounds.width(), clipSpaceIBounds.height()); 540f294b773f0b2b9f05eb45b52dd3cb4d97b96af06robertphillips@google.com 541137f1347abaf0bb6a945e91c2f6cb49f0ee69bc3bsalomon@google.com // Set the matrix so that rendered clip elements are transformed to mask space from clip space. 542137f1347abaf0bb6a945e91c2f6cb49f0ee69bc3bsalomon@google.com SkMatrix translate; 543137f1347abaf0bb6a945e91c2f6cb49f0ee69bc3bsalomon@google.com translate.setTranslate(clipToMaskOffset); 544cf939ae54842fc7408ee68a41427086962b4c3dcbsalomon@google.com 5457b7cdd147f5528865238e5ed98c79e6d319fde9bbsalomon@google.com // The scratch texture that we are drawing into can be substantially larger than the mask. Only 5467b7cdd147f5528865238e5ed98c79e6d319fde9bbsalomon@google.com // clear the part that we care about. 547329bf4862e9d5e05363c2b071d8ca475a0ef1952joshualitt fClipTarget->clear(&maskSpaceIBounds, 548329bf4862e9d5e05363c2b071d8ca475a0ef1952joshualitt GrReducedClip::kAllIn_InitialState == initialState ? 0xffffffff : 0x00000000, 549329bf4862e9d5e05363c2b071d8ca475a0ef1952joshualitt true, 550329bf4862e9d5e05363c2b071d8ca475a0ef1952joshualitt result->asRenderTarget()); 551d9f7503e0cb0c4db856f53b4bdeec1332db6f296skia.committer@gmail.com 552b68addd39f3e7183facc70374a133e7a6fb603c5bsalomon@google.com // When we use the stencil in the below loop it is important to have this clip installed. 553b68addd39f3e7183facc70374a133e7a6fb603c5bsalomon@google.com // The second pass that zeros the stencil buffer renders the rect maskSpaceIBounds so the first 554b68addd39f3e7183facc70374a133e7a6fb603c5bsalomon@google.com // pass must not set values outside of this bounds or stencil values outside the rect won't be 555b68addd39f3e7183facc70374a133e7a6fb603c5bsalomon@google.com // cleared. 556329bf4862e9d5e05363c2b071d8ca475a0ef1952joshualitt GrDrawTarget::AutoClipRestore acr(fClipTarget, maskSpaceIBounds); 557427cf28861867c0ea9aafca3a23878ec4068ad99bsalomon SkAutoTUnref<GrTexture> temp; 5589853ccef19c200be93a6211f32589fa82a53067cjoshualitt 559f294b773f0b2b9f05eb45b52dd3cb4d97b96af06robertphillips@google.com // walk through each clip element and perform its set op 560bf54e49e30cdc92f9ce3f336cc48cf6b236ddeabtfarina for (GrReducedClip::ElementList::Iter iter = elements.headIter(); iter.get(); iter.next()) { 5614c2443e36fdc6c095b17e90baa4a2f26a6f00b08bsalomon@google.com const Element* element = iter.get(); 5628182fa0cac76e7e6d583aebba060229230516887bsalomon@google.com SkRegion::Op op = element->getOp(); 563b68addd39f3e7183facc70374a133e7a6fb603c5bsalomon@google.com bool invert = element->isInverseFilled(); 564b68addd39f3e7183facc70374a133e7a6fb603c5bsalomon@google.com if (invert || SkRegion::kIntersect_Op == op || SkRegion::kReverseDifference_Op == op) { 5659853ccef19c200be93a6211f32589fa82a53067cjoshualitt GrDrawState drawState(translate); 5669853ccef19c200be93a6211f32589fa82a53067cjoshualitt // We're drawing a coverage mask and want coverage to be run through the blend function. 5679853ccef19c200be93a6211f32589fa82a53067cjoshualitt drawState.enableState(GrDrawState::kCoverageDrawing_StateBit | 5689853ccef19c200be93a6211f32589fa82a53067cjoshualitt GrDrawState::kClip_StateBit); 5699853ccef19c200be93a6211f32589fa82a53067cjoshualitt 570e79f320ed6c5ec9f6164ba84be1ff586532e6517robertphillips@google.com GrPathRenderer* pr = NULL; 5719853ccef19c200be93a6211f32589fa82a53067cjoshualitt bool useTemp = !this->canStencilAndDrawElement(&drawState, result, &pr, element); 572b68addd39f3e7183facc70374a133e7a6fb603c5bsalomon@google.com GrTexture* dst; 5734c2443e36fdc6c095b17e90baa4a2f26a6f00b08bsalomon@google.com // This is the bounds of the clip element in the space of the alpha-mask. The temporary 5747b7cdd147f5528865238e5ed98c79e6d319fde9bbsalomon@google.com // mask buffer can be substantially larger than the actually clip stack element. We 5757b7cdd147f5528865238e5ed98c79e6d319fde9bbsalomon@google.com // touch the minimum number of pixels necessary and use decal mode to combine it with 576b68addd39f3e7183facc70374a133e7a6fb603c5bsalomon@google.com // the accumulator. 577fd03d4a829efe2d77a712fd991927c55f59a2ffecommit-bot@chromium.org SkIRect maskSpaceElementIBounds; 578b68addd39f3e7183facc70374a133e7a6fb603c5bsalomon@google.com 579b68addd39f3e7183facc70374a133e7a6fb603c5bsalomon@google.com if (useTemp) { 580b68addd39f3e7183facc70374a133e7a6fb603c5bsalomon@google.com if (invert) { 581b68addd39f3e7183facc70374a133e7a6fb603c5bsalomon@google.com maskSpaceElementIBounds = maskSpaceIBounds; 582b68addd39f3e7183facc70374a133e7a6fb603c5bsalomon@google.com } else { 583fd03d4a829efe2d77a712fd991927c55f59a2ffecommit-bot@chromium.org SkRect elementBounds = element->getBounds(); 584b68addd39f3e7183facc70374a133e7a6fb603c5bsalomon@google.com elementBounds.offset(clipToMaskOffset); 585b68addd39f3e7183facc70374a133e7a6fb603c5bsalomon@google.com elementBounds.roundOut(&maskSpaceElementIBounds); 586b68addd39f3e7183facc70374a133e7a6fb603c5bsalomon@google.com } 587b68addd39f3e7183facc70374a133e7a6fb603c5bsalomon@google.com 588427cf28861867c0ea9aafca3a23878ec4068ad99bsalomon if (!temp) { 589427cf28861867c0ea9aafca3a23878ec4068ad99bsalomon temp.reset(this->createTempMask(maskSpaceIBounds.fRight, 590427cf28861867c0ea9aafca3a23878ec4068ad99bsalomon maskSpaceIBounds.fBottom)); 591427cf28861867c0ea9aafca3a23878ec4068ad99bsalomon if (!temp) { 592427cf28861867c0ea9aafca3a23878ec4068ad99bsalomon fAACache.reset(); 593427cf28861867c0ea9aafca3a23878ec4068ad99bsalomon return NULL; 594427cf28861867c0ea9aafca3a23878ec4068ad99bsalomon } 595a7aedfec9e28db36c97e49f11f2bc2e0eb624c30skia.committer@gmail.com } 596427cf28861867c0ea9aafca3a23878ec4068ad99bsalomon dst = temp; 597b68addd39f3e7183facc70374a133e7a6fb603c5bsalomon@google.com // clear the temp target and set blend to replace 598329bf4862e9d5e05363c2b071d8ca475a0ef1952joshualitt fClipTarget->clear(&maskSpaceElementIBounds, 5999853ccef19c200be93a6211f32589fa82a53067cjoshualitt invert ? 0xffffffff : 0x00000000, 6009853ccef19c200be93a6211f32589fa82a53067cjoshualitt true, 6019853ccef19c200be93a6211f32589fa82a53067cjoshualitt dst->asRenderTarget()); 6029853ccef19c200be93a6211f32589fa82a53067cjoshualitt setup_boolean_blendcoeffs(SkRegion::kReplace_Op, &drawState); 6034c2443e36fdc6c095b17e90baa4a2f26a6f00b08bsalomon@google.com } else { 604b68addd39f3e7183facc70374a133e7a6fb603c5bsalomon@google.com // draw directly into the result with the stencil set to make the pixels affected 605b68addd39f3e7183facc70374a133e7a6fb603c5bsalomon@google.com // by the clip shape be non-zero. 606b68addd39f3e7183facc70374a133e7a6fb603c5bsalomon@google.com dst = result; 607b68addd39f3e7183facc70374a133e7a6fb603c5bsalomon@google.com GR_STATIC_CONST_SAME_STENCIL(kStencilInElement, 608b68addd39f3e7183facc70374a133e7a6fb603c5bsalomon@google.com kReplace_StencilOp, 609b68addd39f3e7183facc70374a133e7a6fb603c5bsalomon@google.com kReplace_StencilOp, 610b68addd39f3e7183facc70374a133e7a6fb603c5bsalomon@google.com kAlways_StencilFunc, 611b68addd39f3e7183facc70374a133e7a6fb603c5bsalomon@google.com 0xffff, 612b68addd39f3e7183facc70374a133e7a6fb603c5bsalomon@google.com 0xffff, 613b68addd39f3e7183facc70374a133e7a6fb603c5bsalomon@google.com 0xffff); 6149853ccef19c200be93a6211f32589fa82a53067cjoshualitt drawState.setStencil(kStencilInElement); 6159853ccef19c200be93a6211f32589fa82a53067cjoshualitt setup_boolean_blendcoeffs(op, &drawState); 6164c2443e36fdc6c095b17e90baa4a2f26a6f00b08bsalomon@google.com } 6177b7cdd147f5528865238e5ed98c79e6d319fde9bbsalomon@google.com 6189853ccef19c200be93a6211f32589fa82a53067cjoshualitt drawState.setAlpha(invert ? 0x00 : 0xff); 619c6b3e48cb3a22d83ba3f4b9a614a5a35b05958a0bsalomon@google.com 6209853ccef19c200be93a6211f32589fa82a53067cjoshualitt // We have to backup the drawstate because the drawElement call may call into 6219853ccef19c200be93a6211f32589fa82a53067cjoshualitt // renderers which consume it. 6229853ccef19c200be93a6211f32589fa82a53067cjoshualitt GrDrawState backupDrawState(drawState); 6239853ccef19c200be93a6211f32589fa82a53067cjoshualitt 6249853ccef19c200be93a6211f32589fa82a53067cjoshualitt if (!this->drawElement(&drawState, dst, element, pr)) { 625e79f320ed6c5ec9f6164ba84be1ff586532e6517robertphillips@google.com fAACache.reset(); 626e79f320ed6c5ec9f6164ba84be1ff586532e6517robertphillips@google.com return NULL; 6274c2443e36fdc6c095b17e90baa4a2f26a6f00b08bsalomon@google.com } 628f294b773f0b2b9f05eb45b52dd3cb4d97b96af06robertphillips@google.com 629b68addd39f3e7183facc70374a133e7a6fb603c5bsalomon@google.com if (useTemp) { 630b68addd39f3e7183facc70374a133e7a6fb603c5bsalomon@google.com // Now draw into the accumulator using the real operation and the temp buffer as a 631b68addd39f3e7183facc70374a133e7a6fb603c5bsalomon@google.com // texture 6329853ccef19c200be93a6211f32589fa82a53067cjoshualitt this->mergeMask(&backupDrawState, 6339853ccef19c200be93a6211f32589fa82a53067cjoshualitt result, 634427cf28861867c0ea9aafca3a23878ec4068ad99bsalomon temp, 635b68addd39f3e7183facc70374a133e7a6fb603c5bsalomon@google.com op, 636b68addd39f3e7183facc70374a133e7a6fb603c5bsalomon@google.com maskSpaceIBounds, 637b68addd39f3e7183facc70374a133e7a6fb603c5bsalomon@google.com maskSpaceElementIBounds); 638b68addd39f3e7183facc70374a133e7a6fb603c5bsalomon@google.com } else { 639b68addd39f3e7183facc70374a133e7a6fb603c5bsalomon@google.com // Draw to the exterior pixels (those with a zero stencil value). 6409853ccef19c200be93a6211f32589fa82a53067cjoshualitt backupDrawState.setAlpha(invert ? 0xff : 0x00); 641b68addd39f3e7183facc70374a133e7a6fb603c5bsalomon@google.com GR_STATIC_CONST_SAME_STENCIL(kDrawOutsideElement, 642b68addd39f3e7183facc70374a133e7a6fb603c5bsalomon@google.com kZero_StencilOp, 643b68addd39f3e7183facc70374a133e7a6fb603c5bsalomon@google.com kZero_StencilOp, 644b68addd39f3e7183facc70374a133e7a6fb603c5bsalomon@google.com kEqual_StencilFunc, 645b68addd39f3e7183facc70374a133e7a6fb603c5bsalomon@google.com 0xffff, 646b68addd39f3e7183facc70374a133e7a6fb603c5bsalomon@google.com 0x0000, 647b68addd39f3e7183facc70374a133e7a6fb603c5bsalomon@google.com 0xffff); 6489853ccef19c200be93a6211f32589fa82a53067cjoshualitt backupDrawState.setStencil(kDrawOutsideElement); 6499853ccef19c200be93a6211f32589fa82a53067cjoshualitt fClipTarget->drawSimpleRect(&backupDrawState, clipSpaceIBounds); 650b68addd39f3e7183facc70374a133e7a6fb603c5bsalomon@google.com } 651f294b773f0b2b9f05eb45b52dd3cb4d97b96af06robertphillips@google.com } else { 6529853ccef19c200be93a6211f32589fa82a53067cjoshualitt GrDrawState drawState(translate); 6539853ccef19c200be93a6211f32589fa82a53067cjoshualitt drawState.enableState(GrDrawState::kCoverageDrawing_StateBit | 6549853ccef19c200be93a6211f32589fa82a53067cjoshualitt GrDrawState::kClip_StateBit); 6559853ccef19c200be93a6211f32589fa82a53067cjoshualitt 656e79f320ed6c5ec9f6164ba84be1ff586532e6517robertphillips@google.com // all the remaining ops can just be directly draw into the accumulation buffer 6579853ccef19c200be93a6211f32589fa82a53067cjoshualitt drawState.setAlpha(0xff); 6589853ccef19c200be93a6211f32589fa82a53067cjoshualitt setup_boolean_blendcoeffs(op, &drawState); 6599853ccef19c200be93a6211f32589fa82a53067cjoshualitt this->drawElement(&drawState, result, element); 660f294b773f0b2b9f05eb45b52dd3cb4d97b96af06robertphillips@google.com } 661f294b773f0b2b9f05eb45b52dd3cb4d97b96af06robertphillips@google.com } 662f294b773f0b2b9f05eb45b52dd3cb4d97b96af06robertphillips@google.com 663c8f7f47afaf8f9471e6d111655c5610a8bd210a2bsalomon@google.com fCurrClipMaskType = kAlpha_ClipMaskType; 6644c2443e36fdc6c095b17e90baa4a2f26a6f00b08bsalomon@google.com return result; 6651e945b7e708c633d4aed937ebfce57d52ba21d83robertphillips@google.com} 6661e945b7e708c633d4aed937ebfce57d52ba21d83robertphillips@google.com 667f294b773f0b2b9f05eb45b52dd3cb4d97b96af06robertphillips@google.com//////////////////////////////////////////////////////////////////////////////// 668fbfcd5602128ec010c82cb733c9cdc0a3254f9f3rmistry@google.com// Create a 1-bit clip mask in the stencil buffer. 'devClipBounds' are in device 669f8d904a7eed435b9de68fd2eef6d7f3c59fcc9ccrobertphillips@google.com// (as opposed to canvas) coordinates 6709853ccef19c200be93a6211f32589fa82a53067cjoshualittbool GrClipMaskManager::createStencilClipMask(GrRenderTarget* rt, 6719853ccef19c200be93a6211f32589fa82a53067cjoshualitt int32_t elementsGenID, 672bf54e49e30cdc92f9ce3f336cc48cf6b236ddeabtfarina GrReducedClip::InitialState initialState, 673bf54e49e30cdc92f9ce3f336cc48cf6b236ddeabtfarina const GrReducedClip::ElementList& elements, 6744c2443e36fdc6c095b17e90baa4a2f26a6f00b08bsalomon@google.com const SkIRect& clipSpaceIBounds, 6754c2443e36fdc6c095b17e90baa4a2f26a6f00b08bsalomon@google.com const SkIPoint& clipSpaceToStencilOffset) { 676f6de475e5cbd143f348ff7738919e397b7fe7f57tfarina@chromium.org SkASSERT(kNone_ClipMaskType == fCurrClipMaskType); 67749f085dddff10473b6ebf832a974288300224e60bsalomon SkASSERT(rt); 6781e945b7e708c633d4aed937ebfce57d52ba21d83robertphillips@google.com 6791e945b7e708c633d4aed937ebfce57d52ba21d83robertphillips@google.com // TODO: dynamically attach a SB when needed. 6801e945b7e708c633d4aed937ebfce57d52ba21d83robertphillips@google.com GrStencilBuffer* stencilBuffer = rt->getStencilBuffer(); 6811e945b7e708c633d4aed937ebfce57d52ba21d83robertphillips@google.com if (NULL == stencilBuffer) { 6821e945b7e708c633d4aed937ebfce57d52ba21d83robertphillips@google.com return false; 6831e945b7e708c633d4aed937ebfce57d52ba21d83robertphillips@google.com } 6841e945b7e708c633d4aed937ebfce57d52ba21d83robertphillips@google.com 685d3e5842db0cb169e10d6da1e62c94ba5cf182bb4commit-bot@chromium.org if (stencilBuffer->mustRenderClip(elementsGenID, clipSpaceIBounds, clipSpaceToStencilOffset)) { 686d3e5842db0cb169e10d6da1e62c94ba5cf182bb4commit-bot@chromium.org stencilBuffer->setLastClip(elementsGenID, clipSpaceIBounds, clipSpaceToStencilOffset); 687137f1347abaf0bb6a945e91c2f6cb49f0ee69bc3bsalomon@google.com // Set the matrix so that rendered clip elements are transformed from clip to stencil space. 688137f1347abaf0bb6a945e91c2f6cb49f0ee69bc3bsalomon@google.com SkVector translate = { 689137f1347abaf0bb6a945e91c2f6cb49f0ee69bc3bsalomon@google.com SkIntToScalar(clipSpaceToStencilOffset.fX), 690137f1347abaf0bb6a945e91c2f6cb49f0ee69bc3bsalomon@google.com SkIntToScalar(clipSpaceToStencilOffset.fY) 691137f1347abaf0bb6a945e91c2f6cb49f0ee69bc3bsalomon@google.com }; 692137f1347abaf0bb6a945e91c2f6cb49f0ee69bc3bsalomon@google.com SkMatrix matrix; 693137f1347abaf0bb6a945e91c2f6cb49f0ee69bc3bsalomon@google.com matrix.setTranslate(translate); 6941e945b7e708c633d4aed937ebfce57d52ba21d83robertphillips@google.com 6959f13174da5295e88d447f29740318003b9cec9c3bsalomon@google.com // We set the current clip to the bounds so that our recursive draws are scissored to them. 6969f13174da5295e88d447f29740318003b9cec9c3bsalomon@google.com SkIRect stencilSpaceIBounds(clipSpaceIBounds); 6979f13174da5295e88d447f29740318003b9cec9c3bsalomon@google.com stencilSpaceIBounds.offset(clipSpaceToStencilOffset); 698329bf4862e9d5e05363c2b071d8ca475a0ef1952joshualitt GrDrawTarget::AutoClipRestore acr(fClipTarget, stencilSpaceIBounds); 6991e945b7e708c633d4aed937ebfce57d52ba21d83robertphillips@google.com 7001e945b7e708c633d4aed937ebfce57d52ba21d83robertphillips@google.com int clipBit = stencilBuffer->bits(); 7014c2443e36fdc6c095b17e90baa4a2f26a6f00b08bsalomon@google.com SkASSERT((clipBit <= 16) && "Ganesh only handles 16b or smaller stencil buffers"); 7021e945b7e708c633d4aed937ebfce57d52ba21d83robertphillips@google.com clipBit = (1 << (clipBit-1)); 7031e945b7e708c633d4aed937ebfce57d52ba21d83robertphillips@google.com 704329bf4862e9d5e05363c2b071d8ca475a0ef1952joshualitt fClipTarget->clearStencilClip(stencilSpaceIBounds, 705329bf4862e9d5e05363c2b071d8ca475a0ef1952joshualitt GrReducedClip::kAllIn_InitialState == initialState, 706329bf4862e9d5e05363c2b071d8ca475a0ef1952joshualitt rt); 7071e945b7e708c633d4aed937ebfce57d52ba21d83robertphillips@google.com 7081e945b7e708c633d4aed937ebfce57d52ba21d83robertphillips@google.com // walk through each clip element and perform its set op 7091e945b7e708c633d4aed937ebfce57d52ba21d83robertphillips@google.com // with the existing clip. 710bf54e49e30cdc92f9ce3f336cc48cf6b236ddeabtfarina for (GrReducedClip::ElementList::Iter iter(elements.headIter()); iter.get(); iter.next()) { 7114c2443e36fdc6c095b17e90baa4a2f26a6f00b08bsalomon@google.com const Element* element = iter.get(); 7129853ccef19c200be93a6211f32589fa82a53067cjoshualitt 7139853ccef19c200be93a6211f32589fa82a53067cjoshualitt GrDrawState drawState(matrix); 7149853ccef19c200be93a6211f32589fa82a53067cjoshualitt drawState.setRenderTarget(rt); 7159853ccef19c200be93a6211f32589fa82a53067cjoshualitt drawState.enableState(GrDrawState::kClip_StateBit); 7169853ccef19c200be93a6211f32589fa82a53067cjoshualitt drawState.enableState(GrDrawState::kNoColorWrites_StateBit); 7179853ccef19c200be93a6211f32589fa82a53067cjoshualitt 718ded4f4b163f5aa19c22c871178c55ecb34623846bsalomon@google.com // if the target is MSAA then we want MSAA enabled when the clip is soft 719ded4f4b163f5aa19c22c871178c55ecb34623846bsalomon@google.com if (rt->isMultisampled()) { 7209853ccef19c200be93a6211f32589fa82a53067cjoshualitt drawState.setState(GrDrawState::kHWAntialias_StateBit, element->isAA()); 721ded4f4b163f5aa19c22c871178c55ecb34623846bsalomon@google.com } 7221e945b7e708c633d4aed937ebfce57d52ba21d83robertphillips@google.com 7239853ccef19c200be93a6211f32589fa82a53067cjoshualitt bool fillInverted = false; 7249853ccef19c200be93a6211f32589fa82a53067cjoshualitt // enabled at bottom of loop 7259853ccef19c200be93a6211f32589fa82a53067cjoshualitt fClipMode = kIgnoreClip_StencilClipMode; 7269853ccef19c200be93a6211f32589fa82a53067cjoshualitt 72745a15f551b5b3c6c747d8eaf6466b7d3b76a8faebsalomon@google.com // This will be used to determine whether the clip shape can be rendered into the 72845a15f551b5b3c6c747d8eaf6466b7d3b76a8faebsalomon@google.com // stencil with arbitrary stencil settings. 72945a15f551b5b3c6c747d8eaf6466b7d3b76a8faebsalomon@google.com GrPathRenderer::StencilSupport stencilSupport; 7301e945b7e708c633d4aed937ebfce57d52ba21d83robertphillips@google.com 7315f74cf8c49701f514b69dc6f1a8b5c0ffd78af0asugoi@google.com SkStrokeRec stroke(SkStrokeRec::kFill_InitStyle); 7328182fa0cac76e7e6d583aebba060229230516887bsalomon@google.com SkRegion::Op op = element->getOp(); 733f294b773f0b2b9f05eb45b52dd3cb4d97b96af06robertphillips@google.com 734e79f320ed6c5ec9f6164ba84be1ff586532e6517robertphillips@google.com GrPathRenderer* pr = NULL; 735e5b2af955b7d06815ddd405659ad62a2a8355ca3commit-bot@chromium.org SkPath clipPath; 7368182fa0cac76e7e6d583aebba060229230516887bsalomon@google.com if (Element::kRect_Type == element->getType()) { 73745a15f551b5b3c6c747d8eaf6466b7d3b76a8faebsalomon@google.com stencilSupport = GrPathRenderer::kNoRestriction_StencilSupport; 7381e945b7e708c633d4aed937ebfce57d52ba21d83robertphillips@google.com fillInverted = false; 7398afae61a57f87e4a50578effce6c428031499301tomhudson@google.com } else { 740e5b2af955b7d06815ddd405659ad62a2a8355ca3commit-bot@chromium.org element->asPath(&clipPath); 741e5b2af955b7d06815ddd405659ad62a2a8355ca3commit-bot@chromium.org fillInverted = clipPath.isInverseFillType(); 742e79f320ed6c5ec9f6164ba84be1ff586532e6517robertphillips@google.com if (fillInverted) { 743e5b2af955b7d06815ddd405659ad62a2a8355ca3commit-bot@chromium.org clipPath.toggleInverseFillType(); 744e79f320ed6c5ec9f6164ba84be1ff586532e6517robertphillips@google.com } 7459853ccef19c200be93a6211f32589fa82a53067cjoshualitt pr = this->getContext()->getPathRenderer(fClipTarget, 7469853ccef19c200be93a6211f32589fa82a53067cjoshualitt &drawState, 7479853ccef19c200be93a6211f32589fa82a53067cjoshualitt clipPath, 74845a15f551b5b3c6c747d8eaf6466b7d3b76a8faebsalomon@google.com stroke, 74945a15f551b5b3c6c747d8eaf6466b7d3b76a8faebsalomon@google.com false, 75045a15f551b5b3c6c747d8eaf6466b7d3b76a8faebsalomon@google.com GrPathRendererChain::kStencilOnly_DrawType, 751e79f320ed6c5ec9f6164ba84be1ff586532e6517robertphillips@google.com &stencilSupport); 752e79f320ed6c5ec9f6164ba84be1ff586532e6517robertphillips@google.com if (NULL == pr) { 7531e945b7e708c633d4aed937ebfce57d52ba21d83robertphillips@google.com return false; 7541e945b7e708c633d4aed937ebfce57d52ba21d83robertphillips@google.com } 7551e945b7e708c633d4aed937ebfce57d52ba21d83robertphillips@google.com } 7561e945b7e708c633d4aed937ebfce57d52ba21d83robertphillips@google.com 7571e945b7e708c633d4aed937ebfce57d52ba21d83robertphillips@google.com int passes; 7581e945b7e708c633d4aed937ebfce57d52ba21d83robertphillips@google.com GrStencilSettings stencilSettings[GrStencilSettings::kMaxStencilClipPasses]; 7591e945b7e708c633d4aed937ebfce57d52ba21d83robertphillips@google.com 76045a15f551b5b3c6c747d8eaf6466b7d3b76a8faebsalomon@google.com bool canRenderDirectToStencil = 76145a15f551b5b3c6c747d8eaf6466b7d3b76a8faebsalomon@google.com GrPathRenderer::kNoRestriction_StencilSupport == stencilSupport; 7621e945b7e708c633d4aed937ebfce57d52ba21d83robertphillips@google.com bool canDrawDirectToClip; // Given the renderer, the element, 7634c2443e36fdc6c095b17e90baa4a2f26a6f00b08bsalomon@google.com // fill rule, and set operation can 7644c2443e36fdc6c095b17e90baa4a2f26a6f00b08bsalomon@google.com // we render the element directly to 7654c2443e36fdc6c095b17e90baa4a2f26a6f00b08bsalomon@google.com // stencil bit used for clipping. 7664c2443e36fdc6c095b17e90baa4a2f26a6f00b08bsalomon@google.com canDrawDirectToClip = GrStencilSettings::GetClipPasses(op, 7674c2443e36fdc6c095b17e90baa4a2f26a6f00b08bsalomon@google.com canRenderDirectToStencil, 7684c2443e36fdc6c095b17e90baa4a2f26a6f00b08bsalomon@google.com clipBit, 7694c2443e36fdc6c095b17e90baa4a2f26a6f00b08bsalomon@google.com fillInverted, 7704c2443e36fdc6c095b17e90baa4a2f26a6f00b08bsalomon@google.com &passes, 7714c2443e36fdc6c095b17e90baa4a2f26a6f00b08bsalomon@google.com stencilSettings); 7721e945b7e708c633d4aed937ebfce57d52ba21d83robertphillips@google.com 7731e945b7e708c633d4aed937ebfce57d52ba21d83robertphillips@google.com // draw the element to the client stencil bits if necessary 7741e945b7e708c633d4aed937ebfce57d52ba21d83robertphillips@google.com if (!canDrawDirectToClip) { 7751e945b7e708c633d4aed937ebfce57d52ba21d83robertphillips@google.com GR_STATIC_CONST_SAME_STENCIL(gDrawToStencil, 7764c2443e36fdc6c095b17e90baa4a2f26a6f00b08bsalomon@google.com kIncClamp_StencilOp, 7774c2443e36fdc6c095b17e90baa4a2f26a6f00b08bsalomon@google.com kIncClamp_StencilOp, 7784c2443e36fdc6c095b17e90baa4a2f26a6f00b08bsalomon@google.com kAlways_StencilFunc, 7794c2443e36fdc6c095b17e90baa4a2f26a6f00b08bsalomon@google.com 0xffff, 7804c2443e36fdc6c095b17e90baa4a2f26a6f00b08bsalomon@google.com 0x0000, 7814c2443e36fdc6c095b17e90baa4a2f26a6f00b08bsalomon@google.com 0xffff); 7828182fa0cac76e7e6d583aebba060229230516887bsalomon@google.com if (Element::kRect_Type == element->getType()) { 7839853ccef19c200be93a6211f32589fa82a53067cjoshualitt *drawState.stencil() = gDrawToStencil; 7849853ccef19c200be93a6211f32589fa82a53067cjoshualitt fClipTarget->drawSimpleRect(&drawState, element->getRect()); 7851e945b7e708c633d4aed937ebfce57d52ba21d83robertphillips@google.com } else { 786e5b2af955b7d06815ddd405659ad62a2a8355ca3commit-bot@chromium.org if (!clipPath.isEmpty()) { 7879853ccef19c200be93a6211f32589fa82a53067cjoshualitt GrDrawTarget::AutoGeometryPush agp(fClipTarget); 78819dd017a6256be636ccb550752bb563c4e7caeb5commit-bot@chromium.org if (canRenderDirectToStencil) { 7899853ccef19c200be93a6211f32589fa82a53067cjoshualitt *drawState.stencil() = gDrawToStencil; 7909853ccef19c200be93a6211f32589fa82a53067cjoshualitt pr->drawPath(fClipTarget, &drawState, clipPath, stroke, false); 79119dd017a6256be636ccb550752bb563c4e7caeb5commit-bot@chromium.org } else { 7929853ccef19c200be93a6211f32589fa82a53067cjoshualitt pr->stencilPath(fClipTarget, &drawState, clipPath, stroke); 79319dd017a6256be636ccb550752bb563c4e7caeb5commit-bot@chromium.org } 7941e945b7e708c633d4aed937ebfce57d52ba21d83robertphillips@google.com } 7951e945b7e708c633d4aed937ebfce57d52ba21d83robertphillips@google.com } 7961e945b7e708c633d4aed937ebfce57d52ba21d83robertphillips@google.com } 7971e945b7e708c633d4aed937ebfce57d52ba21d83robertphillips@google.com 7981e945b7e708c633d4aed937ebfce57d52ba21d83robertphillips@google.com // now we modify the clip bit by rendering either the clip 7991e945b7e708c633d4aed937ebfce57d52ba21d83robertphillips@google.com // element directly or a bounding rect of the entire clip. 8007a6184fdf717a1da0c6e1e37b942b17fdaa236d3joshualitt fClipMode = kModifyClip_StencilClipMode; 8011e945b7e708c633d4aed937ebfce57d52ba21d83robertphillips@google.com for (int p = 0; p < passes; ++p) { 8029853ccef19c200be93a6211f32589fa82a53067cjoshualitt GrDrawState drawStateCopy(drawState); 8039853ccef19c200be93a6211f32589fa82a53067cjoshualitt *drawStateCopy.stencil() = stencilSettings[p]; 8049853ccef19c200be93a6211f32589fa82a53067cjoshualitt 8051e945b7e708c633d4aed937ebfce57d52ba21d83robertphillips@google.com if (canDrawDirectToClip) { 8068182fa0cac76e7e6d583aebba060229230516887bsalomon@google.com if (Element::kRect_Type == element->getType()) { 8079853ccef19c200be93a6211f32589fa82a53067cjoshualitt fClipTarget->drawSimpleRect(&drawStateCopy, element->getRect()); 8081e945b7e708c633d4aed937ebfce57d52ba21d83robertphillips@google.com } else { 8099853ccef19c200be93a6211f32589fa82a53067cjoshualitt GrDrawTarget::AutoGeometryPush agp(fClipTarget); 8109853ccef19c200be93a6211f32589fa82a53067cjoshualitt pr->drawPath(fClipTarget, &drawStateCopy, clipPath, stroke, false); 8111e945b7e708c633d4aed937ebfce57d52ba21d83robertphillips@google.com } 8121e945b7e708c633d4aed937ebfce57d52ba21d83robertphillips@google.com } else { 8134c2443e36fdc6c095b17e90baa4a2f26a6f00b08bsalomon@google.com // The view matrix is setup to do clip space -> stencil space translation, so 8144c2443e36fdc6c095b17e90baa4a2f26a6f00b08bsalomon@google.com // draw rect in clip space. 8159853ccef19c200be93a6211f32589fa82a53067cjoshualitt fClipTarget->drawSimpleRect(&drawStateCopy, SkRect::Make(clipSpaceIBounds)); 8161e945b7e708c633d4aed937ebfce57d52ba21d83robertphillips@google.com } 8171e945b7e708c633d4aed937ebfce57d52ba21d83robertphillips@google.com } 8181e945b7e708c633d4aed937ebfce57d52ba21d83robertphillips@google.com } 8191e945b7e708c633d4aed937ebfce57d52ba21d83robertphillips@google.com } 820c8f7f47afaf8f9471e6d111655c5610a8bd210a2bsalomon@google.com // set this last because recursive draws may overwrite it back to kNone. 821f6de475e5cbd143f348ff7738919e397b7fe7f57tfarina@chromium.org SkASSERT(kNone_ClipMaskType == fCurrClipMaskType); 822c8f7f47afaf8f9471e6d111655c5610a8bd210a2bsalomon@google.com fCurrClipMaskType = kStencil_ClipMaskType; 8237a6184fdf717a1da0c6e1e37b942b17fdaa236d3joshualitt fClipMode = kRespectClip_StencilClipMode; 8241e945b7e708c633d4aed937ebfce57d52ba21d83robertphillips@google.com return true; 8251e945b7e708c633d4aed937ebfce57d52ba21d83robertphillips@google.com} 8261e945b7e708c633d4aed937ebfce57d52ba21d83robertphillips@google.com 827411dad0630913fc07f2412b4be17acfbfd914fbcbsalomon@google.com// mapping of clip-respecting stencil funcs to normal stencil funcs 828411dad0630913fc07f2412b4be17acfbfd914fbcbsalomon@google.com// mapping depends on whether stencil-clipping is in effect. 829fbfcd5602128ec010c82cb733c9cdc0a3254f9f3rmistry@google.comstatic const GrStencilFunc 830411dad0630913fc07f2412b4be17acfbfd914fbcbsalomon@google.com gSpecialToBasicStencilFunc[2][kClipStencilFuncCount] = { 831411dad0630913fc07f2412b4be17acfbfd914fbcbsalomon@google.com {// Stencil-Clipping is DISABLED, we are effectively always inside the clip 832411dad0630913fc07f2412b4be17acfbfd914fbcbsalomon@google.com // In the Clip Funcs 833411dad0630913fc07f2412b4be17acfbfd914fbcbsalomon@google.com kAlways_StencilFunc, // kAlwaysIfInClip_StencilFunc 834411dad0630913fc07f2412b4be17acfbfd914fbcbsalomon@google.com kEqual_StencilFunc, // kEqualIfInClip_StencilFunc 835411dad0630913fc07f2412b4be17acfbfd914fbcbsalomon@google.com kLess_StencilFunc, // kLessIfInClip_StencilFunc 836411dad0630913fc07f2412b4be17acfbfd914fbcbsalomon@google.com kLEqual_StencilFunc, // kLEqualIfInClip_StencilFunc 837411dad0630913fc07f2412b4be17acfbfd914fbcbsalomon@google.com // Special in the clip func that forces user's ref to be 0. 838411dad0630913fc07f2412b4be17acfbfd914fbcbsalomon@google.com kNotEqual_StencilFunc, // kNonZeroIfInClip_StencilFunc 839411dad0630913fc07f2412b4be17acfbfd914fbcbsalomon@google.com // make ref 0 and do normal nequal. 840411dad0630913fc07f2412b4be17acfbfd914fbcbsalomon@google.com }, 841411dad0630913fc07f2412b4be17acfbfd914fbcbsalomon@google.com {// Stencil-Clipping is ENABLED 842411dad0630913fc07f2412b4be17acfbfd914fbcbsalomon@google.com // In the Clip Funcs 843411dad0630913fc07f2412b4be17acfbfd914fbcbsalomon@google.com kEqual_StencilFunc, // kAlwaysIfInClip_StencilFunc 844411dad0630913fc07f2412b4be17acfbfd914fbcbsalomon@google.com // eq stencil clip bit, mask 845411dad0630913fc07f2412b4be17acfbfd914fbcbsalomon@google.com // out user bits. 846411dad0630913fc07f2412b4be17acfbfd914fbcbsalomon@google.com 847411dad0630913fc07f2412b4be17acfbfd914fbcbsalomon@google.com kEqual_StencilFunc, // kEqualIfInClip_StencilFunc 848411dad0630913fc07f2412b4be17acfbfd914fbcbsalomon@google.com // add stencil bit to mask and ref 849411dad0630913fc07f2412b4be17acfbfd914fbcbsalomon@google.com 850411dad0630913fc07f2412b4be17acfbfd914fbcbsalomon@google.com kLess_StencilFunc, // kLessIfInClip_StencilFunc 851411dad0630913fc07f2412b4be17acfbfd914fbcbsalomon@google.com kLEqual_StencilFunc, // kLEqualIfInClip_StencilFunc 852411dad0630913fc07f2412b4be17acfbfd914fbcbsalomon@google.com // for both of these we can add 853411dad0630913fc07f2412b4be17acfbfd914fbcbsalomon@google.com // the clip bit to the mask and 854411dad0630913fc07f2412b4be17acfbfd914fbcbsalomon@google.com // ref and compare as normal 855411dad0630913fc07f2412b4be17acfbfd914fbcbsalomon@google.com // Special in the clip func that forces user's ref to be 0. 856411dad0630913fc07f2412b4be17acfbfd914fbcbsalomon@google.com kLess_StencilFunc, // kNonZeroIfInClip_StencilFunc 857411dad0630913fc07f2412b4be17acfbfd914fbcbsalomon@google.com // make ref have only the clip bit set 858411dad0630913fc07f2412b4be17acfbfd914fbcbsalomon@google.com // and make comparison be less 859411dad0630913fc07f2412b4be17acfbfd914fbcbsalomon@google.com // 10..0 < 1..user_bits.. 860411dad0630913fc07f2412b4be17acfbfd914fbcbsalomon@google.com } 861411dad0630913fc07f2412b4be17acfbfd914fbcbsalomon@google.com}; 862411dad0630913fc07f2412b4be17acfbfd914fbcbsalomon@google.com 863a320194e4242ef0e5e758aea896bfd52bcb3dac7bsalomon@google.comnamespace { 864a320194e4242ef0e5e758aea896bfd52bcb3dac7bsalomon@google.com// Sets the settings to clip against the stencil buffer clip while ignoring the 865a320194e4242ef0e5e758aea896bfd52bcb3dac7bsalomon@google.com// client bits. 866a320194e4242ef0e5e758aea896bfd52bcb3dac7bsalomon@google.comconst GrStencilSettings& basic_apply_stencil_clip_settings() { 867a320194e4242ef0e5e758aea896bfd52bcb3dac7bsalomon@google.com // stencil settings to use when clip is in stencil 868a320194e4242ef0e5e758aea896bfd52bcb3dac7bsalomon@google.com GR_STATIC_CONST_SAME_STENCIL_STRUCT(gSettings, 869a320194e4242ef0e5e758aea896bfd52bcb3dac7bsalomon@google.com kKeep_StencilOp, 870a320194e4242ef0e5e758aea896bfd52bcb3dac7bsalomon@google.com kKeep_StencilOp, 871a320194e4242ef0e5e758aea896bfd52bcb3dac7bsalomon@google.com kAlwaysIfInClip_StencilFunc, 872a320194e4242ef0e5e758aea896bfd52bcb3dac7bsalomon@google.com 0x0000, 873a320194e4242ef0e5e758aea896bfd52bcb3dac7bsalomon@google.com 0x0000, 874fbfcd5602128ec010c82cb733c9cdc0a3254f9f3rmistry@google.com 0x0000); 875a320194e4242ef0e5e758aea896bfd52bcb3dac7bsalomon@google.com return *GR_CONST_STENCIL_SETTINGS_PTR_FROM_STRUCT_PTR(&gSettings); 876a320194e4242ef0e5e758aea896bfd52bcb3dac7bsalomon@google.com} 877a320194e4242ef0e5e758aea896bfd52bcb3dac7bsalomon@google.com} 878a320194e4242ef0e5e758aea896bfd52bcb3dac7bsalomon@google.com 8799853ccef19c200be93a6211f32589fa82a53067cjoshualittvoid GrClipMaskManager::setDrawStateStencil(GrDrawState* drawState, 8809853ccef19c200be93a6211f32589fa82a53067cjoshualitt GrDrawState::AutoRestoreStencil* ars) { 881a320194e4242ef0e5e758aea896bfd52bcb3dac7bsalomon@google.com // We make two copies of the StencilSettings here (except in the early 882a320194e4242ef0e5e758aea896bfd52bcb3dac7bsalomon@google.com // exit scenario. One copy from draw state to the stack var. Then another 883a320194e4242ef0e5e758aea896bfd52bcb3dac7bsalomon@google.com // from the stack var to the gpu. We could make this class hold a ptr to 884a320194e4242ef0e5e758aea896bfd52bcb3dac7bsalomon@google.com // GrGpu's fStencilSettings and eliminate the stack copy here. 885a320194e4242ef0e5e758aea896bfd52bcb3dac7bsalomon@google.com 886a320194e4242ef0e5e758aea896bfd52bcb3dac7bsalomon@google.com // use stencil for clipping if clipping is enabled and the clip 887a320194e4242ef0e5e758aea896bfd52bcb3dac7bsalomon@google.com // has been written into the stencil. 888a320194e4242ef0e5e758aea896bfd52bcb3dac7bsalomon@google.com GrStencilSettings settings; 8899853ccef19c200be93a6211f32589fa82a53067cjoshualitt 890a320194e4242ef0e5e758aea896bfd52bcb3dac7bsalomon@google.com // The GrGpu client may not be using the stencil buffer but we may need to 891a320194e4242ef0e5e758aea896bfd52bcb3dac7bsalomon@google.com // enable it in order to respect a stencil clip. 8929853ccef19c200be93a6211f32589fa82a53067cjoshualitt if (drawState->getStencil().isDisabled()) { 8937a6184fdf717a1da0c6e1e37b942b17fdaa236d3joshualitt if (GrClipMaskManager::kRespectClip_StencilClipMode == fClipMode) { 894a320194e4242ef0e5e758aea896bfd52bcb3dac7bsalomon@google.com settings = basic_apply_stencil_clip_settings(); 895a320194e4242ef0e5e758aea896bfd52bcb3dac7bsalomon@google.com } else { 896a320194e4242ef0e5e758aea896bfd52bcb3dac7bsalomon@google.com return; 897a320194e4242ef0e5e758aea896bfd52bcb3dac7bsalomon@google.com } 898a320194e4242ef0e5e758aea896bfd52bcb3dac7bsalomon@google.com } else { 8999853ccef19c200be93a6211f32589fa82a53067cjoshualitt settings = drawState->getStencil(); 900a320194e4242ef0e5e758aea896bfd52bcb3dac7bsalomon@google.com } 901a320194e4242ef0e5e758aea896bfd52bcb3dac7bsalomon@google.com 902a320194e4242ef0e5e758aea896bfd52bcb3dac7bsalomon@google.com // TODO: dynamically attach a stencil buffer 903a320194e4242ef0e5e758aea896bfd52bcb3dac7bsalomon@google.com int stencilBits = 0; 9049853ccef19c200be93a6211f32589fa82a53067cjoshualitt GrStencilBuffer* stencilBuffer = drawState->getRenderTarget()->getStencilBuffer(); 90549f085dddff10473b6ebf832a974288300224e60bsalomon if (stencilBuffer) { 906a320194e4242ef0e5e758aea896bfd52bcb3dac7bsalomon@google.com stencilBits = stencilBuffer->bits(); 907a320194e4242ef0e5e758aea896bfd52bcb3dac7bsalomon@google.com } 908a320194e4242ef0e5e758aea896bfd52bcb3dac7bsalomon@google.com 909329bf4862e9d5e05363c2b071d8ca475a0ef1952joshualitt SkASSERT(fClipTarget->caps()->stencilWrapOpsSupport() || !settings.usesWrapOp()); 910329bf4862e9d5e05363c2b071d8ca475a0ef1952joshualitt SkASSERT(fClipTarget->caps()->twoSidedStencilSupport() || !settings.isTwoSided()); 9117a6184fdf717a1da0c6e1e37b942b17fdaa236d3joshualitt this->adjustStencilParams(&settings, fClipMode, stencilBits); 9129853ccef19c200be93a6211f32589fa82a53067cjoshualitt ars->set(drawState); 9139853ccef19c200be93a6211f32589fa82a53067cjoshualitt drawState->setStencil(settings); 914a320194e4242ef0e5e758aea896bfd52bcb3dac7bsalomon@google.com} 915a320194e4242ef0e5e758aea896bfd52bcb3dac7bsalomon@google.com 916a320194e4242ef0e5e758aea896bfd52bcb3dac7bsalomon@google.comvoid GrClipMaskManager::adjustStencilParams(GrStencilSettings* settings, 917a320194e4242ef0e5e758aea896bfd52bcb3dac7bsalomon@google.com StencilClipMode mode, 918a320194e4242ef0e5e758aea896bfd52bcb3dac7bsalomon@google.com int stencilBitCnt) { 919f6de475e5cbd143f348ff7738919e397b7fe7f57tfarina@chromium.org SkASSERT(stencilBitCnt > 0); 920411dad0630913fc07f2412b4be17acfbfd914fbcbsalomon@google.com 921411dad0630913fc07f2412b4be17acfbfd914fbcbsalomon@google.com if (kModifyClip_StencilClipMode == mode) { 922a320194e4242ef0e5e758aea896bfd52bcb3dac7bsalomon@google.com // We assume that this clip manager itself is drawing to the GrGpu and 923a320194e4242ef0e5e758aea896bfd52bcb3dac7bsalomon@google.com // has already setup the correct values. 924a320194e4242ef0e5e758aea896bfd52bcb3dac7bsalomon@google.com return; 925411dad0630913fc07f2412b4be17acfbfd914fbcbsalomon@google.com } 926a320194e4242ef0e5e758aea896bfd52bcb3dac7bsalomon@google.com 927411dad0630913fc07f2412b4be17acfbfd914fbcbsalomon@google.com unsigned int clipBit = (1 << (stencilBitCnt - 1)); 928411dad0630913fc07f2412b4be17acfbfd914fbcbsalomon@google.com unsigned int userBits = clipBit - 1; 929411dad0630913fc07f2412b4be17acfbfd914fbcbsalomon@google.com 930a320194e4242ef0e5e758aea896bfd52bcb3dac7bsalomon@google.com GrStencilSettings::Face face = GrStencilSettings::kFront_Face; 931329bf4862e9d5e05363c2b071d8ca475a0ef1952joshualitt bool twoSided = fClipTarget->caps()->twoSidedStencilSupport(); 932a320194e4242ef0e5e758aea896bfd52bcb3dac7bsalomon@google.com 933a320194e4242ef0e5e758aea896bfd52bcb3dac7bsalomon@google.com bool finished = false; 934a320194e4242ef0e5e758aea896bfd52bcb3dac7bsalomon@google.com while (!finished) { 935a320194e4242ef0e5e758aea896bfd52bcb3dac7bsalomon@google.com GrStencilFunc func = settings->func(face); 936a320194e4242ef0e5e758aea896bfd52bcb3dac7bsalomon@google.com uint16_t writeMask = settings->writeMask(face); 937a320194e4242ef0e5e758aea896bfd52bcb3dac7bsalomon@google.com uint16_t funcMask = settings->funcMask(face); 938a320194e4242ef0e5e758aea896bfd52bcb3dac7bsalomon@google.com uint16_t funcRef = settings->funcRef(face); 939a320194e4242ef0e5e758aea896bfd52bcb3dac7bsalomon@google.com 940f6de475e5cbd143f348ff7738919e397b7fe7f57tfarina@chromium.org SkASSERT((unsigned) func < kStencilFuncCount); 941a320194e4242ef0e5e758aea896bfd52bcb3dac7bsalomon@google.com 942a320194e4242ef0e5e758aea896bfd52bcb3dac7bsalomon@google.com writeMask &= userBits; 943a320194e4242ef0e5e758aea896bfd52bcb3dac7bsalomon@google.com 944a320194e4242ef0e5e758aea896bfd52bcb3dac7bsalomon@google.com if (func >= kBasicStencilFuncCount) { 945a320194e4242ef0e5e758aea896bfd52bcb3dac7bsalomon@google.com int respectClip = kRespectClip_StencilClipMode == mode; 946a320194e4242ef0e5e758aea896bfd52bcb3dac7bsalomon@google.com if (respectClip) { 947a320194e4242ef0e5e758aea896bfd52bcb3dac7bsalomon@google.com // The GrGpu class should have checked this 948f6de475e5cbd143f348ff7738919e397b7fe7f57tfarina@chromium.org SkASSERT(this->isClipInStencil()); 949a320194e4242ef0e5e758aea896bfd52bcb3dac7bsalomon@google.com switch (func) { 950a320194e4242ef0e5e758aea896bfd52bcb3dac7bsalomon@google.com case kAlwaysIfInClip_StencilFunc: 951a320194e4242ef0e5e758aea896bfd52bcb3dac7bsalomon@google.com funcMask = clipBit; 952a320194e4242ef0e5e758aea896bfd52bcb3dac7bsalomon@google.com funcRef = clipBit; 953a320194e4242ef0e5e758aea896bfd52bcb3dac7bsalomon@google.com break; 954a320194e4242ef0e5e758aea896bfd52bcb3dac7bsalomon@google.com case kEqualIfInClip_StencilFunc: 955a320194e4242ef0e5e758aea896bfd52bcb3dac7bsalomon@google.com case kLessIfInClip_StencilFunc: 956a320194e4242ef0e5e758aea896bfd52bcb3dac7bsalomon@google.com case kLEqualIfInClip_StencilFunc: 957a320194e4242ef0e5e758aea896bfd52bcb3dac7bsalomon@google.com funcMask = (funcMask & userBits) | clipBit; 958a320194e4242ef0e5e758aea896bfd52bcb3dac7bsalomon@google.com funcRef = (funcRef & userBits) | clipBit; 959a320194e4242ef0e5e758aea896bfd52bcb3dac7bsalomon@google.com break; 960a320194e4242ef0e5e758aea896bfd52bcb3dac7bsalomon@google.com case kNonZeroIfInClip_StencilFunc: 961a320194e4242ef0e5e758aea896bfd52bcb3dac7bsalomon@google.com funcMask = (funcMask & userBits) | clipBit; 962a320194e4242ef0e5e758aea896bfd52bcb3dac7bsalomon@google.com funcRef = clipBit; 963a320194e4242ef0e5e758aea896bfd52bcb3dac7bsalomon@google.com break; 964a320194e4242ef0e5e758aea896bfd52bcb3dac7bsalomon@google.com default: 96588cb22b6b4816c7a9ca6c5b795965b4606f9eb7bcommit-bot@chromium.org SkFAIL("Unknown stencil func"); 966a320194e4242ef0e5e758aea896bfd52bcb3dac7bsalomon@google.com } 967a320194e4242ef0e5e758aea896bfd52bcb3dac7bsalomon@google.com } else { 968a320194e4242ef0e5e758aea896bfd52bcb3dac7bsalomon@google.com funcMask &= userBits; 969a320194e4242ef0e5e758aea896bfd52bcb3dac7bsalomon@google.com funcRef &= userBits; 970411dad0630913fc07f2412b4be17acfbfd914fbcbsalomon@google.com } 971fbfcd5602128ec010c82cb733c9cdc0a3254f9f3rmistry@google.com const GrStencilFunc* table = 972a320194e4242ef0e5e758aea896bfd52bcb3dac7bsalomon@google.com gSpecialToBasicStencilFunc[respectClip]; 973a320194e4242ef0e5e758aea896bfd52bcb3dac7bsalomon@google.com func = table[func - kBasicStencilFuncCount]; 974f6de475e5cbd143f348ff7738919e397b7fe7f57tfarina@chromium.org SkASSERT(func >= 0 && func < kBasicStencilFuncCount); 975411dad0630913fc07f2412b4be17acfbfd914fbcbsalomon@google.com } else { 976a320194e4242ef0e5e758aea896bfd52bcb3dac7bsalomon@google.com funcMask &= userBits; 977a320194e4242ef0e5e758aea896bfd52bcb3dac7bsalomon@google.com funcRef &= userBits; 978411dad0630913fc07f2412b4be17acfbfd914fbcbsalomon@google.com } 979a320194e4242ef0e5e758aea896bfd52bcb3dac7bsalomon@google.com 980a320194e4242ef0e5e758aea896bfd52bcb3dac7bsalomon@google.com settings->setFunc(face, func); 981a320194e4242ef0e5e758aea896bfd52bcb3dac7bsalomon@google.com settings->setWriteMask(face, writeMask); 982a320194e4242ef0e5e758aea896bfd52bcb3dac7bsalomon@google.com settings->setFuncMask(face, funcMask); 983a320194e4242ef0e5e758aea896bfd52bcb3dac7bsalomon@google.com settings->setFuncRef(face, funcRef); 984a320194e4242ef0e5e758aea896bfd52bcb3dac7bsalomon@google.com 985a320194e4242ef0e5e758aea896bfd52bcb3dac7bsalomon@google.com if (GrStencilSettings::kFront_Face == face) { 986a320194e4242ef0e5e758aea896bfd52bcb3dac7bsalomon@google.com face = GrStencilSettings::kBack_Face; 987a320194e4242ef0e5e758aea896bfd52bcb3dac7bsalomon@google.com finished = !twoSided; 988a320194e4242ef0e5e758aea896bfd52bcb3dac7bsalomon@google.com } else { 989a320194e4242ef0e5e758aea896bfd52bcb3dac7bsalomon@google.com finished = true; 990a320194e4242ef0e5e758aea896bfd52bcb3dac7bsalomon@google.com } 991a320194e4242ef0e5e758aea896bfd52bcb3dac7bsalomon@google.com } 992a320194e4242ef0e5e758aea896bfd52bcb3dac7bsalomon@google.com if (!twoSided) { 993a320194e4242ef0e5e758aea896bfd52bcb3dac7bsalomon@google.com settings->copyFrontSettingsToBack(); 994411dad0630913fc07f2412b4be17acfbfd914fbcbsalomon@google.com } 995411dad0630913fc07f2412b4be17acfbfd914fbcbsalomon@google.com} 996411dad0630913fc07f2412b4be17acfbfd914fbcbsalomon@google.com 997411dad0630913fc07f2412b4be17acfbfd914fbcbsalomon@google.com//////////////////////////////////////////////////////////////////////////////// 998d3e5842db0cb169e10d6da1e62c94ba5cf182bb4commit-bot@chromium.orgGrTexture* GrClipMaskManager::createSoftwareClipMask(int32_t elementsGenID, 9994c2443e36fdc6c095b17e90baa4a2f26a6f00b08bsalomon@google.com GrReducedClip::InitialState initialState, 10004c2443e36fdc6c095b17e90baa4a2f26a6f00b08bsalomon@google.com const GrReducedClip::ElementList& elements, 10014c2443e36fdc6c095b17e90baa4a2f26a6f00b08bsalomon@google.com const SkIRect& clipSpaceIBounds) { 1002f6de475e5cbd143f348ff7738919e397b7fe7f57tfarina@chromium.org SkASSERT(kNone_ClipMaskType == fCurrClipMaskType); 10036b70a7bd3328ea0a12be47b1a7f835c905f16147robertphillips@google.com 1004ad1dc589cef8aebf7e14672ffdaa31c6d399675dkrajcevski GrTexture* result = this->getCachedMaskTexture(elementsGenID, clipSpaceIBounds); 100549f085dddff10473b6ebf832a974288300224e60bsalomon if (result) { 10064c2443e36fdc6c095b17e90baa4a2f26a6f00b08bsalomon@google.com return result; 10076b70a7bd3328ea0a12be47b1a7f835c905f16147robertphillips@google.com } 10086b70a7bd3328ea0a12be47b1a7f835c905f16147robertphillips@google.com 10094c2443e36fdc6c095b17e90baa4a2f26a6f00b08bsalomon@google.com // The mask texture may be larger than necessary. We round out the clip space bounds and pin 10104c2443e36fdc6c095b17e90baa4a2f26a6f00b08bsalomon@google.com // the top left corner of the resulting rect to the top left of the texture. 10114c2443e36fdc6c095b17e90baa4a2f26a6f00b08bsalomon@google.com SkIRect maskSpaceIBounds = SkIRect::MakeWH(clipSpaceIBounds.width(), clipSpaceIBounds.height()); 10124c2443e36fdc6c095b17e90baa4a2f26a6f00b08bsalomon@google.com 10132c75681e36b33fcafc5665d7012bbd4fc6647d83robertphillips@google.com GrSWMaskHelper helper(this->getContext()); 10146b70a7bd3328ea0a12be47b1a7f835c905f16147robertphillips@google.com 1015b9086a026844e4cfd08b219e49ce3f12294cba98bsalomon@google.com SkMatrix matrix; 10164c2443e36fdc6c095b17e90baa4a2f26a6f00b08bsalomon@google.com matrix.setTranslate(SkIntToScalar(-clipSpaceIBounds.fLeft), 10174c2443e36fdc6c095b17e90baa4a2f26a6f00b08bsalomon@google.com SkIntToScalar(-clipSpaceIBounds.fTop)); 10184c2443e36fdc6c095b17e90baa4a2f26a6f00b08bsalomon@google.com 10199853ccef19c200be93a6211f32589fa82a53067cjoshualitt helper.init(maskSpaceIBounds, &matrix, false); 1020bf54e49e30cdc92f9ce3f336cc48cf6b236ddeabtfarina helper.clear(GrReducedClip::kAllIn_InitialState == initialState ? 0xFF : 0x00); 10215f74cf8c49701f514b69dc6f1a8b5c0ffd78af0asugoi@google.com SkStrokeRec stroke(SkStrokeRec::kFill_InitStyle); 102212b4e27ae1a29460e91a59f38122483e1faec697sugoi@google.com 1023bf54e49e30cdc92f9ce3f336cc48cf6b236ddeabtfarina for (GrReducedClip::ElementList::Iter iter(elements.headIter()) ; iter.get(); iter.next()) { 10244c2443e36fdc6c095b17e90baa4a2f26a6f00b08bsalomon@google.com const Element* element = iter.get(); 10258182fa0cac76e7e6d583aebba060229230516887bsalomon@google.com SkRegion::Op op = element->getOp(); 1026fa66294c7705831808ce7772d4328fc626d45034robertphillips@google.com 10274c2443e36fdc6c095b17e90baa4a2f26a6f00b08bsalomon@google.com if (SkRegion::kIntersect_Op == op || SkRegion::kReverseDifference_Op == op) { 10284c2443e36fdc6c095b17e90baa4a2f26a6f00b08bsalomon@google.com // Intersect and reverse difference require modifying pixels outside of the geometry 10294c2443e36fdc6c095b17e90baa4a2f26a6f00b08bsalomon@google.com // that is being "drawn". In both cases we erase all the pixels outside of the geometry 10304c2443e36fdc6c095b17e90baa4a2f26a6f00b08bsalomon@google.com // but leave the pixels inside the geometry alone. For reverse difference we invert all 10314c2443e36fdc6c095b17e90baa4a2f26a6f00b08bsalomon@google.com // the pixels before clearing the ones outside the geometry. 1032fa66294c7705831808ce7772d4328fc626d45034robertphillips@google.com if (SkRegion::kReverseDifference_Op == op) { 10334469938e92d779dff05e745559e67907bbf21e78reed@google.com SkRect temp = SkRect::Make(clipSpaceIBounds); 1034fa66294c7705831808ce7772d4328fc626d45034robertphillips@google.com // invert the entire scene 1035366f1c6a09f63c76e78145cb08028f66062f31fdrobertphillips@google.com helper.draw(temp, SkRegion::kXOR_Op, false, 0xFF); 1036fa66294c7705831808ce7772d4328fc626d45034robertphillips@google.com } 10375c056399259bb7ec06ff1eb8ce904001b363276ccommit-bot@chromium.org SkPath clipPath; 10385c056399259bb7ec06ff1eb8ce904001b363276ccommit-bot@chromium.org element->asPath(&clipPath); 10395c056399259bb7ec06ff1eb8ce904001b363276ccommit-bot@chromium.org clipPath.toggleInverseFillType(); 10405c056399259bb7ec06ff1eb8ce904001b363276ccommit-bot@chromium.org helper.draw(clipPath, stroke, SkRegion::kReplace_Op, element->isAA(), 0x00); 1041fa66294c7705831808ce7772d4328fc626d45034robertphillips@google.com continue; 1042fa66294c7705831808ce7772d4328fc626d45034robertphillips@google.com } 1043fa66294c7705831808ce7772d4328fc626d45034robertphillips@google.com 1044fa66294c7705831808ce7772d4328fc626d45034robertphillips@google.com // The other ops (union, xor, diff) only affect pixels inside 1045fa66294c7705831808ce7772d4328fc626d45034robertphillips@google.com // the geometry so they can just be drawn normally 10468182fa0cac76e7e6d583aebba060229230516887bsalomon@google.com if (Element::kRect_Type == element->getType()) { 10478182fa0cac76e7e6d583aebba060229230516887bsalomon@google.com helper.draw(element->getRect(), op, element->isAA(), 0xFF); 10488182fa0cac76e7e6d583aebba060229230516887bsalomon@google.com } else { 10495c056399259bb7ec06ff1eb8ce904001b363276ccommit-bot@chromium.org SkPath path; 10505c056399259bb7ec06ff1eb8ce904001b363276ccommit-bot@chromium.org element->asPath(&path); 10515c056399259bb7ec06ff1eb8ce904001b363276ccommit-bot@chromium.org helper.draw(path, stroke, op, element->isAA(), 0xFF); 10526b70a7bd3328ea0a12be47b1a7f835c905f16147robertphillips@google.com } 10536b70a7bd3328ea0a12be47b1a7f835c905f16147robertphillips@google.com } 10546b70a7bd3328ea0a12be47b1a7f835c905f16147robertphillips@google.com 1055ad1dc589cef8aebf7e14672ffdaa31c6d399675dkrajcevski // Allocate clip mask texture 1056ad1dc589cef8aebf7e14672ffdaa31c6d399675dkrajcevski result = this->allocMaskTexture(elementsGenID, clipSpaceIBounds, true); 1057ad1dc589cef8aebf7e14672ffdaa31c6d399675dkrajcevski if (NULL == result) { 1058ad1dc589cef8aebf7e14672ffdaa31c6d399675dkrajcevski fAACache.reset(); 1059ad1dc589cef8aebf7e14672ffdaa31c6d399675dkrajcevski return NULL; 1060ad1dc589cef8aebf7e14672ffdaa31c6d399675dkrajcevski } 1061d92cf2ebbfbb9d737ea4a551e64ffccb08376875robertphillips@google.com helper.toTexture(result); 10626b70a7bd3328ea0a12be47b1a7f835c905f16147robertphillips@google.com 1063c8f7f47afaf8f9471e6d111655c5610a8bd210a2bsalomon@google.com fCurrClipMaskType = kAlpha_ClipMaskType; 10644c2443e36fdc6c095b17e90baa4a2f26a6f00b08bsalomon@google.com return result; 10656b70a7bd3328ea0a12be47b1a7f835c905f16147robertphillips@google.com} 10666b70a7bd3328ea0a12be47b1a7f835c905f16147robertphillips@google.com 1067f294b773f0b2b9f05eb45b52dd3cb4d97b96af06robertphillips@google.com//////////////////////////////////////////////////////////////////////////////// 1068c8dc1f74b6cdda9a43a638292a608c59c1d72d80bsalomonvoid GrClipMaskManager::purgeResources() { 1069c8dc1f74b6cdda9a43a638292a608c59c1d72d80bsalomon fAACache.purgeResources(); 10701e945b7e708c633d4aed937ebfce57d52ba21d83robertphillips@google.com} 10716e4e65066a7c0dbc9bfbfe4b8f5d49c3d8a79b59bsalomon@google.com 1072329bf4862e9d5e05363c2b071d8ca475a0ef1952joshualittvoid GrClipMaskManager::setClipTarget(GrClipTarget* clipTarget) { 1073329bf4862e9d5e05363c2b071d8ca475a0ef1952joshualitt fClipTarget = clipTarget; 1074329bf4862e9d5e05363c2b071d8ca475a0ef1952joshualitt fAACache.setContext(clipTarget->getContext()); 10756e4e65066a7c0dbc9bfbfe4b8f5d49c3d8a79b59bsalomon@google.com} 1076c4dc0ad8e252a7e30d19b47d3d0d9f2c69faf854commit-bot@chromium.org 10779853ccef19c200be93a6211f32589fa82a53067cjoshualittvoid GrClipMaskManager::adjustPathStencilParams(const GrStencilBuffer* stencilBuffer, 10789853ccef19c200be93a6211f32589fa82a53067cjoshualitt GrStencilSettings* settings) { 1079c4dc0ad8e252a7e30d19b47d3d0d9f2c69faf854commit-bot@chromium.org // TODO: dynamically attach a stencil buffer 108049f085dddff10473b6ebf832a974288300224e60bsalomon if (stencilBuffer) { 10819853ccef19c200be93a6211f32589fa82a53067cjoshualitt int stencilBits = stencilBuffer->bits(); 10827a6184fdf717a1da0c6e1e37b942b17fdaa236d3joshualitt this->adjustStencilParams(settings, fClipMode, stencilBits); 1083c4dc0ad8e252a7e30d19b47d3d0d9f2c69faf854commit-bot@chromium.org } 1084c4dc0ad8e252a7e30d19b47d3d0d9f2c69faf854commit-bot@chromium.org} 1085