GrClipMaskManager.cpp revision 8a4fc40b02fa0a8300ade26863f4ddae69197d62
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" 101e945b7e708c633d4aed937ebfce57d52ba21d83robertphillips@google.com#include "GrGpu.h" 111e945b7e708c633d4aed937ebfce57d52ba21d83robertphillips@google.com#include "GrRenderTarget.h" 121e945b7e708c633d4aed937ebfce57d52ba21d83robertphillips@google.com#include "GrStencilBuffer.h" 131e945b7e708c633d4aed937ebfce57d52ba21d83robertphillips@google.com#include "GrPathRenderer.h" 14a72eef322c686954cdffa849dc26d8133b802f1drobertphillips@google.com#include "GrPaint.h" 156b70a7bd3328ea0a12be47b1a7f835c905f16147robertphillips@google.com#include "SkRasterClip.h" 16fa66294c7705831808ce7772d4328fc626d45034robertphillips@google.com#include "GrAAConvexPathRenderer.h" 17fa66294c7705831808ce7772d4328fc626d45034robertphillips@google.com#include "GrAAHairLinePathRenderer.h" 18fa66294c7705831808ce7772d4328fc626d45034robertphillips@google.com 19fa66294c7705831808ce7772d4328fc626d45034robertphillips@google.com// TODO: move GrSWMaskHelper out of GrSoftwarePathRender.h & remove this include 20fa66294c7705831808ce7772d4328fc626d45034robertphillips@google.com#include "GrSoftwarePathRenderer.h" 21a72eef322c686954cdffa849dc26d8133b802f1drobertphillips@google.com 22a72eef322c686954cdffa849dc26d8133b802f1drobertphillips@google.com//#define GR_AA_CLIP 1 236b70a7bd3328ea0a12be47b1a7f835c905f16147robertphillips@google.com//#define GR_SW_CLIP 1 24a72eef322c686954cdffa849dc26d8133b802f1drobertphillips@google.com 25f294b773f0b2b9f05eb45b52dd3cb4d97b96af06robertphillips@google.com//////////////////////////////////////////////////////////////////////////////// 261e945b7e708c633d4aed937ebfce57d52ba21d83robertphillips@google.comvoid ScissoringSettings::setupScissoring(GrGpu* gpu) { 271e945b7e708c633d4aed937ebfce57d52ba21d83robertphillips@google.com if (!fEnableScissoring) { 281e945b7e708c633d4aed937ebfce57d52ba21d83robertphillips@google.com gpu->disableScissor(); 291e945b7e708c633d4aed937ebfce57d52ba21d83robertphillips@google.com return; 301e945b7e708c633d4aed937ebfce57d52ba21d83robertphillips@google.com } 311e945b7e708c633d4aed937ebfce57d52ba21d83robertphillips@google.com 321e945b7e708c633d4aed937ebfce57d52ba21d83robertphillips@google.com gpu->enableScissoring(fScissorRect); 331e945b7e708c633d4aed937ebfce57d52ba21d83robertphillips@google.com} 341e945b7e708c633d4aed937ebfce57d52ba21d83robertphillips@google.com 35a72eef322c686954cdffa849dc26d8133b802f1drobertphillips@google.comnamespace { 36a72eef322c686954cdffa849dc26d8133b802f1drobertphillips@google.com// set up the draw state to enable the aa clipping mask. Besides setting up the 37a72eef322c686954cdffa849dc26d8133b802f1drobertphillips@google.com// sampler matrix this also alters the vertex layout 386b70a7bd3328ea0a12be47b1a7f835c905f16147robertphillips@google.comvoid setup_drawstate_aaclip(GrGpu* gpu, 396b70a7bd3328ea0a12be47b1a7f835c905f16147robertphillips@google.com GrTexture* result, 406623fcd1ee33b35fa18e304e9c76272faa603cbfrobertphillips@google.com const GrIRect &bound) { 41a72eef322c686954cdffa849dc26d8133b802f1drobertphillips@google.com GrDrawState* drawState = gpu->drawState(); 42a72eef322c686954cdffa849dc26d8133b802f1drobertphillips@google.com GrAssert(drawState); 43a72eef322c686954cdffa849dc26d8133b802f1drobertphillips@google.com 44a72eef322c686954cdffa849dc26d8133b802f1drobertphillips@google.com static const int maskStage = GrPaint::kTotalStages+1; 45a72eef322c686954cdffa849dc26d8133b802f1drobertphillips@google.com 46a72eef322c686954cdffa849dc26d8133b802f1drobertphillips@google.com GrMatrix mat; 47a72eef322c686954cdffa849dc26d8133b802f1drobertphillips@google.com mat.setIDiv(result->width(), result->height()); 486623fcd1ee33b35fa18e304e9c76272faa603cbfrobertphillips@google.com mat.preTranslate(SkIntToScalar(-bound.fLeft), SkIntToScalar(-bound.fTop)); 49a72eef322c686954cdffa849dc26d8133b802f1drobertphillips@google.com mat.preConcat(drawState->getViewMatrix()); 50a72eef322c686954cdffa849dc26d8133b802f1drobertphillips@google.com 51a72eef322c686954cdffa849dc26d8133b802f1drobertphillips@google.com drawState->sampler(maskStage)->reset(GrSamplerState::kClamp_WrapMode, 52a72eef322c686954cdffa849dc26d8133b802f1drobertphillips@google.com GrSamplerState::kNearest_Filter, 53a72eef322c686954cdffa849dc26d8133b802f1drobertphillips@google.com mat); 54a72eef322c686954cdffa849dc26d8133b802f1drobertphillips@google.com 55a72eef322c686954cdffa849dc26d8133b802f1drobertphillips@google.com drawState->setTexture(maskStage, result); 56a72eef322c686954cdffa849dc26d8133b802f1drobertphillips@google.com 57a72eef322c686954cdffa849dc26d8133b802f1drobertphillips@google.com // The AA clipping determination happens long after the geometry has 58a72eef322c686954cdffa849dc26d8133b802f1drobertphillips@google.com // been set up to draw. Here we directly enable the AA clip mask stage 59a72eef322c686954cdffa849dc26d8133b802f1drobertphillips@google.com gpu->addToVertexLayout( 60a72eef322c686954cdffa849dc26d8133b802f1drobertphillips@google.com GrDrawTarget::StagePosAsTexCoordVertexLayoutBit(maskStage)); 61a72eef322c686954cdffa849dc26d8133b802f1drobertphillips@google.com} 62a72eef322c686954cdffa849dc26d8133b802f1drobertphillips@google.com 638a4fc40b02fa0a8300ade26863f4ddae69197d62robertphillips@google.combool path_needs_SW_renderer(GrContext* context, 648a4fc40b02fa0a8300ade26863f4ddae69197d62robertphillips@google.com GrGpu* gpu, 658a4fc40b02fa0a8300ade26863f4ddae69197d62robertphillips@google.com const SkPath& path, 668a4fc40b02fa0a8300ade26863f4ddae69197d62robertphillips@google.com GrPathFill fill, 678a4fc40b02fa0a8300ade26863f4ddae69197d62robertphillips@google.com bool doAA) { 688a4fc40b02fa0a8300ade26863f4ddae69197d62robertphillips@google.com // last (false) parameter disallows use of the SW path renderer 698a4fc40b02fa0a8300ade26863f4ddae69197d62robertphillips@google.com return NULL == context->getPathRenderer(path, fill, gpu, doAA, false); 708a4fc40b02fa0a8300ade26863f4ddae69197d62robertphillips@google.com} 718a4fc40b02fa0a8300ade26863f4ddae69197d62robertphillips@google.com 726b70a7bd3328ea0a12be47b1a7f835c905f16147robertphillips@google.com} 736b70a7bd3328ea0a12be47b1a7f835c905f16147robertphillips@google.com 74fa66294c7705831808ce7772d4328fc626d45034robertphillips@google.com/* 75fa66294c7705831808ce7772d4328fc626d45034robertphillips@google.com * This method traverses the clip stack to see if the GrSoftwarePathRenderer 76fa66294c7705831808ce7772d4328fc626d45034robertphillips@google.com * will be used on any element. If so, it returns true to indicate that the 77fa66294c7705831808ce7772d4328fc626d45034robertphillips@google.com * entire clip should be rendered in SW and then uploaded en masse to the gpu. 78fa66294c7705831808ce7772d4328fc626d45034robertphillips@google.com */ 79fa66294c7705831808ce7772d4328fc626d45034robertphillips@google.combool GrClipMaskManager::useSWOnlyPath(GrGpu* gpu, const GrClip& clipIn) { 80a3e5c63ab0264332169df4583a8a7da186fb4e66robertphillips@google.com 81a3e5c63ab0264332169df4583a8a7da186fb4e66robertphillips@google.com if (!clipIn.requiresAA()) { 82a3e5c63ab0264332169df4583a8a7da186fb4e66robertphillips@google.com // The stencil buffer can handle this case 83a3e5c63ab0264332169df4583a8a7da186fb4e66robertphillips@google.com return false; 84a3e5c63ab0264332169df4583a8a7da186fb4e66robertphillips@google.com } 85fa66294c7705831808ce7772d4328fc626d45034robertphillips@google.com 868a4fc40b02fa0a8300ade26863f4ddae69197d62robertphillips@google.com // TODO: generalize this function so that when 87fa66294c7705831808ce7772d4328fc626d45034robertphillips@google.com // a clip gets complex enough it can just be done in SW regardless 88fa66294c7705831808ce7772d4328fc626d45034robertphillips@google.com // of whether it would invoke the GrSoftwarePathRenderer. 89fa66294c7705831808ce7772d4328fc626d45034robertphillips@google.com bool useSW = false; 90fa66294c7705831808ce7772d4328fc626d45034robertphillips@google.com 91fa66294c7705831808ce7772d4328fc626d45034robertphillips@google.com for (int i = 0; i < clipIn.getElementCount(); ++i) { 92fa66294c7705831808ce7772d4328fc626d45034robertphillips@google.com 93fa66294c7705831808ce7772d4328fc626d45034robertphillips@google.com if (SkRegion::kReplace_Op == clipIn.getOp(i)) { 94fa66294c7705831808ce7772d4328fc626d45034robertphillips@google.com // Everything before a replace op can be ignored so start 95fa66294c7705831808ce7772d4328fc626d45034robertphillips@google.com // afresh w.r.t. determining if any element uses the SW path 96fa66294c7705831808ce7772d4328fc626d45034robertphillips@google.com useSW = false; 97fa66294c7705831808ce7772d4328fc626d45034robertphillips@google.com } 98fa66294c7705831808ce7772d4328fc626d45034robertphillips@google.com 99fa66294c7705831808ce7772d4328fc626d45034robertphillips@google.com if (kRect_ClipType == clipIn.getElementType(i)) { 1008a4fc40b02fa0a8300ade26863f4ddae69197d62robertphillips@google.com // Non-anti-aliased rects can always be drawn directly (w/o 1018a4fc40b02fa0a8300ade26863f4ddae69197d62robertphillips@google.com // using the software path) so the anti-aliased rects are all 1028a4fc40b02fa0a8300ade26863f4ddae69197d62robertphillips@google.com // that need to be checked here 1038a4fc40b02fa0a8300ade26863f4ddae69197d62robertphillips@google.com if (clipIn.getDoAA(i)) { 1048a4fc40b02fa0a8300ade26863f4ddae69197d62robertphillips@google.com // Antialiased rects are converted to paths and then drawn with 1058a4fc40b02fa0a8300ade26863f4ddae69197d62robertphillips@google.com // kEvenOdd_PathFill. 1068a4fc40b02fa0a8300ade26863f4ddae69197d62robertphillips@google.com 1078a4fc40b02fa0a8300ade26863f4ddae69197d62robertphillips@google.com // TODO: wrap GrContext::fillAARect in a helper class and 1088a4fc40b02fa0a8300ade26863f4ddae69197d62robertphillips@google.com // draw AA rects directly rather than converting to paths 1098a4fc40b02fa0a8300ade26863f4ddae69197d62robertphillips@google.com SkPath temp; 1108a4fc40b02fa0a8300ade26863f4ddae69197d62robertphillips@google.com temp.addRect(clipIn.getRect(i)); 1118a4fc40b02fa0a8300ade26863f4ddae69197d62robertphillips@google.com 1128a4fc40b02fa0a8300ade26863f4ddae69197d62robertphillips@google.com if (path_needs_SW_renderer(this->getContext(), gpu, temp, 1138a4fc40b02fa0a8300ade26863f4ddae69197d62robertphillips@google.com kEvenOdd_PathFill, true)) { 1148a4fc40b02fa0a8300ade26863f4ddae69197d62robertphillips@google.com useSW = true; 1158a4fc40b02fa0a8300ade26863f4ddae69197d62robertphillips@google.com } 1168a4fc40b02fa0a8300ade26863f4ddae69197d62robertphillips@google.com } 1178a4fc40b02fa0a8300ade26863f4ddae69197d62robertphillips@google.com } else { 1188a4fc40b02fa0a8300ade26863f4ddae69197d62robertphillips@google.com if (path_needs_SW_renderer(this->getContext(), gpu, 1198a4fc40b02fa0a8300ade26863f4ddae69197d62robertphillips@google.com clipIn.getPath(i), 1208a4fc40b02fa0a8300ade26863f4ddae69197d62robertphillips@google.com clipIn.getPathFill(i), 1218a4fc40b02fa0a8300ade26863f4ddae69197d62robertphillips@google.com clipIn.getDoAA(i))) { 122fa66294c7705831808ce7772d4328fc626d45034robertphillips@google.com useSW = true; 123fa66294c7705831808ce7772d4328fc626d45034robertphillips@google.com } 124fa66294c7705831808ce7772d4328fc626d45034robertphillips@google.com } 125fa66294c7705831808ce7772d4328fc626d45034robertphillips@google.com } 126fa66294c7705831808ce7772d4328fc626d45034robertphillips@google.com 127fa66294c7705831808ce7772d4328fc626d45034robertphillips@google.com return useSW; 128a72eef322c686954cdffa849dc26d8133b802f1drobertphillips@google.com} 129a72eef322c686954cdffa849dc26d8133b802f1drobertphillips@google.com 130f294b773f0b2b9f05eb45b52dd3cb4d97b96af06robertphillips@google.com//////////////////////////////////////////////////////////////////////////////// 1316b70a7bd3328ea0a12be47b1a7f835c905f16147robertphillips@google.com// sort out what kind of clip mask needs to be created: alpha, stencil, 1326b70a7bd3328ea0a12be47b1a7f835c905f16147robertphillips@google.com// scissor, or entirely software 1331e945b7e708c633d4aed937ebfce57d52ba21d83robertphillips@google.combool GrClipMaskManager::createClipMask(GrGpu* gpu, 1341e945b7e708c633d4aed937ebfce57d52ba21d83robertphillips@google.com const GrClip& clipIn, 1351e945b7e708c633d4aed937ebfce57d52ba21d83robertphillips@google.com ScissoringSettings* scissorSettings) { 1361e945b7e708c633d4aed937ebfce57d52ba21d83robertphillips@google.com 1371e945b7e708c633d4aed937ebfce57d52ba21d83robertphillips@google.com GrAssert(scissorSettings); 1381e945b7e708c633d4aed937ebfce57d52ba21d83robertphillips@google.com 1391e945b7e708c633d4aed937ebfce57d52ba21d83robertphillips@google.com scissorSettings->fEnableScissoring = false; 1401e945b7e708c633d4aed937ebfce57d52ba21d83robertphillips@google.com fClipMaskInStencil = false; 141f294b773f0b2b9f05eb45b52dd3cb4d97b96af06robertphillips@google.com fClipMaskInAlpha = false; 1421e945b7e708c633d4aed937ebfce57d52ba21d83robertphillips@google.com 1431e945b7e708c633d4aed937ebfce57d52ba21d83robertphillips@google.com GrDrawState* drawState = gpu->drawState(); 1441e945b7e708c633d4aed937ebfce57d52ba21d83robertphillips@google.com if (!drawState->isClipState()) { 1451e945b7e708c633d4aed937ebfce57d52ba21d83robertphillips@google.com return true; 1461e945b7e708c633d4aed937ebfce57d52ba21d83robertphillips@google.com } 1471e945b7e708c633d4aed937ebfce57d52ba21d83robertphillips@google.com 1481e945b7e708c633d4aed937ebfce57d52ba21d83robertphillips@google.com GrRenderTarget* rt = drawState->getRenderTarget(); 1491e945b7e708c633d4aed937ebfce57d52ba21d83robertphillips@google.com 1501e945b7e708c633d4aed937ebfce57d52ba21d83robertphillips@google.com // GrDrawTarget should have filtered this for us 1511e945b7e708c633d4aed937ebfce57d52ba21d83robertphillips@google.com GrAssert(NULL != rt); 1521e945b7e708c633d4aed937ebfce57d52ba21d83robertphillips@google.com 1536b70a7bd3328ea0a12be47b1a7f835c905f16147robertphillips@google.com#if GR_SW_CLIP 154a3e5c63ab0264332169df4583a8a7da186fb4e66robertphillips@google.com // If MSAA is enabled we can do everything in the stencil buffer. 155a3e5c63ab0264332169df4583a8a7da186fb4e66robertphillips@google.com // Otherwise check if we should just create the entire clip mask 156a3e5c63ab0264332169df4583a8a7da186fb4e66robertphillips@google.com // in software (this will only happen if the clip mask is anti-aliased 157a3e5c63ab0264332169df4583a8a7da186fb4e66robertphillips@google.com // and too complex for the gpu to handle in its entirety) 158a3e5c63ab0264332169df4583a8a7da186fb4e66robertphillips@google.com if (0 == rt->numSamples() && useSWOnlyPath(gpu, clipIn)) { 1596b70a7bd3328ea0a12be47b1a7f835c905f16147robertphillips@google.com // The clip geometry is complex enough that it will be more 1606b70a7bd3328ea0a12be47b1a7f835c905f16147robertphillips@google.com // efficient to create it entirely in software 1616b70a7bd3328ea0a12be47b1a7f835c905f16147robertphillips@google.com GrTexture* result = NULL; 1626623fcd1ee33b35fa18e304e9c76272faa603cbfrobertphillips@google.com GrIRect bound; 1636b70a7bd3328ea0a12be47b1a7f835c905f16147robertphillips@google.com if (this->createSoftwareClipMask(gpu, clipIn, &result, &bound)) { 1646b70a7bd3328ea0a12be47b1a7f835c905f16147robertphillips@google.com fClipMaskInAlpha = true; 1656b70a7bd3328ea0a12be47b1a7f835c905f16147robertphillips@google.com 1666b70a7bd3328ea0a12be47b1a7f835c905f16147robertphillips@google.com setup_drawstate_aaclip(gpu, result, bound); 1676b70a7bd3328ea0a12be47b1a7f835c905f16147robertphillips@google.com return true; 1686b70a7bd3328ea0a12be47b1a7f835c905f16147robertphillips@google.com } 169a3e5c63ab0264332169df4583a8a7da186fb4e66robertphillips@google.com 170a3e5c63ab0264332169df4583a8a7da186fb4e66robertphillips@google.com // if SW clip mask creation fails fall through to the other 171a3e5c63ab0264332169df4583a8a7da186fb4e66robertphillips@google.com // two possible methods (bottoming out at stencil clipping) 1726b70a7bd3328ea0a12be47b1a7f835c905f16147robertphillips@google.com } 173a3e5c63ab0264332169df4583a8a7da186fb4e66robertphillips@google.com#endif // GR_SW_CLIP 1746b70a7bd3328ea0a12be47b1a7f835c905f16147robertphillips@google.com 175f294b773f0b2b9f05eb45b52dd3cb4d97b96af06robertphillips@google.com#if GR_AA_CLIP 176f294b773f0b2b9f05eb45b52dd3cb4d97b96af06robertphillips@google.com // If MSAA is enabled use the (faster) stencil path for AA clipping 177f294b773f0b2b9f05eb45b52dd3cb4d97b96af06robertphillips@google.com // otherwise the alpha clip mask is our only option 178a3e5c63ab0264332169df4583a8a7da186fb4e66robertphillips@google.com if (0 == rt->numSamples() && clipIn.requiresAA()) { 179f294b773f0b2b9f05eb45b52dd3cb4d97b96af06robertphillips@google.com // Since we are going to create a destination texture of the correct 180f294b773f0b2b9f05eb45b52dd3cb4d97b96af06robertphillips@google.com // size for the mask (rather than being bound by the size of the 181f294b773f0b2b9f05eb45b52dd3cb4d97b96af06robertphillips@google.com // render target) we aren't going to use scissoring like the stencil 182f294b773f0b2b9f05eb45b52dd3cb4d97b96af06robertphillips@google.com // path does (see scissorSettings below) 183a72eef322c686954cdffa849dc26d8133b802f1drobertphillips@google.com GrTexture* result = NULL; 1846623fcd1ee33b35fa18e304e9c76272faa603cbfrobertphillips@google.com GrIRect bound; 185a72eef322c686954cdffa849dc26d8133b802f1drobertphillips@google.com if (this->createAlphaClipMask(gpu, clipIn, &result, &bound)) { 186f294b773f0b2b9f05eb45b52dd3cb4d97b96af06robertphillips@google.com fClipMaskInAlpha = true; 187a72eef322c686954cdffa849dc26d8133b802f1drobertphillips@google.com 1886b70a7bd3328ea0a12be47b1a7f835c905f16147robertphillips@google.com setup_drawstate_aaclip(gpu, result, bound); 189f294b773f0b2b9f05eb45b52dd3cb4d97b96af06robertphillips@google.com return true; 190f294b773f0b2b9f05eb45b52dd3cb4d97b96af06robertphillips@google.com } 191f294b773f0b2b9f05eb45b52dd3cb4d97b96af06robertphillips@google.com 192f294b773f0b2b9f05eb45b52dd3cb4d97b96af06robertphillips@google.com // if alpha clip mask creation fails fall through to the stencil 193f294b773f0b2b9f05eb45b52dd3cb4d97b96af06robertphillips@google.com // buffer method 194f294b773f0b2b9f05eb45b52dd3cb4d97b96af06robertphillips@google.com } 195f294b773f0b2b9f05eb45b52dd3cb4d97b96af06robertphillips@google.com#endif // GR_AA_CLIP 196f294b773f0b2b9f05eb45b52dd3cb4d97b96af06robertphillips@google.com 1975acc0e36d987dff3172fd45a14b66c52a51d49e4robertphillips@google.com // Either a hard (stencil buffer) clip was explicitly requested or 1985acc0e36d987dff3172fd45a14b66c52a51d49e4robertphillips@google.com // an antialiased clip couldn't be created. In either case, free up 1995acc0e36d987dff3172fd45a14b66c52a51d49e4robertphillips@google.com // the texture in the antialiased mask cache. 2005acc0e36d987dff3172fd45a14b66c52a51d49e4robertphillips@google.com // TODO: this may require more investigation. Ganesh performs a lot of 201a3e5c63ab0264332169df4583a8a7da186fb4e66robertphillips@google.com // utility draws (e.g., clears, InOrderDrawBuffer playbacks) that hit 202a3e5c63ab0264332169df4583a8a7da186fb4e66robertphillips@google.com // the stencil buffer path. These may be "incorrectly" clearing the 2035acc0e36d987dff3172fd45a14b66c52a51d49e4robertphillips@google.com // AA cache. 2045acc0e36d987dff3172fd45a14b66c52a51d49e4robertphillips@google.com fAACache.reset(); 2055acc0e36d987dff3172fd45a14b66c52a51d49e4robertphillips@google.com 2061e945b7e708c633d4aed937ebfce57d52ba21d83robertphillips@google.com GrRect bounds; 2071e945b7e708c633d4aed937ebfce57d52ba21d83robertphillips@google.com GrRect rtRect; 2081e945b7e708c633d4aed937ebfce57d52ba21d83robertphillips@google.com rtRect.setLTRB(0, 0, 209fa66294c7705831808ce7772d4328fc626d45034robertphillips@google.com GrIntToScalar(rt->width()), GrIntToScalar(rt->height())); 2101e945b7e708c633d4aed937ebfce57d52ba21d83robertphillips@google.com if (clipIn.hasConservativeBounds()) { 2111e945b7e708c633d4aed937ebfce57d52ba21d83robertphillips@google.com bounds = clipIn.getConservativeBounds(); 2121e945b7e708c633d4aed937ebfce57d52ba21d83robertphillips@google.com if (!bounds.intersect(rtRect)) { 2131e945b7e708c633d4aed937ebfce57d52ba21d83robertphillips@google.com bounds.setEmpty(); 2141e945b7e708c633d4aed937ebfce57d52ba21d83robertphillips@google.com } 2151e945b7e708c633d4aed937ebfce57d52ba21d83robertphillips@google.com } else { 2161e945b7e708c633d4aed937ebfce57d52ba21d83robertphillips@google.com bounds = rtRect; 2171e945b7e708c633d4aed937ebfce57d52ba21d83robertphillips@google.com } 2181e945b7e708c633d4aed937ebfce57d52ba21d83robertphillips@google.com 2191e945b7e708c633d4aed937ebfce57d52ba21d83robertphillips@google.com bounds.roundOut(&scissorSettings->fScissorRect); 2201e945b7e708c633d4aed937ebfce57d52ba21d83robertphillips@google.com if (scissorSettings->fScissorRect.isEmpty()) { 2211e945b7e708c633d4aed937ebfce57d52ba21d83robertphillips@google.com scissorSettings->fScissorRect.setLTRB(0,0,0,0); 2221e945b7e708c633d4aed937ebfce57d52ba21d83robertphillips@google.com // TODO: I think we can do an early exit here - after refactoring try: 2231e945b7e708c633d4aed937ebfce57d52ba21d83robertphillips@google.com // set fEnableScissoring to true but leave fClipMaskInStencil false 2241e945b7e708c633d4aed937ebfce57d52ba21d83robertphillips@google.com // and return - everything is going to be scissored away anyway! 2251e945b7e708c633d4aed937ebfce57d52ba21d83robertphillips@google.com } 2261e945b7e708c633d4aed937ebfce57d52ba21d83robertphillips@google.com scissorSettings->fEnableScissoring = true; 2271e945b7e708c633d4aed937ebfce57d52ba21d83robertphillips@google.com 2281e945b7e708c633d4aed937ebfce57d52ba21d83robertphillips@google.com // use the stencil clip if we can't represent the clip as a rectangle. 2291e945b7e708c633d4aed937ebfce57d52ba21d83robertphillips@google.com fClipMaskInStencil = !clipIn.isRect() && !clipIn.isEmpty() && 2301e945b7e708c633d4aed937ebfce57d52ba21d83robertphillips@google.com !bounds.isEmpty(); 2311e945b7e708c633d4aed937ebfce57d52ba21d83robertphillips@google.com 2321e945b7e708c633d4aed937ebfce57d52ba21d83robertphillips@google.com if (fClipMaskInStencil) { 2331e945b7e708c633d4aed937ebfce57d52ba21d83robertphillips@google.com return this->createStencilClipMask(gpu, clipIn, bounds, scissorSettings); 2341e945b7e708c633d4aed937ebfce57d52ba21d83robertphillips@google.com } 2351e945b7e708c633d4aed937ebfce57d52ba21d83robertphillips@google.com 2361e945b7e708c633d4aed937ebfce57d52ba21d83robertphillips@google.com return true; 2371e945b7e708c633d4aed937ebfce57d52ba21d83robertphillips@google.com} 2381e945b7e708c633d4aed937ebfce57d52ba21d83robertphillips@google.com 2391e945b7e708c633d4aed937ebfce57d52ba21d83robertphillips@google.com#define VISUALIZE_COMPLEX_CLIP 0 2401e945b7e708c633d4aed937ebfce57d52ba21d83robertphillips@google.com 2411e945b7e708c633d4aed937ebfce57d52ba21d83robertphillips@google.com#if VISUALIZE_COMPLEX_CLIP 2421e945b7e708c633d4aed937ebfce57d52ba21d83robertphillips@google.com #include "GrRandom.h" 2431e945b7e708c633d4aed937ebfce57d52ba21d83robertphillips@google.com GrRandom gRandom; 2441e945b7e708c633d4aed937ebfce57d52ba21d83robertphillips@google.com #define SET_RANDOM_COLOR drawState->setColor(0xff000000 | gRandom.nextU()); 2451e945b7e708c633d4aed937ebfce57d52ba21d83robertphillips@google.com#else 2461e945b7e708c633d4aed937ebfce57d52ba21d83robertphillips@google.com #define SET_RANDOM_COLOR 2471e945b7e708c633d4aed937ebfce57d52ba21d83robertphillips@google.com#endif 2481e945b7e708c633d4aed937ebfce57d52ba21d83robertphillips@google.com 2491e945b7e708c633d4aed937ebfce57d52ba21d83robertphillips@google.comnamespace { 2506623fcd1ee33b35fa18e304e9c76272faa603cbfrobertphillips@google.com/** 2516623fcd1ee33b35fa18e304e9c76272faa603cbfrobertphillips@google.com * Does "container" contain "containee"? If either is empty then 2526623fcd1ee33b35fa18e304e9c76272faa603cbfrobertphillips@google.com * no containment is possible. 2536623fcd1ee33b35fa18e304e9c76272faa603cbfrobertphillips@google.com */ 2546623fcd1ee33b35fa18e304e9c76272faa603cbfrobertphillips@google.combool contains(const SkRect& container, const SkIRect& containee) { 2556623fcd1ee33b35fa18e304e9c76272faa603cbfrobertphillips@google.com return !containee.isEmpty() && !container.isEmpty() && 2566623fcd1ee33b35fa18e304e9c76272faa603cbfrobertphillips@google.com container.fLeft <= SkIntToScalar(containee.fLeft) && 2576623fcd1ee33b35fa18e304e9c76272faa603cbfrobertphillips@google.com container.fTop <= SkIntToScalar(containee.fTop) && 2586623fcd1ee33b35fa18e304e9c76272faa603cbfrobertphillips@google.com container.fRight >= SkIntToScalar(containee.fRight) && 2596623fcd1ee33b35fa18e304e9c76272faa603cbfrobertphillips@google.com container.fBottom >= SkIntToScalar(containee.fBottom); 2606623fcd1ee33b35fa18e304e9c76272faa603cbfrobertphillips@google.com} 2616623fcd1ee33b35fa18e304e9c76272faa603cbfrobertphillips@google.com 2626623fcd1ee33b35fa18e304e9c76272faa603cbfrobertphillips@google.com 263f294b773f0b2b9f05eb45b52dd3cb4d97b96af06robertphillips@google.com//////////////////////////////////////////////////////////////////////////////// 2641e945b7e708c633d4aed937ebfce57d52ba21d83robertphillips@google.com// determines how many elements at the head of the clip can be skipped and 2651e945b7e708c633d4aed937ebfce57d52ba21d83robertphillips@google.com// whether the initial clear should be to the inside- or outside-the-clip value, 2661e945b7e708c633d4aed937ebfce57d52ba21d83robertphillips@google.com// and what op should be used to draw the first element that isn't skipped. 2671e945b7e708c633d4aed937ebfce57d52ba21d83robertphillips@google.comint process_initial_clip_elements(const GrClip& clip, 2686623fcd1ee33b35fa18e304e9c76272faa603cbfrobertphillips@google.com const GrIRect& bounds, 2691e945b7e708c633d4aed937ebfce57d52ba21d83robertphillips@google.com bool* clearToInside, 2700f191f30af7c067883c97b034baf70bfd92f5ea0robertphillips@google.com SkRegion::Op* startOp) { 2711e945b7e708c633d4aed937ebfce57d52ba21d83robertphillips@google.com 2721e945b7e708c633d4aed937ebfce57d52ba21d83robertphillips@google.com // logically before the first element of the clip stack is 2731e945b7e708c633d4aed937ebfce57d52ba21d83robertphillips@google.com // processed the clip is entirely open. However, depending on the 2741e945b7e708c633d4aed937ebfce57d52ba21d83robertphillips@google.com // first set op we may prefer to clear to 0 for performance. We may 2751e945b7e708c633d4aed937ebfce57d52ba21d83robertphillips@google.com // also be able to skip the initial clip paths/rects. We loop until 2761e945b7e708c633d4aed937ebfce57d52ba21d83robertphillips@google.com // we cannot skip an element. 2771e945b7e708c633d4aed937ebfce57d52ba21d83robertphillips@google.com int curr; 2781e945b7e708c633d4aed937ebfce57d52ba21d83robertphillips@google.com bool done = false; 2791e945b7e708c633d4aed937ebfce57d52ba21d83robertphillips@google.com *clearToInside = true; 2801e945b7e708c633d4aed937ebfce57d52ba21d83robertphillips@google.com int count = clip.getElementCount(); 2811e945b7e708c633d4aed937ebfce57d52ba21d83robertphillips@google.com 2821e945b7e708c633d4aed937ebfce57d52ba21d83robertphillips@google.com for (curr = 0; curr < count && !done; ++curr) { 2831e945b7e708c633d4aed937ebfce57d52ba21d83robertphillips@google.com switch (clip.getOp(curr)) { 2840f191f30af7c067883c97b034baf70bfd92f5ea0robertphillips@google.com case SkRegion::kReplace_Op: 2851e945b7e708c633d4aed937ebfce57d52ba21d83robertphillips@google.com // replace ignores everything previous 2860f191f30af7c067883c97b034baf70bfd92f5ea0robertphillips@google.com *startOp = SkRegion::kReplace_Op; 2871e945b7e708c633d4aed937ebfce57d52ba21d83robertphillips@google.com *clearToInside = false; 2881e945b7e708c633d4aed937ebfce57d52ba21d83robertphillips@google.com done = true; 2891e945b7e708c633d4aed937ebfce57d52ba21d83robertphillips@google.com break; 2900f191f30af7c067883c97b034baf70bfd92f5ea0robertphillips@google.com case SkRegion::kIntersect_Op: 2911e945b7e708c633d4aed937ebfce57d52ba21d83robertphillips@google.com // if this element contains the entire bounds then we 2921e945b7e708c633d4aed937ebfce57d52ba21d83robertphillips@google.com // can skip it. 2931e945b7e708c633d4aed937ebfce57d52ba21d83robertphillips@google.com if (kRect_ClipType == clip.getElementType(curr) 2946623fcd1ee33b35fa18e304e9c76272faa603cbfrobertphillips@google.com && contains(clip.getRect(curr), bounds)) { 2951e945b7e708c633d4aed937ebfce57d52ba21d83robertphillips@google.com break; 2961e945b7e708c633d4aed937ebfce57d52ba21d83robertphillips@google.com } 2971e945b7e708c633d4aed937ebfce57d52ba21d83robertphillips@google.com // if everything is initially clearToInside then intersect is 2981e945b7e708c633d4aed937ebfce57d52ba21d83robertphillips@google.com // same as clear to 0 and treat as a replace. Otherwise, 2991e945b7e708c633d4aed937ebfce57d52ba21d83robertphillips@google.com // set stays empty. 3001e945b7e708c633d4aed937ebfce57d52ba21d83robertphillips@google.com if (*clearToInside) { 3010f191f30af7c067883c97b034baf70bfd92f5ea0robertphillips@google.com *startOp = SkRegion::kReplace_Op; 3021e945b7e708c633d4aed937ebfce57d52ba21d83robertphillips@google.com *clearToInside = false; 3031e945b7e708c633d4aed937ebfce57d52ba21d83robertphillips@google.com done = true; 3041e945b7e708c633d4aed937ebfce57d52ba21d83robertphillips@google.com } 3051e945b7e708c633d4aed937ebfce57d52ba21d83robertphillips@google.com break; 3061e945b7e708c633d4aed937ebfce57d52ba21d83robertphillips@google.com // we can skip a leading union. 3070f191f30af7c067883c97b034baf70bfd92f5ea0robertphillips@google.com case SkRegion::kUnion_Op: 3081e945b7e708c633d4aed937ebfce57d52ba21d83robertphillips@google.com // if everything is initially outside then union is 3091e945b7e708c633d4aed937ebfce57d52ba21d83robertphillips@google.com // same as replace. Otherwise, every pixel is still 3101e945b7e708c633d4aed937ebfce57d52ba21d83robertphillips@google.com // clearToInside 3111e945b7e708c633d4aed937ebfce57d52ba21d83robertphillips@google.com if (!*clearToInside) { 3120f191f30af7c067883c97b034baf70bfd92f5ea0robertphillips@google.com *startOp = SkRegion::kReplace_Op; 3131e945b7e708c633d4aed937ebfce57d52ba21d83robertphillips@google.com done = true; 3141e945b7e708c633d4aed937ebfce57d52ba21d83robertphillips@google.com } 3151e945b7e708c633d4aed937ebfce57d52ba21d83robertphillips@google.com break; 3160f191f30af7c067883c97b034baf70bfd92f5ea0robertphillips@google.com case SkRegion::kXOR_Op: 3171e945b7e708c633d4aed937ebfce57d52ba21d83robertphillips@google.com // xor is same as difference or replace both of which 3181e945b7e708c633d4aed937ebfce57d52ba21d83robertphillips@google.com // can be 1-pass instead of 2 for xor. 3191e945b7e708c633d4aed937ebfce57d52ba21d83robertphillips@google.com if (*clearToInside) { 3200f191f30af7c067883c97b034baf70bfd92f5ea0robertphillips@google.com *startOp = SkRegion::kDifference_Op; 3211e945b7e708c633d4aed937ebfce57d52ba21d83robertphillips@google.com } else { 3220f191f30af7c067883c97b034baf70bfd92f5ea0robertphillips@google.com *startOp = SkRegion::kReplace_Op; 3231e945b7e708c633d4aed937ebfce57d52ba21d83robertphillips@google.com } 3241e945b7e708c633d4aed937ebfce57d52ba21d83robertphillips@google.com done = true; 3251e945b7e708c633d4aed937ebfce57d52ba21d83robertphillips@google.com break; 3260f191f30af7c067883c97b034baf70bfd92f5ea0robertphillips@google.com case SkRegion::kDifference_Op: 3271e945b7e708c633d4aed937ebfce57d52ba21d83robertphillips@google.com // if all pixels are clearToInside then we have to process the 3281e945b7e708c633d4aed937ebfce57d52ba21d83robertphillips@google.com // difference, otherwise it has no effect and all pixels 3291e945b7e708c633d4aed937ebfce57d52ba21d83robertphillips@google.com // remain outside. 3301e945b7e708c633d4aed937ebfce57d52ba21d83robertphillips@google.com if (*clearToInside) { 3310f191f30af7c067883c97b034baf70bfd92f5ea0robertphillips@google.com *startOp = SkRegion::kDifference_Op; 3321e945b7e708c633d4aed937ebfce57d52ba21d83robertphillips@google.com done = true; 3331e945b7e708c633d4aed937ebfce57d52ba21d83robertphillips@google.com } 3341e945b7e708c633d4aed937ebfce57d52ba21d83robertphillips@google.com break; 3350f191f30af7c067883c97b034baf70bfd92f5ea0robertphillips@google.com case SkRegion::kReverseDifference_Op: 3361e945b7e708c633d4aed937ebfce57d52ba21d83robertphillips@google.com // if all pixels are clearToInside then reverse difference 3371e945b7e708c633d4aed937ebfce57d52ba21d83robertphillips@google.com // produces empty set. Otherise it is same as replace 3381e945b7e708c633d4aed937ebfce57d52ba21d83robertphillips@google.com if (*clearToInside) { 3391e945b7e708c633d4aed937ebfce57d52ba21d83robertphillips@google.com *clearToInside = false; 3401e945b7e708c633d4aed937ebfce57d52ba21d83robertphillips@google.com } else { 3410f191f30af7c067883c97b034baf70bfd92f5ea0robertphillips@google.com *startOp = SkRegion::kReplace_Op; 3421e945b7e708c633d4aed937ebfce57d52ba21d83robertphillips@google.com done = true; 3431e945b7e708c633d4aed937ebfce57d52ba21d83robertphillips@google.com } 3441e945b7e708c633d4aed937ebfce57d52ba21d83robertphillips@google.com break; 3451e945b7e708c633d4aed937ebfce57d52ba21d83robertphillips@google.com default: 3461e945b7e708c633d4aed937ebfce57d52ba21d83robertphillips@google.com GrCrash("Unknown set op."); 3471e945b7e708c633d4aed937ebfce57d52ba21d83robertphillips@google.com } 3481e945b7e708c633d4aed937ebfce57d52ba21d83robertphillips@google.com } 3491e945b7e708c633d4aed937ebfce57d52ba21d83robertphillips@google.com return done ? curr-1 : count; 3501e945b7e708c633d4aed937ebfce57d52ba21d83robertphillips@google.com} 351f294b773f0b2b9f05eb45b52dd3cb4d97b96af06robertphillips@google.com 352f294b773f0b2b9f05eb45b52dd3cb4d97b96af06robertphillips@google.com} 353f294b773f0b2b9f05eb45b52dd3cb4d97b96af06robertphillips@google.com 354f294b773f0b2b9f05eb45b52dd3cb4d97b96af06robertphillips@google.com 355f294b773f0b2b9f05eb45b52dd3cb4d97b96af06robertphillips@google.comnamespace { 356f294b773f0b2b9f05eb45b52dd3cb4d97b96af06robertphillips@google.com 357f294b773f0b2b9f05eb45b52dd3cb4d97b96af06robertphillips@google.com//////////////////////////////////////////////////////////////////////////////// 358f294b773f0b2b9f05eb45b52dd3cb4d97b96af06robertphillips@google.com// set up the OpenGL blend function to perform the specified 359f294b773f0b2b9f05eb45b52dd3cb4d97b96af06robertphillips@google.com// boolean operation for alpha clip mask creation 3606b70a7bd3328ea0a12be47b1a7f835c905f16147robertphillips@google.comvoid setup_boolean_blendcoeffs(GrDrawState* drawState, SkRegion::Op op) { 361f294b773f0b2b9f05eb45b52dd3cb4d97b96af06robertphillips@google.com 362f294b773f0b2b9f05eb45b52dd3cb4d97b96af06robertphillips@google.com switch (op) { 363f294b773f0b2b9f05eb45b52dd3cb4d97b96af06robertphillips@google.com case SkRegion::kReplace_Op: 364f294b773f0b2b9f05eb45b52dd3cb4d97b96af06robertphillips@google.com drawState->setBlendFunc(kOne_BlendCoeff, kZero_BlendCoeff); 365f294b773f0b2b9f05eb45b52dd3cb4d97b96af06robertphillips@google.com break; 366f294b773f0b2b9f05eb45b52dd3cb4d97b96af06robertphillips@google.com case SkRegion::kIntersect_Op: 367f294b773f0b2b9f05eb45b52dd3cb4d97b96af06robertphillips@google.com drawState->setBlendFunc(kDC_BlendCoeff, kZero_BlendCoeff); 368f294b773f0b2b9f05eb45b52dd3cb4d97b96af06robertphillips@google.com break; 369f294b773f0b2b9f05eb45b52dd3cb4d97b96af06robertphillips@google.com case SkRegion::kUnion_Op: 370f294b773f0b2b9f05eb45b52dd3cb4d97b96af06robertphillips@google.com drawState->setBlendFunc(kOne_BlendCoeff, kISC_BlendCoeff); 371f294b773f0b2b9f05eb45b52dd3cb4d97b96af06robertphillips@google.com break; 372f294b773f0b2b9f05eb45b52dd3cb4d97b96af06robertphillips@google.com case SkRegion::kXOR_Op: 373f294b773f0b2b9f05eb45b52dd3cb4d97b96af06robertphillips@google.com drawState->setBlendFunc(kIDC_BlendCoeff, kISC_BlendCoeff); 374f294b773f0b2b9f05eb45b52dd3cb4d97b96af06robertphillips@google.com break; 375f294b773f0b2b9f05eb45b52dd3cb4d97b96af06robertphillips@google.com case SkRegion::kDifference_Op: 376f294b773f0b2b9f05eb45b52dd3cb4d97b96af06robertphillips@google.com drawState->setBlendFunc(kZero_BlendCoeff, kISC_BlendCoeff); 377f294b773f0b2b9f05eb45b52dd3cb4d97b96af06robertphillips@google.com break; 378f294b773f0b2b9f05eb45b52dd3cb4d97b96af06robertphillips@google.com case SkRegion::kReverseDifference_Op: 379f294b773f0b2b9f05eb45b52dd3cb4d97b96af06robertphillips@google.com drawState->setBlendFunc(kIDC_BlendCoeff, kZero_BlendCoeff); 380f294b773f0b2b9f05eb45b52dd3cb4d97b96af06robertphillips@google.com break; 381f294b773f0b2b9f05eb45b52dd3cb4d97b96af06robertphillips@google.com default: 382f294b773f0b2b9f05eb45b52dd3cb4d97b96af06robertphillips@google.com GrAssert(false); 383f294b773f0b2b9f05eb45b52dd3cb4d97b96af06robertphillips@google.com break; 384f294b773f0b2b9f05eb45b52dd3cb4d97b96af06robertphillips@google.com } 385f294b773f0b2b9f05eb45b52dd3cb4d97b96af06robertphillips@google.com} 386f294b773f0b2b9f05eb45b52dd3cb4d97b96af06robertphillips@google.com 387f294b773f0b2b9f05eb45b52dd3cb4d97b96af06robertphillips@google.com//////////////////////////////////////////////////////////////////////////////// 3882c75681e36b33fcafc5665d7012bbd4fc6647d83robertphillips@google.combool draw_path(GrContext* context, 3892c75681e36b33fcafc5665d7012bbd4fc6647d83robertphillips@google.com GrGpu* gpu, 3902c75681e36b33fcafc5665d7012bbd4fc6647d83robertphillips@google.com const SkPath& path, 3912c75681e36b33fcafc5665d7012bbd4fc6647d83robertphillips@google.com GrPathFill fill, 3922c75681e36b33fcafc5665d7012bbd4fc6647d83robertphillips@google.com bool doAA) { 393f294b773f0b2b9f05eb45b52dd3cb4d97b96af06robertphillips@google.com 39472176b2d38db005863a54e3dd6657bbabd068bb6robertphillips@google.com GrPathRenderer* pr = context->getPathRenderer(path, fill, gpu, doAA, true); 395f294b773f0b2b9f05eb45b52dd3cb4d97b96af06robertphillips@google.com if (NULL == pr) { 396f294b773f0b2b9f05eb45b52dd3cb4d97b96af06robertphillips@google.com return false; 397f294b773f0b2b9f05eb45b52dd3cb4d97b96af06robertphillips@google.com } 398f294b773f0b2b9f05eb45b52dd3cb4d97b96af06robertphillips@google.com 399f294b773f0b2b9f05eb45b52dd3cb4d97b96af06robertphillips@google.com pr->drawPath(path, fill, NULL, gpu, 0, doAA); 400f294b773f0b2b9f05eb45b52dd3cb4d97b96af06robertphillips@google.com return true; 401f294b773f0b2b9f05eb45b52dd3cb4d97b96af06robertphillips@google.com} 40272176b2d38db005863a54e3dd6657bbabd068bb6robertphillips@google.com 40372176b2d38db005863a54e3dd6657bbabd068bb6robertphillips@google.com} 404f294b773f0b2b9f05eb45b52dd3cb4d97b96af06robertphillips@google.com 405f294b773f0b2b9f05eb45b52dd3cb4d97b96af06robertphillips@google.com//////////////////////////////////////////////////////////////////////////////// 406f294b773f0b2b9f05eb45b52dd3cb4d97b96af06robertphillips@google.combool GrClipMaskManager::drawClipShape(GrGpu* gpu, 407f294b773f0b2b9f05eb45b52dd3cb4d97b96af06robertphillips@google.com GrTexture* target, 408f294b773f0b2b9f05eb45b52dd3cb4d97b96af06robertphillips@google.com const GrClip& clipIn, 409f294b773f0b2b9f05eb45b52dd3cb4d97b96af06robertphillips@google.com int index) { 410f294b773f0b2b9f05eb45b52dd3cb4d97b96af06robertphillips@google.com GrDrawState* drawState = gpu->drawState(); 411f294b773f0b2b9f05eb45b52dd3cb4d97b96af06robertphillips@google.com GrAssert(NULL != drawState); 412f294b773f0b2b9f05eb45b52dd3cb4d97b96af06robertphillips@google.com 413f294b773f0b2b9f05eb45b52dd3cb4d97b96af06robertphillips@google.com drawState->setRenderTarget(target->asRenderTarget()); 414f294b773f0b2b9f05eb45b52dd3cb4d97b96af06robertphillips@google.com 415f294b773f0b2b9f05eb45b52dd3cb4d97b96af06robertphillips@google.com if (kRect_ClipType == clipIn.getElementType(index)) { 416f294b773f0b2b9f05eb45b52dd3cb4d97b96af06robertphillips@google.com if (clipIn.getDoAA(index)) { 417f294b773f0b2b9f05eb45b52dd3cb4d97b96af06robertphillips@google.com // convert the rect to a path for AA 418f294b773f0b2b9f05eb45b52dd3cb4d97b96af06robertphillips@google.com SkPath temp; 419f294b773f0b2b9f05eb45b52dd3cb4d97b96af06robertphillips@google.com temp.addRect(clipIn.getRect(index)); 420f294b773f0b2b9f05eb45b52dd3cb4d97b96af06robertphillips@google.com 4212c75681e36b33fcafc5665d7012bbd4fc6647d83robertphillips@google.com return draw_path(this->getContext(), gpu, temp, 4222c75681e36b33fcafc5665d7012bbd4fc6647d83robertphillips@google.com kEvenOdd_PathFill, clipIn.getDoAA(index)); 423f294b773f0b2b9f05eb45b52dd3cb4d97b96af06robertphillips@google.com } else { 424f294b773f0b2b9f05eb45b52dd3cb4d97b96af06robertphillips@google.com gpu->drawSimpleRect(clipIn.getRect(index), NULL, 0); 425f294b773f0b2b9f05eb45b52dd3cb4d97b96af06robertphillips@google.com } 426f294b773f0b2b9f05eb45b52dd3cb4d97b96af06robertphillips@google.com } else { 4272c75681e36b33fcafc5665d7012bbd4fc6647d83robertphillips@google.com return draw_path(this->getContext(), gpu, 4282c75681e36b33fcafc5665d7012bbd4fc6647d83robertphillips@google.com clipIn.getPath(index), 4292c75681e36b33fcafc5665d7012bbd4fc6647d83robertphillips@google.com clipIn.getPathFill(index), 4302c75681e36b33fcafc5665d7012bbd4fc6647d83robertphillips@google.com clipIn.getDoAA(index)); 431f294b773f0b2b9f05eb45b52dd3cb4d97b96af06robertphillips@google.com } 432f294b773f0b2b9f05eb45b52dd3cb4d97b96af06robertphillips@google.com return true; 433f294b773f0b2b9f05eb45b52dd3cb4d97b96af06robertphillips@google.com} 434f294b773f0b2b9f05eb45b52dd3cb4d97b96af06robertphillips@google.com 435f294b773f0b2b9f05eb45b52dd3cb4d97b96af06robertphillips@google.comvoid GrClipMaskManager::drawTexture(GrGpu* gpu, 436f294b773f0b2b9f05eb45b52dd3cb4d97b96af06robertphillips@google.com GrTexture* target, 437f294b773f0b2b9f05eb45b52dd3cb4d97b96af06robertphillips@google.com GrTexture* texture) { 438f294b773f0b2b9f05eb45b52dd3cb4d97b96af06robertphillips@google.com GrDrawState* drawState = gpu->drawState(); 439f294b773f0b2b9f05eb45b52dd3cb4d97b96af06robertphillips@google.com GrAssert(NULL != drawState); 440f294b773f0b2b9f05eb45b52dd3cb4d97b96af06robertphillips@google.com 441f294b773f0b2b9f05eb45b52dd3cb4d97b96af06robertphillips@google.com // no AA here since it is encoded in the texture 442f294b773f0b2b9f05eb45b52dd3cb4d97b96af06robertphillips@google.com drawState->setRenderTarget(target->asRenderTarget()); 443f294b773f0b2b9f05eb45b52dd3cb4d97b96af06robertphillips@google.com 444f294b773f0b2b9f05eb45b52dd3cb4d97b96af06robertphillips@google.com GrMatrix sampleM; 445f294b773f0b2b9f05eb45b52dd3cb4d97b96af06robertphillips@google.com sampleM.setIDiv(texture->width(), texture->height()); 446f294b773f0b2b9f05eb45b52dd3cb4d97b96af06robertphillips@google.com drawState->setTexture(0, texture); 447f294b773f0b2b9f05eb45b52dd3cb4d97b96af06robertphillips@google.com 448f294b773f0b2b9f05eb45b52dd3cb4d97b96af06robertphillips@google.com drawState->sampler(0)->reset(GrSamplerState::kClamp_WrapMode, 449f294b773f0b2b9f05eb45b52dd3cb4d97b96af06robertphillips@google.com GrSamplerState::kNearest_Filter, 450f294b773f0b2b9f05eb45b52dd3cb4d97b96af06robertphillips@google.com sampleM); 451f294b773f0b2b9f05eb45b52dd3cb4d97b96af06robertphillips@google.com 452f105b109264f71dfb0bfd9977e6a5dd0a5a12f57robertphillips@google.com GrRect rect = GrRect::MakeWH(SkIntToScalar(target->width()), 453f105b109264f71dfb0bfd9977e6a5dd0a5a12f57robertphillips@google.com SkIntToScalar(target->height())); 454f105b109264f71dfb0bfd9977e6a5dd0a5a12f57robertphillips@google.com 455f294b773f0b2b9f05eb45b52dd3cb4d97b96af06robertphillips@google.com gpu->drawSimpleRect(rect, NULL, 1 << 0); 456f294b773f0b2b9f05eb45b52dd3cb4d97b96af06robertphillips@google.com 457f294b773f0b2b9f05eb45b52dd3cb4d97b96af06robertphillips@google.com drawState->setTexture(0, NULL); 458f294b773f0b2b9f05eb45b52dd3cb4d97b96af06robertphillips@google.com} 459f294b773f0b2b9f05eb45b52dd3cb4d97b96af06robertphillips@google.com 460f294b773f0b2b9f05eb45b52dd3cb4d97b96af06robertphillips@google.comnamespace { 461f294b773f0b2b9f05eb45b52dd3cb4d97b96af06robertphillips@google.com 462f294b773f0b2b9f05eb45b52dd3cb4d97b96af06robertphillips@google.comvoid clear(GrGpu* gpu, 463f294b773f0b2b9f05eb45b52dd3cb4d97b96af06robertphillips@google.com GrTexture* target, 464f294b773f0b2b9f05eb45b52dd3cb4d97b96af06robertphillips@google.com GrColor color) { 465f294b773f0b2b9f05eb45b52dd3cb4d97b96af06robertphillips@google.com GrDrawState* drawState = gpu->drawState(); 466f294b773f0b2b9f05eb45b52dd3cb4d97b96af06robertphillips@google.com GrAssert(NULL != drawState); 467f294b773f0b2b9f05eb45b52dd3cb4d97b96af06robertphillips@google.com 468f294b773f0b2b9f05eb45b52dd3cb4d97b96af06robertphillips@google.com // zap entire target to specified color 469f294b773f0b2b9f05eb45b52dd3cb4d97b96af06robertphillips@google.com drawState->setRenderTarget(target->asRenderTarget()); 470f294b773f0b2b9f05eb45b52dd3cb4d97b96af06robertphillips@google.com gpu->clear(NULL, color); 471f294b773f0b2b9f05eb45b52dd3cb4d97b96af06robertphillips@google.com} 472f294b773f0b2b9f05eb45b52dd3cb4d97b96af06robertphillips@google.com 473f105b109264f71dfb0bfd9977e6a5dd0a5a12f57robertphillips@google.com} 474f105b109264f71dfb0bfd9977e6a5dd0a5a12f57robertphillips@google.com 4756d62df404bf420bedff4d7b5edd061740a673d44robertphillips@google.com// get a texture to act as a temporary buffer for AA clip boolean operations 4766d62df404bf420bedff4d7b5edd061740a673d44robertphillips@google.com// TODO: given the expense of createTexture we may want to just cache this too 4776623fcd1ee33b35fa18e304e9c76272faa603cbfrobertphillips@google.comvoid GrClipMaskManager::getTemp(const GrIRect& bounds, 478f105b109264f71dfb0bfd9977e6a5dd0a5a12f57robertphillips@google.com GrAutoScratchTexture* temp) { 479f105b109264f71dfb0bfd9977e6a5dd0a5a12f57robertphillips@google.com if (NULL != temp->texture()) { 4806d62df404bf420bedff4d7b5edd061740a673d44robertphillips@google.com // we've already allocated the temp texture 4816d62df404bf420bedff4d7b5edd061740a673d44robertphillips@google.com return; 4826d62df404bf420bedff4d7b5edd061740a673d44robertphillips@google.com } 4836d62df404bf420bedff4d7b5edd061740a673d44robertphillips@google.com 4846b70a7bd3328ea0a12be47b1a7f835c905f16147robertphillips@google.com const GrTextureDesc desc = { 4856b70a7bd3328ea0a12be47b1a7f835c905f16147robertphillips@google.com kRenderTarget_GrTextureFlagBit|kNoStencil_GrTextureFlagBit, 4866623fcd1ee33b35fa18e304e9c76272faa603cbfrobertphillips@google.com bounds.width(), 4876623fcd1ee33b35fa18e304e9c76272faa603cbfrobertphillips@google.com bounds.height(), 4886b70a7bd3328ea0a12be47b1a7f835c905f16147robertphillips@google.com kAlpha_8_GrPixelConfig, 4896b70a7bd3328ea0a12be47b1a7f835c905f16147robertphillips@google.com 0 // samples 4906b70a7bd3328ea0a12be47b1a7f835c905f16147robertphillips@google.com }; 4916b70a7bd3328ea0a12be47b1a7f835c905f16147robertphillips@google.com 4922c75681e36b33fcafc5665d7012bbd4fc6647d83robertphillips@google.com temp->set(this->getContext(), desc); 4936d62df404bf420bedff4d7b5edd061740a673d44robertphillips@google.com} 4946d62df404bf420bedff4d7b5edd061740a673d44robertphillips@google.com 4956d62df404bf420bedff4d7b5edd061740a673d44robertphillips@google.com 496f105b109264f71dfb0bfd9977e6a5dd0a5a12f57robertphillips@google.comvoid GrClipMaskManager::setupCache(const GrClip& clipIn, 4976623fcd1ee33b35fa18e304e9c76272faa603cbfrobertphillips@google.com const GrIRect& bounds) { 498f105b109264f71dfb0bfd9977e6a5dd0a5a12f57robertphillips@google.com // Since we are setting up the cache we know the last lookup was a miss 499f105b109264f71dfb0bfd9977e6a5dd0a5a12f57robertphillips@google.com // Free up the currently cached mask so it can be reused 500f105b109264f71dfb0bfd9977e6a5dd0a5a12f57robertphillips@google.com fAACache.reset(); 5016d62df404bf420bedff4d7b5edd061740a673d44robertphillips@google.com 502f105b109264f71dfb0bfd9977e6a5dd0a5a12f57robertphillips@google.com const GrTextureDesc desc = { 503f105b109264f71dfb0bfd9977e6a5dd0a5a12f57robertphillips@google.com kRenderTarget_GrTextureFlagBit|kNoStencil_GrTextureFlagBit, 5046623fcd1ee33b35fa18e304e9c76272faa603cbfrobertphillips@google.com bounds.width(), 5056623fcd1ee33b35fa18e304e9c76272faa603cbfrobertphillips@google.com bounds.height(), 506f105b109264f71dfb0bfd9977e6a5dd0a5a12f57robertphillips@google.com kAlpha_8_GrPixelConfig, 507f105b109264f71dfb0bfd9977e6a5dd0a5a12f57robertphillips@google.com 0 // samples 508f105b109264f71dfb0bfd9977e6a5dd0a5a12f57robertphillips@google.com }; 509f294b773f0b2b9f05eb45b52dd3cb4d97b96af06robertphillips@google.com 510f105b109264f71dfb0bfd9977e6a5dd0a5a12f57robertphillips@google.com fAACache.acquireMask(clipIn, desc, bounds); 511f105b109264f71dfb0bfd9977e6a5dd0a5a12f57robertphillips@google.com} 512f294b773f0b2b9f05eb45b52dd3cb4d97b96af06robertphillips@google.com 5136b70a7bd3328ea0a12be47b1a7f835c905f16147robertphillips@google.com//////////////////////////////////////////////////////////////////////////////// 5146b70a7bd3328ea0a12be47b1a7f835c905f16147robertphillips@google.com// Shared preamble between gpu and SW-only AA clip mask creation paths. 5156b70a7bd3328ea0a12be47b1a7f835c905f16147robertphillips@google.com// Handles caching, determination of clip mask bound & allocation (if needed) 5166b70a7bd3328ea0a12be47b1a7f835c905f16147robertphillips@google.com// of the result texture 5176b70a7bd3328ea0a12be47b1a7f835c905f16147robertphillips@google.com// Returns true if there is no more work to be done (i.e., we got a cache hit) 5186b70a7bd3328ea0a12be47b1a7f835c905f16147robertphillips@google.combool GrClipMaskManager::clipMaskPreamble(GrGpu* gpu, 5196b70a7bd3328ea0a12be47b1a7f835c905f16147robertphillips@google.com const GrClip& clipIn, 5206b70a7bd3328ea0a12be47b1a7f835c905f16147robertphillips@google.com GrTexture** result, 5216623fcd1ee33b35fa18e304e9c76272faa603cbfrobertphillips@google.com GrIRect *resultBounds) { 522f294b773f0b2b9f05eb45b52dd3cb4d97b96af06robertphillips@google.com GrDrawState* origDrawState = gpu->drawState(); 523f294b773f0b2b9f05eb45b52dd3cb4d97b96af06robertphillips@google.com GrAssert(origDrawState->isClipState()); 524f294b773f0b2b9f05eb45b52dd3cb4d97b96af06robertphillips@google.com 525f294b773f0b2b9f05eb45b52dd3cb4d97b96af06robertphillips@google.com GrRenderTarget* rt = origDrawState->getRenderTarget(); 526f294b773f0b2b9f05eb45b52dd3cb4d97b96af06robertphillips@google.com GrAssert(NULL != rt); 527f294b773f0b2b9f05eb45b52dd3cb4d97b96af06robertphillips@google.com 528f294b773f0b2b9f05eb45b52dd3cb4d97b96af06robertphillips@google.com GrRect rtRect; 529f294b773f0b2b9f05eb45b52dd3cb4d97b96af06robertphillips@google.com rtRect.setLTRB(0, 0, 530f294b773f0b2b9f05eb45b52dd3cb4d97b96af06robertphillips@google.com GrIntToScalar(rt->width()), GrIntToScalar(rt->height())); 531f294b773f0b2b9f05eb45b52dd3cb4d97b96af06robertphillips@google.com 532f294b773f0b2b9f05eb45b52dd3cb4d97b96af06robertphillips@google.com // unlike the stencil path the alpha path is not bound to the size of the 533f294b773f0b2b9f05eb45b52dd3cb4d97b96af06robertphillips@google.com // render target - determine the minimum size required for the mask 534f294b773f0b2b9f05eb45b52dd3cb4d97b96af06robertphillips@google.com GrRect bounds; 535f294b773f0b2b9f05eb45b52dd3cb4d97b96af06robertphillips@google.com 536f294b773f0b2b9f05eb45b52dd3cb4d97b96af06robertphillips@google.com if (clipIn.hasConservativeBounds()) { 537f294b773f0b2b9f05eb45b52dd3cb4d97b96af06robertphillips@google.com bounds = clipIn.getConservativeBounds(); 538f294b773f0b2b9f05eb45b52dd3cb4d97b96af06robertphillips@google.com if (!bounds.intersect(rtRect)) { 539f294b773f0b2b9f05eb45b52dd3cb4d97b96af06robertphillips@google.com // the mask will be empty in this case 540f294b773f0b2b9f05eb45b52dd3cb4d97b96af06robertphillips@google.com GrAssert(false); 541f294b773f0b2b9f05eb45b52dd3cb4d97b96af06robertphillips@google.com bounds.setEmpty(); 542f294b773f0b2b9f05eb45b52dd3cb4d97b96af06robertphillips@google.com } 543f294b773f0b2b9f05eb45b52dd3cb4d97b96af06robertphillips@google.com } else { 544f294b773f0b2b9f05eb45b52dd3cb4d97b96af06robertphillips@google.com // still locked to the size of the render target 545f294b773f0b2b9f05eb45b52dd3cb4d97b96af06robertphillips@google.com bounds = rtRect; 546f294b773f0b2b9f05eb45b52dd3cb4d97b96af06robertphillips@google.com } 547f294b773f0b2b9f05eb45b52dd3cb4d97b96af06robertphillips@google.com 5486623fcd1ee33b35fa18e304e9c76272faa603cbfrobertphillips@google.com GrIRect intBounds; 5496623fcd1ee33b35fa18e304e9c76272faa603cbfrobertphillips@google.com bounds.roundOut(&intBounds); 550f294b773f0b2b9f05eb45b52dd3cb4d97b96af06robertphillips@google.com 551f294b773f0b2b9f05eb45b52dd3cb4d97b96af06robertphillips@google.com // need to outset a pixel since the standard bounding box computation 552f294b773f0b2b9f05eb45b52dd3cb4d97b96af06robertphillips@google.com // path doesn't leave any room for antialiasing (esp. w.r.t. rects) 5536623fcd1ee33b35fa18e304e9c76272faa603cbfrobertphillips@google.com intBounds.outset(1, 1); 554f294b773f0b2b9f05eb45b52dd3cb4d97b96af06robertphillips@google.com 555a72eef322c686954cdffa849dc26d8133b802f1drobertphillips@google.com // TODO: make sure we don't outset if bounds are still 0,0 @ min 556a72eef322c686954cdffa849dc26d8133b802f1drobertphillips@google.com 5578fff356c8505f2ac78e1fc9dc17c1192e3a608e4robertphillips@google.com if (fAACache.canReuse(clipIn, 5586623fcd1ee33b35fa18e304e9c76272faa603cbfrobertphillips@google.com intBounds.width(), 5596623fcd1ee33b35fa18e304e9c76272faa603cbfrobertphillips@google.com intBounds.height())) { 5608fff356c8505f2ac78e1fc9dc17c1192e3a608e4robertphillips@google.com *result = fAACache.getLastMask(); 5618fff356c8505f2ac78e1fc9dc17c1192e3a608e4robertphillips@google.com fAACache.getLastBound(resultBounds); 5628fff356c8505f2ac78e1fc9dc17c1192e3a608e4robertphillips@google.com return true; 5638fff356c8505f2ac78e1fc9dc17c1192e3a608e4robertphillips@google.com } 5648fff356c8505f2ac78e1fc9dc17c1192e3a608e4robertphillips@google.com 5656623fcd1ee33b35fa18e304e9c76272faa603cbfrobertphillips@google.com this->setupCache(clipIn, intBounds); 566f105b109264f71dfb0bfd9977e6a5dd0a5a12f57robertphillips@google.com 5676623fcd1ee33b35fa18e304e9c76272faa603cbfrobertphillips@google.com *resultBounds = intBounds; 5686b70a7bd3328ea0a12be47b1a7f835c905f16147robertphillips@google.com return false; 5696b70a7bd3328ea0a12be47b1a7f835c905f16147robertphillips@google.com} 570f294b773f0b2b9f05eb45b52dd3cb4d97b96af06robertphillips@google.com 5716b70a7bd3328ea0a12be47b1a7f835c905f16147robertphillips@google.com//////////////////////////////////////////////////////////////////////////////// 5726b70a7bd3328ea0a12be47b1a7f835c905f16147robertphillips@google.com// Create a 8-bit clip mask in alpha 5736b70a7bd3328ea0a12be47b1a7f835c905f16147robertphillips@google.combool GrClipMaskManager::createAlphaClipMask(GrGpu* gpu, 5746b70a7bd3328ea0a12be47b1a7f835c905f16147robertphillips@google.com const GrClip& clipIn, 5756b70a7bd3328ea0a12be47b1a7f835c905f16147robertphillips@google.com GrTexture** result, 5766623fcd1ee33b35fa18e304e9c76272faa603cbfrobertphillips@google.com GrIRect *resultBounds) { 5776b70a7bd3328ea0a12be47b1a7f835c905f16147robertphillips@google.com 578f105b109264f71dfb0bfd9977e6a5dd0a5a12f57robertphillips@google.com if (this->clipMaskPreamble(gpu, clipIn, result, resultBounds)) { 5796b70a7bd3328ea0a12be47b1a7f835c905f16147robertphillips@google.com return true; 5806b70a7bd3328ea0a12be47b1a7f835c905f16147robertphillips@google.com } 581f294b773f0b2b9f05eb45b52dd3cb4d97b96af06robertphillips@google.com 582f105b109264f71dfb0bfd9977e6a5dd0a5a12f57robertphillips@google.com GrTexture* accum = fAACache.getLastMask(); 5836d62df404bf420bedff4d7b5edd061740a673d44robertphillips@google.com if (NULL == accum) { 584f294b773f0b2b9f05eb45b52dd3cb4d97b96af06robertphillips@google.com fClipMaskInAlpha = false; 585f105b109264f71dfb0bfd9977e6a5dd0a5a12f57robertphillips@google.com fAACache.reset(); 586f294b773f0b2b9f05eb45b52dd3cb4d97b96af06robertphillips@google.com return false; 587f294b773f0b2b9f05eb45b52dd3cb4d97b96af06robertphillips@google.com } 588f294b773f0b2b9f05eb45b52dd3cb4d97b96af06robertphillips@google.com 589f294b773f0b2b9f05eb45b52dd3cb4d97b96af06robertphillips@google.com GrDrawTarget::AutoStateRestore asr(gpu, GrDrawTarget::kReset_ASRInit); 590f294b773f0b2b9f05eb45b52dd3cb4d97b96af06robertphillips@google.com GrDrawState* drawState = gpu->drawState(); 591f294b773f0b2b9f05eb45b52dd3cb4d97b96af06robertphillips@google.com 592f294b773f0b2b9f05eb45b52dd3cb4d97b96af06robertphillips@google.com GrDrawTarget::AutoGeometryPush agp(gpu); 593f294b773f0b2b9f05eb45b52dd3cb4d97b96af06robertphillips@google.com 594f294b773f0b2b9f05eb45b52dd3cb4d97b96af06robertphillips@google.com int count = clipIn.getElementCount(); 595f294b773f0b2b9f05eb45b52dd3cb4d97b96af06robertphillips@google.com 5966b70a7bd3328ea0a12be47b1a7f835c905f16147robertphillips@google.com if (0 != resultBounds->fTop || 0 != resultBounds->fLeft) { 597f294b773f0b2b9f05eb45b52dd3cb4d97b96af06robertphillips@google.com // if we were able to trim down the size of the mask we need to 598f294b773f0b2b9f05eb45b52dd3cb4d97b96af06robertphillips@google.com // offset the paths & rects that will be used to compute it 599f294b773f0b2b9f05eb45b52dd3cb4d97b96af06robertphillips@google.com GrMatrix m; 600f294b773f0b2b9f05eb45b52dd3cb4d97b96af06robertphillips@google.com 6016623fcd1ee33b35fa18e304e9c76272faa603cbfrobertphillips@google.com m.setTranslate(SkIntToScalar(-resultBounds->fLeft), 6026623fcd1ee33b35fa18e304e9c76272faa603cbfrobertphillips@google.com SkIntToScalar(-resultBounds->fTop)); 603f294b773f0b2b9f05eb45b52dd3cb4d97b96af06robertphillips@google.com 6046d62df404bf420bedff4d7b5edd061740a673d44robertphillips@google.com drawState->setViewMatrix(m); 605f294b773f0b2b9f05eb45b52dd3cb4d97b96af06robertphillips@google.com } 606f294b773f0b2b9f05eb45b52dd3cb4d97b96af06robertphillips@google.com 607f294b773f0b2b9f05eb45b52dd3cb4d97b96af06robertphillips@google.com bool clearToInside; 608f294b773f0b2b9f05eb45b52dd3cb4d97b96af06robertphillips@google.com SkRegion::Op startOp = SkRegion::kReplace_Op; // suppress warning 609f294b773f0b2b9f05eb45b52dd3cb4d97b96af06robertphillips@google.com int start = process_initial_clip_elements(clipIn, 6106b70a7bd3328ea0a12be47b1a7f835c905f16147robertphillips@google.com *resultBounds, 611f294b773f0b2b9f05eb45b52dd3cb4d97b96af06robertphillips@google.com &clearToInside, 612f294b773f0b2b9f05eb45b52dd3cb4d97b96af06robertphillips@google.com &startOp); 613f294b773f0b2b9f05eb45b52dd3cb4d97b96af06robertphillips@google.com 6146d62df404bf420bedff4d7b5edd061740a673d44robertphillips@google.com clear(gpu, accum, clearToInside ? 0xffffffff : 0x00000000); 615f294b773f0b2b9f05eb45b52dd3cb4d97b96af06robertphillips@google.com 616f105b109264f71dfb0bfd9977e6a5dd0a5a12f57robertphillips@google.com GrAutoScratchTexture temp; 6176b70a7bd3328ea0a12be47b1a7f835c905f16147robertphillips@google.com 618f294b773f0b2b9f05eb45b52dd3cb4d97b96af06robertphillips@google.com // walk through each clip element and perform its set op 619f294b773f0b2b9f05eb45b52dd3cb4d97b96af06robertphillips@google.com for (int c = start; c < count; ++c) { 620f294b773f0b2b9f05eb45b52dd3cb4d97b96af06robertphillips@google.com 621f294b773f0b2b9f05eb45b52dd3cb4d97b96af06robertphillips@google.com SkRegion::Op op = (c == start) ? startOp : clipIn.getOp(c); 622f294b773f0b2b9f05eb45b52dd3cb4d97b96af06robertphillips@google.com 623f294b773f0b2b9f05eb45b52dd3cb4d97b96af06robertphillips@google.com if (SkRegion::kReplace_Op == op) { 624f294b773f0b2b9f05eb45b52dd3cb4d97b96af06robertphillips@google.com // TODO: replace is actually a lot faster then intersection 625f294b773f0b2b9f05eb45b52dd3cb4d97b96af06robertphillips@google.com // for this path - refactor the stencil path so it can handle 626f294b773f0b2b9f05eb45b52dd3cb4d97b96af06robertphillips@google.com // replace ops and alter GrClip to allow them through 627f294b773f0b2b9f05eb45b52dd3cb4d97b96af06robertphillips@google.com 628f294b773f0b2b9f05eb45b52dd3cb4d97b96af06robertphillips@google.com // clear the accumulator and draw the new object directly into it 6296d62df404bf420bedff4d7b5edd061740a673d44robertphillips@google.com clear(gpu, accum, 0x00000000); 630f294b773f0b2b9f05eb45b52dd3cb4d97b96af06robertphillips@google.com 6316b70a7bd3328ea0a12be47b1a7f835c905f16147robertphillips@google.com setup_boolean_blendcoeffs(drawState, op); 632f294b773f0b2b9f05eb45b52dd3cb4d97b96af06robertphillips@google.com this->drawClipShape(gpu, accum, clipIn, c); 633f294b773f0b2b9f05eb45b52dd3cb4d97b96af06robertphillips@google.com 634f294b773f0b2b9f05eb45b52dd3cb4d97b96af06robertphillips@google.com } else if (SkRegion::kReverseDifference_Op == op || 635f294b773f0b2b9f05eb45b52dd3cb4d97b96af06robertphillips@google.com SkRegion::kIntersect_Op == op) { 636f294b773f0b2b9f05eb45b52dd3cb4d97b96af06robertphillips@google.com // there is no point in intersecting a screen filling rectangle. 637f294b773f0b2b9f05eb45b52dd3cb4d97b96af06robertphillips@google.com if (SkRegion::kIntersect_Op == op && 638f294b773f0b2b9f05eb45b52dd3cb4d97b96af06robertphillips@google.com kRect_ClipType == clipIn.getElementType(c) && 6396623fcd1ee33b35fa18e304e9c76272faa603cbfrobertphillips@google.com contains(clipIn.getRect(c), *resultBounds)) { 640f294b773f0b2b9f05eb45b52dd3cb4d97b96af06robertphillips@google.com continue; 641f294b773f0b2b9f05eb45b52dd3cb4d97b96af06robertphillips@google.com } 642f294b773f0b2b9f05eb45b52dd3cb4d97b96af06robertphillips@google.com 643f105b109264f71dfb0bfd9977e6a5dd0a5a12f57robertphillips@google.com getTemp(*resultBounds, &temp); 644f105b109264f71dfb0bfd9977e6a5dd0a5a12f57robertphillips@google.com if (NULL == temp.texture()) { 6456d62df404bf420bedff4d7b5edd061740a673d44robertphillips@google.com fClipMaskInAlpha = false; 646f105b109264f71dfb0bfd9977e6a5dd0a5a12f57robertphillips@google.com fAACache.reset(); 6476d62df404bf420bedff4d7b5edd061740a673d44robertphillips@google.com return false; 6486d62df404bf420bedff4d7b5edd061740a673d44robertphillips@google.com } 6496d62df404bf420bedff4d7b5edd061740a673d44robertphillips@google.com 650f294b773f0b2b9f05eb45b52dd3cb4d97b96af06robertphillips@google.com // clear the temp target & draw into it 651f105b109264f71dfb0bfd9977e6a5dd0a5a12f57robertphillips@google.com clear(gpu, temp.texture(), 0x00000000); 652f294b773f0b2b9f05eb45b52dd3cb4d97b96af06robertphillips@google.com 6536b70a7bd3328ea0a12be47b1a7f835c905f16147robertphillips@google.com setup_boolean_blendcoeffs(drawState, SkRegion::kReplace_Op); 654f105b109264f71dfb0bfd9977e6a5dd0a5a12f57robertphillips@google.com this->drawClipShape(gpu, temp.texture(), clipIn, c); 655f294b773f0b2b9f05eb45b52dd3cb4d97b96af06robertphillips@google.com 656f294b773f0b2b9f05eb45b52dd3cb4d97b96af06robertphillips@google.com // TODO: rather than adding these two translations here 657f294b773f0b2b9f05eb45b52dd3cb4d97b96af06robertphillips@google.com // compute the bounding box needed to render the texture 658f294b773f0b2b9f05eb45b52dd3cb4d97b96af06robertphillips@google.com // into temp 6596b70a7bd3328ea0a12be47b1a7f835c905f16147robertphillips@google.com if (0 != resultBounds->fTop || 0 != resultBounds->fLeft) { 660f294b773f0b2b9f05eb45b52dd3cb4d97b96af06robertphillips@google.com GrMatrix m; 661f294b773f0b2b9f05eb45b52dd3cb4d97b96af06robertphillips@google.com 6626623fcd1ee33b35fa18e304e9c76272faa603cbfrobertphillips@google.com m.setTranslate(SkIntToScalar(resultBounds->fLeft), 6636623fcd1ee33b35fa18e304e9c76272faa603cbfrobertphillips@google.com SkIntToScalar(resultBounds->fTop)); 664f294b773f0b2b9f05eb45b52dd3cb4d97b96af06robertphillips@google.com 665f294b773f0b2b9f05eb45b52dd3cb4d97b96af06robertphillips@google.com drawState->preConcatViewMatrix(m); 666f294b773f0b2b9f05eb45b52dd3cb4d97b96af06robertphillips@google.com } 667f294b773f0b2b9f05eb45b52dd3cb4d97b96af06robertphillips@google.com 668f294b773f0b2b9f05eb45b52dd3cb4d97b96af06robertphillips@google.com // Now draw into the accumulator using the real operation 669f294b773f0b2b9f05eb45b52dd3cb4d97b96af06robertphillips@google.com // and the temp buffer as a texture 6706b70a7bd3328ea0a12be47b1a7f835c905f16147robertphillips@google.com setup_boolean_blendcoeffs(drawState, op); 671f105b109264f71dfb0bfd9977e6a5dd0a5a12f57robertphillips@google.com this->drawTexture(gpu, accum, temp.texture()); 672f294b773f0b2b9f05eb45b52dd3cb4d97b96af06robertphillips@google.com 6736b70a7bd3328ea0a12be47b1a7f835c905f16147robertphillips@google.com if (0 != resultBounds->fTop || 0 != resultBounds->fLeft) { 674f294b773f0b2b9f05eb45b52dd3cb4d97b96af06robertphillips@google.com GrMatrix m; 675f294b773f0b2b9f05eb45b52dd3cb4d97b96af06robertphillips@google.com 6766623fcd1ee33b35fa18e304e9c76272faa603cbfrobertphillips@google.com m.setTranslate(SkIntToScalar(-resultBounds->fLeft), 6776623fcd1ee33b35fa18e304e9c76272faa603cbfrobertphillips@google.com SkIntToScalar(-resultBounds->fTop)); 678f294b773f0b2b9f05eb45b52dd3cb4d97b96af06robertphillips@google.com 679f294b773f0b2b9f05eb45b52dd3cb4d97b96af06robertphillips@google.com drawState->preConcatViewMatrix(m); 680f294b773f0b2b9f05eb45b52dd3cb4d97b96af06robertphillips@google.com } 681f294b773f0b2b9f05eb45b52dd3cb4d97b96af06robertphillips@google.com 682f294b773f0b2b9f05eb45b52dd3cb4d97b96af06robertphillips@google.com } else { 683f294b773f0b2b9f05eb45b52dd3cb4d97b96af06robertphillips@google.com // all the remaining ops can just be directly draw into 684f294b773f0b2b9f05eb45b52dd3cb4d97b96af06robertphillips@google.com // the accumulation buffer 6856b70a7bd3328ea0a12be47b1a7f835c905f16147robertphillips@google.com setup_boolean_blendcoeffs(drawState, op); 686f294b773f0b2b9f05eb45b52dd3cb4d97b96af06robertphillips@google.com this->drawClipShape(gpu, accum, clipIn, c); 687f294b773f0b2b9f05eb45b52dd3cb4d97b96af06robertphillips@google.com } 688f294b773f0b2b9f05eb45b52dd3cb4d97b96af06robertphillips@google.com } 689f294b773f0b2b9f05eb45b52dd3cb4d97b96af06robertphillips@google.com 690a72eef322c686954cdffa849dc26d8133b802f1drobertphillips@google.com *result = accum; 6916d62df404bf420bedff4d7b5edd061740a673d44robertphillips@google.com 692f294b773f0b2b9f05eb45b52dd3cb4d97b96af06robertphillips@google.com return true; 6931e945b7e708c633d4aed937ebfce57d52ba21d83robertphillips@google.com} 6941e945b7e708c633d4aed937ebfce57d52ba21d83robertphillips@google.com 695f294b773f0b2b9f05eb45b52dd3cb4d97b96af06robertphillips@google.com//////////////////////////////////////////////////////////////////////////////// 6961e945b7e708c633d4aed937ebfce57d52ba21d83robertphillips@google.com// Create a 1-bit clip mask in the stencil buffer 6971e945b7e708c633d4aed937ebfce57d52ba21d83robertphillips@google.combool GrClipMaskManager::createStencilClipMask(GrGpu* gpu, 6981e945b7e708c633d4aed937ebfce57d52ba21d83robertphillips@google.com const GrClip& clipIn, 6991e945b7e708c633d4aed937ebfce57d52ba21d83robertphillips@google.com const GrRect& bounds, 7001e945b7e708c633d4aed937ebfce57d52ba21d83robertphillips@google.com ScissoringSettings* scissorSettings) { 7011e945b7e708c633d4aed937ebfce57d52ba21d83robertphillips@google.com 7021e945b7e708c633d4aed937ebfce57d52ba21d83robertphillips@google.com GrAssert(fClipMaskInStencil); 7031e945b7e708c633d4aed937ebfce57d52ba21d83robertphillips@google.com 7041e945b7e708c633d4aed937ebfce57d52ba21d83robertphillips@google.com GrDrawState* drawState = gpu->drawState(); 7051e945b7e708c633d4aed937ebfce57d52ba21d83robertphillips@google.com GrAssert(drawState->isClipState()); 7061e945b7e708c633d4aed937ebfce57d52ba21d83robertphillips@google.com 7071e945b7e708c633d4aed937ebfce57d52ba21d83robertphillips@google.com GrRenderTarget* rt = drawState->getRenderTarget(); 7081e945b7e708c633d4aed937ebfce57d52ba21d83robertphillips@google.com GrAssert(NULL != rt); 7091e945b7e708c633d4aed937ebfce57d52ba21d83robertphillips@google.com 7101e945b7e708c633d4aed937ebfce57d52ba21d83robertphillips@google.com // TODO: dynamically attach a SB when needed. 7111e945b7e708c633d4aed937ebfce57d52ba21d83robertphillips@google.com GrStencilBuffer* stencilBuffer = rt->getStencilBuffer(); 7121e945b7e708c633d4aed937ebfce57d52ba21d83robertphillips@google.com if (NULL == stencilBuffer) { 7131e945b7e708c633d4aed937ebfce57d52ba21d83robertphillips@google.com return false; 7141e945b7e708c633d4aed937ebfce57d52ba21d83robertphillips@google.com } 7151e945b7e708c633d4aed937ebfce57d52ba21d83robertphillips@google.com 7161e945b7e708c633d4aed937ebfce57d52ba21d83robertphillips@google.com if (stencilBuffer->mustRenderClip(clipIn, rt->width(), rt->height())) { 7171e945b7e708c633d4aed937ebfce57d52ba21d83robertphillips@google.com 7181e945b7e708c633d4aed937ebfce57d52ba21d83robertphillips@google.com stencilBuffer->setLastClip(clipIn, rt->width(), rt->height()); 7191e945b7e708c633d4aed937ebfce57d52ba21d83robertphillips@google.com 7201e945b7e708c633d4aed937ebfce57d52ba21d83robertphillips@google.com // we set the current clip to the bounds so that our recursive 7211e945b7e708c633d4aed937ebfce57d52ba21d83robertphillips@google.com // draws are scissored to them. We use the copy of the complex clip 7221e945b7e708c633d4aed937ebfce57d52ba21d83robertphillips@google.com // we just stashed on the SB to render from. We set it back after 7231e945b7e708c633d4aed937ebfce57d52ba21d83robertphillips@google.com // we finish drawing it into the stencil. 7241e945b7e708c633d4aed937ebfce57d52ba21d83robertphillips@google.com const GrClip& clipCopy = stencilBuffer->getLastClip(); 7251e945b7e708c633d4aed937ebfce57d52ba21d83robertphillips@google.com gpu->setClip(GrClip(bounds)); 7261e945b7e708c633d4aed937ebfce57d52ba21d83robertphillips@google.com 7271e945b7e708c633d4aed937ebfce57d52ba21d83robertphillips@google.com GrDrawTarget::AutoStateRestore asr(gpu, GrDrawTarget::kReset_ASRInit); 7281e945b7e708c633d4aed937ebfce57d52ba21d83robertphillips@google.com drawState = gpu->drawState(); 7291e945b7e708c633d4aed937ebfce57d52ba21d83robertphillips@google.com drawState->setRenderTarget(rt); 7301e945b7e708c633d4aed937ebfce57d52ba21d83robertphillips@google.com GrDrawTarget::AutoGeometryPush agp(gpu); 7311e945b7e708c633d4aed937ebfce57d52ba21d83robertphillips@google.com 7321e945b7e708c633d4aed937ebfce57d52ba21d83robertphillips@google.com gpu->disableScissor(); 7331e945b7e708c633d4aed937ebfce57d52ba21d83robertphillips@google.com#if !VISUALIZE_COMPLEX_CLIP 7341e945b7e708c633d4aed937ebfce57d52ba21d83robertphillips@google.com drawState->enableState(GrDrawState::kNoColorWrites_StateBit); 7351e945b7e708c633d4aed937ebfce57d52ba21d83robertphillips@google.com#endif 7361e945b7e708c633d4aed937ebfce57d52ba21d83robertphillips@google.com 7371e945b7e708c633d4aed937ebfce57d52ba21d83robertphillips@google.com int count = clipCopy.getElementCount(); 7381e945b7e708c633d4aed937ebfce57d52ba21d83robertphillips@google.com int clipBit = stencilBuffer->bits(); 7391e945b7e708c633d4aed937ebfce57d52ba21d83robertphillips@google.com SkASSERT((clipBit <= 16) && 7401e945b7e708c633d4aed937ebfce57d52ba21d83robertphillips@google.com "Ganesh only handles 16b or smaller stencil buffers"); 7411e945b7e708c633d4aed937ebfce57d52ba21d83robertphillips@google.com clipBit = (1 << (clipBit-1)); 7421e945b7e708c633d4aed937ebfce57d52ba21d83robertphillips@google.com 7436623fcd1ee33b35fa18e304e9c76272faa603cbfrobertphillips@google.com GrIRect rtRect = GrIRect::MakeWH(rt->width(), rt->height()); 7441e945b7e708c633d4aed937ebfce57d52ba21d83robertphillips@google.com 7451e945b7e708c633d4aed937ebfce57d52ba21d83robertphillips@google.com bool clearToInside; 7460f191f30af7c067883c97b034baf70bfd92f5ea0robertphillips@google.com SkRegion::Op startOp = SkRegion::kReplace_Op; // suppress warning 7471e945b7e708c633d4aed937ebfce57d52ba21d83robertphillips@google.com int start = process_initial_clip_elements(clipCopy, 7481e945b7e708c633d4aed937ebfce57d52ba21d83robertphillips@google.com rtRect, 7491e945b7e708c633d4aed937ebfce57d52ba21d83robertphillips@google.com &clearToInside, 7501e945b7e708c633d4aed937ebfce57d52ba21d83robertphillips@google.com &startOp); 7511e945b7e708c633d4aed937ebfce57d52ba21d83robertphillips@google.com 7521e945b7e708c633d4aed937ebfce57d52ba21d83robertphillips@google.com gpu->clearStencilClip(scissorSettings->fScissorRect, clearToInside); 7531e945b7e708c633d4aed937ebfce57d52ba21d83robertphillips@google.com 7541e945b7e708c633d4aed937ebfce57d52ba21d83robertphillips@google.com // walk through each clip element and perform its set op 7551e945b7e708c633d4aed937ebfce57d52ba21d83robertphillips@google.com // with the existing clip. 7561e945b7e708c633d4aed937ebfce57d52ba21d83robertphillips@google.com for (int c = start; c < count; ++c) { 7571e945b7e708c633d4aed937ebfce57d52ba21d83robertphillips@google.com GrPathFill fill; 7581e945b7e708c633d4aed937ebfce57d52ba21d83robertphillips@google.com bool fillInverted; 7591e945b7e708c633d4aed937ebfce57d52ba21d83robertphillips@google.com // enabled at bottom of loop 7601e945b7e708c633d4aed937ebfce57d52ba21d83robertphillips@google.com drawState->disableState(GrGpu::kModifyStencilClip_StateBit); 7611e945b7e708c633d4aed937ebfce57d52ba21d83robertphillips@google.com 7621e945b7e708c633d4aed937ebfce57d52ba21d83robertphillips@google.com bool canRenderDirectToStencil; // can the clip element be drawn 7636b70a7bd3328ea0a12be47b1a7f835c905f16147robertphillips@google.com // directly to the stencil buffer 7646b70a7bd3328ea0a12be47b1a7f835c905f16147robertphillips@google.com // with a non-inverted fill rule 7656b70a7bd3328ea0a12be47b1a7f835c905f16147robertphillips@google.com // without extra passes to 7666b70a7bd3328ea0a12be47b1a7f835c905f16147robertphillips@google.com // resolve in/out status. 7671e945b7e708c633d4aed937ebfce57d52ba21d83robertphillips@google.com 768f294b773f0b2b9f05eb45b52dd3cb4d97b96af06robertphillips@google.com SkRegion::Op op = (c == start) ? startOp : clipCopy.getOp(c); 769f294b773f0b2b9f05eb45b52dd3cb4d97b96af06robertphillips@google.com 7701e945b7e708c633d4aed937ebfce57d52ba21d83robertphillips@google.com GrPathRenderer* pr = NULL; 7718d033a1b125886c62906d975b5cc28a382064526bsalomon@google.com const SkPath* clipPath = NULL; 7721e945b7e708c633d4aed937ebfce57d52ba21d83robertphillips@google.com if (kRect_ClipType == clipCopy.getElementType(c)) { 7731e945b7e708c633d4aed937ebfce57d52ba21d83robertphillips@google.com canRenderDirectToStencil = true; 7741e945b7e708c633d4aed937ebfce57d52ba21d83robertphillips@google.com fill = kEvenOdd_PathFill; 7751e945b7e708c633d4aed937ebfce57d52ba21d83robertphillips@google.com fillInverted = false; 7761e945b7e708c633d4aed937ebfce57d52ba21d83robertphillips@google.com // there is no point in intersecting a screen filling 7771e945b7e708c633d4aed937ebfce57d52ba21d83robertphillips@google.com // rectangle. 778f294b773f0b2b9f05eb45b52dd3cb4d97b96af06robertphillips@google.com if (SkRegion::kIntersect_Op == op && 7796623fcd1ee33b35fa18e304e9c76272faa603cbfrobertphillips@google.com contains(clipCopy.getRect(c), rtRect)) { 7801e945b7e708c633d4aed937ebfce57d52ba21d83robertphillips@google.com continue; 7811e945b7e708c633d4aed937ebfce57d52ba21d83robertphillips@google.com } 7821e945b7e708c633d4aed937ebfce57d52ba21d83robertphillips@google.com } else { 7831e945b7e708c633d4aed937ebfce57d52ba21d83robertphillips@google.com fill = clipCopy.getPathFill(c); 7841e945b7e708c633d4aed937ebfce57d52ba21d83robertphillips@google.com fillInverted = GrIsFillInverted(fill); 7851e945b7e708c633d4aed937ebfce57d52ba21d83robertphillips@google.com fill = GrNonInvertedFill(fill); 7861e945b7e708c633d4aed937ebfce57d52ba21d83robertphillips@google.com clipPath = &clipCopy.getPath(c); 7872c75681e36b33fcafc5665d7012bbd4fc6647d83robertphillips@google.com pr = this->getContext()->getPathRenderer(*clipPath, 78872176b2d38db005863a54e3dd6657bbabd068bb6robertphillips@google.com fill, gpu, false, 78972176b2d38db005863a54e3dd6657bbabd068bb6robertphillips@google.com true); 7901e945b7e708c633d4aed937ebfce57d52ba21d83robertphillips@google.com if (NULL == pr) { 7911e945b7e708c633d4aed937ebfce57d52ba21d83robertphillips@google.com fClipMaskInStencil = false; 7921e945b7e708c633d4aed937ebfce57d52ba21d83robertphillips@google.com gpu->setClip(clipCopy); // restore to the original 7931e945b7e708c633d4aed937ebfce57d52ba21d83robertphillips@google.com return false; 7941e945b7e708c633d4aed937ebfce57d52ba21d83robertphillips@google.com } 7951e945b7e708c633d4aed937ebfce57d52ba21d83robertphillips@google.com canRenderDirectToStencil = 7961e945b7e708c633d4aed937ebfce57d52ba21d83robertphillips@google.com !pr->requiresStencilPass(*clipPath, fill, gpu); 7971e945b7e708c633d4aed937ebfce57d52ba21d83robertphillips@google.com } 7981e945b7e708c633d4aed937ebfce57d52ba21d83robertphillips@google.com 7991e945b7e708c633d4aed937ebfce57d52ba21d83robertphillips@google.com int passes; 8001e945b7e708c633d4aed937ebfce57d52ba21d83robertphillips@google.com GrStencilSettings stencilSettings[GrStencilSettings::kMaxStencilClipPasses]; 8011e945b7e708c633d4aed937ebfce57d52ba21d83robertphillips@google.com 8021e945b7e708c633d4aed937ebfce57d52ba21d83robertphillips@google.com bool canDrawDirectToClip; // Given the renderer, the element, 8031e945b7e708c633d4aed937ebfce57d52ba21d83robertphillips@google.com // fill rule, and set operation can 8041e945b7e708c633d4aed937ebfce57d52ba21d83robertphillips@google.com // we render the element directly to 8051e945b7e708c633d4aed937ebfce57d52ba21d83robertphillips@google.com // stencil bit used for clipping. 8061e945b7e708c633d4aed937ebfce57d52ba21d83robertphillips@google.com canDrawDirectToClip = 8071e945b7e708c633d4aed937ebfce57d52ba21d83robertphillips@google.com GrStencilSettings::GetClipPasses(op, 8081e945b7e708c633d4aed937ebfce57d52ba21d83robertphillips@google.com canRenderDirectToStencil, 8091e945b7e708c633d4aed937ebfce57d52ba21d83robertphillips@google.com clipBit, 8101e945b7e708c633d4aed937ebfce57d52ba21d83robertphillips@google.com fillInverted, 8111e945b7e708c633d4aed937ebfce57d52ba21d83robertphillips@google.com &passes, stencilSettings); 8121e945b7e708c633d4aed937ebfce57d52ba21d83robertphillips@google.com 8131e945b7e708c633d4aed937ebfce57d52ba21d83robertphillips@google.com // draw the element to the client stencil bits if necessary 8141e945b7e708c633d4aed937ebfce57d52ba21d83robertphillips@google.com if (!canDrawDirectToClip) { 8151e945b7e708c633d4aed937ebfce57d52ba21d83robertphillips@google.com GR_STATIC_CONST_SAME_STENCIL(gDrawToStencil, 8161e945b7e708c633d4aed937ebfce57d52ba21d83robertphillips@google.com kIncClamp_StencilOp, 8171e945b7e708c633d4aed937ebfce57d52ba21d83robertphillips@google.com kIncClamp_StencilOp, 8181e945b7e708c633d4aed937ebfce57d52ba21d83robertphillips@google.com kAlways_StencilFunc, 8191e945b7e708c633d4aed937ebfce57d52ba21d83robertphillips@google.com 0xffff, 8201e945b7e708c633d4aed937ebfce57d52ba21d83robertphillips@google.com 0x0000, 8211e945b7e708c633d4aed937ebfce57d52ba21d83robertphillips@google.com 0xffff); 8221e945b7e708c633d4aed937ebfce57d52ba21d83robertphillips@google.com SET_RANDOM_COLOR 8231e945b7e708c633d4aed937ebfce57d52ba21d83robertphillips@google.com if (kRect_ClipType == clipCopy.getElementType(c)) { 8241e945b7e708c633d4aed937ebfce57d52ba21d83robertphillips@google.com *drawState->stencil() = gDrawToStencil; 8251e945b7e708c633d4aed937ebfce57d52ba21d83robertphillips@google.com gpu->drawSimpleRect(clipCopy.getRect(c), NULL, 0); 8261e945b7e708c633d4aed937ebfce57d52ba21d83robertphillips@google.com } else { 8271e945b7e708c633d4aed937ebfce57d52ba21d83robertphillips@google.com if (canRenderDirectToStencil) { 8281e945b7e708c633d4aed937ebfce57d52ba21d83robertphillips@google.com *drawState->stencil() = gDrawToStencil; 8291e945b7e708c633d4aed937ebfce57d52ba21d83robertphillips@google.com pr->drawPath(*clipPath, fill, NULL, gpu, 0, false); 8301e945b7e708c633d4aed937ebfce57d52ba21d83robertphillips@google.com } else { 8311e945b7e708c633d4aed937ebfce57d52ba21d83robertphillips@google.com pr->drawPathToStencil(*clipPath, fill, gpu); 8321e945b7e708c633d4aed937ebfce57d52ba21d83robertphillips@google.com } 8331e945b7e708c633d4aed937ebfce57d52ba21d83robertphillips@google.com } 8341e945b7e708c633d4aed937ebfce57d52ba21d83robertphillips@google.com } 8351e945b7e708c633d4aed937ebfce57d52ba21d83robertphillips@google.com 8361e945b7e708c633d4aed937ebfce57d52ba21d83robertphillips@google.com // now we modify the clip bit by rendering either the clip 8371e945b7e708c633d4aed937ebfce57d52ba21d83robertphillips@google.com // element directly or a bounding rect of the entire clip. 8381e945b7e708c633d4aed937ebfce57d52ba21d83robertphillips@google.com drawState->enableState(GrGpu::kModifyStencilClip_StateBit); 8391e945b7e708c633d4aed937ebfce57d52ba21d83robertphillips@google.com for (int p = 0; p < passes; ++p) { 8401e945b7e708c633d4aed937ebfce57d52ba21d83robertphillips@google.com *drawState->stencil() = stencilSettings[p]; 8411e945b7e708c633d4aed937ebfce57d52ba21d83robertphillips@google.com if (canDrawDirectToClip) { 8421e945b7e708c633d4aed937ebfce57d52ba21d83robertphillips@google.com if (kRect_ClipType == clipCopy.getElementType(c)) { 8431e945b7e708c633d4aed937ebfce57d52ba21d83robertphillips@google.com SET_RANDOM_COLOR 8441e945b7e708c633d4aed937ebfce57d52ba21d83robertphillips@google.com gpu->drawSimpleRect(clipCopy.getRect(c), NULL, 0); 8451e945b7e708c633d4aed937ebfce57d52ba21d83robertphillips@google.com } else { 8461e945b7e708c633d4aed937ebfce57d52ba21d83robertphillips@google.com SET_RANDOM_COLOR 8471e945b7e708c633d4aed937ebfce57d52ba21d83robertphillips@google.com pr->drawPath(*clipPath, fill, NULL, gpu, 0, false); 8481e945b7e708c633d4aed937ebfce57d52ba21d83robertphillips@google.com } 8491e945b7e708c633d4aed937ebfce57d52ba21d83robertphillips@google.com } else { 8501e945b7e708c633d4aed937ebfce57d52ba21d83robertphillips@google.com SET_RANDOM_COLOR 8511e945b7e708c633d4aed937ebfce57d52ba21d83robertphillips@google.com gpu->drawSimpleRect(bounds, NULL, 0); 8521e945b7e708c633d4aed937ebfce57d52ba21d83robertphillips@google.com } 8531e945b7e708c633d4aed937ebfce57d52ba21d83robertphillips@google.com } 8541e945b7e708c633d4aed937ebfce57d52ba21d83robertphillips@google.com } 8551e945b7e708c633d4aed937ebfce57d52ba21d83robertphillips@google.com // restore clip 8561e945b7e708c633d4aed937ebfce57d52ba21d83robertphillips@google.com gpu->setClip(clipCopy); 8571e945b7e708c633d4aed937ebfce57d52ba21d83robertphillips@google.com // recusive draws would have disabled this since they drew with 8581e945b7e708c633d4aed937ebfce57d52ba21d83robertphillips@google.com // the clip bounds as clip. 8591e945b7e708c633d4aed937ebfce57d52ba21d83robertphillips@google.com fClipMaskInStencil = true; 8601e945b7e708c633d4aed937ebfce57d52ba21d83robertphillips@google.com } 8611e945b7e708c633d4aed937ebfce57d52ba21d83robertphillips@google.com 8621e945b7e708c633d4aed937ebfce57d52ba21d83robertphillips@google.com return true; 8631e945b7e708c633d4aed937ebfce57d52ba21d83robertphillips@google.com} 8641e945b7e708c633d4aed937ebfce57d52ba21d83robertphillips@google.com 865fa66294c7705831808ce7772d4328fc626d45034robertphillips@google.comnamespace { 866fa66294c7705831808ce7772d4328fc626d45034robertphillips@google.com 867fa66294c7705831808ce7772d4328fc626d45034robertphillips@google.comGrPathFill invert_fill(GrPathFill fill) { 868fa66294c7705831808ce7772d4328fc626d45034robertphillips@google.com static const GrPathFill gInvertedFillTable[] = { 869fa66294c7705831808ce7772d4328fc626d45034robertphillips@google.com kInverseWinding_PathFill, // kWinding_PathFill 870fa66294c7705831808ce7772d4328fc626d45034robertphillips@google.com kInverseEvenOdd_PathFill, // kEvenOdd_PathFill 871fa66294c7705831808ce7772d4328fc626d45034robertphillips@google.com kWinding_PathFill, // kInverseWinding_PathFill 872fa66294c7705831808ce7772d4328fc626d45034robertphillips@google.com kEvenOdd_PathFill, // kInverseEvenOdd_PathFill 873fa66294c7705831808ce7772d4328fc626d45034robertphillips@google.com kHairLine_PathFill, // kHairLine_PathFill 874fa66294c7705831808ce7772d4328fc626d45034robertphillips@google.com }; 875fa66294c7705831808ce7772d4328fc626d45034robertphillips@google.com GR_STATIC_ASSERT(0 == kWinding_PathFill); 876fa66294c7705831808ce7772d4328fc626d45034robertphillips@google.com GR_STATIC_ASSERT(1 == kEvenOdd_PathFill); 877fa66294c7705831808ce7772d4328fc626d45034robertphillips@google.com GR_STATIC_ASSERT(2 == kInverseWinding_PathFill); 878fa66294c7705831808ce7772d4328fc626d45034robertphillips@google.com GR_STATIC_ASSERT(3 == kInverseEvenOdd_PathFill); 879fa66294c7705831808ce7772d4328fc626d45034robertphillips@google.com GR_STATIC_ASSERT(4 == kHairLine_PathFill); 880fa66294c7705831808ce7772d4328fc626d45034robertphillips@google.com GR_STATIC_ASSERT(5 == kPathFillCount); 881fa66294c7705831808ce7772d4328fc626d45034robertphillips@google.com return gInvertedFillTable[fill]; 882fa66294c7705831808ce7772d4328fc626d45034robertphillips@google.com} 883fa66294c7705831808ce7772d4328fc626d45034robertphillips@google.com 884fa66294c7705831808ce7772d4328fc626d45034robertphillips@google.com} 885fa66294c7705831808ce7772d4328fc626d45034robertphillips@google.com 886f294b773f0b2b9f05eb45b52dd3cb4d97b96af06robertphillips@google.com//////////////////////////////////////////////////////////////////////////////// 8876b70a7bd3328ea0a12be47b1a7f835c905f16147robertphillips@google.combool GrClipMaskManager::createSoftwareClipMask(GrGpu* gpu, 8886b70a7bd3328ea0a12be47b1a7f835c905f16147robertphillips@google.com const GrClip& clipIn, 8896b70a7bd3328ea0a12be47b1a7f835c905f16147robertphillips@google.com GrTexture** result, 8906623fcd1ee33b35fa18e304e9c76272faa603cbfrobertphillips@google.com GrIRect *resultBounds) { 8916b70a7bd3328ea0a12be47b1a7f835c905f16147robertphillips@google.com 892f105b109264f71dfb0bfd9977e6a5dd0a5a12f57robertphillips@google.com if (this->clipMaskPreamble(gpu, clipIn, result, resultBounds)) { 8936b70a7bd3328ea0a12be47b1a7f835c905f16147robertphillips@google.com return true; 8946b70a7bd3328ea0a12be47b1a7f835c905f16147robertphillips@google.com } 8956b70a7bd3328ea0a12be47b1a7f835c905f16147robertphillips@google.com 896f105b109264f71dfb0bfd9977e6a5dd0a5a12f57robertphillips@google.com GrTexture* accum = fAACache.getLastMask(); 8976b70a7bd3328ea0a12be47b1a7f835c905f16147robertphillips@google.com if (NULL == accum) { 8986b70a7bd3328ea0a12be47b1a7f835c905f16147robertphillips@google.com fClipMaskInAlpha = false; 899f105b109264f71dfb0bfd9977e6a5dd0a5a12f57robertphillips@google.com fAACache.reset(); 9006b70a7bd3328ea0a12be47b1a7f835c905f16147robertphillips@google.com return false; 9016b70a7bd3328ea0a12be47b1a7f835c905f16147robertphillips@google.com } 9026b70a7bd3328ea0a12be47b1a7f835c905f16147robertphillips@google.com 9032c75681e36b33fcafc5665d7012bbd4fc6647d83robertphillips@google.com GrSWMaskHelper helper(this->getContext()); 9046b70a7bd3328ea0a12be47b1a7f835c905f16147robertphillips@google.com 905fa66294c7705831808ce7772d4328fc626d45034robertphillips@google.com helper.init(*resultBounds, NULL, false); 906fa66294c7705831808ce7772d4328fc626d45034robertphillips@google.com 907fa66294c7705831808ce7772d4328fc626d45034robertphillips@google.com int count = clipIn.getElementCount(); 908fa66294c7705831808ce7772d4328fc626d45034robertphillips@google.com 909fa66294c7705831808ce7772d4328fc626d45034robertphillips@google.com bool clearToInside; 910fa66294c7705831808ce7772d4328fc626d45034robertphillips@google.com SkRegion::Op startOp = SkRegion::kReplace_Op; // suppress warning 911fa66294c7705831808ce7772d4328fc626d45034robertphillips@google.com int start = process_initial_clip_elements(clipIn, 912fa66294c7705831808ce7772d4328fc626d45034robertphillips@google.com *resultBounds, 913fa66294c7705831808ce7772d4328fc626d45034robertphillips@google.com &clearToInside, 914fa66294c7705831808ce7772d4328fc626d45034robertphillips@google.com &startOp); 915fa66294c7705831808ce7772d4328fc626d45034robertphillips@google.com 916fa66294c7705831808ce7772d4328fc626d45034robertphillips@google.com helper.clear(clearToInside ? SK_ColorWHITE : 0x00000000); 917fa66294c7705831808ce7772d4328fc626d45034robertphillips@google.com 918fa66294c7705831808ce7772d4328fc626d45034robertphillips@google.com for (int i = start; i < count; ++i) { 919fa66294c7705831808ce7772d4328fc626d45034robertphillips@google.com 920fa66294c7705831808ce7772d4328fc626d45034robertphillips@google.com SkRegion::Op op = (i == start) ? startOp : clipIn.getOp(i); 921fa66294c7705831808ce7772d4328fc626d45034robertphillips@google.com 922fa66294c7705831808ce7772d4328fc626d45034robertphillips@google.com if (SkRegion::kIntersect_Op == op || 923fa66294c7705831808ce7772d4328fc626d45034robertphillips@google.com SkRegion::kReverseDifference_Op == op) { 924fa66294c7705831808ce7772d4328fc626d45034robertphillips@google.com // Intersect and reverse difference require modifying pixels 925fa66294c7705831808ce7772d4328fc626d45034robertphillips@google.com // outside of the geometry that is being "drawn". In both cases 926fa66294c7705831808ce7772d4328fc626d45034robertphillips@google.com // we erase all the pixels outside of the geometry but 927fa66294c7705831808ce7772d4328fc626d45034robertphillips@google.com // leave the pixels inside the geometry alone. For reverse 928fa66294c7705831808ce7772d4328fc626d45034robertphillips@google.com // difference we invert all the pixels before clearing the ones 929fa66294c7705831808ce7772d4328fc626d45034robertphillips@google.com // outside the geometry. 930fa66294c7705831808ce7772d4328fc626d45034robertphillips@google.com if (SkRegion::kReverseDifference_Op == op) { 931fa66294c7705831808ce7772d4328fc626d45034robertphillips@google.com SkRect temp = SkRect::MakeLTRB( 932fa66294c7705831808ce7772d4328fc626d45034robertphillips@google.com SkIntToScalar(resultBounds->left()), 933fa66294c7705831808ce7772d4328fc626d45034robertphillips@google.com SkIntToScalar(resultBounds->top()), 934fa66294c7705831808ce7772d4328fc626d45034robertphillips@google.com SkIntToScalar(resultBounds->right()), 935fa66294c7705831808ce7772d4328fc626d45034robertphillips@google.com SkIntToScalar(resultBounds->bottom())); 936fa66294c7705831808ce7772d4328fc626d45034robertphillips@google.com 937fa66294c7705831808ce7772d4328fc626d45034robertphillips@google.com // invert the entire scene 938fa66294c7705831808ce7772d4328fc626d45034robertphillips@google.com helper.draw(temp, SkRegion::kXOR_Op, false, SK_ColorWHITE); 939fa66294c7705831808ce7772d4328fc626d45034robertphillips@google.com } 940fa66294c7705831808ce7772d4328fc626d45034robertphillips@google.com 941fa66294c7705831808ce7772d4328fc626d45034robertphillips@google.com if (kRect_ClipType == clipIn.getElementType(i)) { 942fa66294c7705831808ce7772d4328fc626d45034robertphillips@google.com 943fa66294c7705831808ce7772d4328fc626d45034robertphillips@google.com // convert the rect to a path so we can invert the fill 944fa66294c7705831808ce7772d4328fc626d45034robertphillips@google.com SkPath temp; 945fa66294c7705831808ce7772d4328fc626d45034robertphillips@google.com temp.addRect(clipIn.getRect(i)); 946fa66294c7705831808ce7772d4328fc626d45034robertphillips@google.com 947fa66294c7705831808ce7772d4328fc626d45034robertphillips@google.com helper.draw(temp, SkRegion::kReplace_Op, 948fa66294c7705831808ce7772d4328fc626d45034robertphillips@google.com kInverseEvenOdd_PathFill, clipIn.getDoAA(i), 949fa66294c7705831808ce7772d4328fc626d45034robertphillips@google.com 0x00000000); 950fa66294c7705831808ce7772d4328fc626d45034robertphillips@google.com } else { 951fa66294c7705831808ce7772d4328fc626d45034robertphillips@google.com GrAssert(kPath_ClipType == clipIn.getElementType(i)); 952fa66294c7705831808ce7772d4328fc626d45034robertphillips@google.com 953fa66294c7705831808ce7772d4328fc626d45034robertphillips@google.com helper.draw(clipIn.getPath(i), 954fa66294c7705831808ce7772d4328fc626d45034robertphillips@google.com SkRegion::kReplace_Op, 955fa66294c7705831808ce7772d4328fc626d45034robertphillips@google.com invert_fill(clipIn.getPathFill(i)), 956fa66294c7705831808ce7772d4328fc626d45034robertphillips@google.com clipIn.getDoAA(i), 957fa66294c7705831808ce7772d4328fc626d45034robertphillips@google.com 0x00000000); 958fa66294c7705831808ce7772d4328fc626d45034robertphillips@google.com } 959fa66294c7705831808ce7772d4328fc626d45034robertphillips@google.com 960fa66294c7705831808ce7772d4328fc626d45034robertphillips@google.com continue; 961fa66294c7705831808ce7772d4328fc626d45034robertphillips@google.com } 962fa66294c7705831808ce7772d4328fc626d45034robertphillips@google.com 963fa66294c7705831808ce7772d4328fc626d45034robertphillips@google.com // The other ops (union, xor, diff) only affect pixels inside 964fa66294c7705831808ce7772d4328fc626d45034robertphillips@google.com // the geometry so they can just be drawn normally 9656b70a7bd3328ea0a12be47b1a7f835c905f16147robertphillips@google.com if (kRect_ClipType == clipIn.getElementType(i)) { 966fa66294c7705831808ce7772d4328fc626d45034robertphillips@google.com 967fa66294c7705831808ce7772d4328fc626d45034robertphillips@google.com helper.draw(clipIn.getRect(i), 968fa66294c7705831808ce7772d4328fc626d45034robertphillips@google.com op, 969fa66294c7705831808ce7772d4328fc626d45034robertphillips@google.com clipIn.getDoAA(i), SK_ColorWHITE); 970fa66294c7705831808ce7772d4328fc626d45034robertphillips@google.com 9716b70a7bd3328ea0a12be47b1a7f835c905f16147robertphillips@google.com } else { 9726b70a7bd3328ea0a12be47b1a7f835c905f16147robertphillips@google.com GrAssert(kPath_ClipType == clipIn.getElementType(i)); 9736b70a7bd3328ea0a12be47b1a7f835c905f16147robertphillips@google.com 974fa66294c7705831808ce7772d4328fc626d45034robertphillips@google.com helper.draw(clipIn.getPath(i), 975fa66294c7705831808ce7772d4328fc626d45034robertphillips@google.com op, 976fa66294c7705831808ce7772d4328fc626d45034robertphillips@google.com clipIn.getPathFill(i), 977fa66294c7705831808ce7772d4328fc626d45034robertphillips@google.com clipIn.getDoAA(i), SK_ColorWHITE); 9786b70a7bd3328ea0a12be47b1a7f835c905f16147robertphillips@google.com } 9796b70a7bd3328ea0a12be47b1a7f835c905f16147robertphillips@google.com } 9806b70a7bd3328ea0a12be47b1a7f835c905f16147robertphillips@google.com 981fa66294c7705831808ce7772d4328fc626d45034robertphillips@google.com // Because we are using the scratch texture cache, "accum" may be 982fa66294c7705831808ce7772d4328fc626d45034robertphillips@google.com // larger than expected and have some cruft in the areas we aren't using. 983fa66294c7705831808ce7772d4328fc626d45034robertphillips@google.com // Clear it out. 984fa66294c7705831808ce7772d4328fc626d45034robertphillips@google.com 985fa66294c7705831808ce7772d4328fc626d45034robertphillips@google.com // TODO: need a simpler way to clear the texture - can we combine 986fa66294c7705831808ce7772d4328fc626d45034robertphillips@google.com // the clear and the writePixels (inside toTexture) 987fa66294c7705831808ce7772d4328fc626d45034robertphillips@google.com GrDrawState* drawState = gpu->drawState(); 988fa66294c7705831808ce7772d4328fc626d45034robertphillips@google.com GrAssert(NULL != drawState); 989fa66294c7705831808ce7772d4328fc626d45034robertphillips@google.com GrRenderTarget* temp = drawState->getRenderTarget(); 990fa66294c7705831808ce7772d4328fc626d45034robertphillips@google.com clear(gpu, accum, 0x00000000); 991fa66294c7705831808ce7772d4328fc626d45034robertphillips@google.com // can't leave the accum bound as a rendertarget 992fa66294c7705831808ce7772d4328fc626d45034robertphillips@google.com drawState->setRenderTarget(temp); 993fa66294c7705831808ce7772d4328fc626d45034robertphillips@google.com 994fa66294c7705831808ce7772d4328fc626d45034robertphillips@google.com helper.toTexture(accum); 9956b70a7bd3328ea0a12be47b1a7f835c905f16147robertphillips@google.com 9966b70a7bd3328ea0a12be47b1a7f835c905f16147robertphillips@google.com *result = accum; 9976b70a7bd3328ea0a12be47b1a7f835c905f16147robertphillips@google.com 9986b70a7bd3328ea0a12be47b1a7f835c905f16147robertphillips@google.com return true; 9996b70a7bd3328ea0a12be47b1a7f835c905f16147robertphillips@google.com} 10006b70a7bd3328ea0a12be47b1a7f835c905f16147robertphillips@google.com 1001f294b773f0b2b9f05eb45b52dd3cb4d97b96af06robertphillips@google.com//////////////////////////////////////////////////////////////////////////////// 1002f105b109264f71dfb0bfd9977e6a5dd0a5a12f57robertphillips@google.comvoid GrClipMaskManager::releaseResources() { 1003f105b109264f71dfb0bfd9977e6a5dd0a5a12f57robertphillips@google.com fAACache.releaseResources(); 10041e945b7e708c633d4aed937ebfce57d52ba21d83robertphillips@google.com} 1005