GrClipMaskManager.cpp revision d92cf2ebbfbb9d737ea4a551e64ffccb08376875
11e945b7e708c633d4aed937ebfce57d52ba21d83robertphillips@google.com 21e945b7e708c633d4aed937ebfce57d52ba21d83robertphillips@google.com/* 31e945b7e708c633d4aed937ebfce57d52ba21d83robertphillips@google.com * Copyright 2012 Google Inc. 41e945b7e708c633d4aed937ebfce57d52ba21d83robertphillips@google.com * 51e945b7e708c633d4aed937ebfce57d52ba21d83robertphillips@google.com * Use of this source code is governed by a BSD-style license that can be 61e945b7e708c633d4aed937ebfce57d52ba21d83robertphillips@google.com * found in the LICENSE file. 71e945b7e708c633d4aed937ebfce57d52ba21d83robertphillips@google.com */ 81e945b7e708c633d4aed937ebfce57d52ba21d83robertphillips@google.com 91e945b7e708c633d4aed937ebfce57d52ba21d83robertphillips@google.com#include "GrClipMaskManager.h" 10c26d94fd7dc0b00cd6d0e42d28285f4a38aff021bsalomon@google.com#include "GrAAConvexPathRenderer.h" 11c26d94fd7dc0b00cd6d0e42d28285f4a38aff021bsalomon@google.com#include "GrAAHairLinePathRenderer.h" 12c26d94fd7dc0b00cd6d0e42d28285f4a38aff021bsalomon@google.com#include "GrDrawTargetCaps.h" 131e945b7e708c633d4aed937ebfce57d52ba21d83robertphillips@google.com#include "GrGpu.h" 14c26d94fd7dc0b00cd6d0e42d28285f4a38aff021bsalomon@google.com#include "GrPaint.h" 15c26d94fd7dc0b00cd6d0e42d28285f4a38aff021bsalomon@google.com#include "GrPathRenderer.h" 161e945b7e708c633d4aed937ebfce57d52ba21d83robertphillips@google.com#include "GrRenderTarget.h" 171e945b7e708c633d4aed937ebfce57d52ba21d83robertphillips@google.com#include "GrStencilBuffer.h" 18c26d94fd7dc0b00cd6d0e42d28285f4a38aff021bsalomon@google.com#include "GrSWMaskHelper.h" 19c26d94fd7dc0b00cd6d0e42d28285f4a38aff021bsalomon@google.com#include "effects/GrTextureDomainEffect.h" 206b70a7bd3328ea0a12be47b1a7f835c905f16147robertphillips@google.com#include "SkRasterClip.h" 215f74cf8c49701f514b69dc6f1a8b5c0ffd78af0asugoi@google.com#include "SkStrokeRec.h" 22c6b3e48cb3a22d83ba3f4b9a614a5a35b05958a0bsalomon@google.com#include "SkTLazy.h" 23c6b3e48cb3a22d83ba3f4b9a614a5a35b05958a0bsalomon@google.com 24ba998f2ddc5a904376bfdb118976868b9ee2b6e8robertphillips@google.com#define GR_AA_CLIP 1 25a72eef322c686954cdffa849dc26d8133b802f1drobertphillips@google.com 268182fa0cac76e7e6d583aebba060229230516887bsalomon@google.comtypedef SkClipStack::Element Element; 2751a6286c241c1dc750d263ed9676079c898148b0bsalomon@google.com 284c2443e36fdc6c095b17e90baa4a2f26a6f00b08bsalomon@google.comusing namespace GrReducedClip; 294c2443e36fdc6c095b17e90baa4a2f26a6f00b08bsalomon@google.com 3051a6286c241c1dc750d263ed9676079c898148b0bsalomon@google.com//////////////////////////////////////////////////////////////////////////////// 31a72eef322c686954cdffa849dc26d8133b802f1drobertphillips@google.comnamespace { 32fbfcd5602128ec010c82cb733c9cdc0a3254f9f3rmistry@google.com// set up the draw state to enable the aa clipping mask. Besides setting up the 3308283afc265f1153834256fc1012519813ba6b73bsalomon@google.com// stage matrix this also alters the vertex layout 34fbfcd5602128ec010c82cb733c9cdc0a3254f9f3rmistry@google.comvoid setup_drawstate_aaclip(GrGpu* gpu, 35fbfcd5602128ec010c82cb733c9cdc0a3254f9f3rmistry@google.com GrTexture* result, 36fd03d4a829efe2d77a712fd991927c55f59a2ffecommit-bot@chromium.org const SkIRect &devBound) { 37a72eef322c686954cdffa849dc26d8133b802f1drobertphillips@google.com GrDrawState* drawState = gpu->drawState(); 38a72eef322c686954cdffa849dc26d8133b802f1drobertphillips@google.com GrAssert(drawState); 39a72eef322c686954cdffa849dc26d8133b802f1drobertphillips@google.com 40b9086a026844e4cfd08b219e49ce3f12294cba98bsalomon@google.com SkMatrix mat; 41c78188896e28a4ae49e406a7422b345ae177dafebsalomon@google.com // We want to use device coords to compute the texture coordinates. We set our matrix to be 42c78188896e28a4ae49e406a7422b345ae177dafebsalomon@google.com // equal to the view matrix followed by an offset to the devBound, and then a scaling matrix to 43c78188896e28a4ae49e406a7422b345ae177dafebsalomon@google.com // normalized coords. We apply this matrix to the vertex positions rather than local coords. 44a72eef322c686954cdffa849dc26d8133b802f1drobertphillips@google.com mat.setIDiv(result->width(), result->height()); 45fbfcd5602128ec010c82cb733c9cdc0a3254f9f3rmistry@google.com mat.preTranslate(SkIntToScalar(-devBound.fLeft), 467b11289b4e4d117bbcee6d2460b057d0fcf6e437robertphillips@google.com SkIntToScalar(-devBound.fTop)); 47a72eef322c686954cdffa849dc26d8133b802f1drobertphillips@google.com mat.preConcat(drawState->getViewMatrix()); 48a72eef322c686954cdffa849dc26d8133b802f1drobertphillips@google.com 497b7cdd147f5528865238e5ed98c79e6d319fde9bbsalomon@google.com SkIRect domainTexels = SkIRect::MakeWH(devBound.width(), devBound.height()); 504c2443e36fdc6c095b17e90baa4a2f26a6f00b08bsalomon@google.com // This could be a long-lived effect that is cached with the alpha-mask. 51eb6879f50a5564eeb981ec5616b55bf685eb76fcbsalomon@google.com drawState->addCoverageEffect( 52eb6879f50a5564eeb981ec5616b55bf685eb76fcbsalomon@google.com GrTextureDomainEffect::Create(result, 537b7cdd147f5528865238e5ed98c79e6d319fde9bbsalomon@google.com mat, 547b7cdd147f5528865238e5ed98c79e6d319fde9bbsalomon@google.com GrTextureDomainEffect::MakeTexelDomain(result, domainTexels), 55c78188896e28a4ae49e406a7422b345ae177dafebsalomon@google.com GrTextureDomainEffect::kDecal_WrapMode, 56c78188896e28a4ae49e406a7422b345ae177dafebsalomon@google.com false, 57c78188896e28a4ae49e406a7422b345ae177dafebsalomon@google.com GrEffect::kPosition_CoordsType))->unref(); 58a72eef322c686954cdffa849dc26d8133b802f1drobertphillips@google.com} 59a72eef322c686954cdffa849dc26d8133b802f1drobertphillips@google.com 608a4fc40b02fa0a8300ade26863f4ddae69197d62robertphillips@google.combool path_needs_SW_renderer(GrContext* context, 6113b85aab6e1ff2ffd5475e329f9d1d21863b8eb6bsalomon@google.com GrGpu* gpu, 62c6b3e48cb3a22d83ba3f4b9a614a5a35b05958a0bsalomon@google.com const SkPath& origPath, 635f74cf8c49701f514b69dc6f1a8b5c0ffd78af0asugoi@google.com const SkStrokeRec& stroke, 6413b85aab6e1ff2ffd5475e329f9d1d21863b8eb6bsalomon@google.com bool doAA) { 65c6b3e48cb3a22d83ba3f4b9a614a5a35b05958a0bsalomon@google.com // the gpu alpha mask will draw the inverse paths as non-inverse to a temp buffer 66c6b3e48cb3a22d83ba3f4b9a614a5a35b05958a0bsalomon@google.com SkTCopyOnFirstWrite<SkPath> path(origPath); 67c6b3e48cb3a22d83ba3f4b9a614a5a35b05958a0bsalomon@google.com if (path->isInverseFillType()) { 68c6b3e48cb3a22d83ba3f4b9a614a5a35b05958a0bsalomon@google.com path.writable()->toggleInverseFillType(); 69c6b3e48cb3a22d83ba3f4b9a614a5a35b05958a0bsalomon@google.com } 708a4fc40b02fa0a8300ade26863f4ddae69197d62robertphillips@google.com // last (false) parameter disallows use of the SW path renderer 7145a15f551b5b3c6c747d8eaf6466b7d3b76a8faebsalomon@google.com GrPathRendererChain::DrawType type = doAA ? 7245a15f551b5b3c6c747d8eaf6466b7d3b76a8faebsalomon@google.com GrPathRendererChain::kColorAntiAlias_DrawType : 7345a15f551b5b3c6c747d8eaf6466b7d3b76a8faebsalomon@google.com GrPathRendererChain::kColor_DrawType; 7445a15f551b5b3c6c747d8eaf6466b7d3b76a8faebsalomon@google.com 7545a15f551b5b3c6c747d8eaf6466b7d3b76a8faebsalomon@google.com return NULL == context->getPathRenderer(*path, stroke, gpu, false, type); 76a6f11c4f717961070cd6fc5e60c361db14c5c4f3robertphillips@google.com} 77a6f11c4f717961070cd6fc5e60c361db14c5c4f3robertphillips@google.com 786b70a7bd3328ea0a12be47b1a7f835c905f16147robertphillips@google.com} 796b70a7bd3328ea0a12be47b1a7f835c905f16147robertphillips@google.com 80fa66294c7705831808ce7772d4328fc626d45034robertphillips@google.com/* 81fa66294c7705831808ce7772d4328fc626d45034robertphillips@google.com * This method traverses the clip stack to see if the GrSoftwarePathRenderer 82fa66294c7705831808ce7772d4328fc626d45034robertphillips@google.com * will be used on any element. If so, it returns true to indicate that the 83fa66294c7705831808ce7772d4328fc626d45034robertphillips@google.com * entire clip should be rendered in SW and then uploaded en masse to the gpu. 84fa66294c7705831808ce7772d4328fc626d45034robertphillips@google.com */ 854c2443e36fdc6c095b17e90baa4a2f26a6f00b08bsalomon@google.combool GrClipMaskManager::useSWOnlyPath(const ElementList& elements) { 86a3e5c63ab0264332169df4583a8a7da186fb4e66robertphillips@google.com 878a4fc40b02fa0a8300ade26863f4ddae69197d62robertphillips@google.com // TODO: generalize this function so that when 88fa66294c7705831808ce7772d4328fc626d45034robertphillips@google.com // a clip gets complex enough it can just be done in SW regardless 89fa66294c7705831808ce7772d4328fc626d45034robertphillips@google.com // of whether it would invoke the GrSoftwarePathRenderer. 905f74cf8c49701f514b69dc6f1a8b5c0ffd78af0asugoi@google.com SkStrokeRec stroke(SkStrokeRec::kFill_InitStyle); 91d21444aab7128c97f4e0eb5e9bf05111d5037292skia.committer@gmail.com 924c2443e36fdc6c095b17e90baa4a2f26a6f00b08bsalomon@google.com for (ElementList::Iter iter(elements.headIter()); iter.get(); iter.next()) { 934c2443e36fdc6c095b17e90baa4a2f26a6f00b08bsalomon@google.com const Element* element = iter.get(); 94f69a11b5c5dc5ae02489dfe7ca6432d641b9f121robertphillips@google.com // rects can always be drawn directly w/o using the software path 95f69a11b5c5dc5ae02489dfe7ca6432d641b9f121robertphillips@google.com // so only paths need to be checked 968182fa0cac76e7e6d583aebba060229230516887bsalomon@google.com if (Element::kPath_Type == element->getType() && 97fbfcd5602128ec010c82cb733c9cdc0a3254f9f3rmistry@google.com path_needs_SW_renderer(this->getContext(), fGpu, 988182fa0cac76e7e6d583aebba060229230516887bsalomon@google.com element->getPath(), 9912b4e27ae1a29460e91a59f38122483e1faec697sugoi@google.com stroke, 1008182fa0cac76e7e6d583aebba060229230516887bsalomon@google.com element->isAA())) { 1014c2443e36fdc6c095b17e90baa4a2f26a6f00b08bsalomon@google.com return true; 102fa66294c7705831808ce7772d4328fc626d45034robertphillips@google.com } 103fa66294c7705831808ce7772d4328fc626d45034robertphillips@google.com } 1044c2443e36fdc6c095b17e90baa4a2f26a6f00b08bsalomon@google.com return false; 105a72eef322c686954cdffa849dc26d8133b802f1drobertphillips@google.com} 106a72eef322c686954cdffa849dc26d8133b802f1drobertphillips@google.com 107f294b773f0b2b9f05eb45b52dd3cb4d97b96af06robertphillips@google.com//////////////////////////////////////////////////////////////////////////////// 1086b70a7bd3328ea0a12be47b1a7f835c905f16147robertphillips@google.com// sort out what kind of clip mask needs to be created: alpha, stencil, 1096b70a7bd3328ea0a12be47b1a7f835c905f16147robertphillips@google.com// scissor, or entirely software 110eb6879f50a5564eeb981ec5616b55bf685eb76fcbsalomon@google.combool GrClipMaskManager::setupClipping(const GrClipData* clipDataIn, 111eb6879f50a5564eeb981ec5616b55bf685eb76fcbsalomon@google.com GrDrawState::AutoRestoreEffects* are) { 112c8f7f47afaf8f9471e6d111655c5610a8bd210a2bsalomon@google.com fCurrClipMaskType = kNone_ClipMaskType; 113a320194e4242ef0e5e758aea896bfd52bcb3dac7bsalomon@google.com 1144c2443e36fdc6c095b17e90baa4a2f26a6f00b08bsalomon@google.com ElementList elements(16); 1154c2443e36fdc6c095b17e90baa4a2f26a6f00b08bsalomon@google.com InitialState initialState; 1164c2443e36fdc6c095b17e90baa4a2f26a6f00b08bsalomon@google.com SkIRect clipSpaceIBounds; 1174c2443e36fdc6c095b17e90baa4a2f26a6f00b08bsalomon@google.com bool requiresAA; 1184c2443e36fdc6c095b17e90baa4a2f26a6f00b08bsalomon@google.com bool isRect = false; 1194c2443e36fdc6c095b17e90baa4a2f26a6f00b08bsalomon@google.com 12013b85aab6e1ff2ffd5475e329f9d1d21863b8eb6bsalomon@google.com GrDrawState* drawState = fGpu->drawState(); 1211e945b7e708c633d4aed937ebfce57d52ba21d83robertphillips@google.com 1224c2443e36fdc6c095b17e90baa4a2f26a6f00b08bsalomon@google.com const GrRenderTarget* rt = drawState->getRenderTarget(); 1231e945b7e708c633d4aed937ebfce57d52ba21d83robertphillips@google.com // GrDrawTarget should have filtered this for us 1241e945b7e708c633d4aed937ebfce57d52ba21d83robertphillips@google.com GrAssert(NULL != rt); 1251e945b7e708c633d4aed937ebfce57d52ba21d83robertphillips@google.com 1264c2443e36fdc6c095b17e90baa4a2f26a6f00b08bsalomon@google.com bool ignoreClip = !drawState->isClipState() || clipDataIn->fClipStack->isWideOpen(); 1274c2443e36fdc6c095b17e90baa4a2f26a6f00b08bsalomon@google.com 1284c2443e36fdc6c095b17e90baa4a2f26a6f00b08bsalomon@google.com if (!ignoreClip) { 1294c2443e36fdc6c095b17e90baa4a2f26a6f00b08bsalomon@google.com SkIRect clipSpaceRTIBounds = SkIRect::MakeWH(rt->width(), rt->height()); 1304c2443e36fdc6c095b17e90baa4a2f26a6f00b08bsalomon@google.com clipSpaceRTIBounds.offset(clipDataIn->fOrigin); 1314c2443e36fdc6c095b17e90baa4a2f26a6f00b08bsalomon@google.com ReduceClipStack(*clipDataIn->fClipStack, 1324c2443e36fdc6c095b17e90baa4a2f26a6f00b08bsalomon@google.com clipSpaceRTIBounds, 1334c2443e36fdc6c095b17e90baa4a2f26a6f00b08bsalomon@google.com &elements, 1344c2443e36fdc6c095b17e90baa4a2f26a6f00b08bsalomon@google.com &initialState, 1354c2443e36fdc6c095b17e90baa4a2f26a6f00b08bsalomon@google.com &clipSpaceIBounds, 1364c2443e36fdc6c095b17e90baa4a2f26a6f00b08bsalomon@google.com &requiresAA); 1374c2443e36fdc6c095b17e90baa4a2f26a6f00b08bsalomon@google.com if (elements.isEmpty()) { 1384c2443e36fdc6c095b17e90baa4a2f26a6f00b08bsalomon@google.com if (kAllIn_InitialState == initialState) { 1394c2443e36fdc6c095b17e90baa4a2f26a6f00b08bsalomon@google.com ignoreClip = clipSpaceIBounds == clipSpaceRTIBounds; 1404c2443e36fdc6c095b17e90baa4a2f26a6f00b08bsalomon@google.com isRect = true; 1414c2443e36fdc6c095b17e90baa4a2f26a6f00b08bsalomon@google.com } else { 1424c2443e36fdc6c095b17e90baa4a2f26a6f00b08bsalomon@google.com return false; 1434c2443e36fdc6c095b17e90baa4a2f26a6f00b08bsalomon@google.com } 1444c2443e36fdc6c095b17e90baa4a2f26a6f00b08bsalomon@google.com } 1454c2443e36fdc6c095b17e90baa4a2f26a6f00b08bsalomon@google.com } 1463e11c0bd92fbd12f59080c3f9450201d6105db83robertphillips@google.com 1474c2443e36fdc6c095b17e90baa4a2f26a6f00b08bsalomon@google.com if (ignoreClip) { 1484c2443e36fdc6c095b17e90baa4a2f26a6f00b08bsalomon@google.com fGpu->disableScissor(); 1494c2443e36fdc6c095b17e90baa4a2f26a6f00b08bsalomon@google.com this->setGpuStencil(); 1504c2443e36fdc6c095b17e90baa4a2f26a6f00b08bsalomon@google.com return true; 151a320194e4242ef0e5e758aea896bfd52bcb3dac7bsalomon@google.com } 152a320194e4242ef0e5e758aea896bfd52bcb3dac7bsalomon@google.com 1534c2443e36fdc6c095b17e90baa4a2f26a6f00b08bsalomon@google.com#if GR_AA_CLIP 1544c2443e36fdc6c095b17e90baa4a2f26a6f00b08bsalomon@google.com // TODO: catch isRect && requiresAA and use clip planes if available rather than a mask. 155b99225c92bc6d7d0ea7030716ade6a302862e84frobertphillips@google.com 156a3e5c63ab0264332169df4583a8a7da186fb4e66robertphillips@google.com // If MSAA is enabled we can do everything in the stencil buffer. 1574c2443e36fdc6c095b17e90baa4a2f26a6f00b08bsalomon@google.com if (0 == rt->numSamples() && requiresAA) { 1584c2443e36fdc6c095b17e90baa4a2f26a6f00b08bsalomon@google.com int32_t genID = clipDataIn->fClipStack->getTopmostGenID(); 1596b70a7bd3328ea0a12be47b1a7f835c905f16147robertphillips@google.com GrTexture* result = NULL; 160a3e5c63ab0264332169df4583a8a7da186fb4e66robertphillips@google.com 1614c2443e36fdc6c095b17e90baa4a2f26a6f00b08bsalomon@google.com if (this->useSWOnlyPath(elements)) { 1624c2443e36fdc6c095b17e90baa4a2f26a6f00b08bsalomon@google.com // The clip geometry is complex enough that it will be more efficient to create it 1634c2443e36fdc6c095b17e90baa4a2f26a6f00b08bsalomon@google.com // entirely in software 1644c2443e36fdc6c095b17e90baa4a2f26a6f00b08bsalomon@google.com result = this->createSoftwareClipMask(genID, 1654c2443e36fdc6c095b17e90baa4a2f26a6f00b08bsalomon@google.com initialState, 1664c2443e36fdc6c095b17e90baa4a2f26a6f00b08bsalomon@google.com elements, 1674c2443e36fdc6c095b17e90baa4a2f26a6f00b08bsalomon@google.com clipSpaceIBounds); 1684c2443e36fdc6c095b17e90baa4a2f26a6f00b08bsalomon@google.com } else { 1694c2443e36fdc6c095b17e90baa4a2f26a6f00b08bsalomon@google.com result = this->createAlphaClipMask(genID, 1704c2443e36fdc6c095b17e90baa4a2f26a6f00b08bsalomon@google.com initialState, 1714c2443e36fdc6c095b17e90baa4a2f26a6f00b08bsalomon@google.com elements, 1724c2443e36fdc6c095b17e90baa4a2f26a6f00b08bsalomon@google.com clipSpaceIBounds); 1734c2443e36fdc6c095b17e90baa4a2f26a6f00b08bsalomon@google.com } 1746b70a7bd3328ea0a12be47b1a7f835c905f16147robertphillips@google.com 1754c2443e36fdc6c095b17e90baa4a2f26a6f00b08bsalomon@google.com if (NULL != result) { 1764c2443e36fdc6c095b17e90baa4a2f26a6f00b08bsalomon@google.com // The mask's top left coord should be pinned to the rounded-out top left corner of 1774c2443e36fdc6c095b17e90baa4a2f26a6f00b08bsalomon@google.com // clipSpace bounds. We determine the mask's position WRT to the render target here. 1784c2443e36fdc6c095b17e90baa4a2f26a6f00b08bsalomon@google.com SkIRect rtSpaceMaskBounds = clipSpaceIBounds; 1794c2443e36fdc6c095b17e90baa4a2f26a6f00b08bsalomon@google.com rtSpaceMaskBounds.offset(-clipDataIn->fOrigin); 180eb6879f50a5564eeb981ec5616b55bf685eb76fcbsalomon@google.com are->set(fGpu->drawState()); 1814c2443e36fdc6c095b17e90baa4a2f26a6f00b08bsalomon@google.com setup_drawstate_aaclip(fGpu, result, rtSpaceMaskBounds); 182a320194e4242ef0e5e758aea896bfd52bcb3dac7bsalomon@google.com fGpu->disableScissor(); 183a320194e4242ef0e5e758aea896bfd52bcb3dac7bsalomon@google.com this->setGpuStencil(); 184f294b773f0b2b9f05eb45b52dd3cb4d97b96af06robertphillips@google.com return true; 185f294b773f0b2b9f05eb45b52dd3cb4d97b96af06robertphillips@google.com } 1864c2443e36fdc6c095b17e90baa4a2f26a6f00b08bsalomon@google.com // if alpha clip mask creation fails fall through to the non-AA code paths 187f294b773f0b2b9f05eb45b52dd3cb4d97b96af06robertphillips@google.com } 188f294b773f0b2b9f05eb45b52dd3cb4d97b96af06robertphillips@google.com#endif // GR_AA_CLIP 189f294b773f0b2b9f05eb45b52dd3cb4d97b96af06robertphillips@google.com 1904c2443e36fdc6c095b17e90baa4a2f26a6f00b08bsalomon@google.com // Either a hard (stencil buffer) clip was explicitly requested or an anti-aliased clip couldn't 1914c2443e36fdc6c095b17e90baa4a2f26a6f00b08bsalomon@google.com // be created. In either case, free up the texture in the anti-aliased mask cache. 1924c2443e36fdc6c095b17e90baa4a2f26a6f00b08bsalomon@google.com // TODO: this may require more investigation. Ganesh performs a lot of utility draws (e.g., 1934c2443e36fdc6c095b17e90baa4a2f26a6f00b08bsalomon@google.com // clears, InOrderDrawBuffer playbacks) that hit the stencil buffer path. These may be 1944c2443e36fdc6c095b17e90baa4a2f26a6f00b08bsalomon@google.com // "incorrectly" clearing the AA cache. 1955acc0e36d987dff3172fd45a14b66c52a51d49e4robertphillips@google.com fAACache.reset(); 1965acc0e36d987dff3172fd45a14b66c52a51d49e4robertphillips@google.com 197a320194e4242ef0e5e758aea896bfd52bcb3dac7bsalomon@google.com // If the clip is a rectangle then just set the scissor. Otherwise, create 198a320194e4242ef0e5e758aea896bfd52bcb3dac7bsalomon@google.com // a stencil mask. 1994c2443e36fdc6c095b17e90baa4a2f26a6f00b08bsalomon@google.com if (isRect) { 2004c2443e36fdc6c095b17e90baa4a2f26a6f00b08bsalomon@google.com SkIRect clipRect = clipSpaceIBounds; 2014c2443e36fdc6c095b17e90baa4a2f26a6f00b08bsalomon@google.com clipRect.offset(-clipDataIn->fOrigin); 2024c2443e36fdc6c095b17e90baa4a2f26a6f00b08bsalomon@google.com fGpu->enableScissor(clipRect); 203a320194e4242ef0e5e758aea896bfd52bcb3dac7bsalomon@google.com this->setGpuStencil(); 204a320194e4242ef0e5e758aea896bfd52bcb3dac7bsalomon@google.com return true; 2051e945b7e708c633d4aed937ebfce57d52ba21d83robertphillips@google.com } 2061e945b7e708c633d4aed937ebfce57d52ba21d83robertphillips@google.com 2071e945b7e708c633d4aed937ebfce57d52ba21d83robertphillips@google.com // use the stencil clip if we can't represent the clip as a rectangle. 2084c2443e36fdc6c095b17e90baa4a2f26a6f00b08bsalomon@google.com SkIPoint clipSpaceToStencilSpaceOffset = -clipDataIn->fOrigin; 2094c2443e36fdc6c095b17e90baa4a2f26a6f00b08bsalomon@google.com this->createStencilClipMask(initialState, 2104c2443e36fdc6c095b17e90baa4a2f26a6f00b08bsalomon@google.com elements, 2114c2443e36fdc6c095b17e90baa4a2f26a6f00b08bsalomon@google.com clipSpaceIBounds, 2124c2443e36fdc6c095b17e90baa4a2f26a6f00b08bsalomon@google.com clipSpaceToStencilSpaceOffset); 2134c2443e36fdc6c095b17e90baa4a2f26a6f00b08bsalomon@google.com 2144c2443e36fdc6c095b17e90baa4a2f26a6f00b08bsalomon@google.com // This must occur after createStencilClipMask. That function may change the scissor. Also, it 2154c2443e36fdc6c095b17e90baa4a2f26a6f00b08bsalomon@google.com // only guarantees that the stencil mask is correct within the bounds it was passed, so we must 2164c2443e36fdc6c095b17e90baa4a2f26a6f00b08bsalomon@google.com // use both stencil and scissor test to the bounds for the final draw. 2174c2443e36fdc6c095b17e90baa4a2f26a6f00b08bsalomon@google.com SkIRect scissorSpaceIBounds(clipSpaceIBounds); 2184c2443e36fdc6c095b17e90baa4a2f26a6f00b08bsalomon@google.com scissorSpaceIBounds.offset(clipSpaceToStencilSpaceOffset); 2194c2443e36fdc6c095b17e90baa4a2f26a6f00b08bsalomon@google.com fGpu->enableScissor(scissorSpaceIBounds); 220a320194e4242ef0e5e758aea896bfd52bcb3dac7bsalomon@google.com this->setGpuStencil(); 2211e945b7e708c633d4aed937ebfce57d52ba21d83robertphillips@google.com return true; 2221e945b7e708c633d4aed937ebfce57d52ba21d83robertphillips@google.com} 2231e945b7e708c633d4aed937ebfce57d52ba21d83robertphillips@google.com 2241e945b7e708c633d4aed937ebfce57d52ba21d83robertphillips@google.com#define VISUALIZE_COMPLEX_CLIP 0 2251e945b7e708c633d4aed937ebfce57d52ba21d83robertphillips@google.com 2261e945b7e708c633d4aed937ebfce57d52ba21d83robertphillips@google.com#if VISUALIZE_COMPLEX_CLIP 227223137f49d1a4e805f5c1b1c20b7fd68719ac54btfarina@chromium.org #include "SkRandom.h" 228223137f49d1a4e805f5c1b1c20b7fd68719ac54btfarina@chromium.org SkRandom gRandom; 2291e945b7e708c633d4aed937ebfce57d52ba21d83robertphillips@google.com #define SET_RANDOM_COLOR drawState->setColor(0xff000000 | gRandom.nextU()); 2301e945b7e708c633d4aed937ebfce57d52ba21d83robertphillips@google.com#else 2311e945b7e708c633d4aed937ebfce57d52ba21d83robertphillips@google.com #define SET_RANDOM_COLOR 2321e945b7e708c633d4aed937ebfce57d52ba21d83robertphillips@google.com#endif 2331e945b7e708c633d4aed937ebfce57d52ba21d83robertphillips@google.com 2341e945b7e708c633d4aed937ebfce57d52ba21d83robertphillips@google.comnamespace { 235f294b773f0b2b9f05eb45b52dd3cb4d97b96af06robertphillips@google.com 236f294b773f0b2b9f05eb45b52dd3cb4d97b96af06robertphillips@google.com//////////////////////////////////////////////////////////////////////////////// 237fbfcd5602128ec010c82cb733c9cdc0a3254f9f3rmistry@google.com// set up the OpenGL blend function to perform the specified 238fbfcd5602128ec010c82cb733c9cdc0a3254f9f3rmistry@google.com// boolean operation for alpha clip mask creation 2396b70a7bd3328ea0a12be47b1a7f835c905f16147robertphillips@google.comvoid setup_boolean_blendcoeffs(GrDrawState* drawState, SkRegion::Op op) { 240f294b773f0b2b9f05eb45b52dd3cb4d97b96af06robertphillips@google.com 241f294b773f0b2b9f05eb45b52dd3cb4d97b96af06robertphillips@google.com switch (op) { 242f294b773f0b2b9f05eb45b52dd3cb4d97b96af06robertphillips@google.com case SkRegion::kReplace_Op: 24347059542e7aa153926377456a6c611e55c8e428cbsalomon@google.com drawState->setBlendFunc(kOne_GrBlendCoeff, kZero_GrBlendCoeff); 244f294b773f0b2b9f05eb45b52dd3cb4d97b96af06robertphillips@google.com break; 245f294b773f0b2b9f05eb45b52dd3cb4d97b96af06robertphillips@google.com case SkRegion::kIntersect_Op: 24647059542e7aa153926377456a6c611e55c8e428cbsalomon@google.com drawState->setBlendFunc(kDC_GrBlendCoeff, kZero_GrBlendCoeff); 247f294b773f0b2b9f05eb45b52dd3cb4d97b96af06robertphillips@google.com break; 248f294b773f0b2b9f05eb45b52dd3cb4d97b96af06robertphillips@google.com case SkRegion::kUnion_Op: 24947059542e7aa153926377456a6c611e55c8e428cbsalomon@google.com drawState->setBlendFunc(kOne_GrBlendCoeff, kISC_GrBlendCoeff); 250f294b773f0b2b9f05eb45b52dd3cb4d97b96af06robertphillips@google.com break; 251f294b773f0b2b9f05eb45b52dd3cb4d97b96af06robertphillips@google.com case SkRegion::kXOR_Op: 25247059542e7aa153926377456a6c611e55c8e428cbsalomon@google.com drawState->setBlendFunc(kIDC_GrBlendCoeff, kISC_GrBlendCoeff); 253f294b773f0b2b9f05eb45b52dd3cb4d97b96af06robertphillips@google.com break; 254f294b773f0b2b9f05eb45b52dd3cb4d97b96af06robertphillips@google.com case SkRegion::kDifference_Op: 25547059542e7aa153926377456a6c611e55c8e428cbsalomon@google.com drawState->setBlendFunc(kZero_GrBlendCoeff, kISC_GrBlendCoeff); 256f294b773f0b2b9f05eb45b52dd3cb4d97b96af06robertphillips@google.com break; 257f294b773f0b2b9f05eb45b52dd3cb4d97b96af06robertphillips@google.com case SkRegion::kReverseDifference_Op: 25847059542e7aa153926377456a6c611e55c8e428cbsalomon@google.com drawState->setBlendFunc(kIDC_GrBlendCoeff, kZero_GrBlendCoeff); 259f294b773f0b2b9f05eb45b52dd3cb4d97b96af06robertphillips@google.com break; 260f294b773f0b2b9f05eb45b52dd3cb4d97b96af06robertphillips@google.com default: 261f294b773f0b2b9f05eb45b52dd3cb4d97b96af06robertphillips@google.com GrAssert(false); 262f294b773f0b2b9f05eb45b52dd3cb4d97b96af06robertphillips@google.com break; 263f294b773f0b2b9f05eb45b52dd3cb4d97b96af06robertphillips@google.com } 264f294b773f0b2b9f05eb45b52dd3cb4d97b96af06robertphillips@google.com} 265f294b773f0b2b9f05eb45b52dd3cb4d97b96af06robertphillips@google.com 26672176b2d38db005863a54e3dd6657bbabd068bb6robertphillips@google.com} 267f294b773f0b2b9f05eb45b52dd3cb4d97b96af06robertphillips@google.com 268f294b773f0b2b9f05eb45b52dd3cb4d97b96af06robertphillips@google.com//////////////////////////////////////////////////////////////////////////////// 269b68addd39f3e7183facc70374a133e7a6fb603c5bsalomon@google.combool GrClipMaskManager::drawElement(GrTexture* target, 270b68addd39f3e7183facc70374a133e7a6fb603c5bsalomon@google.com const SkClipStack::Element* element, 271b68addd39f3e7183facc70374a133e7a6fb603c5bsalomon@google.com GrPathRenderer* pr) { 27213b85aab6e1ff2ffd5475e329f9d1d21863b8eb6bsalomon@google.com GrDrawState* drawState = fGpu->drawState(); 273f294b773f0b2b9f05eb45b52dd3cb4d97b96af06robertphillips@google.com 274f294b773f0b2b9f05eb45b52dd3cb4d97b96af06robertphillips@google.com drawState->setRenderTarget(target->asRenderTarget()); 275f294b773f0b2b9f05eb45b52dd3cb4d97b96af06robertphillips@google.com 2768182fa0cac76e7e6d583aebba060229230516887bsalomon@google.com switch (element->getType()) { 2778182fa0cac76e7e6d583aebba060229230516887bsalomon@google.com case Element::kRect_Type: 2784c2443e36fdc6c095b17e90baa4a2f26a6f00b08bsalomon@google.com // TODO: Do rects directly to the accumulator using a aa-rect GrEffect that covers the 2794c2443e36fdc6c095b17e90baa4a2f26a6f00b08bsalomon@google.com // entire mask bounds and writes 0 outside the rect. 2808182fa0cac76e7e6d583aebba060229230516887bsalomon@google.com if (element->isAA()) { 281cf939ae54842fc7408ee68a41427086962b4c3dcbsalomon@google.com getContext()->getAARectRenderer()->fillAARect(fGpu, 282cf939ae54842fc7408ee68a41427086962b4c3dcbsalomon@google.com fGpu, 283cf939ae54842fc7408ee68a41427086962b4c3dcbsalomon@google.com element->getRect(), 284b19cb7f36785f3ad3b1512c342fc662ab79e3fcarobertphillips@google.com SkMatrix::I(), 285afd1cba5237eba5394ee011106eede9f6c8074c8robertphillips@google.com element->getRect(), 286cf939ae54842fc7408ee68a41427086962b4c3dcbsalomon@google.com false); 2878182fa0cac76e7e6d583aebba060229230516887bsalomon@google.com } else { 2888182fa0cac76e7e6d583aebba060229230516887bsalomon@google.com fGpu->drawSimpleRect(element->getRect(), NULL); 2898182fa0cac76e7e6d583aebba060229230516887bsalomon@google.com } 2908182fa0cac76e7e6d583aebba060229230516887bsalomon@google.com return true; 2914c2443e36fdc6c095b17e90baa4a2f26a6f00b08bsalomon@google.com case Element::kPath_Type: { 292c6b3e48cb3a22d83ba3f4b9a614a5a35b05958a0bsalomon@google.com SkTCopyOnFirstWrite<SkPath> path(element->getPath()); 293c6b3e48cb3a22d83ba3f4b9a614a5a35b05958a0bsalomon@google.com if (path->isInverseFillType()) { 294c6b3e48cb3a22d83ba3f4b9a614a5a35b05958a0bsalomon@google.com path.writable()->toggleInverseFillType(); 295c6b3e48cb3a22d83ba3f4b9a614a5a35b05958a0bsalomon@google.com } 2965f74cf8c49701f514b69dc6f1a8b5c0ffd78af0asugoi@google.com SkStrokeRec stroke(SkStrokeRec::kFill_InitStyle); 297b68addd39f3e7183facc70374a133e7a6fb603c5bsalomon@google.com if (NULL == pr) { 298b68addd39f3e7183facc70374a133e7a6fb603c5bsalomon@google.com GrPathRendererChain::DrawType type; 299b68addd39f3e7183facc70374a133e7a6fb603c5bsalomon@google.com type = element->isAA() ? GrPathRendererChain::kColorAntiAlias_DrawType : 300b68addd39f3e7183facc70374a133e7a6fb603c5bsalomon@google.com GrPathRendererChain::kColor_DrawType; 301b68addd39f3e7183facc70374a133e7a6fb603c5bsalomon@google.com pr = this->getContext()->getPathRenderer(*path, stroke, fGpu, false, type); 302b68addd39f3e7183facc70374a133e7a6fb603c5bsalomon@google.com } 3034c2443e36fdc6c095b17e90baa4a2f26a6f00b08bsalomon@google.com if (NULL == pr) { 3044c2443e36fdc6c095b17e90baa4a2f26a6f00b08bsalomon@google.com return false; 3054c2443e36fdc6c095b17e90baa4a2f26a6f00b08bsalomon@google.com } 3064c2443e36fdc6c095b17e90baa4a2f26a6f00b08bsalomon@google.com pr->drawPath(element->getPath(), stroke, fGpu, element->isAA()); 3074c2443e36fdc6c095b17e90baa4a2f26a6f00b08bsalomon@google.com break; 3084c2443e36fdc6c095b17e90baa4a2f26a6f00b08bsalomon@google.com } 3098182fa0cac76e7e6d583aebba060229230516887bsalomon@google.com default: 3108182fa0cac76e7e6d583aebba060229230516887bsalomon@google.com // something is wrong if we're trying to draw an empty element. 3118182fa0cac76e7e6d583aebba060229230516887bsalomon@google.com GrCrash("Unexpected element type"); 3128182fa0cac76e7e6d583aebba060229230516887bsalomon@google.com return false; 313f294b773f0b2b9f05eb45b52dd3cb4d97b96af06robertphillips@google.com } 314f294b773f0b2b9f05eb45b52dd3cb4d97b96af06robertphillips@google.com return true; 315f294b773f0b2b9f05eb45b52dd3cb4d97b96af06robertphillips@google.com} 316f294b773f0b2b9f05eb45b52dd3cb4d97b96af06robertphillips@google.com 317b68addd39f3e7183facc70374a133e7a6fb603c5bsalomon@google.combool GrClipMaskManager::canStencilAndDrawElement(GrTexture* target, 318b68addd39f3e7183facc70374a133e7a6fb603c5bsalomon@google.com const SkClipStack::Element* element, 319b68addd39f3e7183facc70374a133e7a6fb603c5bsalomon@google.com GrPathRenderer** pr) { 320b68addd39f3e7183facc70374a133e7a6fb603c5bsalomon@google.com GrDrawState* drawState = fGpu->drawState(); 321b68addd39f3e7183facc70374a133e7a6fb603c5bsalomon@google.com drawState->setRenderTarget(target->asRenderTarget()); 322b68addd39f3e7183facc70374a133e7a6fb603c5bsalomon@google.com 323b68addd39f3e7183facc70374a133e7a6fb603c5bsalomon@google.com switch (element->getType()) { 324b68addd39f3e7183facc70374a133e7a6fb603c5bsalomon@google.com case Element::kRect_Type: 325b68addd39f3e7183facc70374a133e7a6fb603c5bsalomon@google.com return true; 326b68addd39f3e7183facc70374a133e7a6fb603c5bsalomon@google.com case Element::kPath_Type: { 327b68addd39f3e7183facc70374a133e7a6fb603c5bsalomon@google.com SkTCopyOnFirstWrite<SkPath> path(element->getPath()); 328b68addd39f3e7183facc70374a133e7a6fb603c5bsalomon@google.com if (path->isInverseFillType()) { 329b68addd39f3e7183facc70374a133e7a6fb603c5bsalomon@google.com path.writable()->toggleInverseFillType(); 330b68addd39f3e7183facc70374a133e7a6fb603c5bsalomon@google.com } 3315f74cf8c49701f514b69dc6f1a8b5c0ffd78af0asugoi@google.com SkStrokeRec stroke(SkStrokeRec::kFill_InitStyle); 332b68addd39f3e7183facc70374a133e7a6fb603c5bsalomon@google.com GrPathRendererChain::DrawType type = element->isAA() ? 333b68addd39f3e7183facc70374a133e7a6fb603c5bsalomon@google.com GrPathRendererChain::kStencilAndColorAntiAlias_DrawType : 334b68addd39f3e7183facc70374a133e7a6fb603c5bsalomon@google.com GrPathRendererChain::kStencilAndColor_DrawType; 335b68addd39f3e7183facc70374a133e7a6fb603c5bsalomon@google.com *pr = this->getContext()->getPathRenderer(*path, stroke, fGpu, false, type); 336b68addd39f3e7183facc70374a133e7a6fb603c5bsalomon@google.com return NULL != *pr; 337b68addd39f3e7183facc70374a133e7a6fb603c5bsalomon@google.com } 338b68addd39f3e7183facc70374a133e7a6fb603c5bsalomon@google.com default: 339b68addd39f3e7183facc70374a133e7a6fb603c5bsalomon@google.com // something is wrong if we're trying to draw an empty element. 340b68addd39f3e7183facc70374a133e7a6fb603c5bsalomon@google.com GrCrash("Unexpected element type"); 341b68addd39f3e7183facc70374a133e7a6fb603c5bsalomon@google.com return false; 342b68addd39f3e7183facc70374a133e7a6fb603c5bsalomon@google.com } 343b68addd39f3e7183facc70374a133e7a6fb603c5bsalomon@google.com} 344b68addd39f3e7183facc70374a133e7a6fb603c5bsalomon@google.com 3457b7cdd147f5528865238e5ed98c79e6d319fde9bbsalomon@google.comvoid GrClipMaskManager::mergeMask(GrTexture* dstMask, 3467b7cdd147f5528865238e5ed98c79e6d319fde9bbsalomon@google.com GrTexture* srcMask, 3477b7cdd147f5528865238e5ed98c79e6d319fde9bbsalomon@google.com SkRegion::Op op, 348fd03d4a829efe2d77a712fd991927c55f59a2ffecommit-bot@chromium.org const SkIRect& dstBound, 349fd03d4a829efe2d77a712fd991927c55f59a2ffecommit-bot@chromium.org const SkIRect& srcBound) { 350137f1347abaf0bb6a945e91c2f6cb49f0ee69bc3bsalomon@google.com GrDrawState::AutoViewMatrixRestore avmr; 35113b85aab6e1ff2ffd5475e329f9d1d21863b8eb6bsalomon@google.com GrDrawState* drawState = fGpu->drawState(); 352137f1347abaf0bb6a945e91c2f6cb49f0ee69bc3bsalomon@google.com SkAssertResult(avmr.setIdentity(drawState)); 353eb6879f50a5564eeb981ec5616b55bf685eb76fcbsalomon@google.com GrDrawState::AutoRestoreEffects are(drawState); 354f294b773f0b2b9f05eb45b52dd3cb4d97b96af06robertphillips@google.com 3557b7cdd147f5528865238e5ed98c79e6d319fde9bbsalomon@google.com drawState->setRenderTarget(dstMask->asRenderTarget()); 356f294b773f0b2b9f05eb45b52dd3cb4d97b96af06robertphillips@google.com 3577b7cdd147f5528865238e5ed98c79e6d319fde9bbsalomon@google.com setup_boolean_blendcoeffs(drawState, op); 35872b2e6fff3f54c6aa80a98eab4c73f02a8cd450dskia.committer@gmail.com 359b9086a026844e4cfd08b219e49ce3f12294cba98bsalomon@google.com SkMatrix sampleM; 3607b7cdd147f5528865238e5ed98c79e6d319fde9bbsalomon@google.com sampleM.setIDiv(srcMask->width(), srcMask->height()); 361eb6879f50a5564eeb981ec5616b55bf685eb76fcbsalomon@google.com drawState->addColorEffect( 3627b7cdd147f5528865238e5ed98c79e6d319fde9bbsalomon@google.com GrTextureDomainEffect::Create(srcMask, 3637b7cdd147f5528865238e5ed98c79e6d319fde9bbsalomon@google.com sampleM, 3647b7cdd147f5528865238e5ed98c79e6d319fde9bbsalomon@google.com GrTextureDomainEffect::MakeTexelDomain(srcMask, srcBound), 365c78188896e28a4ae49e406a7422b345ae177dafebsalomon@google.com GrTextureDomainEffect::kDecal_WrapMode, 366c78188896e28a4ae49e406a7422b345ae177dafebsalomon@google.com false))->unref(); 3677b7cdd147f5528865238e5ed98c79e6d319fde9bbsalomon@google.com fGpu->drawSimpleRect(SkRect::MakeFromIRect(dstBound), NULL); 368f294b773f0b2b9f05eb45b52dd3cb4d97b96af06robertphillips@google.com} 369f294b773f0b2b9f05eb45b52dd3cb4d97b96af06robertphillips@google.com 3706d62df404bf420bedff4d7b5edd061740a673d44robertphillips@google.com// get a texture to act as a temporary buffer for AA clip boolean operations 3716d62df404bf420bedff4d7b5edd061740a673d44robertphillips@google.com// TODO: given the expense of createTexture we may want to just cache this too 3724c2443e36fdc6c095b17e90baa4a2f26a6f00b08bsalomon@google.comvoid GrClipMaskManager::getTemp(int width, int height, GrAutoScratchTexture* temp) { 373f105b109264f71dfb0bfd9977e6a5dd0a5a12f57robertphillips@google.com if (NULL != temp->texture()) { 3746d62df404bf420bedff4d7b5edd061740a673d44robertphillips@google.com // we've already allocated the temp texture 3756d62df404bf420bedff4d7b5edd061740a673d44robertphillips@google.com return; 3766d62df404bf420bedff4d7b5edd061740a673d44robertphillips@google.com } 3776d62df404bf420bedff4d7b5edd061740a673d44robertphillips@google.com 37875b3c9633cb9a594dab0ccf51dab1e694c149a18robertphillips@google.com GrTextureDesc desc; 37975b3c9633cb9a594dab0ccf51dab1e694c149a18robertphillips@google.com desc.fFlags = kRenderTarget_GrTextureFlagBit|kNoStencil_GrTextureFlagBit; 3804c2443e36fdc6c095b17e90baa4a2f26a6f00b08bsalomon@google.com desc.fWidth = width; 3814c2443e36fdc6c095b17e90baa4a2f26a6f00b08bsalomon@google.com desc.fHeight = height; 38275b3c9633cb9a594dab0ccf51dab1e694c149a18robertphillips@google.com desc.fConfig = kAlpha_8_GrPixelConfig; 3836b70a7bd3328ea0a12be47b1a7f835c905f16147robertphillips@google.com 3842c75681e36b33fcafc5665d7012bbd4fc6647d83robertphillips@google.com temp->set(this->getContext(), desc); 3856d62df404bf420bedff4d7b5edd061740a673d44robertphillips@google.com} 3866d62df404bf420bedff4d7b5edd061740a673d44robertphillips@google.com 3876b70a7bd3328ea0a12be47b1a7f835c905f16147robertphillips@google.com//////////////////////////////////////////////////////////////////////////////// 3884c2443e36fdc6c095b17e90baa4a2f26a6f00b08bsalomon@google.com// Handles caching & allocation (if needed) of a clip alpha-mask texture for both the sw-upload 3894c2443e36fdc6c095b17e90baa4a2f26a6f00b08bsalomon@google.com// or gpu-rendered cases. Returns true if there is no more work to be done (i.e., we got a cache 3904c2443e36fdc6c095b17e90baa4a2f26a6f00b08bsalomon@google.com// hit) 3914c2443e36fdc6c095b17e90baa4a2f26a6f00b08bsalomon@google.combool GrClipMaskManager::getMaskTexture(int32_t clipStackGenID, 3924c2443e36fdc6c095b17e90baa4a2f26a6f00b08bsalomon@google.com const SkIRect& clipSpaceIBounds, 3934c2443e36fdc6c095b17e90baa4a2f26a6f00b08bsalomon@google.com GrTexture** result) { 3944c2443e36fdc6c095b17e90baa4a2f26a6f00b08bsalomon@google.com bool cached = fAACache.canReuse(clipStackGenID, clipSpaceIBounds); 3954c2443e36fdc6c095b17e90baa4a2f26a6f00b08bsalomon@google.com if (!cached) { 3964c2443e36fdc6c095b17e90baa4a2f26a6f00b08bsalomon@google.com 3974c2443e36fdc6c095b17e90baa4a2f26a6f00b08bsalomon@google.com // There isn't a suitable entry in the cache so we create a new texture to store the mask. 3984c2443e36fdc6c095b17e90baa4a2f26a6f00b08bsalomon@google.com // Since we are setting up the cache we know the last lookup was a miss. Free up the 3994c2443e36fdc6c095b17e90baa4a2f26a6f00b08bsalomon@google.com // currently cached mask so it can be reused. 4004c2443e36fdc6c095b17e90baa4a2f26a6f00b08bsalomon@google.com fAACache.reset(); 401f294b773f0b2b9f05eb45b52dd3cb4d97b96af06robertphillips@google.com 4024c2443e36fdc6c095b17e90baa4a2f26a6f00b08bsalomon@google.com GrTextureDesc desc; 403b68addd39f3e7183facc70374a133e7a6fb603c5bsalomon@google.com desc.fFlags = kRenderTarget_GrTextureFlagBit; 4044c2443e36fdc6c095b17e90baa4a2f26a6f00b08bsalomon@google.com desc.fWidth = clipSpaceIBounds.width(); 4054c2443e36fdc6c095b17e90baa4a2f26a6f00b08bsalomon@google.com desc.fHeight = clipSpaceIBounds.height(); 40613f181f28f4336adcc93b7297b6d16503f4c323crobertphillips@google.com desc.fConfig = kRGBA_8888_GrPixelConfig; 40713f181f28f4336adcc93b7297b6d16503f4c323crobertphillips@google.com if (this->getContext()->isConfigRenderable(kAlpha_8_GrPixelConfig)) { 40813f181f28f4336adcc93b7297b6d16503f4c323crobertphillips@google.com // We would always like A8 but it isn't supported on all platforms 40913f181f28f4336adcc93b7297b6d16503f4c323crobertphillips@google.com desc.fConfig = kAlpha_8_GrPixelConfig; 41013f181f28f4336adcc93b7297b6d16503f4c323crobertphillips@google.com } 411a72eef322c686954cdffa849dc26d8133b802f1drobertphillips@google.com 4124c2443e36fdc6c095b17e90baa4a2f26a6f00b08bsalomon@google.com fAACache.acquireMask(clipStackGenID, desc, clipSpaceIBounds); 4138fff356c8505f2ac78e1fc9dc17c1192e3a608e4robertphillips@google.com } 4148fff356c8505f2ac78e1fc9dc17c1192e3a608e4robertphillips@google.com 4154c2443e36fdc6c095b17e90baa4a2f26a6f00b08bsalomon@google.com *result = fAACache.getLastMask(); 4164c2443e36fdc6c095b17e90baa4a2f26a6f00b08bsalomon@google.com return cached; 4176b70a7bd3328ea0a12be47b1a7f835c905f16147robertphillips@google.com} 418f294b773f0b2b9f05eb45b52dd3cb4d97b96af06robertphillips@google.com 4196b70a7bd3328ea0a12be47b1a7f835c905f16147robertphillips@google.com//////////////////////////////////////////////////////////////////////////////// 4206b70a7bd3328ea0a12be47b1a7f835c905f16147robertphillips@google.com// Create a 8-bit clip mask in alpha 4214c2443e36fdc6c095b17e90baa4a2f26a6f00b08bsalomon@google.comGrTexture* GrClipMaskManager::createAlphaClipMask(int32_t clipStackGenID, 4224c2443e36fdc6c095b17e90baa4a2f26a6f00b08bsalomon@google.com InitialState initialState, 4234c2443e36fdc6c095b17e90baa4a2f26a6f00b08bsalomon@google.com const ElementList& elements, 4244c2443e36fdc6c095b17e90baa4a2f26a6f00b08bsalomon@google.com const SkIRect& clipSpaceIBounds) { 425c8f7f47afaf8f9471e6d111655c5610a8bd210a2bsalomon@google.com GrAssert(kNone_ClipMaskType == fCurrClipMaskType); 426c8f7f47afaf8f9471e6d111655c5610a8bd210a2bsalomon@google.com 4274c2443e36fdc6c095b17e90baa4a2f26a6f00b08bsalomon@google.com GrTexture* result; 4284c2443e36fdc6c095b17e90baa4a2f26a6f00b08bsalomon@google.com if (this->getMaskTexture(clipStackGenID, clipSpaceIBounds, &result)) { 429c8f7f47afaf8f9471e6d111655c5610a8bd210a2bsalomon@google.com fCurrClipMaskType = kAlpha_ClipMaskType; 4304c2443e36fdc6c095b17e90baa4a2f26a6f00b08bsalomon@google.com return result; 4316b70a7bd3328ea0a12be47b1a7f835c905f16147robertphillips@google.com } 432f294b773f0b2b9f05eb45b52dd3cb4d97b96af06robertphillips@google.com 4334c2443e36fdc6c095b17e90baa4a2f26a6f00b08bsalomon@google.com if (NULL == result) { 434f105b109264f71dfb0bfd9977e6a5dd0a5a12f57robertphillips@google.com fAACache.reset(); 4354c2443e36fdc6c095b17e90baa4a2f26a6f00b08bsalomon@google.com return NULL; 436f294b773f0b2b9f05eb45b52dd3cb4d97b96af06robertphillips@google.com } 437f294b773f0b2b9f05eb45b52dd3cb4d97b96af06robertphillips@google.com 4384c2443e36fdc6c095b17e90baa4a2f26a6f00b08bsalomon@google.com // The top-left of the mask corresponds to the top-left corner of the bounds. 4397b7cdd147f5528865238e5ed98c79e6d319fde9bbsalomon@google.com SkVector clipToMaskOffset = { 4404c2443e36fdc6c095b17e90baa4a2f26a6f00b08bsalomon@google.com SkIntToScalar(-clipSpaceIBounds.fLeft), 4414c2443e36fdc6c095b17e90baa4a2f26a6f00b08bsalomon@google.com SkIntToScalar(-clipSpaceIBounds.fTop) 4427b7cdd147f5528865238e5ed98c79e6d319fde9bbsalomon@google.com }; 4434c2443e36fdc6c095b17e90baa4a2f26a6f00b08bsalomon@google.com // The texture may be larger than necessary, this rect represents the part of the texture 4444c2443e36fdc6c095b17e90baa4a2f26a6f00b08bsalomon@google.com // we populate with a rasterization of the clip. 4454c2443e36fdc6c095b17e90baa4a2f26a6f00b08bsalomon@google.com SkIRect maskSpaceIBounds = SkIRect::MakeWH(clipSpaceIBounds.width(), clipSpaceIBounds.height()); 446f294b773f0b2b9f05eb45b52dd3cb4d97b96af06robertphillips@google.com 447137f1347abaf0bb6a945e91c2f6cb49f0ee69bc3bsalomon@google.com // Set the matrix so that rendered clip elements are transformed to mask space from clip space. 448137f1347abaf0bb6a945e91c2f6cb49f0ee69bc3bsalomon@google.com SkMatrix translate; 449137f1347abaf0bb6a945e91c2f6cb49f0ee69bc3bsalomon@google.com translate.setTranslate(clipToMaskOffset); 450137f1347abaf0bb6a945e91c2f6cb49f0ee69bc3bsalomon@google.com GrDrawTarget::AutoGeometryAndStatePush agasp(fGpu, GrDrawTarget::kReset_ASRInit, &translate); 451137f1347abaf0bb6a945e91c2f6cb49f0ee69bc3bsalomon@google.com 452137f1347abaf0bb6a945e91c2f6cb49f0ee69bc3bsalomon@google.com GrDrawState* drawState = fGpu->drawState(); 453137f1347abaf0bb6a945e91c2f6cb49f0ee69bc3bsalomon@google.com 454cf939ae54842fc7408ee68a41427086962b4c3dcbsalomon@google.com // We're drawing a coverage mask and want coverage to be run through the blend function. 455cf939ae54842fc7408ee68a41427086962b4c3dcbsalomon@google.com drawState->enableState(GrDrawState::kCoverageDrawing_StateBit); 456cf939ae54842fc7408ee68a41427086962b4c3dcbsalomon@google.com 4577b7cdd147f5528865238e5ed98c79e6d319fde9bbsalomon@google.com // The scratch texture that we are drawing into can be substantially larger than the mask. Only 4587b7cdd147f5528865238e5ed98c79e6d319fde9bbsalomon@google.com // clear the part that we care about. 4594c2443e36fdc6c095b17e90baa4a2f26a6f00b08bsalomon@google.com fGpu->clear(&maskSpaceIBounds, 4604c2443e36fdc6c095b17e90baa4a2f26a6f00b08bsalomon@google.com kAllIn_InitialState == initialState ? 0xffffffff : 0x00000000, 4614c2443e36fdc6c095b17e90baa4a2f26a6f00b08bsalomon@google.com result->asRenderTarget()); 462d9f7503e0cb0c4db856f53b4bdeec1332db6f296skia.committer@gmail.com 463b68addd39f3e7183facc70374a133e7a6fb603c5bsalomon@google.com // When we use the stencil in the below loop it is important to have this clip installed. 464b68addd39f3e7183facc70374a133e7a6fb603c5bsalomon@google.com // The second pass that zeros the stencil buffer renders the rect maskSpaceIBounds so the first 465b68addd39f3e7183facc70374a133e7a6fb603c5bsalomon@google.com // pass must not set values outside of this bounds or stencil values outside the rect won't be 466b68addd39f3e7183facc70374a133e7a6fb603c5bsalomon@google.com // cleared. 467b68addd39f3e7183facc70374a133e7a6fb603c5bsalomon@google.com GrDrawTarget::AutoClipRestore acr(fGpu, maskSpaceIBounds); 468b68addd39f3e7183facc70374a133e7a6fb603c5bsalomon@google.com drawState->enableState(GrDrawState::kClip_StateBit); 469b68addd39f3e7183facc70374a133e7a6fb603c5bsalomon@google.com 470f105b109264f71dfb0bfd9977e6a5dd0a5a12f57robertphillips@google.com GrAutoScratchTexture temp; 471f294b773f0b2b9f05eb45b52dd3cb4d97b96af06robertphillips@google.com // walk through each clip element and perform its set op 4724c2443e36fdc6c095b17e90baa4a2f26a6f00b08bsalomon@google.com for (ElementList::Iter iter = elements.headIter(); iter.get(); iter.next()) { 4734c2443e36fdc6c095b17e90baa4a2f26a6f00b08bsalomon@google.com const Element* element = iter.get(); 4748182fa0cac76e7e6d583aebba060229230516887bsalomon@google.com SkRegion::Op op = element->getOp(); 475b68addd39f3e7183facc70374a133e7a6fb603c5bsalomon@google.com bool invert = element->isInverseFilled(); 476f294b773f0b2b9f05eb45b52dd3cb4d97b96af06robertphillips@google.com 477b68addd39f3e7183facc70374a133e7a6fb603c5bsalomon@google.com if (invert || SkRegion::kIntersect_Op == op || SkRegion::kReverseDifference_Op == op) { 478b68addd39f3e7183facc70374a133e7a6fb603c5bsalomon@google.com GrPathRenderer* pr = NULL; 479b68addd39f3e7183facc70374a133e7a6fb603c5bsalomon@google.com bool useTemp = !this->canStencilAndDrawElement(result, element, &pr); 480b68addd39f3e7183facc70374a133e7a6fb603c5bsalomon@google.com GrTexture* dst; 4814c2443e36fdc6c095b17e90baa4a2f26a6f00b08bsalomon@google.com // This is the bounds of the clip element in the space of the alpha-mask. The temporary 4827b7cdd147f5528865238e5ed98c79e6d319fde9bbsalomon@google.com // mask buffer can be substantially larger than the actually clip stack element. We 4837b7cdd147f5528865238e5ed98c79e6d319fde9bbsalomon@google.com // touch the minimum number of pixels necessary and use decal mode to combine it with 484b68addd39f3e7183facc70374a133e7a6fb603c5bsalomon@google.com // the accumulator. 485fd03d4a829efe2d77a712fd991927c55f59a2ffecommit-bot@chromium.org SkIRect maskSpaceElementIBounds; 486b68addd39f3e7183facc70374a133e7a6fb603c5bsalomon@google.com 487b68addd39f3e7183facc70374a133e7a6fb603c5bsalomon@google.com if (useTemp) { 488b68addd39f3e7183facc70374a133e7a6fb603c5bsalomon@google.com if (invert) { 489b68addd39f3e7183facc70374a133e7a6fb603c5bsalomon@google.com maskSpaceElementIBounds = maskSpaceIBounds; 490b68addd39f3e7183facc70374a133e7a6fb603c5bsalomon@google.com } else { 491fd03d4a829efe2d77a712fd991927c55f59a2ffecommit-bot@chromium.org SkRect elementBounds = element->getBounds(); 492b68addd39f3e7183facc70374a133e7a6fb603c5bsalomon@google.com elementBounds.offset(clipToMaskOffset); 493b68addd39f3e7183facc70374a133e7a6fb603c5bsalomon@google.com elementBounds.roundOut(&maskSpaceElementIBounds); 494b68addd39f3e7183facc70374a133e7a6fb603c5bsalomon@google.com } 495b68addd39f3e7183facc70374a133e7a6fb603c5bsalomon@google.com 496b68addd39f3e7183facc70374a133e7a6fb603c5bsalomon@google.com this->getTemp(maskSpaceIBounds.fRight, maskSpaceIBounds.fBottom, &temp); 497b68addd39f3e7183facc70374a133e7a6fb603c5bsalomon@google.com if (NULL == temp.texture()) { 498b68addd39f3e7183facc70374a133e7a6fb603c5bsalomon@google.com fAACache.reset(); 499b68addd39f3e7183facc70374a133e7a6fb603c5bsalomon@google.com return NULL; 500a7aedfec9e28db36c97e49f11f2bc2e0eb624c30skia.committer@gmail.com } 501b68addd39f3e7183facc70374a133e7a6fb603c5bsalomon@google.com dst = temp.texture(); 502b68addd39f3e7183facc70374a133e7a6fb603c5bsalomon@google.com // clear the temp target and set blend to replace 503b68addd39f3e7183facc70374a133e7a6fb603c5bsalomon@google.com fGpu->clear(&maskSpaceElementIBounds, 504b68addd39f3e7183facc70374a133e7a6fb603c5bsalomon@google.com invert ? 0xffffffff : 0x00000000, 505b68addd39f3e7183facc70374a133e7a6fb603c5bsalomon@google.com dst->asRenderTarget()); 506b68addd39f3e7183facc70374a133e7a6fb603c5bsalomon@google.com setup_boolean_blendcoeffs(drawState, SkRegion::kReplace_Op); 507a7aedfec9e28db36c97e49f11f2bc2e0eb624c30skia.committer@gmail.com 5084c2443e36fdc6c095b17e90baa4a2f26a6f00b08bsalomon@google.com } else { 509b68addd39f3e7183facc70374a133e7a6fb603c5bsalomon@google.com // draw directly into the result with the stencil set to make the pixels affected 510b68addd39f3e7183facc70374a133e7a6fb603c5bsalomon@google.com // by the clip shape be non-zero. 511b68addd39f3e7183facc70374a133e7a6fb603c5bsalomon@google.com dst = result; 512b68addd39f3e7183facc70374a133e7a6fb603c5bsalomon@google.com GR_STATIC_CONST_SAME_STENCIL(kStencilInElement, 513b68addd39f3e7183facc70374a133e7a6fb603c5bsalomon@google.com kReplace_StencilOp, 514b68addd39f3e7183facc70374a133e7a6fb603c5bsalomon@google.com kReplace_StencilOp, 515b68addd39f3e7183facc70374a133e7a6fb603c5bsalomon@google.com kAlways_StencilFunc, 516b68addd39f3e7183facc70374a133e7a6fb603c5bsalomon@google.com 0xffff, 517b68addd39f3e7183facc70374a133e7a6fb603c5bsalomon@google.com 0xffff, 518b68addd39f3e7183facc70374a133e7a6fb603c5bsalomon@google.com 0xffff); 519b68addd39f3e7183facc70374a133e7a6fb603c5bsalomon@google.com drawState->setStencil(kStencilInElement); 520a7aedfec9e28db36c97e49f11f2bc2e0eb624c30skia.committer@gmail.com setup_boolean_blendcoeffs(drawState, op); 5214c2443e36fdc6c095b17e90baa4a2f26a6f00b08bsalomon@google.com } 5227b7cdd147f5528865238e5ed98c79e6d319fde9bbsalomon@google.com 523c6b3e48cb3a22d83ba3f4b9a614a5a35b05958a0bsalomon@google.com drawState->setAlpha(invert ? 0x00 : 0xff); 524c6b3e48cb3a22d83ba3f4b9a614a5a35b05958a0bsalomon@google.com 525b68addd39f3e7183facc70374a133e7a6fb603c5bsalomon@google.com if (!this->drawElement(dst, element, pr)) { 5264c2443e36fdc6c095b17e90baa4a2f26a6f00b08bsalomon@google.com fAACache.reset(); 5274c2443e36fdc6c095b17e90baa4a2f26a6f00b08bsalomon@google.com return NULL; 5284c2443e36fdc6c095b17e90baa4a2f26a6f00b08bsalomon@google.com } 529f294b773f0b2b9f05eb45b52dd3cb4d97b96af06robertphillips@google.com 530b68addd39f3e7183facc70374a133e7a6fb603c5bsalomon@google.com if (useTemp) { 531b68addd39f3e7183facc70374a133e7a6fb603c5bsalomon@google.com // Now draw into the accumulator using the real operation and the temp buffer as a 532b68addd39f3e7183facc70374a133e7a6fb603c5bsalomon@google.com // texture 533b68addd39f3e7183facc70374a133e7a6fb603c5bsalomon@google.com this->mergeMask(result, 534b68addd39f3e7183facc70374a133e7a6fb603c5bsalomon@google.com temp.texture(), 535b68addd39f3e7183facc70374a133e7a6fb603c5bsalomon@google.com op, 536b68addd39f3e7183facc70374a133e7a6fb603c5bsalomon@google.com maskSpaceIBounds, 537b68addd39f3e7183facc70374a133e7a6fb603c5bsalomon@google.com maskSpaceElementIBounds); 538b68addd39f3e7183facc70374a133e7a6fb603c5bsalomon@google.com } else { 539b68addd39f3e7183facc70374a133e7a6fb603c5bsalomon@google.com // Draw to the exterior pixels (those with a zero stencil value). 540b68addd39f3e7183facc70374a133e7a6fb603c5bsalomon@google.com drawState->setAlpha(invert ? 0xff : 0x00); 541b68addd39f3e7183facc70374a133e7a6fb603c5bsalomon@google.com GR_STATIC_CONST_SAME_STENCIL(kDrawOutsideElement, 542b68addd39f3e7183facc70374a133e7a6fb603c5bsalomon@google.com kZero_StencilOp, 543b68addd39f3e7183facc70374a133e7a6fb603c5bsalomon@google.com kZero_StencilOp, 544b68addd39f3e7183facc70374a133e7a6fb603c5bsalomon@google.com kEqual_StencilFunc, 545b68addd39f3e7183facc70374a133e7a6fb603c5bsalomon@google.com 0xffff, 546b68addd39f3e7183facc70374a133e7a6fb603c5bsalomon@google.com 0x0000, 547b68addd39f3e7183facc70374a133e7a6fb603c5bsalomon@google.com 0xffff); 548b68addd39f3e7183facc70374a133e7a6fb603c5bsalomon@google.com drawState->setStencil(kDrawOutsideElement); 549b68addd39f3e7183facc70374a133e7a6fb603c5bsalomon@google.com fGpu->drawSimpleRect(clipSpaceIBounds); 550b68addd39f3e7183facc70374a133e7a6fb603c5bsalomon@google.com drawState->disableStencil(); 551b68addd39f3e7183facc70374a133e7a6fb603c5bsalomon@google.com } 552f294b773f0b2b9f05eb45b52dd3cb4d97b96af06robertphillips@google.com } else { 553c6b3e48cb3a22d83ba3f4b9a614a5a35b05958a0bsalomon@google.com // all the remaining ops can just be directly draw into the accumulation buffer 554c6b3e48cb3a22d83ba3f4b9a614a5a35b05958a0bsalomon@google.com drawState->setAlpha(0xff); 5556b70a7bd3328ea0a12be47b1a7f835c905f16147robertphillips@google.com setup_boolean_blendcoeffs(drawState, op); 556b68addd39f3e7183facc70374a133e7a6fb603c5bsalomon@google.com this->drawElement(result, element); 557f294b773f0b2b9f05eb45b52dd3cb4d97b96af06robertphillips@google.com } 558f294b773f0b2b9f05eb45b52dd3cb4d97b96af06robertphillips@google.com } 559f294b773f0b2b9f05eb45b52dd3cb4d97b96af06robertphillips@google.com 560c8f7f47afaf8f9471e6d111655c5610a8bd210a2bsalomon@google.com fCurrClipMaskType = kAlpha_ClipMaskType; 5614c2443e36fdc6c095b17e90baa4a2f26a6f00b08bsalomon@google.com return result; 5621e945b7e708c633d4aed937ebfce57d52ba21d83robertphillips@google.com} 5631e945b7e708c633d4aed937ebfce57d52ba21d83robertphillips@google.com 564f294b773f0b2b9f05eb45b52dd3cb4d97b96af06robertphillips@google.com//////////////////////////////////////////////////////////////////////////////// 565fbfcd5602128ec010c82cb733c9cdc0a3254f9f3rmistry@google.com// Create a 1-bit clip mask in the stencil buffer. 'devClipBounds' are in device 566f8d904a7eed435b9de68fd2eef6d7f3c59fcc9ccrobertphillips@google.com// (as opposed to canvas) coordinates 5674c2443e36fdc6c095b17e90baa4a2f26a6f00b08bsalomon@google.combool GrClipMaskManager::createStencilClipMask(InitialState initialState, 5684c2443e36fdc6c095b17e90baa4a2f26a6f00b08bsalomon@google.com const ElementList& elements, 5694c2443e36fdc6c095b17e90baa4a2f26a6f00b08bsalomon@google.com const SkIRect& clipSpaceIBounds, 5704c2443e36fdc6c095b17e90baa4a2f26a6f00b08bsalomon@google.com const SkIPoint& clipSpaceToStencilOffset) { 5711e945b7e708c633d4aed937ebfce57d52ba21d83robertphillips@google.com 572c8f7f47afaf8f9471e6d111655c5610a8bd210a2bsalomon@google.com GrAssert(kNone_ClipMaskType == fCurrClipMaskType); 5731e945b7e708c633d4aed937ebfce57d52ba21d83robertphillips@google.com 57413b85aab6e1ff2ffd5475e329f9d1d21863b8eb6bsalomon@google.com GrDrawState* drawState = fGpu->drawState(); 5751e945b7e708c633d4aed937ebfce57d52ba21d83robertphillips@google.com GrAssert(drawState->isClipState()); 5761e945b7e708c633d4aed937ebfce57d52ba21d83robertphillips@google.com 5771e945b7e708c633d4aed937ebfce57d52ba21d83robertphillips@google.com GrRenderTarget* rt = drawState->getRenderTarget(); 5781e945b7e708c633d4aed937ebfce57d52ba21d83robertphillips@google.com GrAssert(NULL != rt); 5791e945b7e708c633d4aed937ebfce57d52ba21d83robertphillips@google.com 5801e945b7e708c633d4aed937ebfce57d52ba21d83robertphillips@google.com // TODO: dynamically attach a SB when needed. 5811e945b7e708c633d4aed937ebfce57d52ba21d83robertphillips@google.com GrStencilBuffer* stencilBuffer = rt->getStencilBuffer(); 5821e945b7e708c633d4aed937ebfce57d52ba21d83robertphillips@google.com if (NULL == stencilBuffer) { 5831e945b7e708c633d4aed937ebfce57d52ba21d83robertphillips@google.com return false; 5841e945b7e708c633d4aed937ebfce57d52ba21d83robertphillips@google.com } 5854c2443e36fdc6c095b17e90baa4a2f26a6f00b08bsalomon@google.com int32_t genID = elements.tail()->getGenID(); 5861e945b7e708c633d4aed937ebfce57d52ba21d83robertphillips@google.com 5874c2443e36fdc6c095b17e90baa4a2f26a6f00b08bsalomon@google.com if (stencilBuffer->mustRenderClip(genID, clipSpaceIBounds, clipSpaceToStencilOffset)) { 5881e945b7e708c633d4aed937ebfce57d52ba21d83robertphillips@google.com 5894c2443e36fdc6c095b17e90baa4a2f26a6f00b08bsalomon@google.com stencilBuffer->setLastClip(genID, clipSpaceIBounds, clipSpaceToStencilOffset); 5901e945b7e708c633d4aed937ebfce57d52ba21d83robertphillips@google.com 591137f1347abaf0bb6a945e91c2f6cb49f0ee69bc3bsalomon@google.com // Set the matrix so that rendered clip elements are transformed from clip to stencil space. 592137f1347abaf0bb6a945e91c2f6cb49f0ee69bc3bsalomon@google.com SkVector translate = { 593137f1347abaf0bb6a945e91c2f6cb49f0ee69bc3bsalomon@google.com SkIntToScalar(clipSpaceToStencilOffset.fX), 594137f1347abaf0bb6a945e91c2f6cb49f0ee69bc3bsalomon@google.com SkIntToScalar(clipSpaceToStencilOffset.fY) 595137f1347abaf0bb6a945e91c2f6cb49f0ee69bc3bsalomon@google.com }; 596137f1347abaf0bb6a945e91c2f6cb49f0ee69bc3bsalomon@google.com SkMatrix matrix; 597137f1347abaf0bb6a945e91c2f6cb49f0ee69bc3bsalomon@google.com matrix.setTranslate(translate); 598137f1347abaf0bb6a945e91c2f6cb49f0ee69bc3bsalomon@google.com GrDrawTarget::AutoGeometryAndStatePush agasp(fGpu, GrDrawTarget::kReset_ASRInit, &matrix); 59913b85aab6e1ff2ffd5475e329f9d1d21863b8eb6bsalomon@google.com drawState = fGpu->drawState(); 600137f1347abaf0bb6a945e91c2f6cb49f0ee69bc3bsalomon@google.com 6011e945b7e708c633d4aed937ebfce57d52ba21d83robertphillips@google.com drawState->setRenderTarget(rt); 6021e945b7e708c633d4aed937ebfce57d52ba21d83robertphillips@google.com 6039f13174da5295e88d447f29740318003b9cec9c3bsalomon@google.com // We set the current clip to the bounds so that our recursive draws are scissored to them. 6049f13174da5295e88d447f29740318003b9cec9c3bsalomon@google.com SkIRect stencilSpaceIBounds(clipSpaceIBounds); 6059f13174da5295e88d447f29740318003b9cec9c3bsalomon@google.com stencilSpaceIBounds.offset(clipSpaceToStencilOffset); 6069f13174da5295e88d447f29740318003b9cec9c3bsalomon@google.com GrDrawTarget::AutoClipRestore acr(fGpu, stencilSpaceIBounds); 6079f13174da5295e88d447f29740318003b9cec9c3bsalomon@google.com drawState->enableState(GrDrawState::kClip_StateBit); 6089f13174da5295e88d447f29740318003b9cec9c3bsalomon@google.com 6091e945b7e708c633d4aed937ebfce57d52ba21d83robertphillips@google.com#if !VISUALIZE_COMPLEX_CLIP 6101e945b7e708c633d4aed937ebfce57d52ba21d83robertphillips@google.com drawState->enableState(GrDrawState::kNoColorWrites_StateBit); 6111e945b7e708c633d4aed937ebfce57d52ba21d83robertphillips@google.com#endif 6121e945b7e708c633d4aed937ebfce57d52ba21d83robertphillips@google.com 6131e945b7e708c633d4aed937ebfce57d52ba21d83robertphillips@google.com int clipBit = stencilBuffer->bits(); 6144c2443e36fdc6c095b17e90baa4a2f26a6f00b08bsalomon@google.com SkASSERT((clipBit <= 16) && "Ganesh only handles 16b or smaller stencil buffers"); 6151e945b7e708c633d4aed937ebfce57d52ba21d83robertphillips@google.com clipBit = (1 << (clipBit-1)); 6161e945b7e708c633d4aed937ebfce57d52ba21d83robertphillips@google.com 6174c2443e36fdc6c095b17e90baa4a2f26a6f00b08bsalomon@google.com fGpu->clearStencilClip(stencilSpaceIBounds, kAllIn_InitialState == initialState); 6181e945b7e708c633d4aed937ebfce57d52ba21d83robertphillips@google.com 6191e945b7e708c633d4aed937ebfce57d52ba21d83robertphillips@google.com // walk through each clip element and perform its set op 6201e945b7e708c633d4aed937ebfce57d52ba21d83robertphillips@google.com // with the existing clip. 6214c2443e36fdc6c095b17e90baa4a2f26a6f00b08bsalomon@google.com for (ElementList::Iter iter(elements.headIter()); NULL != iter.get(); iter.next()) { 6224c2443e36fdc6c095b17e90baa4a2f26a6f00b08bsalomon@google.com const Element* element = iter.get(); 6238afae61a57f87e4a50578effce6c428031499301tomhudson@google.com bool fillInverted = false; 6241e945b7e708c633d4aed937ebfce57d52ba21d83robertphillips@google.com // enabled at bottom of loop 6251e945b7e708c633d4aed937ebfce57d52ba21d83robertphillips@google.com drawState->disableState(GrGpu::kModifyStencilClip_StateBit); 626ded4f4b163f5aa19c22c871178c55ecb34623846bsalomon@google.com // if the target is MSAA then we want MSAA enabled when the clip is soft 627ded4f4b163f5aa19c22c871178c55ecb34623846bsalomon@google.com if (rt->isMultisampled()) { 6288182fa0cac76e7e6d583aebba060229230516887bsalomon@google.com drawState->setState(GrDrawState::kHWAntialias_StateBit, element->isAA()); 629ded4f4b163f5aa19c22c871178c55ecb34623846bsalomon@google.com } 6301e945b7e708c633d4aed937ebfce57d52ba21d83robertphillips@google.com 63145a15f551b5b3c6c747d8eaf6466b7d3b76a8faebsalomon@google.com // This will be used to determine whether the clip shape can be rendered into the 63245a15f551b5b3c6c747d8eaf6466b7d3b76a8faebsalomon@google.com // stencil with arbitrary stencil settings. 63345a15f551b5b3c6c747d8eaf6466b7d3b76a8faebsalomon@google.com GrPathRenderer::StencilSupport stencilSupport; 6341e945b7e708c633d4aed937ebfce57d52ba21d83robertphillips@google.com 6355f74cf8c49701f514b69dc6f1a8b5c0ffd78af0asugoi@google.com SkStrokeRec stroke(SkStrokeRec::kFill_InitStyle); 63612b4e27ae1a29460e91a59f38122483e1faec697sugoi@google.com 6378182fa0cac76e7e6d583aebba060229230516887bsalomon@google.com SkRegion::Op op = element->getOp(); 638f294b773f0b2b9f05eb45b52dd3cb4d97b96af06robertphillips@google.com 6391e945b7e708c633d4aed937ebfce57d52ba21d83robertphillips@google.com GrPathRenderer* pr = NULL; 64045a15f551b5b3c6c747d8eaf6466b7d3b76a8faebsalomon@google.com SkTCopyOnFirstWrite<SkPath> clipPath; 6418182fa0cac76e7e6d583aebba060229230516887bsalomon@google.com if (Element::kRect_Type == element->getType()) { 64245a15f551b5b3c6c747d8eaf6466b7d3b76a8faebsalomon@google.com stencilSupport = GrPathRenderer::kNoRestriction_StencilSupport; 6431e945b7e708c633d4aed937ebfce57d52ba21d83robertphillips@google.com fillInverted = false; 6448afae61a57f87e4a50578effce6c428031499301tomhudson@google.com } else { 6458182fa0cac76e7e6d583aebba060229230516887bsalomon@google.com GrAssert(Element::kPath_Type == element->getType()); 64645a15f551b5b3c6c747d8eaf6466b7d3b76a8faebsalomon@google.com clipPath.init(element->getPath()); 64745a15f551b5b3c6c747d8eaf6466b7d3b76a8faebsalomon@google.com fillInverted = clipPath->isInverseFillType(); 64845a15f551b5b3c6c747d8eaf6466b7d3b76a8faebsalomon@google.com if (fillInverted) { 64945a15f551b5b3c6c747d8eaf6466b7d3b76a8faebsalomon@google.com clipPath.writable()->toggleInverseFillType(); 65045a15f551b5b3c6c747d8eaf6466b7d3b76a8faebsalomon@google.com } 65145a15f551b5b3c6c747d8eaf6466b7d3b76a8faebsalomon@google.com pr = this->getContext()->getPathRenderer(*clipPath, 65245a15f551b5b3c6c747d8eaf6466b7d3b76a8faebsalomon@google.com stroke, 65345a15f551b5b3c6c747d8eaf6466b7d3b76a8faebsalomon@google.com fGpu, 65445a15f551b5b3c6c747d8eaf6466b7d3b76a8faebsalomon@google.com false, 65545a15f551b5b3c6c747d8eaf6466b7d3b76a8faebsalomon@google.com GrPathRendererChain::kStencilOnly_DrawType, 65645a15f551b5b3c6c747d8eaf6466b7d3b76a8faebsalomon@google.com &stencilSupport); 6571e945b7e708c633d4aed937ebfce57d52ba21d83robertphillips@google.com if (NULL == pr) { 6581e945b7e708c633d4aed937ebfce57d52ba21d83robertphillips@google.com return false; 6591e945b7e708c633d4aed937ebfce57d52ba21d83robertphillips@google.com } 6601e945b7e708c633d4aed937ebfce57d52ba21d83robertphillips@google.com } 6611e945b7e708c633d4aed937ebfce57d52ba21d83robertphillips@google.com 6621e945b7e708c633d4aed937ebfce57d52ba21d83robertphillips@google.com int passes; 6631e945b7e708c633d4aed937ebfce57d52ba21d83robertphillips@google.com GrStencilSettings stencilSettings[GrStencilSettings::kMaxStencilClipPasses]; 6641e945b7e708c633d4aed937ebfce57d52ba21d83robertphillips@google.com 66545a15f551b5b3c6c747d8eaf6466b7d3b76a8faebsalomon@google.com bool canRenderDirectToStencil = 66645a15f551b5b3c6c747d8eaf6466b7d3b76a8faebsalomon@google.com GrPathRenderer::kNoRestriction_StencilSupport == stencilSupport; 6671e945b7e708c633d4aed937ebfce57d52ba21d83robertphillips@google.com bool canDrawDirectToClip; // Given the renderer, the element, 6684c2443e36fdc6c095b17e90baa4a2f26a6f00b08bsalomon@google.com // fill rule, and set operation can 6694c2443e36fdc6c095b17e90baa4a2f26a6f00b08bsalomon@google.com // we render the element directly to 6704c2443e36fdc6c095b17e90baa4a2f26a6f00b08bsalomon@google.com // stencil bit used for clipping. 6714c2443e36fdc6c095b17e90baa4a2f26a6f00b08bsalomon@google.com canDrawDirectToClip = GrStencilSettings::GetClipPasses(op, 6724c2443e36fdc6c095b17e90baa4a2f26a6f00b08bsalomon@google.com canRenderDirectToStencil, 6734c2443e36fdc6c095b17e90baa4a2f26a6f00b08bsalomon@google.com clipBit, 6744c2443e36fdc6c095b17e90baa4a2f26a6f00b08bsalomon@google.com fillInverted, 6754c2443e36fdc6c095b17e90baa4a2f26a6f00b08bsalomon@google.com &passes, 6764c2443e36fdc6c095b17e90baa4a2f26a6f00b08bsalomon@google.com stencilSettings); 6771e945b7e708c633d4aed937ebfce57d52ba21d83robertphillips@google.com 6781e945b7e708c633d4aed937ebfce57d52ba21d83robertphillips@google.com // draw the element to the client stencil bits if necessary 6791e945b7e708c633d4aed937ebfce57d52ba21d83robertphillips@google.com if (!canDrawDirectToClip) { 6801e945b7e708c633d4aed937ebfce57d52ba21d83robertphillips@google.com GR_STATIC_CONST_SAME_STENCIL(gDrawToStencil, 6814c2443e36fdc6c095b17e90baa4a2f26a6f00b08bsalomon@google.com kIncClamp_StencilOp, 6824c2443e36fdc6c095b17e90baa4a2f26a6f00b08bsalomon@google.com kIncClamp_StencilOp, 6834c2443e36fdc6c095b17e90baa4a2f26a6f00b08bsalomon@google.com kAlways_StencilFunc, 6844c2443e36fdc6c095b17e90baa4a2f26a6f00b08bsalomon@google.com 0xffff, 6854c2443e36fdc6c095b17e90baa4a2f26a6f00b08bsalomon@google.com 0x0000, 6864c2443e36fdc6c095b17e90baa4a2f26a6f00b08bsalomon@google.com 0xffff); 6871e945b7e708c633d4aed937ebfce57d52ba21d83robertphillips@google.com SET_RANDOM_COLOR 6888182fa0cac76e7e6d583aebba060229230516887bsalomon@google.com if (Element::kRect_Type == element->getType()) { 6891e945b7e708c633d4aed937ebfce57d52ba21d83robertphillips@google.com *drawState->stencil() = gDrawToStencil; 6908182fa0cac76e7e6d583aebba060229230516887bsalomon@google.com fGpu->drawSimpleRect(element->getRect(), NULL); 6911e945b7e708c633d4aed937ebfce57d52ba21d83robertphillips@google.com } else { 6928182fa0cac76e7e6d583aebba060229230516887bsalomon@google.com GrAssert(Element::kPath_Type == element->getType()); 6931e945b7e708c633d4aed937ebfce57d52ba21d83robertphillips@google.com if (canRenderDirectToStencil) { 6941e945b7e708c633d4aed937ebfce57d52ba21d83robertphillips@google.com *drawState->stencil() = gDrawToStencil; 69545a15f551b5b3c6c747d8eaf6466b7d3b76a8faebsalomon@google.com pr->drawPath(*clipPath, stroke, fGpu, false); 6961e945b7e708c633d4aed937ebfce57d52ba21d83robertphillips@google.com } else { 69745a15f551b5b3c6c747d8eaf6466b7d3b76a8faebsalomon@google.com pr->stencilPath(*clipPath, stroke, fGpu); 6981e945b7e708c633d4aed937ebfce57d52ba21d83robertphillips@google.com } 6991e945b7e708c633d4aed937ebfce57d52ba21d83robertphillips@google.com } 7001e945b7e708c633d4aed937ebfce57d52ba21d83robertphillips@google.com } 7011e945b7e708c633d4aed937ebfce57d52ba21d83robertphillips@google.com 7021e945b7e708c633d4aed937ebfce57d52ba21d83robertphillips@google.com // now we modify the clip bit by rendering either the clip 7031e945b7e708c633d4aed937ebfce57d52ba21d83robertphillips@google.com // element directly or a bounding rect of the entire clip. 7041e945b7e708c633d4aed937ebfce57d52ba21d83robertphillips@google.com drawState->enableState(GrGpu::kModifyStencilClip_StateBit); 7051e945b7e708c633d4aed937ebfce57d52ba21d83robertphillips@google.com for (int p = 0; p < passes; ++p) { 7061e945b7e708c633d4aed937ebfce57d52ba21d83robertphillips@google.com *drawState->stencil() = stencilSettings[p]; 7071e945b7e708c633d4aed937ebfce57d52ba21d83robertphillips@google.com if (canDrawDirectToClip) { 7088182fa0cac76e7e6d583aebba060229230516887bsalomon@google.com if (Element::kRect_Type == element->getType()) { 7091e945b7e708c633d4aed937ebfce57d52ba21d83robertphillips@google.com SET_RANDOM_COLOR 7108182fa0cac76e7e6d583aebba060229230516887bsalomon@google.com fGpu->drawSimpleRect(element->getRect(), NULL); 7111e945b7e708c633d4aed937ebfce57d52ba21d83robertphillips@google.com } else { 7128182fa0cac76e7e6d583aebba060229230516887bsalomon@google.com GrAssert(Element::kPath_Type == element->getType()); 7131e945b7e708c633d4aed937ebfce57d52ba21d83robertphillips@google.com SET_RANDOM_COLOR 71445a15f551b5b3c6c747d8eaf6466b7d3b76a8faebsalomon@google.com pr->drawPath(*clipPath, stroke, fGpu, false); 7151e945b7e708c633d4aed937ebfce57d52ba21d83robertphillips@google.com } 7161e945b7e708c633d4aed937ebfce57d52ba21d83robertphillips@google.com } else { 7171e945b7e708c633d4aed937ebfce57d52ba21d83robertphillips@google.com SET_RANDOM_COLOR 7184c2443e36fdc6c095b17e90baa4a2f26a6f00b08bsalomon@google.com // The view matrix is setup to do clip space -> stencil space translation, so 7194c2443e36fdc6c095b17e90baa4a2f26a6f00b08bsalomon@google.com // draw rect in clip space. 7204c2443e36fdc6c095b17e90baa4a2f26a6f00b08bsalomon@google.com fGpu->drawSimpleRect(SkRect::MakeFromIRect(clipSpaceIBounds), NULL); 7211e945b7e708c633d4aed937ebfce57d52ba21d83robertphillips@google.com } 7221e945b7e708c633d4aed937ebfce57d52ba21d83robertphillips@google.com } 7231e945b7e708c633d4aed937ebfce57d52ba21d83robertphillips@google.com } 7241e945b7e708c633d4aed937ebfce57d52ba21d83robertphillips@google.com } 725c8f7f47afaf8f9471e6d111655c5610a8bd210a2bsalomon@google.com // set this last because recursive draws may overwrite it back to kNone. 726c8f7f47afaf8f9471e6d111655c5610a8bd210a2bsalomon@google.com GrAssert(kNone_ClipMaskType == fCurrClipMaskType); 727c8f7f47afaf8f9471e6d111655c5610a8bd210a2bsalomon@google.com fCurrClipMaskType = kStencil_ClipMaskType; 7281e945b7e708c633d4aed937ebfce57d52ba21d83robertphillips@google.com return true; 7291e945b7e708c633d4aed937ebfce57d52ba21d83robertphillips@google.com} 7301e945b7e708c633d4aed937ebfce57d52ba21d83robertphillips@google.com 731f8d904a7eed435b9de68fd2eef6d7f3c59fcc9ccrobertphillips@google.com 732411dad0630913fc07f2412b4be17acfbfd914fbcbsalomon@google.com// mapping of clip-respecting stencil funcs to normal stencil funcs 733411dad0630913fc07f2412b4be17acfbfd914fbcbsalomon@google.com// mapping depends on whether stencil-clipping is in effect. 734fbfcd5602128ec010c82cb733c9cdc0a3254f9f3rmistry@google.comstatic const GrStencilFunc 735411dad0630913fc07f2412b4be17acfbfd914fbcbsalomon@google.com gSpecialToBasicStencilFunc[2][kClipStencilFuncCount] = { 736411dad0630913fc07f2412b4be17acfbfd914fbcbsalomon@google.com {// Stencil-Clipping is DISABLED, we are effectively always inside the clip 737411dad0630913fc07f2412b4be17acfbfd914fbcbsalomon@google.com // In the Clip Funcs 738411dad0630913fc07f2412b4be17acfbfd914fbcbsalomon@google.com kAlways_StencilFunc, // kAlwaysIfInClip_StencilFunc 739411dad0630913fc07f2412b4be17acfbfd914fbcbsalomon@google.com kEqual_StencilFunc, // kEqualIfInClip_StencilFunc 740411dad0630913fc07f2412b4be17acfbfd914fbcbsalomon@google.com kLess_StencilFunc, // kLessIfInClip_StencilFunc 741411dad0630913fc07f2412b4be17acfbfd914fbcbsalomon@google.com kLEqual_StencilFunc, // kLEqualIfInClip_StencilFunc 742411dad0630913fc07f2412b4be17acfbfd914fbcbsalomon@google.com // Special in the clip func that forces user's ref to be 0. 743411dad0630913fc07f2412b4be17acfbfd914fbcbsalomon@google.com kNotEqual_StencilFunc, // kNonZeroIfInClip_StencilFunc 744411dad0630913fc07f2412b4be17acfbfd914fbcbsalomon@google.com // make ref 0 and do normal nequal. 745411dad0630913fc07f2412b4be17acfbfd914fbcbsalomon@google.com }, 746411dad0630913fc07f2412b4be17acfbfd914fbcbsalomon@google.com {// Stencil-Clipping is ENABLED 747411dad0630913fc07f2412b4be17acfbfd914fbcbsalomon@google.com // In the Clip Funcs 748411dad0630913fc07f2412b4be17acfbfd914fbcbsalomon@google.com kEqual_StencilFunc, // kAlwaysIfInClip_StencilFunc 749411dad0630913fc07f2412b4be17acfbfd914fbcbsalomon@google.com // eq stencil clip bit, mask 750411dad0630913fc07f2412b4be17acfbfd914fbcbsalomon@google.com // out user bits. 751411dad0630913fc07f2412b4be17acfbfd914fbcbsalomon@google.com 752411dad0630913fc07f2412b4be17acfbfd914fbcbsalomon@google.com kEqual_StencilFunc, // kEqualIfInClip_StencilFunc 753411dad0630913fc07f2412b4be17acfbfd914fbcbsalomon@google.com // add stencil bit to mask and ref 754411dad0630913fc07f2412b4be17acfbfd914fbcbsalomon@google.com 755411dad0630913fc07f2412b4be17acfbfd914fbcbsalomon@google.com kLess_StencilFunc, // kLessIfInClip_StencilFunc 756411dad0630913fc07f2412b4be17acfbfd914fbcbsalomon@google.com kLEqual_StencilFunc, // kLEqualIfInClip_StencilFunc 757411dad0630913fc07f2412b4be17acfbfd914fbcbsalomon@google.com // for both of these we can add 758411dad0630913fc07f2412b4be17acfbfd914fbcbsalomon@google.com // the clip bit to the mask and 759411dad0630913fc07f2412b4be17acfbfd914fbcbsalomon@google.com // ref and compare as normal 760411dad0630913fc07f2412b4be17acfbfd914fbcbsalomon@google.com // Special in the clip func that forces user's ref to be 0. 761411dad0630913fc07f2412b4be17acfbfd914fbcbsalomon@google.com kLess_StencilFunc, // kNonZeroIfInClip_StencilFunc 762411dad0630913fc07f2412b4be17acfbfd914fbcbsalomon@google.com // make ref have only the clip bit set 763411dad0630913fc07f2412b4be17acfbfd914fbcbsalomon@google.com // and make comparison be less 764411dad0630913fc07f2412b4be17acfbfd914fbcbsalomon@google.com // 10..0 < 1..user_bits.. 765411dad0630913fc07f2412b4be17acfbfd914fbcbsalomon@google.com } 766411dad0630913fc07f2412b4be17acfbfd914fbcbsalomon@google.com}; 767411dad0630913fc07f2412b4be17acfbfd914fbcbsalomon@google.com 768a320194e4242ef0e5e758aea896bfd52bcb3dac7bsalomon@google.comnamespace { 769a320194e4242ef0e5e758aea896bfd52bcb3dac7bsalomon@google.com// Sets the settings to clip against the stencil buffer clip while ignoring the 770a320194e4242ef0e5e758aea896bfd52bcb3dac7bsalomon@google.com// client bits. 771a320194e4242ef0e5e758aea896bfd52bcb3dac7bsalomon@google.comconst GrStencilSettings& basic_apply_stencil_clip_settings() { 772a320194e4242ef0e5e758aea896bfd52bcb3dac7bsalomon@google.com // stencil settings to use when clip is in stencil 773a320194e4242ef0e5e758aea896bfd52bcb3dac7bsalomon@google.com GR_STATIC_CONST_SAME_STENCIL_STRUCT(gSettings, 774a320194e4242ef0e5e758aea896bfd52bcb3dac7bsalomon@google.com kKeep_StencilOp, 775a320194e4242ef0e5e758aea896bfd52bcb3dac7bsalomon@google.com kKeep_StencilOp, 776a320194e4242ef0e5e758aea896bfd52bcb3dac7bsalomon@google.com kAlwaysIfInClip_StencilFunc, 777a320194e4242ef0e5e758aea896bfd52bcb3dac7bsalomon@google.com 0x0000, 778a320194e4242ef0e5e758aea896bfd52bcb3dac7bsalomon@google.com 0x0000, 779fbfcd5602128ec010c82cb733c9cdc0a3254f9f3rmistry@google.com 0x0000); 780a320194e4242ef0e5e758aea896bfd52bcb3dac7bsalomon@google.com return *GR_CONST_STENCIL_SETTINGS_PTR_FROM_STRUCT_PTR(&gSettings); 781a320194e4242ef0e5e758aea896bfd52bcb3dac7bsalomon@google.com} 782a320194e4242ef0e5e758aea896bfd52bcb3dac7bsalomon@google.com} 783a320194e4242ef0e5e758aea896bfd52bcb3dac7bsalomon@google.com 784a320194e4242ef0e5e758aea896bfd52bcb3dac7bsalomon@google.comvoid GrClipMaskManager::setGpuStencil() { 785a320194e4242ef0e5e758aea896bfd52bcb3dac7bsalomon@google.com // We make two copies of the StencilSettings here (except in the early 786a320194e4242ef0e5e758aea896bfd52bcb3dac7bsalomon@google.com // exit scenario. One copy from draw state to the stack var. Then another 787a320194e4242ef0e5e758aea896bfd52bcb3dac7bsalomon@google.com // from the stack var to the gpu. We could make this class hold a ptr to 788a320194e4242ef0e5e758aea896bfd52bcb3dac7bsalomon@google.com // GrGpu's fStencilSettings and eliminate the stack copy here. 789a320194e4242ef0e5e758aea896bfd52bcb3dac7bsalomon@google.com 790a320194e4242ef0e5e758aea896bfd52bcb3dac7bsalomon@google.com const GrDrawState& drawState = fGpu->getDrawState(); 791a320194e4242ef0e5e758aea896bfd52bcb3dac7bsalomon@google.com 792a320194e4242ef0e5e758aea896bfd52bcb3dac7bsalomon@google.com // use stencil for clipping if clipping is enabled and the clip 793a320194e4242ef0e5e758aea896bfd52bcb3dac7bsalomon@google.com // has been written into the stencil. 794a320194e4242ef0e5e758aea896bfd52bcb3dac7bsalomon@google.com GrClipMaskManager::StencilClipMode clipMode; 795a320194e4242ef0e5e758aea896bfd52bcb3dac7bsalomon@google.com if (this->isClipInStencil() && drawState.isClipState()) { 796a320194e4242ef0e5e758aea896bfd52bcb3dac7bsalomon@google.com clipMode = GrClipMaskManager::kRespectClip_StencilClipMode; 797a320194e4242ef0e5e758aea896bfd52bcb3dac7bsalomon@google.com // We can't be modifying the clip and respecting it at the same time. 798a320194e4242ef0e5e758aea896bfd52bcb3dac7bsalomon@google.com GrAssert(!drawState.isStateFlagEnabled( 799a320194e4242ef0e5e758aea896bfd52bcb3dac7bsalomon@google.com GrGpu::kModifyStencilClip_StateBit)); 800a320194e4242ef0e5e758aea896bfd52bcb3dac7bsalomon@google.com } else if (drawState.isStateFlagEnabled( 801a320194e4242ef0e5e758aea896bfd52bcb3dac7bsalomon@google.com GrGpu::kModifyStencilClip_StateBit)) { 802a320194e4242ef0e5e758aea896bfd52bcb3dac7bsalomon@google.com clipMode = GrClipMaskManager::kModifyClip_StencilClipMode; 803a320194e4242ef0e5e758aea896bfd52bcb3dac7bsalomon@google.com } else { 804a320194e4242ef0e5e758aea896bfd52bcb3dac7bsalomon@google.com clipMode = GrClipMaskManager::kIgnoreClip_StencilClipMode; 805a320194e4242ef0e5e758aea896bfd52bcb3dac7bsalomon@google.com } 806a320194e4242ef0e5e758aea896bfd52bcb3dac7bsalomon@google.com 807a320194e4242ef0e5e758aea896bfd52bcb3dac7bsalomon@google.com GrStencilSettings settings; 808a320194e4242ef0e5e758aea896bfd52bcb3dac7bsalomon@google.com // The GrGpu client may not be using the stencil buffer but we may need to 809a320194e4242ef0e5e758aea896bfd52bcb3dac7bsalomon@google.com // enable it in order to respect a stencil clip. 810a320194e4242ef0e5e758aea896bfd52bcb3dac7bsalomon@google.com if (drawState.getStencil().isDisabled()) { 811a320194e4242ef0e5e758aea896bfd52bcb3dac7bsalomon@google.com if (GrClipMaskManager::kRespectClip_StencilClipMode == clipMode) { 812a320194e4242ef0e5e758aea896bfd52bcb3dac7bsalomon@google.com settings = basic_apply_stencil_clip_settings(); 813a320194e4242ef0e5e758aea896bfd52bcb3dac7bsalomon@google.com } else { 814a320194e4242ef0e5e758aea896bfd52bcb3dac7bsalomon@google.com fGpu->disableStencil(); 815a320194e4242ef0e5e758aea896bfd52bcb3dac7bsalomon@google.com return; 816a320194e4242ef0e5e758aea896bfd52bcb3dac7bsalomon@google.com } 817a320194e4242ef0e5e758aea896bfd52bcb3dac7bsalomon@google.com } else { 818a320194e4242ef0e5e758aea896bfd52bcb3dac7bsalomon@google.com settings = drawState.getStencil(); 819a320194e4242ef0e5e758aea896bfd52bcb3dac7bsalomon@google.com } 820a320194e4242ef0e5e758aea896bfd52bcb3dac7bsalomon@google.com 821a320194e4242ef0e5e758aea896bfd52bcb3dac7bsalomon@google.com // TODO: dynamically attach a stencil buffer 822a320194e4242ef0e5e758aea896bfd52bcb3dac7bsalomon@google.com int stencilBits = 0; 823fbfcd5602128ec010c82cb733c9cdc0a3254f9f3rmistry@google.com GrStencilBuffer* stencilBuffer = 824a320194e4242ef0e5e758aea896bfd52bcb3dac7bsalomon@google.com drawState.getRenderTarget()->getStencilBuffer(); 825a320194e4242ef0e5e758aea896bfd52bcb3dac7bsalomon@google.com if (NULL != stencilBuffer) { 826a320194e4242ef0e5e758aea896bfd52bcb3dac7bsalomon@google.com stencilBits = stencilBuffer->bits(); 827a320194e4242ef0e5e758aea896bfd52bcb3dac7bsalomon@google.com } 828a320194e4242ef0e5e758aea896bfd52bcb3dac7bsalomon@google.com 829bcce8926524827775539874346dd424a9510dbc9bsalomon@google.com GrAssert(fGpu->caps()->stencilWrapOpsSupport() || !settings.usesWrapOp()); 830bcce8926524827775539874346dd424a9510dbc9bsalomon@google.com GrAssert(fGpu->caps()->twoSidedStencilSupport() || !settings.isTwoSided()); 831a320194e4242ef0e5e758aea896bfd52bcb3dac7bsalomon@google.com this->adjustStencilParams(&settings, clipMode, stencilBits); 832a320194e4242ef0e5e758aea896bfd52bcb3dac7bsalomon@google.com fGpu->setStencilSettings(settings); 833a320194e4242ef0e5e758aea896bfd52bcb3dac7bsalomon@google.com} 834a320194e4242ef0e5e758aea896bfd52bcb3dac7bsalomon@google.com 835a320194e4242ef0e5e758aea896bfd52bcb3dac7bsalomon@google.comvoid GrClipMaskManager::adjustStencilParams(GrStencilSettings* settings, 836a320194e4242ef0e5e758aea896bfd52bcb3dac7bsalomon@google.com StencilClipMode mode, 837a320194e4242ef0e5e758aea896bfd52bcb3dac7bsalomon@google.com int stencilBitCnt) { 838411dad0630913fc07f2412b4be17acfbfd914fbcbsalomon@google.com GrAssert(stencilBitCnt > 0); 839411dad0630913fc07f2412b4be17acfbfd914fbcbsalomon@google.com 840411dad0630913fc07f2412b4be17acfbfd914fbcbsalomon@google.com if (kModifyClip_StencilClipMode == mode) { 841a320194e4242ef0e5e758aea896bfd52bcb3dac7bsalomon@google.com // We assume that this clip manager itself is drawing to the GrGpu and 842a320194e4242ef0e5e758aea896bfd52bcb3dac7bsalomon@google.com // has already setup the correct values. 843a320194e4242ef0e5e758aea896bfd52bcb3dac7bsalomon@google.com return; 844411dad0630913fc07f2412b4be17acfbfd914fbcbsalomon@google.com } 845a320194e4242ef0e5e758aea896bfd52bcb3dac7bsalomon@google.com 846411dad0630913fc07f2412b4be17acfbfd914fbcbsalomon@google.com unsigned int clipBit = (1 << (stencilBitCnt - 1)); 847411dad0630913fc07f2412b4be17acfbfd914fbcbsalomon@google.com unsigned int userBits = clipBit - 1; 848411dad0630913fc07f2412b4be17acfbfd914fbcbsalomon@google.com 849a320194e4242ef0e5e758aea896bfd52bcb3dac7bsalomon@google.com GrStencilSettings::Face face = GrStencilSettings::kFront_Face; 850bcce8926524827775539874346dd424a9510dbc9bsalomon@google.com bool twoSided = fGpu->caps()->twoSidedStencilSupport(); 851a320194e4242ef0e5e758aea896bfd52bcb3dac7bsalomon@google.com 852a320194e4242ef0e5e758aea896bfd52bcb3dac7bsalomon@google.com bool finished = false; 853a320194e4242ef0e5e758aea896bfd52bcb3dac7bsalomon@google.com while (!finished) { 854a320194e4242ef0e5e758aea896bfd52bcb3dac7bsalomon@google.com GrStencilFunc func = settings->func(face); 855a320194e4242ef0e5e758aea896bfd52bcb3dac7bsalomon@google.com uint16_t writeMask = settings->writeMask(face); 856a320194e4242ef0e5e758aea896bfd52bcb3dac7bsalomon@google.com uint16_t funcMask = settings->funcMask(face); 857a320194e4242ef0e5e758aea896bfd52bcb3dac7bsalomon@google.com uint16_t funcRef = settings->funcRef(face); 858a320194e4242ef0e5e758aea896bfd52bcb3dac7bsalomon@google.com 859a320194e4242ef0e5e758aea896bfd52bcb3dac7bsalomon@google.com GrAssert((unsigned) func < kStencilFuncCount); 860a320194e4242ef0e5e758aea896bfd52bcb3dac7bsalomon@google.com 861a320194e4242ef0e5e758aea896bfd52bcb3dac7bsalomon@google.com writeMask &= userBits; 862a320194e4242ef0e5e758aea896bfd52bcb3dac7bsalomon@google.com 863a320194e4242ef0e5e758aea896bfd52bcb3dac7bsalomon@google.com if (func >= kBasicStencilFuncCount) { 864a320194e4242ef0e5e758aea896bfd52bcb3dac7bsalomon@google.com int respectClip = kRespectClip_StencilClipMode == mode; 865a320194e4242ef0e5e758aea896bfd52bcb3dac7bsalomon@google.com if (respectClip) { 866a320194e4242ef0e5e758aea896bfd52bcb3dac7bsalomon@google.com // The GrGpu class should have checked this 867a320194e4242ef0e5e758aea896bfd52bcb3dac7bsalomon@google.com GrAssert(this->isClipInStencil()); 868a320194e4242ef0e5e758aea896bfd52bcb3dac7bsalomon@google.com switch (func) { 869a320194e4242ef0e5e758aea896bfd52bcb3dac7bsalomon@google.com case kAlwaysIfInClip_StencilFunc: 870a320194e4242ef0e5e758aea896bfd52bcb3dac7bsalomon@google.com funcMask = clipBit; 871a320194e4242ef0e5e758aea896bfd52bcb3dac7bsalomon@google.com funcRef = clipBit; 872a320194e4242ef0e5e758aea896bfd52bcb3dac7bsalomon@google.com break; 873a320194e4242ef0e5e758aea896bfd52bcb3dac7bsalomon@google.com case kEqualIfInClip_StencilFunc: 874a320194e4242ef0e5e758aea896bfd52bcb3dac7bsalomon@google.com case kLessIfInClip_StencilFunc: 875a320194e4242ef0e5e758aea896bfd52bcb3dac7bsalomon@google.com case kLEqualIfInClip_StencilFunc: 876a320194e4242ef0e5e758aea896bfd52bcb3dac7bsalomon@google.com funcMask = (funcMask & userBits) | clipBit; 877a320194e4242ef0e5e758aea896bfd52bcb3dac7bsalomon@google.com funcRef = (funcRef & userBits) | clipBit; 878a320194e4242ef0e5e758aea896bfd52bcb3dac7bsalomon@google.com break; 879a320194e4242ef0e5e758aea896bfd52bcb3dac7bsalomon@google.com case kNonZeroIfInClip_StencilFunc: 880a320194e4242ef0e5e758aea896bfd52bcb3dac7bsalomon@google.com funcMask = (funcMask & userBits) | clipBit; 881a320194e4242ef0e5e758aea896bfd52bcb3dac7bsalomon@google.com funcRef = clipBit; 882a320194e4242ef0e5e758aea896bfd52bcb3dac7bsalomon@google.com break; 883a320194e4242ef0e5e758aea896bfd52bcb3dac7bsalomon@google.com default: 884a320194e4242ef0e5e758aea896bfd52bcb3dac7bsalomon@google.com GrCrash("Unknown stencil func"); 885a320194e4242ef0e5e758aea896bfd52bcb3dac7bsalomon@google.com } 886a320194e4242ef0e5e758aea896bfd52bcb3dac7bsalomon@google.com } else { 887a320194e4242ef0e5e758aea896bfd52bcb3dac7bsalomon@google.com funcMask &= userBits; 888a320194e4242ef0e5e758aea896bfd52bcb3dac7bsalomon@google.com funcRef &= userBits; 889411dad0630913fc07f2412b4be17acfbfd914fbcbsalomon@google.com } 890fbfcd5602128ec010c82cb733c9cdc0a3254f9f3rmistry@google.com const GrStencilFunc* table = 891a320194e4242ef0e5e758aea896bfd52bcb3dac7bsalomon@google.com gSpecialToBasicStencilFunc[respectClip]; 892a320194e4242ef0e5e758aea896bfd52bcb3dac7bsalomon@google.com func = table[func - kBasicStencilFuncCount]; 893a320194e4242ef0e5e758aea896bfd52bcb3dac7bsalomon@google.com GrAssert(func >= 0 && func < kBasicStencilFuncCount); 894411dad0630913fc07f2412b4be17acfbfd914fbcbsalomon@google.com } else { 895a320194e4242ef0e5e758aea896bfd52bcb3dac7bsalomon@google.com funcMask &= userBits; 896a320194e4242ef0e5e758aea896bfd52bcb3dac7bsalomon@google.com funcRef &= userBits; 897411dad0630913fc07f2412b4be17acfbfd914fbcbsalomon@google.com } 898a320194e4242ef0e5e758aea896bfd52bcb3dac7bsalomon@google.com 899a320194e4242ef0e5e758aea896bfd52bcb3dac7bsalomon@google.com settings->setFunc(face, func); 900a320194e4242ef0e5e758aea896bfd52bcb3dac7bsalomon@google.com settings->setWriteMask(face, writeMask); 901a320194e4242ef0e5e758aea896bfd52bcb3dac7bsalomon@google.com settings->setFuncMask(face, funcMask); 902a320194e4242ef0e5e758aea896bfd52bcb3dac7bsalomon@google.com settings->setFuncRef(face, funcRef); 903a320194e4242ef0e5e758aea896bfd52bcb3dac7bsalomon@google.com 904a320194e4242ef0e5e758aea896bfd52bcb3dac7bsalomon@google.com if (GrStencilSettings::kFront_Face == face) { 905a320194e4242ef0e5e758aea896bfd52bcb3dac7bsalomon@google.com face = GrStencilSettings::kBack_Face; 906a320194e4242ef0e5e758aea896bfd52bcb3dac7bsalomon@google.com finished = !twoSided; 907a320194e4242ef0e5e758aea896bfd52bcb3dac7bsalomon@google.com } else { 908a320194e4242ef0e5e758aea896bfd52bcb3dac7bsalomon@google.com finished = true; 909a320194e4242ef0e5e758aea896bfd52bcb3dac7bsalomon@google.com } 910a320194e4242ef0e5e758aea896bfd52bcb3dac7bsalomon@google.com } 911a320194e4242ef0e5e758aea896bfd52bcb3dac7bsalomon@google.com if (!twoSided) { 912a320194e4242ef0e5e758aea896bfd52bcb3dac7bsalomon@google.com settings->copyFrontSettingsToBack(); 913411dad0630913fc07f2412b4be17acfbfd914fbcbsalomon@google.com } 914411dad0630913fc07f2412b4be17acfbfd914fbcbsalomon@google.com} 915411dad0630913fc07f2412b4be17acfbfd914fbcbsalomon@google.com 916411dad0630913fc07f2412b4be17acfbfd914fbcbsalomon@google.com//////////////////////////////////////////////////////////////////////////////// 9174c2443e36fdc6c095b17e90baa4a2f26a6f00b08bsalomon@google.comGrTexture* GrClipMaskManager::createSoftwareClipMask(int32_t clipStackGenID, 9184c2443e36fdc6c095b17e90baa4a2f26a6f00b08bsalomon@google.com GrReducedClip::InitialState initialState, 9194c2443e36fdc6c095b17e90baa4a2f26a6f00b08bsalomon@google.com const GrReducedClip::ElementList& elements, 9204c2443e36fdc6c095b17e90baa4a2f26a6f00b08bsalomon@google.com const SkIRect& clipSpaceIBounds) { 921c8f7f47afaf8f9471e6d111655c5610a8bd210a2bsalomon@google.com GrAssert(kNone_ClipMaskType == fCurrClipMaskType); 9226b70a7bd3328ea0a12be47b1a7f835c905f16147robertphillips@google.com 9234c2443e36fdc6c095b17e90baa4a2f26a6f00b08bsalomon@google.com GrTexture* result; 9244c2443e36fdc6c095b17e90baa4a2f26a6f00b08bsalomon@google.com if (this->getMaskTexture(clipStackGenID, clipSpaceIBounds, &result)) { 9254c2443e36fdc6c095b17e90baa4a2f26a6f00b08bsalomon@google.com return result; 9266b70a7bd3328ea0a12be47b1a7f835c905f16147robertphillips@google.com } 9276b70a7bd3328ea0a12be47b1a7f835c905f16147robertphillips@google.com 9284c2443e36fdc6c095b17e90baa4a2f26a6f00b08bsalomon@google.com if (NULL == result) { 929f105b109264f71dfb0bfd9977e6a5dd0a5a12f57robertphillips@google.com fAACache.reset(); 9304c2443e36fdc6c095b17e90baa4a2f26a6f00b08bsalomon@google.com return NULL; 9316b70a7bd3328ea0a12be47b1a7f835c905f16147robertphillips@google.com } 9326b70a7bd3328ea0a12be47b1a7f835c905f16147robertphillips@google.com 9334c2443e36fdc6c095b17e90baa4a2f26a6f00b08bsalomon@google.com // The mask texture may be larger than necessary. We round out the clip space bounds and pin 9344c2443e36fdc6c095b17e90baa4a2f26a6f00b08bsalomon@google.com // the top left corner of the resulting rect to the top left of the texture. 9354c2443e36fdc6c095b17e90baa4a2f26a6f00b08bsalomon@google.com SkIRect maskSpaceIBounds = SkIRect::MakeWH(clipSpaceIBounds.width(), clipSpaceIBounds.height()); 9364c2443e36fdc6c095b17e90baa4a2f26a6f00b08bsalomon@google.com 9372c75681e36b33fcafc5665d7012bbd4fc6647d83robertphillips@google.com GrSWMaskHelper helper(this->getContext()); 9386b70a7bd3328ea0a12be47b1a7f835c905f16147robertphillips@google.com 939b9086a026844e4cfd08b219e49ce3f12294cba98bsalomon@google.com SkMatrix matrix; 9404c2443e36fdc6c095b17e90baa4a2f26a6f00b08bsalomon@google.com matrix.setTranslate(SkIntToScalar(-clipSpaceIBounds.fLeft), 9414c2443e36fdc6c095b17e90baa4a2f26a6f00b08bsalomon@google.com SkIntToScalar(-clipSpaceIBounds.fTop)); 9424c2443e36fdc6c095b17e90baa4a2f26a6f00b08bsalomon@google.com helper.init(maskSpaceIBounds, &matrix); 9434c2443e36fdc6c095b17e90baa4a2f26a6f00b08bsalomon@google.com 9444c2443e36fdc6c095b17e90baa4a2f26a6f00b08bsalomon@google.com helper.clear(kAllIn_InitialState == initialState ? 0xFF : 0x00); 945fa66294c7705831808ce7772d4328fc626d45034robertphillips@google.com 9465f74cf8c49701f514b69dc6f1a8b5c0ffd78af0asugoi@google.com SkStrokeRec stroke(SkStrokeRec::kFill_InitStyle); 94712b4e27ae1a29460e91a59f38122483e1faec697sugoi@google.com 9484c2443e36fdc6c095b17e90baa4a2f26a6f00b08bsalomon@google.com for (ElementList::Iter iter(elements.headIter()) ; NULL != iter.get(); iter.next()) { 949fa66294c7705831808ce7772d4328fc626d45034robertphillips@google.com 9504c2443e36fdc6c095b17e90baa4a2f26a6f00b08bsalomon@google.com const Element* element = iter.get(); 9518182fa0cac76e7e6d583aebba060229230516887bsalomon@google.com SkRegion::Op op = element->getOp(); 952fa66294c7705831808ce7772d4328fc626d45034robertphillips@google.com 9534c2443e36fdc6c095b17e90baa4a2f26a6f00b08bsalomon@google.com if (SkRegion::kIntersect_Op == op || SkRegion::kReverseDifference_Op == op) { 9544c2443e36fdc6c095b17e90baa4a2f26a6f00b08bsalomon@google.com // Intersect and reverse difference require modifying pixels outside of the geometry 9554c2443e36fdc6c095b17e90baa4a2f26a6f00b08bsalomon@google.com // that is being "drawn". In both cases we erase all the pixels outside of the geometry 9564c2443e36fdc6c095b17e90baa4a2f26a6f00b08bsalomon@google.com // but leave the pixels inside the geometry alone. For reverse difference we invert all 9574c2443e36fdc6c095b17e90baa4a2f26a6f00b08bsalomon@google.com // the pixels before clearing the ones outside the geometry. 958fa66294c7705831808ce7772d4328fc626d45034robertphillips@google.com if (SkRegion::kReverseDifference_Op == op) { 9594c2443e36fdc6c095b17e90baa4a2f26a6f00b08bsalomon@google.com SkRect temp = SkRect::MakeFromIRect(clipSpaceIBounds); 960fa66294c7705831808ce7772d4328fc626d45034robertphillips@google.com // invert the entire scene 961366f1c6a09f63c76e78145cb08028f66062f31fdrobertphillips@google.com helper.draw(temp, SkRegion::kXOR_Op, false, 0xFF); 962fa66294c7705831808ce7772d4328fc626d45034robertphillips@google.com } 963fa66294c7705831808ce7772d4328fc626d45034robertphillips@google.com 9648182fa0cac76e7e6d583aebba060229230516887bsalomon@google.com if (Element::kRect_Type == element->getType()) { 965fa66294c7705831808ce7772d4328fc626d45034robertphillips@google.com // convert the rect to a path so we can invert the fill 966fa66294c7705831808ce7772d4328fc626d45034robertphillips@google.com SkPath temp; 9678182fa0cac76e7e6d583aebba060229230516887bsalomon@google.com temp.addRect(element->getRect()); 96812b4e27ae1a29460e91a59f38122483e1faec697sugoi@google.com temp.setFillType(SkPath::kInverseEvenOdd_FillType); 969fa66294c7705831808ce7772d4328fc626d45034robertphillips@google.com 97012b4e27ae1a29460e91a59f38122483e1faec697sugoi@google.com helper.draw(temp, stroke, SkRegion::kReplace_Op, 97112b4e27ae1a29460e91a59f38122483e1faec697sugoi@google.com element->isAA(), 972366f1c6a09f63c76e78145cb08028f66062f31fdrobertphillips@google.com 0x00); 9738182fa0cac76e7e6d583aebba060229230516887bsalomon@google.com } else { 9748182fa0cac76e7e6d583aebba060229230516887bsalomon@google.com GrAssert(Element::kPath_Type == element->getType()); 97512b4e27ae1a29460e91a59f38122483e1faec697sugoi@google.com SkPath clipPath = element->getPath(); 97612b4e27ae1a29460e91a59f38122483e1faec697sugoi@google.com clipPath.toggleInverseFillType(); 977d21444aab7128c97f4e0eb5e9bf05111d5037292skia.committer@gmail.com helper.draw(clipPath, stroke, 978fa66294c7705831808ce7772d4328fc626d45034robertphillips@google.com SkRegion::kReplace_Op, 9798182fa0cac76e7e6d583aebba060229230516887bsalomon@google.com element->isAA(), 980366f1c6a09f63c76e78145cb08028f66062f31fdrobertphillips@google.com 0x00); 981fa66294c7705831808ce7772d4328fc626d45034robertphillips@google.com } 982fa66294c7705831808ce7772d4328fc626d45034robertphillips@google.com 983fa66294c7705831808ce7772d4328fc626d45034robertphillips@google.com continue; 984fa66294c7705831808ce7772d4328fc626d45034robertphillips@google.com } 985fa66294c7705831808ce7772d4328fc626d45034robertphillips@google.com 986fa66294c7705831808ce7772d4328fc626d45034robertphillips@google.com // The other ops (union, xor, diff) only affect pixels inside 987fa66294c7705831808ce7772d4328fc626d45034robertphillips@google.com // the geometry so they can just be drawn normally 9888182fa0cac76e7e6d583aebba060229230516887bsalomon@google.com if (Element::kRect_Type == element->getType()) { 9898182fa0cac76e7e6d583aebba060229230516887bsalomon@google.com helper.draw(element->getRect(), op, element->isAA(), 0xFF); 9908182fa0cac76e7e6d583aebba060229230516887bsalomon@google.com } else { 9918182fa0cac76e7e6d583aebba060229230516887bsalomon@google.com GrAssert(Element::kPath_Type == element->getType()); 99212b4e27ae1a29460e91a59f38122483e1faec697sugoi@google.com helper.draw(element->getPath(), stroke, op, element->isAA(), 0xFF); 9936b70a7bd3328ea0a12be47b1a7f835c905f16147robertphillips@google.com } 9946b70a7bd3328ea0a12be47b1a7f835c905f16147robertphillips@google.com } 9956b70a7bd3328ea0a12be47b1a7f835c905f16147robertphillips@google.com 996d92cf2ebbfbb9d737ea4a551e64ffccb08376875robertphillips@google.com helper.toTexture(result); 9976b70a7bd3328ea0a12be47b1a7f835c905f16147robertphillips@google.com 998c8f7f47afaf8f9471e6d111655c5610a8bd210a2bsalomon@google.com fCurrClipMaskType = kAlpha_ClipMaskType; 9994c2443e36fdc6c095b17e90baa4a2f26a6f00b08bsalomon@google.com return result; 10006b70a7bd3328ea0a12be47b1a7f835c905f16147robertphillips@google.com} 10016b70a7bd3328ea0a12be47b1a7f835c905f16147robertphillips@google.com 1002f294b773f0b2b9f05eb45b52dd3cb4d97b96af06robertphillips@google.com//////////////////////////////////////////////////////////////////////////////// 1003f105b109264f71dfb0bfd9977e6a5dd0a5a12f57robertphillips@google.comvoid GrClipMaskManager::releaseResources() { 1004f105b109264f71dfb0bfd9977e6a5dd0a5a12f57robertphillips@google.com fAACache.releaseResources(); 10051e945b7e708c633d4aed937ebfce57d52ba21d83robertphillips@google.com} 10066e4e65066a7c0dbc9bfbfe4b8f5d49c3d8a79b59bsalomon@google.com 10076e4e65066a7c0dbc9bfbfe4b8f5d49c3d8a79b59bsalomon@google.comvoid GrClipMaskManager::setGpu(GrGpu* gpu) { 10086e4e65066a7c0dbc9bfbfe4b8f5d49c3d8a79b59bsalomon@google.com fGpu = gpu; 10096e4e65066a7c0dbc9bfbfe4b8f5d49c3d8a79b59bsalomon@google.com fAACache.setContext(gpu->getContext()); 10106e4e65066a7c0dbc9bfbfe4b8f5d49c3d8a79b59bsalomon@google.com} 1011