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 9c26d94fd7dc0b00cd6d0e42d28285f4a38aff021bsalomon@google.com#include "GrClipMaskManager.h" 10c26d94fd7dc0b00cd6d0e42d28285f4a38aff021bsalomon@google.com#include "GrGpu.h" 11bfe2b9d3a290d0153b82617cd6b65a4814fe89e3jvanverth@google.com#include "GrRenderTarget.h" 12c26d94fd7dc0b00cd6d0e42d28285f4a38aff021bsalomon@google.com#include "GrStencilBuffer.h" 13c26d94fd7dc0b00cd6d0e42d28285f4a38aff021bsalomon@google.com#include "GrPathRenderer.h" 14c26d94fd7dc0b00cd6d0e42d28285f4a38aff021bsalomon@google.com#include "GrPaint.h" 151e945b7e708c633d4aed937ebfce57d52ba21d83robertphillips@google.com#include "SkRasterClip.h" 166bc1b5fab8554a9cb643277b4867965dd4535cd6bsalomon#include "GrAAConvexPathRenderer.h" 171e945b7e708c633d4aed937ebfce57d52ba21d83robertphillips@google.com#include "GrAAHairLinePathRenderer.h" 18c26d94fd7dc0b00cd6d0e42d28285f4a38aff021bsalomon@google.com 193a0cfeb96185934c0a36f1313f21b96c57ca6341joshualitt// TODO: move GrSWMaskHelper out of GrSoftwarePathRender.h & remove this include 203a0cfeb96185934c0a36f1313f21b96c57ca6341joshualitt#include "GrSoftwarePathRenderer.h" 213a0cfeb96185934c0a36f1313f21b96c57ca6341joshualitt 22a58fe35fdae3481cf43062f7032820c320c3d163joshualitt//#define GR_AA_CLIP 1 239513143efa734bef0c1a0c7f945022572dbc8518egdaniel//#define GR_SW_CLIP 1 24a58fe35fdae3481cf43062f7032820c320c3d163joshualitt 259513143efa734bef0c1a0c7f945022572dbc8518egdaniel//////////////////////////////////////////////////////////////////////////////// 26c6b3e48cb3a22d83ba3f4b9a614a5a35b05958a0bsalomon@google.comvoid ScissoringSettings::setupScissoring(GrGpu* gpu) { 278182fa0cac76e7e6d583aebba060229230516887bsalomon@google.com if (!fEnableScissoring) { 2851a6286c241c1dc750d263ed9676079c898148b0bsalomon@google.com gpu->disableScissor(); 2951a6286c241c1dc750d263ed9676079c898148b0bsalomon@google.com return; 30e79f320ed6c5ec9f6164ba84be1ff586532e6517robertphillips@google.com } 31fbfcd5602128ec010c82cb733c9cdc0a3254f9f3rmistry@google.com 3208283afc265f1153834256fc1012519813ba6b73bsalomon@google.com gpu->enableScissoring(fScissorRect); 339853ccef19c200be93a6211f32589fa82a53067cjoshualitt} 348dd688b7569df569a672a8a67b2db86a9d376cfcegdaniel 359853ccef19c200be93a6211f32589fa82a53067cjoshualittnamespace { 368dd688b7569df569a672a8a67b2db86a9d376cfcegdaniel// 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 38b9086a026844e4cfd08b219e49ce3f12294cba98bsalomon@google.comvoid setup_drawstate_aaclip(GrGpu* gpu, 39309d4d590964fbf7443c5bc892c132faa61a9abbbsalomon GrTexture* result, 40309d4d590964fbf7443c5bc892c132faa61a9abbbsalomon const GrIRect &bound) { 41a72eef322c686954cdffa849dc26d8133b802f1drobertphillips@google.com GrDrawState* drawState = gpu->drawState(); 42fbfcd5602128ec010c82cb733c9cdc0a3254f9f3rmistry@google.com GrAssert(drawState); 437b11289b4e4d117bbcee6d2460b057d0fcf6e437robertphillips@google.com 44a72eef322c686954cdffa849dc26d8133b802f1drobertphillips@google.com static const int maskStage = GrPaint::kTotalStages+1; 457b7cdd147f5528865238e5ed98c79e6d319fde9bbsalomon@google.com 464c2443e36fdc6c095b17e90baa4a2f26a6f00b08bsalomon@google.com GrMatrix mat; 478dd688b7569df569a672a8a67b2db86a9d376cfcegdaniel mat.setIDiv(result->width(), result->height()); 48eb6879f50a5564eeb981ec5616b55bf685eb76fcbsalomon@google.com mat.preTranslate(SkIntToScalar(-bound.fLeft), SkIntToScalar(-bound.fTop)); 497b7cdd147f5528865238e5ed98c79e6d319fde9bbsalomon@google.com mat.preConcat(drawState->getViewMatrix()); 50907fbd53c5e5dd4cbde7b72f9242b51febd7ef95commit-bot@chromium.org 51907fbd53c5e5dd4cbde7b72f9242b51febd7ef95commit-bot@chromium.org drawState->sampler(maskStage)->reset(GrSamplerState::kClamp_WrapMode, 52b86add1ad37776818e1f730359ec587c9fdbff5fhumper@google.com GrSamplerState::kNearest_Filter, 53309d4d590964fbf7443c5bc892c132faa61a9abbbsalomon mat); 54a72eef322c686954cdffa849dc26d8133b802f1drobertphillips@google.com 55a72eef322c686954cdffa849dc26d8133b802f1drobertphillips@google.com drawState->setTexture(maskStage, result); 56e79f320ed6c5ec9f6164ba84be1ff586532e6517robertphillips@google.com 579853ccef19c200be93a6211f32589fa82a53067cjoshualitt // The AA clipping determination happens long after the geometry has 588dd688b7569df569a672a8a67b2db86a9d376cfcegdaniel // been set up to draw. Here we directly enable the AA clip mask stage 598059eb9f6e24ed609393fbda4ad71edea03ac258joshualitt gpu->addToVertexLayout( 60e79f320ed6c5ec9f6164ba84be1ff586532e6517robertphillips@google.com GrDrawTarget::StagePosAsTexCoordVertexLayoutBit(maskStage)); 61e79f320ed6c5ec9f6164ba84be1ff586532e6517robertphillips@google.com} 62e79f320ed6c5ec9f6164ba84be1ff586532e6517robertphillips@google.com 63e79f320ed6c5ec9f6164ba84be1ff586532e6517robertphillips@google.combool path_needs_SW_renderer(GrContext* context, 64e79f320ed6c5ec9f6164ba84be1ff586532e6517robertphillips@google.com GrGpu* gpu, 65e79f320ed6c5ec9f6164ba84be1ff586532e6517robertphillips@google.com const SkPath& path, 66e79f320ed6c5ec9f6164ba84be1ff586532e6517robertphillips@google.com GrPathFill fill, 67e79f320ed6c5ec9f6164ba84be1ff586532e6517robertphillips@google.com bool doAA) { 68e79f320ed6c5ec9f6164ba84be1ff586532e6517robertphillips@google.com // last (false) parameter disallows use of the SW path renderer 6945a15f551b5b3c6c747d8eaf6466b7d3b76a8faebsalomon@google.com return NULL == context->getPathRenderer(path, fill, gpu, doAA, false); 7045a15f551b5b3c6c747d8eaf6466b7d3b76a8faebsalomon@google.com} 7145a15f551b5b3c6c747d8eaf6466b7d3b76a8faebsalomon@google.com 7245a15f551b5b3c6c747d8eaf6466b7d3b76a8faebsalomon@google.com} 738dd688b7569df569a672a8a67b2db86a9d376cfcegdaniel 748dd688b7569df569a672a8a67b2db86a9d376cfcegdaniel/* 75e79f320ed6c5ec9f6164ba84be1ff586532e6517robertphillips@google.com * This method traverses the clip stack to see if the GrSoftwarePathRenderer 766b70a7bd3328ea0a12be47b1a7f835c905f16147robertphillips@google.com * will be used on any element. If so, it returns true to indicate that the 776b70a7bd3328ea0a12be47b1a7f835c905f16147robertphillips@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) { 80fa66294c7705831808ce7772d4328fc626d45034robertphillips@google.com 81fa66294c7705831808ce7772d4328fc626d45034robertphillips@google.com if (!clipIn.requiresAA()) { 82fa66294c7705831808ce7772d4328fc626d45034robertphillips@google.com // The stencil buffer can handle this case 838dd688b7569df569a672a8a67b2db86a9d376cfcegdaniel return false; 848059eb9f6e24ed609393fbda4ad71edea03ac258joshualitt } 859853ccef19c200be93a6211f32589fa82a53067cjoshualitt 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. 895f74cf8c49701f514b69dc6f1a8b5c0ffd78af0asugoi@google.com bool useSW = false; 90d21444aab7128c97f4e0eb5e9bf05111d5037292skia.committer@gmail.com 918059eb9f6e24ed609393fbda4ad71edea03ac258joshualitt for (int i = 0; i < clipIn.getElementCount(); ++i) { 928059eb9f6e24ed609393fbda4ad71edea03ac258joshualitt 938059eb9f6e24ed609393fbda4ad71edea03ac258joshualitt if (SkRegion::kReplace_Op == clipIn.getOp(i)) { 948059eb9f6e24ed609393fbda4ad71edea03ac258joshualitt // Everything before a replace op can be ignored so start 958059eb9f6e24ed609393fbda4ad71edea03ac258joshualitt // afresh w.r.t. determining if any element uses the SW path 96bf54e49e30cdc92f9ce3f336cc48cf6b236ddeabtfarina useSW = false; 974c2443e36fdc6c095b17e90baa4a2f26a6f00b08bsalomon@google.com } 98f69a11b5c5dc5ae02489dfe7ca6432d641b9f121robertphillips@google.com 99e5b2af955b7d06815ddd405659ad62a2a8355ca3commit-bot@chromium.org if (kRect_ClipType == clipIn.getElementType(i)) { 100e5b2af955b7d06815ddd405659ad62a2a8355ca3commit-bot@chromium.org // Non-anti-aliased rects can always be drawn directly (w/o 101e5b2af955b7d06815ddd405659ad62a2a8355ca3commit-bot@chromium.org // using the software path) so the anti-aliased rects are all 102e5b2af955b7d06815ddd405659ad62a2a8355ca3commit-bot@chromium.org // that need to be checked here 1038dd688b7569df569a672a8a67b2db86a9d376cfcegdaniel if (clipIn.getDoAA(i)) { 1048059eb9f6e24ed609393fbda4ad71edea03ac258joshualitt // Antialiased rects are converted to paths and then drawn with 105e5b2af955b7d06815ddd405659ad62a2a8355ca3commit-bot@chromium.org // kEvenOdd_PathFill. 106e5b2af955b7d06815ddd405659ad62a2a8355ca3commit-bot@chromium.org 107fa66294c7705831808ce7772d4328fc626d45034robertphillips@google.com // TODO: wrap GrContext::fillAARect in a helper class and 108fa66294c7705831808ce7772d4328fc626d45034robertphillips@google.com // draw AA rects directly rather than converting to paths 1094c2443e36fdc6c095b17e90baa4a2f26a6f00b08bsalomon@google.com SkPath temp; 110a72eef322c686954cdffa849dc26d8133b802f1drobertphillips@google.com temp.addRect(clipIn.getRect(i)); 111a72eef322c686954cdffa849dc26d8133b802f1drobertphillips@google.com 1128dd688b7569df569a672a8a67b2db86a9d376cfcegdaniel if (path_needs_SW_renderer(this->getContext(), gpu, temp, 1138dd688b7569df569a672a8a67b2db86a9d376cfcegdaniel kEvenOdd_PathFill, true)) { 1149853ccef19c200be93a6211f32589fa82a53067cjoshualitt useSW = true; 115e5a041c0688ccb861cc85f8917338602864d8e5acommit-bot@chromium.org } 116217daa7ec592fc306edffb9fb2a3d8c7ebff8c2dmtklein } 117e5a041c0688ccb861cc85f8917338602864d8e5acommit-bot@chromium.org } else { 11849f085dddff10473b6ebf832a974288300224e60bsalomon if (path_needs_SW_renderer(this->getContext(), gpu, 119e5a041c0688ccb861cc85f8917338602864d8e5acommit-bot@chromium.org clipIn.getPath(i), 120e5a041c0688ccb861cc85f8917338602864d8e5acommit-bot@chromium.org clipIn.getPathFill(i), 121e5a041c0688ccb861cc85f8917338602864d8e5acommit-bot@chromium.org clipIn.getDoAA(i))) { 122e5a041c0688ccb861cc85f8917338602864d8e5acommit-bot@chromium.org useSW = true; 1238dd688b7569df569a672a8a67b2db86a9d376cfcegdaniel } 1248dd688b7569df569a672a8a67b2db86a9d376cfcegdaniel } 125bf54e49e30cdc92f9ce3f336cc48cf6b236ddeabtfarina } 126e5a041c0688ccb861cc85f8917338602864d8e5acommit-bot@chromium.org 12749f085dddff10473b6ebf832a974288300224e60bsalomon return useSW; 128e5a041c0688ccb861cc85f8917338602864d8e5acommit-bot@chromium.org} 129e5a041c0688ccb861cc85f8917338602864d8e5acommit-bot@chromium.org 130e5a041c0688ccb861cc85f8917338602864d8e5acommit-bot@chromium.org//////////////////////////////////////////////////////////////////////////////// 131e5a041c0688ccb861cc85f8917338602864d8e5acommit-bot@chromium.org// sort out what kind of clip mask needs to be created: alpha, stencil, 132e5a041c0688ccb861cc85f8917338602864d8e5acommit-bot@chromium.org// scissor, or entirely software 133e5a041c0688ccb861cc85f8917338602864d8e5acommit-bot@chromium.orgbool GrClipMaskManager::createClipMask(GrGpu* gpu, 134e5a041c0688ccb861cc85f8917338602864d8e5acommit-bot@chromium.org const GrClip& clipIn, 135e5a041c0688ccb861cc85f8917338602864d8e5acommit-bot@chromium.org ScissoringSettings* scissorSettings) { 136e5a041c0688ccb861cc85f8917338602864d8e5acommit-bot@chromium.org 13749f085dddff10473b6ebf832a974288300224e60bsalomon GrAssert(scissorSettings); 138e5a041c0688ccb861cc85f8917338602864d8e5acommit-bot@chromium.org 139e5a041c0688ccb861cc85f8917338602864d8e5acommit-bot@chromium.org scissorSettings->fEnableScissoring = false; 140e5a041c0688ccb861cc85f8917338602864d8e5acommit-bot@chromium.org fClipMaskInStencil = false; 141e5a041c0688ccb861cc85f8917338602864d8e5acommit-bot@chromium.org fClipMaskInAlpha = false; 142e5a041c0688ccb861cc85f8917338602864d8e5acommit-bot@chromium.org 143e5a041c0688ccb861cc85f8917338602864d8e5acommit-bot@chromium.org GrDrawState* drawState = gpu->drawState(); 144e5a041c0688ccb861cc85f8917338602864d8e5acommit-bot@chromium.org if (!drawState->isClipState()) { 145e5a041c0688ccb861cc85f8917338602864d8e5acommit-bot@chromium.org return true; 146e5a041c0688ccb861cc85f8917338602864d8e5acommit-bot@chromium.org } 147e5a041c0688ccb861cc85f8917338602864d8e5acommit-bot@chromium.org 148e5a041c0688ccb861cc85f8917338602864d8e5acommit-bot@chromium.org GrRenderTarget* rt = drawState->getRenderTarget(); 149e5a041c0688ccb861cc85f8917338602864d8e5acommit-bot@chromium.org 150e5a041c0688ccb861cc85f8917338602864d8e5acommit-bot@chromium.org // GrDrawTarget should have filtered this for us 151e5a041c0688ccb861cc85f8917338602864d8e5acommit-bot@chromium.org GrAssert(NULL != rt); 152e5a041c0688ccb861cc85f8917338602864d8e5acommit-bot@chromium.org 153e5a041c0688ccb861cc85f8917338602864d8e5acommit-bot@chromium.org#if GR_SW_CLIP 154e5a041c0688ccb861cc85f8917338602864d8e5acommit-bot@chromium.org // If MSAA is enabled we can do everything in the stencil buffer. 155b0a8a377f832c59cee939ad721e1f87d378b7142joshualitt // Otherwise check if we should just create the entire clip mask 156e85a32d4f8ce7fb9b6aaae89137dbf3766d833f2robertphillips // in software (this will only happen if the clip mask is anti-aliased 157e5a041c0688ccb861cc85f8917338602864d8e5acommit-bot@chromium.org // and too complex for the gpu to handle in its entirety) 158217daa7ec592fc306edffb9fb2a3d8c7ebff8c2dmtklein if (0 == rt->numSamples() && useSWOnlyPath(gpu, clipIn)) { 159e5a041c0688ccb861cc85f8917338602864d8e5acommit-bot@chromium.org // The clip geometry is complex enough that it will be more 160e5a041c0688ccb861cc85f8917338602864d8e5acommit-bot@chromium.org // efficient to create it entirely in software 161e5a041c0688ccb861cc85f8917338602864d8e5acommit-bot@chromium.org GrTexture* result = NULL; 162b0a8a377f832c59cee939ad721e1f87d378b7142joshualitt GrIRect bound; 163b0a8a377f832c59cee939ad721e1f87d378b7142joshualitt if (this->createSoftwareClipMask(gpu, clipIn, &result, &bound)) { 164e5a041c0688ccb861cc85f8917338602864d8e5acommit-bot@chromium.org fClipMaskInAlpha = true; 165b0a8a377f832c59cee939ad721e1f87d378b7142joshualitt 166b0a8a377f832c59cee939ad721e1f87d378b7142joshualitt setup_drawstate_aaclip(gpu, result, bound); 167e5a041c0688ccb861cc85f8917338602864d8e5acommit-bot@chromium.org return true; 168b0a8a377f832c59cee939ad721e1f87d378b7142joshualitt } 169e5a041c0688ccb861cc85f8917338602864d8e5acommit-bot@chromium.org 170e5a041c0688ccb861cc85f8917338602864d8e5acommit-bot@chromium.org // if SW clip mask creation fails fall through to the other 171b0a8a377f832c59cee939ad721e1f87d378b7142joshualitt // two possible methods (bottoming out at stencil clipping) 172e5a041c0688ccb861cc85f8917338602864d8e5acommit-bot@chromium.org } 173e5a041c0688ccb861cc85f8917338602864d8e5acommit-bot@chromium.org#endif // GR_SW_CLIP 174e5a041c0688ccb861cc85f8917338602864d8e5acommit-bot@chromium.org 175e5a041c0688ccb861cc85f8917338602864d8e5acommit-bot@chromium.org#if GR_AA_CLIP 176e5a041c0688ccb861cc85f8917338602864d8e5acommit-bot@chromium.org // If MSAA is enabled use the (faster) stencil path for AA clipping 177b0a8a377f832c59cee939ad721e1f87d378b7142joshualitt // otherwise the alpha clip mask is our only option 178e5a041c0688ccb861cc85f8917338602864d8e5acommit-bot@chromium.org if (0 == rt->numSamples() && clipIn.requiresAA()) { 179e5a041c0688ccb861cc85f8917338602864d8e5acommit-bot@chromium.org // Since we are going to create a destination texture of the correct 180e5a041c0688ccb861cc85f8917338602864d8e5acommit-bot@chromium.org // size for the mask (rather than being bound by the size of the 181e5a041c0688ccb861cc85f8917338602864d8e5acommit-bot@chromium.org // render target) we aren't going to use scissoring like the stencil 182e5a041c0688ccb861cc85f8917338602864d8e5acommit-bot@chromium.org // path does (see scissorSettings below) 183b0a8a377f832c59cee939ad721e1f87d378b7142joshualitt GrTexture* result = NULL; 184e5a041c0688ccb861cc85f8917338602864d8e5acommit-bot@chromium.org GrIRect bound; 185e5a041c0688ccb861cc85f8917338602864d8e5acommit-bot@chromium.org if (this->createAlphaClipMask(gpu, clipIn, &result, &bound)) { 186e5a041c0688ccb861cc85f8917338602864d8e5acommit-bot@chromium.org fClipMaskInAlpha = true; 187e5a041c0688ccb861cc85f8917338602864d8e5acommit-bot@chromium.org 188e5a041c0688ccb861cc85f8917338602864d8e5acommit-bot@chromium.org setup_drawstate_aaclip(gpu, result, bound); 189b0a8a377f832c59cee939ad721e1f87d378b7142joshualitt return true; 1908dd688b7569df569a672a8a67b2db86a9d376cfcegdaniel } 191217daa7ec592fc306edffb9fb2a3d8c7ebff8c2dmtklein 192e5a041c0688ccb861cc85f8917338602864d8e5acommit-bot@chromium.org // if alpha clip mask creation fails fall through to the stencil 193e5a041c0688ccb861cc85f8917338602864d8e5acommit-bot@chromium.org // buffer method 194e5a041c0688ccb861cc85f8917338602864d8e5acommit-bot@chromium.org } 195e5a041c0688ccb861cc85f8917338602864d8e5acommit-bot@chromium.org#endif // GR_AA_CLIP 196217daa7ec592fc306edffb9fb2a3d8c7ebff8c2dmtklein 197e5a041c0688ccb861cc85f8917338602864d8e5acommit-bot@chromium.org // Either a hard (stencil buffer) clip was explicitly requested or 198e5a041c0688ccb861cc85f8917338602864d8e5acommit-bot@chromium.org // an antialiased clip couldn't be created. In either case, free up 199e5a041c0688ccb861cc85f8917338602864d8e5acommit-bot@chromium.org // the texture in the antialiased mask cache. 200e5a041c0688ccb861cc85f8917338602864d8e5acommit-bot@chromium.org // TODO: this may require more investigation. Ganesh performs a lot of 201e5a041c0688ccb861cc85f8917338602864d8e5acommit-bot@chromium.org // utility draws (e.g., clears, InOrderDrawBuffer playbacks) that hit 202e5a041c0688ccb861cc85f8917338602864d8e5acommit-bot@chromium.org // the stencil buffer path. These may be "incorrectly" clearing the 203e5a041c0688ccb861cc85f8917338602864d8e5acommit-bot@chromium.org // AA cache. 204e5a041c0688ccb861cc85f8917338602864d8e5acommit-bot@chromium.org fAACache.reset(); 205f294b773f0b2b9f05eb45b52dd3cb4d97b96af06robertphillips@google.com 2066b70a7bd3328ea0a12be47b1a7f835c905f16147robertphillips@google.com GrRect bounds; 2076b70a7bd3328ea0a12be47b1a7f835c905f16147robertphillips@google.com GrRect rtRect; 2088dd688b7569df569a672a8a67b2db86a9d376cfcegdaniel rtRect.setLTRB(0, 0, 2098dd688b7569df569a672a8a67b2db86a9d376cfcegdaniel GrIntToScalar(rt->width()), GrIntToScalar(rt->height())); 2108dd688b7569df569a672a8a67b2db86a9d376cfcegdaniel if (clipIn.hasConservativeBounds()) { 2113e79124a69d4806f0a1a776090bff718e1b90970bsalomon bounds = clipIn.getConservativeBounds(); 2129853ccef19c200be93a6211f32589fa82a53067cjoshualitt if (!bounds.intersect(rtRect)) { 2139853ccef19c200be93a6211f32589fa82a53067cjoshualitt bounds.setEmpty(); 214c8f7f47afaf8f9471e6d111655c5610a8bd210a2bsalomon@google.com } 2157a6184fdf717a1da0c6e1e37b942b17fdaa236d3joshualitt } else { 2167a6184fdf717a1da0c6e1e37b942b17fdaa236d3joshualitt bounds = rtRect; 2177a6184fdf717a1da0c6e1e37b942b17fdaa236d3joshualitt } 218a320194e4242ef0e5e758aea896bfd52bcb3dac7bsalomon@google.com 219bf54e49e30cdc92f9ce3f336cc48cf6b236ddeabtfarina bounds.roundOut(&scissorSettings->fScissorRect); 220d3e5842db0cb169e10d6da1e62c94ba5cf182bb4commit-bot@chromium.org if (scissorSettings->fScissorRect.isEmpty()) { 221bf54e49e30cdc92f9ce3f336cc48cf6b236ddeabtfarina scissorSettings->fScissorRect.setLTRB(0,0,0,0); 2224c2443e36fdc6c095b17e90baa4a2f26a6f00b08bsalomon@google.com // TODO: I think we can do an early exit here - after refactoring try: 2234c2443e36fdc6c095b17e90baa4a2f26a6f00b08bsalomon@google.com // set fEnableScissoring to true but leave fClipMaskInStencil false 2248dd688b7569df569a672a8a67b2db86a9d376cfcegdaniel // and return - everything is going to be scissored away anyway! 2254c2443e36fdc6c095b17e90baa4a2f26a6f00b08bsalomon@google.com } 2261e945b7e708c633d4aed937ebfce57d52ba21d83robertphillips@google.com scissorSettings->fEnableScissoring = true; 22749f085dddff10473b6ebf832a974288300224e60bsalomon 2281e945b7e708c633d4aed937ebfce57d52ba21d83robertphillips@google.com // use the stencil clip if we can't represent the clip as a rectangle. 2298dd688b7569df569a672a8a67b2db86a9d376cfcegdaniel fClipMaskInStencil = !clipIn.isRect() && !clipIn.isEmpty() && 2304c2443e36fdc6c095b17e90baa4a2f26a6f00b08bsalomon@google.com !bounds.isEmpty(); 2314c2443e36fdc6c095b17e90baa4a2f26a6f00b08bsalomon@google.com 2324c2443e36fdc6c095b17e90baa4a2f26a6f00b08bsalomon@google.com if (fClipMaskInStencil) { 233bf54e49e30cdc92f9ce3f336cc48cf6b236ddeabtfarina return this->createStencilClipMask(gpu, clipIn, bounds, scissorSettings); 234bf54e49e30cdc92f9ce3f336cc48cf6b236ddeabtfarina } 235bf54e49e30cdc92f9ce3f336cc48cf6b236ddeabtfarina 236bf54e49e30cdc92f9ce3f336cc48cf6b236ddeabtfarina return true; 237bf54e49e30cdc92f9ce3f336cc48cf6b236ddeabtfarina} 238bf54e49e30cdc92f9ce3f336cc48cf6b236ddeabtfarina 239bf54e49e30cdc92f9ce3f336cc48cf6b236ddeabtfarina#define VISUALIZE_COMPLEX_CLIP 0 2404c2443e36fdc6c095b17e90baa4a2f26a6f00b08bsalomon@google.com 241bf54e49e30cdc92f9ce3f336cc48cf6b236ddeabtfarina#if VISUALIZE_COMPLEX_CLIP 2424c2443e36fdc6c095b17e90baa4a2f26a6f00b08bsalomon@google.com #include "GrRandom.h" 2434c2443e36fdc6c095b17e90baa4a2f26a6f00b08bsalomon@google.com GrRandom gRandom; 2444c2443e36fdc6c095b17e90baa4a2f26a6f00b08bsalomon@google.com #define SET_RANDOM_COLOR drawState->setColor(0xff000000 | gRandom.nextU()); 2454c2443e36fdc6c095b17e90baa4a2f26a6f00b08bsalomon@google.com#else 2464c2443e36fdc6c095b17e90baa4a2f26a6f00b08bsalomon@google.com #define SET_RANDOM_COLOR 2474c2443e36fdc6c095b17e90baa4a2f26a6f00b08bsalomon@google.com#endif 2483e11c0bd92fbd12f59080c3f9450201d6105db83robertphillips@google.com 2494c2443e36fdc6c095b17e90baa4a2f26a6f00b08bsalomon@google.comnamespace { 2508dd688b7569df569a672a8a67b2db86a9d376cfcegdaniel/** 2514c2443e36fdc6c095b17e90baa4a2f26a6f00b08bsalomon@google.com * Does "container" contain "containee"? If either is empty then 252a320194e4242ef0e5e758aea896bfd52bcb3dac7bsalomon@google.com * no containment is possible. 253a320194e4242ef0e5e758aea896bfd52bcb3dac7bsalomon@google.com */ 254e5a041c0688ccb861cc85f8917338602864d8e5acommit-bot@chromium.orgbool contains(const SkRect& container, const SkIRect& containee) { 255e5a041c0688ccb861cc85f8917338602864d8e5acommit-bot@chromium.org return !containee.isEmpty() && !container.isEmpty() && 256e5a041c0688ccb861cc85f8917338602864d8e5acommit-bot@chromium.org container.fLeft <= SkIntToScalar(containee.fLeft) && 257e5a041c0688ccb861cc85f8917338602864d8e5acommit-bot@chromium.org container.fTop <= SkIntToScalar(containee.fTop) && 258e5a041c0688ccb861cc85f8917338602864d8e5acommit-bot@chromium.org container.fRight >= SkIntToScalar(containee.fRight) && 259e5a041c0688ccb861cc85f8917338602864d8e5acommit-bot@chromium.org container.fBottom >= SkIntToScalar(containee.fBottom); 260e5a041c0688ccb861cc85f8917338602864d8e5acommit-bot@chromium.org} 261e5a041c0688ccb861cc85f8917338602864d8e5acommit-bot@chromium.org 262e5a041c0688ccb861cc85f8917338602864d8e5acommit-bot@chromium.org 263e5a041c0688ccb861cc85f8917338602864d8e5acommit-bot@chromium.org//////////////////////////////////////////////////////////////////////////////// 264b21fac156d9287d6c0cfd446d707c4c7be6fae6ecommit-bot@chromium.org// determines how many elements at the head of the clip can be skipped and 265e5a041c0688ccb861cc85f8917338602864d8e5acommit-bot@chromium.org// whether the initial clear should be to the inside- or outside-the-clip value, 266259656779334689ab1624ec4e2e234b35fe4024bbsalomon// and what op should be used to draw the first element that isn't skipped. 267217daa7ec592fc306edffb9fb2a3d8c7ebff8c2dmtkleinint process_initial_clip_elements(const GrClip& clip, 268217daa7ec592fc306edffb9fb2a3d8c7ebff8c2dmtklein const GrIRect& bounds, 269217daa7ec592fc306edffb9fb2a3d8c7ebff8c2dmtklein bool* clearToInside, 270217daa7ec592fc306edffb9fb2a3d8c7ebff8c2dmtklein SkRegion::Op* startOp) { 27177b1307c1f5dac019575a6d431d5ce657370c4fbjoshualitt 272e5a041c0688ccb861cc85f8917338602864d8e5acommit-bot@chromium.org // logically before the first element of the clip stack is 2738dd688b7569df569a672a8a67b2db86a9d376cfcegdaniel // processed the clip is entirely open. However, depending on the 27465ee5f424cb4dabd453268902c00086605d77c1dcommit-bot@chromium.org // first set op we may prefer to clear to 0 for performance. We may 27565ee5f424cb4dabd453268902c00086605d77c1dcommit-bot@chromium.org // also be able to skip the initial clip paths/rects. We loop until 27665ee5f424cb4dabd453268902c00086605d77c1dcommit-bot@chromium.org // we cannot skip an element. 277d3066bd9b4a37cf4a39e7df7e1432f3df10dbc67bsalomon@google.com int curr; 278a3e5c63ab0264332169df4583a8a7da186fb4e66robertphillips@google.com bool done = false; 2794c2443e36fdc6c095b17e90baa4a2f26a6f00b08bsalomon@google.com *clearToInside = true; 2806b70a7bd3328ea0a12be47b1a7f835c905f16147robertphillips@google.com int count = clip.getElementCount(); 281a3e5c63ab0264332169df4583a8a7da186fb4e66robertphillips@google.com 2828059eb9f6e24ed609393fbda4ad71edea03ac258joshualitt for (curr = 0; curr < count && !done; ++curr) { 2838059eb9f6e24ed609393fbda4ad71edea03ac258joshualitt switch (clip.getOp(curr)) { 2848059eb9f6e24ed609393fbda4ad71edea03ac258joshualitt case SkRegion::kReplace_Op: 2858059eb9f6e24ed609393fbda4ad71edea03ac258joshualitt // replace ignores everything previous 2868059eb9f6e24ed609393fbda4ad71edea03ac258joshualitt *startOp = SkRegion::kReplace_Op; 2878059eb9f6e24ed609393fbda4ad71edea03ac258joshualitt *clearToInside = false; 2888dd688b7569df569a672a8a67b2db86a9d376cfcegdaniel done = true; 2894c2443e36fdc6c095b17e90baa4a2f26a6f00b08bsalomon@google.com break; 2904c2443e36fdc6c095b17e90baa4a2f26a6f00b08bsalomon@google.com case SkRegion::kIntersect_Op: 2914c2443e36fdc6c095b17e90baa4a2f26a6f00b08bsalomon@google.com // if this element contains the entire bounds then we 2924c2443e36fdc6c095b17e90baa4a2f26a6f00b08bsalomon@google.com // can skip it. 2934c2443e36fdc6c095b17e90baa4a2f26a6f00b08bsalomon@google.com if (kRect_ClipType == clip.getElementType(curr) 2948059eb9f6e24ed609393fbda4ad71edea03ac258joshualitt && contains(clip.getRect(curr), bounds)) { 2954c2443e36fdc6c095b17e90baa4a2f26a6f00b08bsalomon@google.com break; 2964c2443e36fdc6c095b17e90baa4a2f26a6f00b08bsalomon@google.com } 2974c2443e36fdc6c095b17e90baa4a2f26a6f00b08bsalomon@google.com // if everything is initially clearToInside then intersect is 2984c2443e36fdc6c095b17e90baa4a2f26a6f00b08bsalomon@google.com // same as clear to 0 and treat as a replace. Otherwise, 2994c2443e36fdc6c095b17e90baa4a2f26a6f00b08bsalomon@google.com // set stays empty. 3008059eb9f6e24ed609393fbda4ad71edea03ac258joshualitt if (*clearToInside) { 3014c2443e36fdc6c095b17e90baa4a2f26a6f00b08bsalomon@google.com *startOp = SkRegion::kReplace_Op; 3024c2443e36fdc6c095b17e90baa4a2f26a6f00b08bsalomon@google.com *clearToInside = false; 3036b70a7bd3328ea0a12be47b1a7f835c905f16147robertphillips@google.com done = true; 30449f085dddff10473b6ebf832a974288300224e60bsalomon } 3054c2443e36fdc6c095b17e90baa4a2f26a6f00b08bsalomon@google.com break; 3064c2443e36fdc6c095b17e90baa4a2f26a6f00b08bsalomon@google.com // we can skip a leading union. 3074c2443e36fdc6c095b17e90baa4a2f26a6f00b08bsalomon@google.com case SkRegion::kUnion_Op: 3084c2443e36fdc6c095b17e90baa4a2f26a6f00b08bsalomon@google.com // if everything is initially outside then union is 3098dd688b7569df569a672a8a67b2db86a9d376cfcegdaniel // same as replace. Otherwise, every pixel is still 3108dd688b7569df569a672a8a67b2db86a9d376cfcegdaniel // clearToInside 311f294b773f0b2b9f05eb45b52dd3cb4d97b96af06robertphillips@google.com if (!*clearToInside) { 312f294b773f0b2b9f05eb45b52dd3cb4d97b96af06robertphillips@google.com *startOp = SkRegion::kReplace_Op; 3134c2443e36fdc6c095b17e90baa4a2f26a6f00b08bsalomon@google.com done = true; 314f294b773f0b2b9f05eb45b52dd3cb4d97b96af06robertphillips@google.com } 315f294b773f0b2b9f05eb45b52dd3cb4d97b96af06robertphillips@google.com break; 3164c2443e36fdc6c095b17e90baa4a2f26a6f00b08bsalomon@google.com case SkRegion::kXOR_Op: 3174c2443e36fdc6c095b17e90baa4a2f26a6f00b08bsalomon@google.com // xor is same as difference or replace both of which 3184c2443e36fdc6c095b17e90baa4a2f26a6f00b08bsalomon@google.com // can be 1-pass instead of 2 for xor. 3194c2443e36fdc6c095b17e90baa4a2f26a6f00b08bsalomon@google.com if (*clearToInside) { 3204c2443e36fdc6c095b17e90baa4a2f26a6f00b08bsalomon@google.com *startOp = SkRegion::kDifference_Op; 3215acc0e36d987dff3172fd45a14b66c52a51d49e4robertphillips@google.com } else { 3225acc0e36d987dff3172fd45a14b66c52a51d49e4robertphillips@google.com *startOp = SkRegion::kReplace_Op; 3231e945b7e708c633d4aed937ebfce57d52ba21d83robertphillips@google.com } 3244c2443e36fdc6c095b17e90baa4a2f26a6f00b08bsalomon@google.com done = true; 3259853ccef19c200be93a6211f32589fa82a53067cjoshualitt break; 3269853ccef19c200be93a6211f32589fa82a53067cjoshualitt case SkRegion::kDifference_Op: 327d3e5842db0cb169e10d6da1e62c94ba5cf182bb4commit-bot@chromium.org // if all pixels are clearToInside then we have to process the 3284c2443e36fdc6c095b17e90baa4a2f26a6f00b08bsalomon@google.com // difference, otherwise it has no effect and all pixels 3294c2443e36fdc6c095b17e90baa4a2f26a6f00b08bsalomon@google.com // remain outside. 3304c2443e36fdc6c095b17e90baa4a2f26a6f00b08bsalomon@google.com if (*clearToInside) { 3314c2443e36fdc6c095b17e90baa4a2f26a6f00b08bsalomon@google.com *startOp = SkRegion::kDifference_Op; 3324c2443e36fdc6c095b17e90baa4a2f26a6f00b08bsalomon@google.com done = true; 3334c2443e36fdc6c095b17e90baa4a2f26a6f00b08bsalomon@google.com } 3344c2443e36fdc6c095b17e90baa4a2f26a6f00b08bsalomon@google.com break; 3354c2443e36fdc6c095b17e90baa4a2f26a6f00b08bsalomon@google.com case SkRegion::kReverseDifference_Op: 3364c2443e36fdc6c095b17e90baa4a2f26a6f00b08bsalomon@google.com // if all pixels are clearToInside then reverse difference 33777b1307c1f5dac019575a6d431d5ce657370c4fbjoshualitt // produces empty set. Otherise it is same as replace 3388dd688b7569df569a672a8a67b2db86a9d376cfcegdaniel if (*clearToInside) { 3391e945b7e708c633d4aed937ebfce57d52ba21d83robertphillips@google.com *clearToInside = false; 3401e945b7e708c633d4aed937ebfce57d52ba21d83robertphillips@google.com } else { 3411e945b7e708c633d4aed937ebfce57d52ba21d83robertphillips@google.com *startOp = SkRegion::kReplace_Op; 3421e945b7e708c633d4aed937ebfce57d52ba21d83robertphillips@google.com done = true; 343f294b773f0b2b9f05eb45b52dd3cb4d97b96af06robertphillips@google.com } 3448dd688b7569df569a672a8a67b2db86a9d376cfcegdaniel break; 3458dd688b7569df569a672a8a67b2db86a9d376cfcegdaniel default: 3468dd688b7569df569a672a8a67b2db86a9d376cfcegdaniel GrCrash("Unknown set op."); 3478750924a1470e8215b2a344155259b93062d3fa2egdaniel } 3488dd688b7569df569a672a8a67b2db86a9d376cfcegdaniel } 349f294b773f0b2b9f05eb45b52dd3cb4d97b96af06robertphillips@google.com return done ? curr-1 : count; 35072176b2d38db005863a54e3dd6657bbabd068bb6robertphillips@google.com} 351f294b773f0b2b9f05eb45b52dd3cb4d97b96af06robertphillips@google.com 352f294b773f0b2b9f05eb45b52dd3cb4d97b96af06robertphillips@google.com} 3538dd688b7569df569a672a8a67b2db86a9d376cfcegdaniel 3548059eb9f6e24ed609393fbda4ad71edea03ac258joshualitt 3559853ccef19c200be93a6211f32589fa82a53067cjoshualittnamespace { 356e79f320ed6c5ec9f6164ba84be1ff586532e6517robertphillips@google.com 357e79f320ed6c5ec9f6164ba84be1ff586532e6517robertphillips@google.com//////////////////////////////////////////////////////////////////////////////// 3589853ccef19c200be93a6211f32589fa82a53067cjoshualitt// set up the OpenGL blend function to perform the specified 359f294b773f0b2b9f05eb45b52dd3cb4d97b96af06robertphillips@google.com// boolean operation for alpha clip mask creation 3608dd688b7569df569a672a8a67b2db86a9d376cfcegdanielvoid setup_boolean_blendcoeffs(GrDrawState* drawState, SkRegion::Op op) { 361f294b773f0b2b9f05eb45b52dd3cb4d97b96af06robertphillips@google.com 3628750924a1470e8215b2a344155259b93062d3fa2egdaniel switch (op) { 3638750924a1470e8215b2a344155259b93062d3fa2egdaniel case SkRegion::kReplace_Op: 3648750924a1470e8215b2a344155259b93062d3fa2egdaniel drawState->setBlendFunc(kOne_BlendCoeff, kZero_BlendCoeff); 3658750924a1470e8215b2a344155259b93062d3fa2egdaniel break; 366e5b2af955b7d06815ddd405659ad62a2a8355ca3commit-bot@chromium.org case SkRegion::kIntersect_Op: 3678182fa0cac76e7e6d583aebba060229230516887bsalomon@google.com drawState->setBlendFunc(kDC_BlendCoeff, kZero_BlendCoeff); 368e5b2af955b7d06815ddd405659ad62a2a8355ca3commit-bot@chromium.org break; 369e5b2af955b7d06815ddd405659ad62a2a8355ca3commit-bot@chromium.org case SkRegion::kUnion_Op: 370e5b2af955b7d06815ddd405659ad62a2a8355ca3commit-bot@chromium.org drawState->setBlendFunc(kOne_BlendCoeff, kISC_BlendCoeff); 3718182fa0cac76e7e6d583aebba060229230516887bsalomon@google.com break; 372b0a8a377f832c59cee939ad721e1f87d378b7142joshualitt case SkRegion::kXOR_Op: 373b0a8a377f832c59cee939ad721e1f87d378b7142joshualitt drawState->setBlendFunc(kIDC_BlendCoeff, kISC_BlendCoeff); 3748182fa0cac76e7e6d583aebba060229230516887bsalomon@google.com break; 3758059eb9f6e24ed609393fbda4ad71edea03ac258joshualitt case SkRegion::kDifference_Op: 3768059eb9f6e24ed609393fbda4ad71edea03ac258joshualitt drawState->setBlendFunc(kZero_BlendCoeff, kISC_BlendCoeff); 377329bf4862e9d5e05363c2b071d8ca475a0ef1952joshualitt break; 3788dd688b7569df569a672a8a67b2db86a9d376cfcegdaniel case SkRegion::kReverseDifference_Op: 3792e3b3e369d79e78f7635d4c20e83a47ab571bdf2joshualitt drawState->setBlendFunc(kIDC_BlendCoeff, kZero_BlendCoeff); 3808059eb9f6e24ed609393fbda4ad71edea03ac258joshualitt break; 381a58fe35fdae3481cf43062f7032820c320c3d163joshualitt default: 3828059eb9f6e24ed609393fbda4ad71edea03ac258joshualitt GrAssert(false); 3838182fa0cac76e7e6d583aebba060229230516887bsalomon@google.com break; 3848dd688b7569df569a672a8a67b2db86a9d376cfcegdaniel } 3858182fa0cac76e7e6d583aebba060229230516887bsalomon@google.com} 3868182fa0cac76e7e6d583aebba060229230516887bsalomon@google.com 387e5b2af955b7d06815ddd405659ad62a2a8355ca3commit-bot@chromium.org//////////////////////////////////////////////////////////////////////////////// 388e5b2af955b7d06815ddd405659ad62a2a8355ca3commit-bot@chromium.orgbool draw_path(GrContext* context, 389e5b2af955b7d06815ddd405659ad62a2a8355ca3commit-bot@chromium.org GrGpu* gpu, 390b3eb687f8a89eb1eacd1afb4016401eb392f66abjvanverth const SkPath& path, 391e5b2af955b7d06815ddd405659ad62a2a8355ca3commit-bot@chromium.org GrPathFill fill, 392e5b2af955b7d06815ddd405659ad62a2a8355ca3commit-bot@chromium.org bool doAA) { 393e79f320ed6c5ec9f6164ba84be1ff586532e6517robertphillips@google.com 3945f74cf8c49701f514b69dc6f1a8b5c0ffd78af0asugoi@google.com GrPathRenderer* pr = context->getPathRenderer(path, fill, gpu, doAA, true); 395e79f320ed6c5ec9f6164ba84be1ff586532e6517robertphillips@google.com if (NULL == pr) { 396e79f320ed6c5ec9f6164ba84be1ff586532e6517robertphillips@google.com return false; 397e79f320ed6c5ec9f6164ba84be1ff586532e6517robertphillips@google.com } 398e79f320ed6c5ec9f6164ba84be1ff586532e6517robertphillips@google.com 3998dd688b7569df569a672a8a67b2db86a9d376cfcegdaniel pr->drawPath(path, fill, NULL, gpu, 0, doAA); 4008dd688b7569df569a672a8a67b2db86a9d376cfcegdaniel return true; 401e79f320ed6c5ec9f6164ba84be1ff586532e6517robertphillips@google.com} 402e79f320ed6c5ec9f6164ba84be1ff586532e6517robertphillips@google.com 4034c2443e36fdc6c095b17e90baa4a2f26a6f00b08bsalomon@google.com} 4044c2443e36fdc6c095b17e90baa4a2f26a6f00b08bsalomon@google.com 4059853ccef19c200be93a6211f32589fa82a53067cjoshualitt//////////////////////////////////////////////////////////////////////////////// 4068dd688b7569df569a672a8a67b2db86a9d376cfcegdanielbool GrClipMaskManager::drawClipShape(GrGpu* gpu, 4078dd688b7569df569a672a8a67b2db86a9d376cfcegdaniel GrTexture* target, 4084c2443e36fdc6c095b17e90baa4a2f26a6f00b08bsalomon@google.com const GrClip& clipIn, 4094c2443e36fdc6c095b17e90baa4a2f26a6f00b08bsalomon@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()); 4148dd688b7569df569a672a8a67b2db86a9d376cfcegdaniel 4159853ccef19c200be93a6211f32589fa82a53067cjoshualitt if (kRect_ClipType == clipIn.getElementType(index)) { 4169853ccef19c200be93a6211f32589fa82a53067cjoshualitt if (clipIn.getDoAA(index)) { 4179853ccef19c200be93a6211f32589fa82a53067cjoshualitt // convert the rect to a path for AA 4188dd688b7569df569a672a8a67b2db86a9d376cfcegdaniel SkPath temp; 419b68addd39f3e7183facc70374a133e7a6fb603c5bsalomon@google.com temp.addRect(clipIn.getRect(index)); 420e5b2af955b7d06815ddd405659ad62a2a8355ca3commit-bot@chromium.org 421e5b2af955b7d06815ddd405659ad62a2a8355ca3commit-bot@chromium.org return draw_path(this->getContext(), gpu, temp, 422e5b2af955b7d06815ddd405659ad62a2a8355ca3commit-bot@chromium.org kEvenOdd_PathFill, clipIn.getDoAA(index)); 423e5b2af955b7d06815ddd405659ad62a2a8355ca3commit-bot@chromium.org } else { 424e5b2af955b7d06815ddd405659ad62a2a8355ca3commit-bot@chromium.org gpu->drawSimpleRect(clipIn.getRect(index), NULL, 0); 425e5b2af955b7d06815ddd405659ad62a2a8355ca3commit-bot@chromium.org } 426e5b2af955b7d06815ddd405659ad62a2a8355ca3commit-bot@chromium.org } else { 427e5b2af955b7d06815ddd405659ad62a2a8355ca3commit-bot@chromium.org return draw_path(this->getContext(), gpu, 428e5b2af955b7d06815ddd405659ad62a2a8355ca3commit-bot@chromium.org clipIn.getPath(index), 429b68addd39f3e7183facc70374a133e7a6fb603c5bsalomon@google.com clipIn.getPathFill(index), 430e5b2af955b7d06815ddd405659ad62a2a8355ca3commit-bot@chromium.org clipIn.getDoAA(index)); 431e5b2af955b7d06815ddd405659ad62a2a8355ca3commit-bot@chromium.org } 432e5b2af955b7d06815ddd405659ad62a2a8355ca3commit-bot@chromium.org return true; 433e5b2af955b7d06815ddd405659ad62a2a8355ca3commit-bot@chromium.org} 4348dd688b7569df569a672a8a67b2db86a9d376cfcegdaniel 4358059eb9f6e24ed609393fbda4ad71edea03ac258joshualittvoid GrClipMaskManager::drawTexture(GrGpu* gpu, 43649f085dddff10473b6ebf832a974288300224e60bsalomon GrTexture* target, 437b68addd39f3e7183facc70374a133e7a6fb603c5bsalomon@google.com GrTexture* texture) { 438b68addd39f3e7183facc70374a133e7a6fb603c5bsalomon@google.com GrDrawState* drawState = gpu->drawState(); 439b68addd39f3e7183facc70374a133e7a6fb603c5bsalomon@google.com GrAssert(NULL != drawState); 4408dd688b7569df569a672a8a67b2db86a9d376cfcegdaniel 4419853ccef19c200be93a6211f32589fa82a53067cjoshualitt // no AA here since it is encoded in the texture 4427b7cdd147f5528865238e5ed98c79e6d319fde9bbsalomon@google.com drawState->setRenderTarget(target->asRenderTarget()); 4437b7cdd147f5528865238e5ed98c79e6d319fde9bbsalomon@google.com 444fd03d4a829efe2d77a712fd991927c55f59a2ffecommit-bot@chromium.org GrMatrix sampleM; 445fd03d4a829efe2d77a712fd991927c55f59a2ffecommit-bot@chromium.org sampleM.setIDiv(texture->width(), texture->height()); 4468dd688b7569df569a672a8a67b2db86a9d376cfcegdaniel drawState->setTexture(0, texture); 447f294b773f0b2b9f05eb45b52dd3cb4d97b96af06robertphillips@google.com 4488750924a1470e8215b2a344155259b93062d3fa2egdaniel drawState->sampler(0)->reset(GrSamplerState::kClamp_WrapMode, 4498dd688b7569df569a672a8a67b2db86a9d376cfcegdaniel GrSamplerState::kNearest_Filter, 45072b2e6fff3f54c6aa80a98eab4c73f02a8cd450dskia.committer@gmail.com sampleM); 451b9086a026844e4cfd08b219e49ce3f12294cba98bsalomon@google.com 4527b7cdd147f5528865238e5ed98c79e6d319fde9bbsalomon@google.com GrRect rect = GrRect::MakeWH(SkIntToScalar(target->width()), 453956b310f13c7412c035406c658ff16ca85eac656skia.committer@gmail.com SkIntToScalar(target->height())); 4548dd688b7569df569a672a8a67b2db86a9d376cfcegdaniel 4557b7cdd147f5528865238e5ed98c79e6d319fde9bbsalomon@google.com gpu->drawSimpleRect(rect, NULL, 1 << 0); 4567b7cdd147f5528865238e5ed98c79e6d319fde9bbsalomon@google.com 457907fbd53c5e5dd4cbde7b72f9242b51febd7ef95commit-bot@chromium.org drawState->setTexture(0, NULL); 458907fbd53c5e5dd4cbde7b72f9242b51febd7ef95commit-bot@chromium.org} 459b86add1ad37776818e1f730359ec587c9fdbff5fhumper@google.com 4608750924a1470e8215b2a344155259b93062d3fa2egdanielnamespace { 4618dd688b7569df569a672a8a67b2db86a9d376cfcegdaniel 4628dd688b7569df569a672a8a67b2db86a9d376cfcegdanielvoid clear(GrGpu* gpu, 463f294b773f0b2b9f05eb45b52dd3cb4d97b96af06robertphillips@google.com GrTexture* target, 464f294b773f0b2b9f05eb45b52dd3cb4d97b96af06robertphillips@google.com GrColor color) { 465427cf28861867c0ea9aafca3a23878ec4068ad99bsalomon GrDrawState* drawState = gpu->drawState(); 466f2703d83da3ab2ae18b45231fd4f11e16cce3184bsalomon GrAssert(NULL != drawState); 4673f490a0c0170feb8b53c220d6c5331c23aeb3f23bsalomon 4684c2443e36fdc6c095b17e90baa4a2f26a6f00b08bsalomon@google.com // zap entire target to specified color 4694c2443e36fdc6c095b17e90baa4a2f26a6f00b08bsalomon@google.com drawState->setRenderTarget(target->asRenderTarget()); 47051d1f7e3a4305e517586dc158a0329bbaa8896aabsalomon gpu->clear(NULL, color); 47151d1f7e3a4305e517586dc158a0329bbaa8896aabsalomon} 47251d1f7e3a4305e517586dc158a0329bbaa8896aabsalomon 47351d1f7e3a4305e517586dc158a0329bbaa8896aabsalomon} 47451d1f7e3a4305e517586dc158a0329bbaa8896aabsalomon 4756b70a7bd3328ea0a12be47b1a7f835c905f16147robertphillips@google.com// get a texture to act as a temporary buffer for AA clip boolean operations 476329bf4862e9d5e05363c2b071d8ca475a0ef1952joshualitt// TODO: given the expense of createTexture we may want to just cache this too 4776d62df404bf420bedff4d7b5edd061740a673d44robertphillips@google.comvoid GrClipMaskManager::getTemp(const GrIRect& bounds, 4786d62df404bf420bedff4d7b5edd061740a673d44robertphillips@google.com GrAutoScratchTexture* temp) { 4796b70a7bd3328ea0a12be47b1a7f835c905f16147robertphillips@google.com if (NULL != temp->texture()) { 480ad1dc589cef8aebf7e14672ffdaa31c6d399675dkrajcevski // we've already allocated the temp texture 481ad1dc589cef8aebf7e14672ffdaa31c6d399675dkrajcevski return; 482ad1dc589cef8aebf7e14672ffdaa31c6d399675dkrajcevski } 483d3e5842db0cb169e10d6da1e62c94ba5cf182bb4commit-bot@chromium.org 4844c2443e36fdc6c095b17e90baa4a2f26a6f00b08bsalomon@google.com const GrTextureDesc desc = { 485ad1dc589cef8aebf7e14672ffdaa31c6d399675dkrajcevski kRenderTarget_GrTextureFlagBit|kNoStencil_GrTextureFlagBit, 486ad1dc589cef8aebf7e14672ffdaa31c6d399675dkrajcevski bounds.width(), 4874c2443e36fdc6c095b17e90baa4a2f26a6f00b08bsalomon@google.com bounds.height(), 488ad1dc589cef8aebf7e14672ffdaa31c6d399675dkrajcevski kAlpha_8_GrPixelConfig, 489ad1dc589cef8aebf7e14672ffdaa31c6d399675dkrajcevski 0 // samples 490f294b773f0b2b9f05eb45b52dd3cb4d97b96af06robertphillips@google.com }; 491ad1dc589cef8aebf7e14672ffdaa31c6d399675dkrajcevski 492ad1dc589cef8aebf7e14672ffdaa31c6d399675dkrajcevski temp->set(this->getContext(), desc); 493ad1dc589cef8aebf7e14672ffdaa31c6d399675dkrajcevski} 494ad1dc589cef8aebf7e14672ffdaa31c6d399675dkrajcevski 495ad1dc589cef8aebf7e14672ffdaa31c6d399675dkrajcevski 496ad1dc589cef8aebf7e14672ffdaa31c6d399675dkrajcevskivoid GrClipMaskManager::setupCache(const GrClip& clipIn, 497ad1dc589cef8aebf7e14672ffdaa31c6d399675dkrajcevski const GrIRect& bounds) { 498ad1dc589cef8aebf7e14672ffdaa31c6d399675dkrajcevski // Since we are setting up the cache we know the last lookup was a miss 499ad1dc589cef8aebf7e14672ffdaa31c6d399675dkrajcevski // Free up the currently cached mask so it can be reused 500a72eef322c686954cdffa849dc26d8133b802f1drobertphillips@google.com fAACache.reset(); 501f2703d83da3ab2ae18b45231fd4f11e16cce3184bsalomon 502f2703d83da3ab2ae18b45231fd4f11e16cce3184bsalomon const GrTextureDesc desc = { 503ad1dc589cef8aebf7e14672ffdaa31c6d399675dkrajcevski kRenderTarget_GrTextureFlagBit|kNoStencil_GrTextureFlagBit, 504ad1dc589cef8aebf7e14672ffdaa31c6d399675dkrajcevski bounds.width(), 505ad1dc589cef8aebf7e14672ffdaa31c6d399675dkrajcevski bounds.height(), 506ad1dc589cef8aebf7e14672ffdaa31c6d399675dkrajcevski kAlpha_8_GrPixelConfig, 507ad1dc589cef8aebf7e14672ffdaa31c6d399675dkrajcevski 0 // samples 508ad1dc589cef8aebf7e14672ffdaa31c6d399675dkrajcevski }; 5098fff356c8505f2ac78e1fc9dc17c1192e3a608e4robertphillips@google.com 5108fff356c8505f2ac78e1fc9dc17c1192e3a608e4robertphillips@google.com fAACache.acquireMask(clipIn, desc, bounds); 511ad1dc589cef8aebf7e14672ffdaa31c6d399675dkrajcevski} 512ad1dc589cef8aebf7e14672ffdaa31c6d399675dkrajcevski 5136b70a7bd3328ea0a12be47b1a7f835c905f16147robertphillips@google.com//////////////////////////////////////////////////////////////////////////////// 514f294b773f0b2b9f05eb45b52dd3cb4d97b96af06robertphillips@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 517d3e5842db0cb169e10d6da1e62c94ba5cf182bb4commit-bot@chromium.org// Returns true if there is no more work to be done (i.e., we got a cache hit) 518bf54e49e30cdc92f9ce3f336cc48cf6b236ddeabtfarinabool GrClipMaskManager::clipMaskPreamble(GrGpu* gpu, 519bf54e49e30cdc92f9ce3f336cc48cf6b236ddeabtfarina const GrClip& clipIn, 5208059eb9f6e24ed609393fbda4ad71edea03ac258joshualitt GrTexture** result, 5214c2443e36fdc6c095b17e90baa4a2f26a6f00b08bsalomon@google.com GrIRect *resultBounds) { 522f6de475e5cbd143f348ff7738919e397b7fe7f57tfarina@chromium.org GrDrawState* origDrawState = gpu->drawState(); 523c8f7f47afaf8f9471e6d111655c5610a8bd210a2bsalomon@google.com GrAssert(origDrawState->isClipState()); 524ad1dc589cef8aebf7e14672ffdaa31c6d399675dkrajcevski 525ad1dc589cef8aebf7e14672ffdaa31c6d399675dkrajcevski GrRenderTarget* rt = origDrawState->getRenderTarget(); 52649f085dddff10473b6ebf832a974288300224e60bsalomon GrAssert(NULL != rt); 527c8f7f47afaf8f9471e6d111655c5610a8bd210a2bsalomon@google.com 5284c2443e36fdc6c095b17e90baa4a2f26a6f00b08bsalomon@google.com GrRect rtRect; 5296b70a7bd3328ea0a12be47b1a7f835c905f16147robertphillips@google.com rtRect.setLTRB(0, 0, 530f294b773f0b2b9f05eb45b52dd3cb4d97b96af06robertphillips@google.com GrIntToScalar(rt->width()), GrIntToScalar(rt->height())); 531ad1dc589cef8aebf7e14672ffdaa31c6d399675dkrajcevski 532ad1dc589cef8aebf7e14672ffdaa31c6d399675dkrajcevski // unlike the stencil path the alpha path is not bound to the size of the 5334c2443e36fdc6c095b17e90baa4a2f26a6f00b08bsalomon@google.com // render target - determine the minimum size required for the mask 534f105b109264f71dfb0bfd9977e6a5dd0a5a12f57robertphillips@google.com GrRect bounds; 5354c2443e36fdc6c095b17e90baa4a2f26a6f00b08bsalomon@google.com 536f294b773f0b2b9f05eb45b52dd3cb4d97b96af06robertphillips@google.com if (clipIn.hasConservativeBounds()) { 537f294b773f0b2b9f05eb45b52dd3cb4d97b96af06robertphillips@google.com bounds = clipIn.getConservativeBounds(); 5388059eb9f6e24ed609393fbda4ad71edea03ac258joshualitt if (!bounds.intersect(rtRect)) { 5398059eb9f6e24ed609393fbda4ad71edea03ac258joshualitt // the mask will be empty in this case 5408059eb9f6e24ed609393fbda4ad71edea03ac258joshualitt GrAssert(false); 5418059eb9f6e24ed609393fbda4ad71edea03ac258joshualitt bounds.setEmpty(); 5428059eb9f6e24ed609393fbda4ad71edea03ac258joshualitt } 5434c2443e36fdc6c095b17e90baa4a2f26a6f00b08bsalomon@google.com } else { 5444c2443e36fdc6c095b17e90baa4a2f26a6f00b08bsalomon@google.com // still locked to the size of the render target 5454c2443e36fdc6c095b17e90baa4a2f26a6f00b08bsalomon@google.com bounds = rtRect; 546f294b773f0b2b9f05eb45b52dd3cb4d97b96af06robertphillips@google.com } 5477b7cdd147f5528865238e5ed98c79e6d319fde9bbsalomon@google.com 5487b7cdd147f5528865238e5ed98c79e6d319fde9bbsalomon@google.com GrIRect intBounds; 549329bf4862e9d5e05363c2b071d8ca475a0ef1952joshualitt bounds.roundOut(&intBounds); 550329bf4862e9d5e05363c2b071d8ca475a0ef1952joshualitt 551329bf4862e9d5e05363c2b071d8ca475a0ef1952joshualitt // need to outset a pixel since the standard bounding box computation 552329bf4862e9d5e05363c2b071d8ca475a0ef1952joshualitt // path doesn't leave any room for antialiasing (esp. w.r.t. rects) 553d9f7503e0cb0c4db856f53b4bdeec1332db6f296skia.committer@gmail.com intBounds.outset(1, 1); 554b68addd39f3e7183facc70374a133e7a6fb603c5bsalomon@google.com 555b68addd39f3e7183facc70374a133e7a6fb603c5bsalomon@google.com // TODO: make sure we don't outset if bounds are still 0,0 @ min 556b68addd39f3e7183facc70374a133e7a6fb603c5bsalomon@google.com 557b68addd39f3e7183facc70374a133e7a6fb603c5bsalomon@google.com if (fAACache.canReuse(clipIn, 558329bf4862e9d5e05363c2b071d8ca475a0ef1952joshualitt intBounds.width(), 559427cf28861867c0ea9aafca3a23878ec4068ad99bsalomon intBounds.height())) { 5609853ccef19c200be93a6211f32589fa82a53067cjoshualitt *result = fAACache.getLastMask(); 561f294b773f0b2b9f05eb45b52dd3cb4d97b96af06robertphillips@google.com fAACache.getLastBound(resultBounds); 562bf54e49e30cdc92f9ce3f336cc48cf6b236ddeabtfarina return true; 5634c2443e36fdc6c095b17e90baa4a2f26a6f00b08bsalomon@google.com } 5648182fa0cac76e7e6d583aebba060229230516887bsalomon@google.com 565b68addd39f3e7183facc70374a133e7a6fb603c5bsalomon@google.com this->setupCache(clipIn, intBounds); 566b68addd39f3e7183facc70374a133e7a6fb603c5bsalomon@google.com 5678dd688b7569df569a672a8a67b2db86a9d376cfcegdaniel *resultBounds = intBounds; 5689853ccef19c200be93a6211f32589fa82a53067cjoshualitt return false; 569e79f320ed6c5ec9f6164ba84be1ff586532e6517robertphillips@google.com} 5708dd688b7569df569a672a8a67b2db86a9d376cfcegdaniel 571b68addd39f3e7183facc70374a133e7a6fb603c5bsalomon@google.com//////////////////////////////////////////////////////////////////////////////// 5724c2443e36fdc6c095b17e90baa4a2f26a6f00b08bsalomon@google.com// Create a 8-bit clip mask in alpha 5737b7cdd147f5528865238e5ed98c79e6d319fde9bbsalomon@google.combool GrClipMaskManager::createAlphaClipMask(GrGpu* gpu, 5747b7cdd147f5528865238e5ed98c79e6d319fde9bbsalomon@google.com const GrClip& clipIn, 575b68addd39f3e7183facc70374a133e7a6fb603c5bsalomon@google.com GrTexture** result, 576fd03d4a829efe2d77a712fd991927c55f59a2ffecommit-bot@chromium.org GrIRect *resultBounds) { 577b68addd39f3e7183facc70374a133e7a6fb603c5bsalomon@google.com 578b68addd39f3e7183facc70374a133e7a6fb603c5bsalomon@google.com if (this->clipMaskPreamble(gpu, clipIn, result, resultBounds)) { 579b68addd39f3e7183facc70374a133e7a6fb603c5bsalomon@google.com return true; 580b68addd39f3e7183facc70374a133e7a6fb603c5bsalomon@google.com } 581b68addd39f3e7183facc70374a133e7a6fb603c5bsalomon@google.com 582fd03d4a829efe2d77a712fd991927c55f59a2ffecommit-bot@chromium.org GrTexture* accum = fAACache.getLastMask(); 583b68addd39f3e7183facc70374a133e7a6fb603c5bsalomon@google.com if (NULL == accum) { 584b68addd39f3e7183facc70374a133e7a6fb603c5bsalomon@google.com fClipMaskInAlpha = false; 585b68addd39f3e7183facc70374a133e7a6fb603c5bsalomon@google.com fAACache.reset(); 586b68addd39f3e7183facc70374a133e7a6fb603c5bsalomon@google.com return false; 587427cf28861867c0ea9aafca3a23878ec4068ad99bsalomon } 588427cf28861867c0ea9aafca3a23878ec4068ad99bsalomon 589427cf28861867c0ea9aafca3a23878ec4068ad99bsalomon GrDrawTarget::AutoStateRestore asr(gpu, GrDrawTarget::kReset_ASRInit); 590427cf28861867c0ea9aafca3a23878ec4068ad99bsalomon GrDrawState* drawState = gpu->drawState(); 591427cf28861867c0ea9aafca3a23878ec4068ad99bsalomon 592427cf28861867c0ea9aafca3a23878ec4068ad99bsalomon GrDrawTarget::AutoGeometryPush agp(gpu); 593427cf28861867c0ea9aafca3a23878ec4068ad99bsalomon 594a7aedfec9e28db36c97e49f11f2bc2e0eb624c30skia.committer@gmail.com int count = clipIn.getElementCount(); 595427cf28861867c0ea9aafca3a23878ec4068ad99bsalomon 596b68addd39f3e7183facc70374a133e7a6fb603c5bsalomon@google.com if (0 != resultBounds->fTop || 0 != resultBounds->fLeft) { 597329bf4862e9d5e05363c2b071d8ca475a0ef1952joshualitt // if we were able to trim down the size of the mask we need to 5989853ccef19c200be93a6211f32589fa82a53067cjoshualitt // offset the paths & rects that will be used to compute it 5999853ccef19c200be93a6211f32589fa82a53067cjoshualitt GrMatrix m; 6009853ccef19c200be93a6211f32589fa82a53067cjoshualitt 6018dd688b7569df569a672a8a67b2db86a9d376cfcegdaniel m.setTranslate(SkIntToScalar(-resultBounds->fLeft), 6024c2443e36fdc6c095b17e90baa4a2f26a6f00b08bsalomon@google.com SkIntToScalar(-resultBounds->fTop)); 603b68addd39f3e7183facc70374a133e7a6fb603c5bsalomon@google.com 604b68addd39f3e7183facc70374a133e7a6fb603c5bsalomon@google.com drawState->setViewMatrix(m); 605b68addd39f3e7183facc70374a133e7a6fb603c5bsalomon@google.com } 606b68addd39f3e7183facc70374a133e7a6fb603c5bsalomon@google.com 607b68addd39f3e7183facc70374a133e7a6fb603c5bsalomon@google.com bool clearToInside; 608b68addd39f3e7183facc70374a133e7a6fb603c5bsalomon@google.com SkRegion::Op startOp = SkRegion::kReplace_Op; // suppress warning 609b68addd39f3e7183facc70374a133e7a6fb603c5bsalomon@google.com int start = process_initial_clip_elements(clipIn, 610b68addd39f3e7183facc70374a133e7a6fb603c5bsalomon@google.com *resultBounds, 611b68addd39f3e7183facc70374a133e7a6fb603c5bsalomon@google.com &clearToInside, 612b68addd39f3e7183facc70374a133e7a6fb603c5bsalomon@google.com &startOp); 6138dd688b7569df569a672a8a67b2db86a9d376cfcegdaniel 6148dd688b7569df569a672a8a67b2db86a9d376cfcegdaniel clear(gpu, accum, clearToInside ? 0xffffffff : 0x00000000); 6154c2443e36fdc6c095b17e90baa4a2f26a6f00b08bsalomon@google.com 6167b7cdd147f5528865238e5ed98c79e6d319fde9bbsalomon@google.com GrAutoScratchTexture temp; 6178dd688b7569df569a672a8a67b2db86a9d376cfcegdaniel 618e79f320ed6c5ec9f6164ba84be1ff586532e6517robertphillips@google.com // walk through each clip element and perform its set op 619e79f320ed6c5ec9f6164ba84be1ff586532e6517robertphillips@google.com for (int c = start; c < count; ++c) { 6204c2443e36fdc6c095b17e90baa4a2f26a6f00b08bsalomon@google.com 621f294b773f0b2b9f05eb45b52dd3cb4d97b96af06robertphillips@google.com SkRegion::Op op = (c == start) ? startOp : clipIn.getOp(c); 622b68addd39f3e7183facc70374a133e7a6fb603c5bsalomon@google.com 6238dd688b7569df569a672a8a67b2db86a9d376cfcegdaniel if (SkRegion::kReplace_Op == op) { 6248dd688b7569df569a672a8a67b2db86a9d376cfcegdaniel // TODO: replace is actually a lot faster then intersection 6258fc6c2d82c1f30ff82274334c01f0799def6a609joshualitt // for this path - refactor the stencil path so it can handle 626b68addd39f3e7183facc70374a133e7a6fb603c5bsalomon@google.com // replace ops and alter GrClip to allow them through 627b68addd39f3e7183facc70374a133e7a6fb603c5bsalomon@google.com 6288dd688b7569df569a672a8a67b2db86a9d376cfcegdaniel // clear the accumulator and draw the new object directly into it 6299853ccef19c200be93a6211f32589fa82a53067cjoshualitt clear(gpu, accum, 0x00000000); 630427cf28861867c0ea9aafca3a23878ec4068ad99bsalomon 631b68addd39f3e7183facc70374a133e7a6fb603c5bsalomon@google.com setup_boolean_blendcoeffs(drawState, op); 632b68addd39f3e7183facc70374a133e7a6fb603c5bsalomon@google.com this->drawClipShape(gpu, accum, clipIn, c); 633b68addd39f3e7183facc70374a133e7a6fb603c5bsalomon@google.com 634b68addd39f3e7183facc70374a133e7a6fb603c5bsalomon@google.com } else if (SkRegion::kReverseDifference_Op == op || 6358dd688b7569df569a672a8a67b2db86a9d376cfcegdaniel SkRegion::kIntersect_Op == op) { 6368dd688b7569df569a672a8a67b2db86a9d376cfcegdaniel // there is no point in intersecting a screen filling rectangle. 6378fc6c2d82c1f30ff82274334c01f0799def6a609joshualitt if (SkRegion::kIntersect_Op == op && 6388dd688b7569df569a672a8a67b2db86a9d376cfcegdaniel kRect_ClipType == clipIn.getElementType(c) && 639b68addd39f3e7183facc70374a133e7a6fb603c5bsalomon@google.com contains(clipIn.getRect(c), *resultBounds)) { 640b68addd39f3e7183facc70374a133e7a6fb603c5bsalomon@google.com continue; 641b68addd39f3e7183facc70374a133e7a6fb603c5bsalomon@google.com } 642b68addd39f3e7183facc70374a133e7a6fb603c5bsalomon@google.com 643b68addd39f3e7183facc70374a133e7a6fb603c5bsalomon@google.com getTemp(*resultBounds, &temp); 644b68addd39f3e7183facc70374a133e7a6fb603c5bsalomon@google.com if (NULL == temp.texture()) { 645b68addd39f3e7183facc70374a133e7a6fb603c5bsalomon@google.com fClipMaskInAlpha = false; 646b68addd39f3e7183facc70374a133e7a6fb603c5bsalomon@google.com fAACache.reset(); 6478dd688b7569df569a672a8a67b2db86a9d376cfcegdaniel return false; 6488750924a1470e8215b2a344155259b93062d3fa2egdaniel } 6498dd688b7569df569a672a8a67b2db86a9d376cfcegdaniel 6508059eb9f6e24ed609393fbda4ad71edea03ac258joshualitt // clear the temp target & draw into it 651b68addd39f3e7183facc70374a133e7a6fb603c5bsalomon@google.com clear(gpu, temp.texture(), 0x00000000); 652f294b773f0b2b9f05eb45b52dd3cb4d97b96af06robertphillips@google.com 6538dd688b7569df569a672a8a67b2db86a9d376cfcegdaniel setup_boolean_blendcoeffs(drawState, SkRegion::kReplace_Op); 6549853ccef19c200be93a6211f32589fa82a53067cjoshualitt this->drawClipShape(gpu, temp.texture(), clipIn, c); 655e79f320ed6c5ec9f6164ba84be1ff586532e6517robertphillips@google.com 6568dd688b7569df569a672a8a67b2db86a9d376cfcegdaniel // TODO: rather than adding these two translations here 6578750924a1470e8215b2a344155259b93062d3fa2egdaniel // compute the bounding box needed to render the texture 6588dd688b7569df569a672a8a67b2db86a9d376cfcegdaniel // into temp 659f294b773f0b2b9f05eb45b52dd3cb4d97b96af06robertphillips@google.com if (0 != resultBounds->fTop || 0 != resultBounds->fLeft) { 660f294b773f0b2b9f05eb45b52dd3cb4d97b96af06robertphillips@google.com GrMatrix m; 661f294b773f0b2b9f05eb45b52dd3cb4d97b96af06robertphillips@google.com 662c8f7f47afaf8f9471e6d111655c5610a8bd210a2bsalomon@google.com m.setTranslate(SkIntToScalar(resultBounds->fLeft), 6634c2443e36fdc6c095b17e90baa4a2f26a6f00b08bsalomon@google.com SkIntToScalar(resultBounds->fTop)); 6641e945b7e708c633d4aed937ebfce57d52ba21d83robertphillips@google.com 6651e945b7e708c633d4aed937ebfce57d52ba21d83robertphillips@google.com drawState->preConcatViewMatrix(m); 666f294b773f0b2b9f05eb45b52dd3cb4d97b96af06robertphillips@google.com } 667fbfcd5602128ec010c82cb733c9cdc0a3254f9f3rmistry@google.com 668f8d904a7eed435b9de68fd2eef6d7f3c59fcc9ccrobertphillips@google.com // Now draw into the accumulator using the real operation 6699853ccef19c200be93a6211f32589fa82a53067cjoshualitt // and the temp buffer as a texture 6709853ccef19c200be93a6211f32589fa82a53067cjoshualitt setup_boolean_blendcoeffs(drawState, op); 671bf54e49e30cdc92f9ce3f336cc48cf6b236ddeabtfarina this->drawTexture(gpu, accum, temp.texture()); 672bf54e49e30cdc92f9ce3f336cc48cf6b236ddeabtfarina 6734c2443e36fdc6c095b17e90baa4a2f26a6f00b08bsalomon@google.com if (0 != resultBounds->fTop || 0 != resultBounds->fLeft) { 6744c2443e36fdc6c095b17e90baa4a2f26a6f00b08bsalomon@google.com GrMatrix m; 675f6de475e5cbd143f348ff7738919e397b7fe7f57tfarina@chromium.org 67649f085dddff10473b6ebf832a974288300224e60bsalomon m.setTranslate(SkIntToScalar(-resultBounds->fLeft), 6771e945b7e708c633d4aed937ebfce57d52ba21d83robertphillips@google.com SkIntToScalar(-resultBounds->fTop)); 6786bc1b5fab8554a9cb643277b4867965dd4535cd6bsalomon 6791e945b7e708c633d4aed937ebfce57d52ba21d83robertphillips@google.com drawState->preConcatViewMatrix(m); 6801e945b7e708c633d4aed937ebfce57d52ba21d83robertphillips@google.com } 6811e945b7e708c633d4aed937ebfce57d52ba21d83robertphillips@google.com 6821e945b7e708c633d4aed937ebfce57d52ba21d83robertphillips@google.com } else { 683d3e5842db0cb169e10d6da1e62c94ba5cf182bb4commit-bot@chromium.org // all the remaining ops can just be directly draw into 684d3e5842db0cb169e10d6da1e62c94ba5cf182bb4commit-bot@chromium.org // the accumulation buffer 685137f1347abaf0bb6a945e91c2f6cb49f0ee69bc3bsalomon@google.com setup_boolean_blendcoeffs(drawState, op); 686137f1347abaf0bb6a945e91c2f6cb49f0ee69bc3bsalomon@google.com this->drawClipShape(gpu, accum, clipIn, c); 687137f1347abaf0bb6a945e91c2f6cb49f0ee69bc3bsalomon@google.com } 688137f1347abaf0bb6a945e91c2f6cb49f0ee69bc3bsalomon@google.com } 689137f1347abaf0bb6a945e91c2f6cb49f0ee69bc3bsalomon@google.com 6908059eb9f6e24ed609393fbda4ad71edea03ac258joshualitt *result = accum; 6918059eb9f6e24ed609393fbda4ad71edea03ac258joshualitt 6921e945b7e708c633d4aed937ebfce57d52ba21d83robertphillips@google.com return true; 6939f13174da5295e88d447f29740318003b9cec9c3bsalomon@google.com} 6949f13174da5295e88d447f29740318003b9cec9c3bsalomon@google.com 6959f13174da5295e88d447f29740318003b9cec9c3bsalomon@google.com//////////////////////////////////////////////////////////////////////////////// 696329bf4862e9d5e05363c2b071d8ca475a0ef1952joshualitt// Create a 1-bit clip mask in the stencil buffer 6971e945b7e708c633d4aed937ebfce57d52ba21d83robertphillips@google.combool GrClipMaskManager::createStencilClipMask(GrGpu* gpu, 6981e945b7e708c633d4aed937ebfce57d52ba21d83robertphillips@google.com const GrClip& clipIn, 6994c2443e36fdc6c095b17e90baa4a2f26a6f00b08bsalomon@google.com const GrRect& bounds, 7001e945b7e708c633d4aed937ebfce57d52ba21d83robertphillips@google.com ScissoringSettings* scissorSettings) { 7011e945b7e708c633d4aed937ebfce57d52ba21d83robertphillips@google.com 702329bf4862e9d5e05363c2b071d8ca475a0ef1952joshualitt GrAssert(fClipMaskInStencil); 703329bf4862e9d5e05363c2b071d8ca475a0ef1952joshualitt 704329bf4862e9d5e05363c2b071d8ca475a0ef1952joshualitt GrDrawState* drawState = gpu->drawState(); 7051e945b7e708c633d4aed937ebfce57d52ba21d83robertphillips@google.com GrAssert(drawState->isClipState()); 7061e945b7e708c633d4aed937ebfce57d52ba21d83robertphillips@google.com 7071e945b7e708c633d4aed937ebfce57d52ba21d83robertphillips@google.com GrRenderTarget* rt = drawState->getRenderTarget(); 708bf54e49e30cdc92f9ce3f336cc48cf6b236ddeabtfarina GrAssert(NULL != rt); 7094c2443e36fdc6c095b17e90baa4a2f26a6f00b08bsalomon@google.com 7109853ccef19c200be93a6211f32589fa82a53067cjoshualitt // TODO: dynamically attach a SB when needed. 7118dd688b7569df569a672a8a67b2db86a9d376cfcegdaniel GrStencilBuffer* stencilBuffer = rt->getStencilBuffer(); 7128dd688b7569df569a672a8a67b2db86a9d376cfcegdaniel if (NULL == stencilBuffer) { 713080e673b10ac607305f140ddb245e140ccde40c6egdaniel return false; 7148dd688b7569df569a672a8a67b2db86a9d376cfcegdaniel } 7159853ccef19c200be93a6211f32589fa82a53067cjoshualitt 716ded4f4b163f5aa19c22c871178c55ecb34623846bsalomon@google.com if (stencilBuffer->mustRenderClip(clipIn, rt->width(), rt->height())) { 717ded4f4b163f5aa19c22c871178c55ecb34623846bsalomon@google.com 7188dd688b7569df569a672a8a67b2db86a9d376cfcegdaniel stencilBuffer->setLastClip(clipIn, rt->width(), rt->height()); 719ded4f4b163f5aa19c22c871178c55ecb34623846bsalomon@google.com 7201e945b7e708c633d4aed937ebfce57d52ba21d83robertphillips@google.com // we set the current clip to the bounds so that our recursive 7219853ccef19c200be93a6211f32589fa82a53067cjoshualitt // draws are scissored to them. We use the copy of the complex clip 7229853ccef19c200be93a6211f32589fa82a53067cjoshualitt // we just stashed on the SB to render from. We set it back after 7239853ccef19c200be93a6211f32589fa82a53067cjoshualitt // we finish drawing it into the stencil. 7249853ccef19c200be93a6211f32589fa82a53067cjoshualitt const GrClip& clipCopy = stencilBuffer->getLastClip(); 72545a15f551b5b3c6c747d8eaf6466b7d3b76a8faebsalomon@google.com gpu->setClip(GrClip(bounds)); 72645a15f551b5b3c6c747d8eaf6466b7d3b76a8faebsalomon@google.com 72745a15f551b5b3c6c747d8eaf6466b7d3b76a8faebsalomon@google.com GrDrawTarget::AutoStateRestore asr(gpu, GrDrawTarget::kReset_ASRInit); 7281e945b7e708c633d4aed937ebfce57d52ba21d83robertphillips@google.com drawState = gpu->drawState(); 7295f74cf8c49701f514b69dc6f1a8b5c0ffd78af0asugoi@google.com drawState->setRenderTarget(rt); 7308182fa0cac76e7e6d583aebba060229230516887bsalomon@google.com GrDrawTarget::AutoGeometryPush agp(gpu); 731f294b773f0b2b9f05eb45b52dd3cb4d97b96af06robertphillips@google.com 732e79f320ed6c5ec9f6164ba84be1ff586532e6517robertphillips@google.com gpu->disableScissor(); 733e5b2af955b7d06815ddd405659ad62a2a8355ca3commit-bot@chromium.org#if !VISUALIZE_COMPLEX_CLIP 7348182fa0cac76e7e6d583aebba060229230516887bsalomon@google.com drawState->enableState(GrDrawState::kNoColorWrites_StateBit); 73545a15f551b5b3c6c747d8eaf6466b7d3b76a8faebsalomon@google.com#endif 7361e945b7e708c633d4aed937ebfce57d52ba21d83robertphillips@google.com 7378afae61a57f87e4a50578effce6c428031499301tomhudson@google.com int count = clipCopy.getElementCount(); 738e5b2af955b7d06815ddd405659ad62a2a8355ca3commit-bot@chromium.org int clipBit = stencilBuffer->bits(); 739e5b2af955b7d06815ddd405659ad62a2a8355ca3commit-bot@chromium.org SkASSERT((clipBit <= 16) && 740e79f320ed6c5ec9f6164ba84be1ff586532e6517robertphillips@google.com "Ganesh only handles 16b or smaller stencil buffers"); 741e5b2af955b7d06815ddd405659ad62a2a8355ca3commit-bot@chromium.org clipBit = (1 << (clipBit-1)); 742e79f320ed6c5ec9f6164ba84be1ff586532e6517robertphillips@google.com 7439853ccef19c200be93a6211f32589fa82a53067cjoshualitt GrIRect rtRect = GrIRect::MakeWH(rt->width(), rt->height()); 7448dd688b7569df569a672a8a67b2db86a9d376cfcegdaniel 7458059eb9f6e24ed609393fbda4ad71edea03ac258joshualitt bool clearToInside; 7469853ccef19c200be93a6211f32589fa82a53067cjoshualitt SkRegion::Op startOp = SkRegion::kReplace_Op; // suppress warning 74745a15f551b5b3c6c747d8eaf6466b7d3b76a8faebsalomon@google.com int start = process_initial_clip_elements(clipCopy, 74845a15f551b5b3c6c747d8eaf6466b7d3b76a8faebsalomon@google.com rtRect, 74945a15f551b5b3c6c747d8eaf6466b7d3b76a8faebsalomon@google.com &clearToInside, 750e79f320ed6c5ec9f6164ba84be1ff586532e6517robertphillips@google.com &startOp); 751e79f320ed6c5ec9f6164ba84be1ff586532e6517robertphillips@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; 75945a15f551b5b3c6c747d8eaf6466b7d3b76a8faebsalomon@google.com // enabled at bottom of loop 76045a15f551b5b3c6c747d8eaf6466b7d3b76a8faebsalomon@google.com drawState->disableState(GrGpu::kModifyStencilClip_StateBit); 7611e945b7e708c633d4aed937ebfce57d52ba21d83robertphillips@google.com 7624c2443e36fdc6c095b17e90baa4a2f26a6f00b08bsalomon@google.com bool canRenderDirectToStencil; // can the clip element be drawn 7634c2443e36fdc6c095b17e90baa4a2f26a6f00b08bsalomon@google.com // directly to the stencil buffer 7644c2443e36fdc6c095b17e90baa4a2f26a6f00b08bsalomon@google.com // with a non-inverted fill rule 7654c2443e36fdc6c095b17e90baa4a2f26a6f00b08bsalomon@google.com // without extra passes to 7664c2443e36fdc6c095b17e90baa4a2f26a6f00b08bsalomon@google.com // resolve in/out status. 7674c2443e36fdc6c095b17e90baa4a2f26a6f00b08bsalomon@google.com 7684c2443e36fdc6c095b17e90baa4a2f26a6f00b08bsalomon@google.com SkRegion::Op op = (c == start) ? startOp : clipCopy.getOp(c); 7694c2443e36fdc6c095b17e90baa4a2f26a6f00b08bsalomon@google.com 7704c2443e36fdc6c095b17e90baa4a2f26a6f00b08bsalomon@google.com GrPathRenderer* pr = NULL; 7711e945b7e708c633d4aed937ebfce57d52ba21d83robertphillips@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; 7754c2443e36fdc6c095b17e90baa4a2f26a6f00b08bsalomon@google.com fillInverted = false; 7764c2443e36fdc6c095b17e90baa4a2f26a6f00b08bsalomon@google.com // there is no point in intersecting a screen filling 7774c2443e36fdc6c095b17e90baa4a2f26a6f00b08bsalomon@google.com // rectangle. 7784c2443e36fdc6c095b17e90baa4a2f26a6f00b08bsalomon@google.com if (SkRegion::kIntersect_Op == op && 7794c2443e36fdc6c095b17e90baa4a2f26a6f00b08bsalomon@google.com contains(clipCopy.getRect(c), rtRect)) { 7804c2443e36fdc6c095b17e90baa4a2f26a6f00b08bsalomon@google.com continue; 7818182fa0cac76e7e6d583aebba060229230516887bsalomon@google.com } 7828dd688b7569df569a672a8a67b2db86a9d376cfcegdaniel } else { 7838dd688b7569df569a672a8a67b2db86a9d376cfcegdaniel fill = clipCopy.getPathFill(c); 7848059eb9f6e24ed609393fbda4ad71edea03ac258joshualitt fillInverted = GrIsFillInverted(fill); 7851e945b7e708c633d4aed937ebfce57d52ba21d83robertphillips@google.com fill = GrNonInvertedFill(fill); 786e5b2af955b7d06815ddd405659ad62a2a8355ca3commit-bot@chromium.org clipPath = &clipCopy.getPath(c); 7879853ccef19c200be93a6211f32589fa82a53067cjoshualitt pr = this->getContext()->getPathRenderer(*clipPath, 78819dd017a6256be636ccb550752bb563c4e7caeb5commit-bot@chromium.org fill, gpu, false, 7898dd688b7569df569a672a8a67b2db86a9d376cfcegdaniel true); 7908dd688b7569df569a672a8a67b2db86a9d376cfcegdaniel if (NULL == pr) { 7918059eb9f6e24ed609393fbda4ad71edea03ac258joshualitt fClipMaskInStencil = false; 79219dd017a6256be636ccb550752bb563c4e7caeb5commit-bot@chromium.org gpu->setClip(clipCopy); // restore to the original 7938dd688b7569df569a672a8a67b2db86a9d376cfcegdaniel return false; 7948dd688b7569df569a672a8a67b2db86a9d376cfcegdaniel } 79519dd017a6256be636ccb550752bb563c4e7caeb5commit-bot@chromium.org 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 8027a6184fdf717a1da0c6e1e37b942b17fdaa236d3joshualitt bool canDrawDirectToClip; // Given the renderer, the element, 8031e945b7e708c633d4aed937ebfce57d52ba21d83robertphillips@google.com // fill rule, and set operation can 8048dd688b7569df569a672a8a67b2db86a9d376cfcegdaniel // we render the element directly to 8058dd688b7569df569a672a8a67b2db86a9d376cfcegdaniel // stencil bit used for clipping. 8069853ccef19c200be93a6211f32589fa82a53067cjoshualitt canDrawDirectToClip = 8071e945b7e708c633d4aed937ebfce57d52ba21d83robertphillips@google.com GrStencilSettings::GetClipPasses(op, 8088182fa0cac76e7e6d583aebba060229230516887bsalomon@google.com canRenderDirectToStencil, 8098dd688b7569df569a672a8a67b2db86a9d376cfcegdaniel clipBit, 8102e3b3e369d79e78f7635d4c20e83a47ab571bdf2joshualitt fillInverted, 8111e945b7e708c633d4aed937ebfce57d52ba21d83robertphillips@google.com &passes, stencilSettings); 8129853ccef19c200be93a6211f32589fa82a53067cjoshualitt 8138dd688b7569df569a672a8a67b2db86a9d376cfcegdaniel // draw the element to the client stencil bits if necessary 8148059eb9f6e24ed609393fbda4ad71edea03ac258joshualitt if (!canDrawDirectToClip) { 8151e945b7e708c633d4aed937ebfce57d52ba21d83robertphillips@google.com GR_STATIC_CONST_SAME_STENCIL(gDrawToStencil, 8161e945b7e708c633d4aed937ebfce57d52ba21d83robertphillips@google.com kIncClamp_StencilOp, 8174c2443e36fdc6c095b17e90baa4a2f26a6f00b08bsalomon@google.com kIncClamp_StencilOp, 8184c2443e36fdc6c095b17e90baa4a2f26a6f00b08bsalomon@google.com kAlways_StencilFunc, 8198dd688b7569df569a672a8a67b2db86a9d376cfcegdaniel 0xffff, 8202e3b3e369d79e78f7635d4c20e83a47ab571bdf2joshualitt 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; 825c8f7f47afaf8f9471e6d111655c5610a8bd210a2bsalomon@google.com gpu->drawSimpleRect(clipCopy.getRect(c), NULL, 0); 826f6de475e5cbd143f348ff7738919e397b7fe7f57tfarina@chromium.org } else { 827c8f7f47afaf8f9471e6d111655c5610a8bd210a2bsalomon@google.com if (canRenderDirectToStencil) { 8287a6184fdf717a1da0c6e1e37b942b17fdaa236d3joshualitt *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); 832411dad0630913fc07f2412b4be17acfbfd914fbcbsalomon@google.com } 833411dad0630913fc07f2412b4be17acfbfd914fbcbsalomon@google.com } 834fbfcd5602128ec010c82cb733c9cdc0a3254f9f3rmistry@google.com } 835411dad0630913fc07f2412b4be17acfbfd914fbcbsalomon@google.com 836411dad0630913fc07f2412b4be17acfbfd914fbcbsalomon@google.com // now we modify the clip bit by rendering either the clip 837411dad0630913fc07f2412b4be17acfbfd914fbcbsalomon@google.com // element directly or a bounding rect of the entire clip. 838411dad0630913fc07f2412b4be17acfbfd914fbcbsalomon@google.com drawState->enableState(GrGpu::kModifyStencilClip_StateBit); 839411dad0630913fc07f2412b4be17acfbfd914fbcbsalomon@google.com for (int p = 0; p < passes; ++p) { 840411dad0630913fc07f2412b4be17acfbfd914fbcbsalomon@google.com *drawState->stencil() = stencilSettings[p]; 841411dad0630913fc07f2412b4be17acfbfd914fbcbsalomon@google.com if (canDrawDirectToClip) { 842411dad0630913fc07f2412b4be17acfbfd914fbcbsalomon@google.com if (kRect_ClipType == clipCopy.getElementType(c)) { 843411dad0630913fc07f2412b4be17acfbfd914fbcbsalomon@google.com SET_RANDOM_COLOR 844411dad0630913fc07f2412b4be17acfbfd914fbcbsalomon@google.com gpu->drawSimpleRect(clipCopy.getRect(c), NULL, 0); 845411dad0630913fc07f2412b4be17acfbfd914fbcbsalomon@google.com } else { 846411dad0630913fc07f2412b4be17acfbfd914fbcbsalomon@google.com SET_RANDOM_COLOR 847411dad0630913fc07f2412b4be17acfbfd914fbcbsalomon@google.com pr->drawPath(*clipPath, fill, NULL, gpu, 0, false); 848411dad0630913fc07f2412b4be17acfbfd914fbcbsalomon@google.com } 849411dad0630913fc07f2412b4be17acfbfd914fbcbsalomon@google.com } else { 850411dad0630913fc07f2412b4be17acfbfd914fbcbsalomon@google.com SET_RANDOM_COLOR 851411dad0630913fc07f2412b4be17acfbfd914fbcbsalomon@google.com gpu->drawSimpleRect(bounds, NULL, 0); 852411dad0630913fc07f2412b4be17acfbfd914fbcbsalomon@google.com } 853411dad0630913fc07f2412b4be17acfbfd914fbcbsalomon@google.com } 854411dad0630913fc07f2412b4be17acfbfd914fbcbsalomon@google.com } 855411dad0630913fc07f2412b4be17acfbfd914fbcbsalomon@google.com // restore clip 856411dad0630913fc07f2412b4be17acfbfd914fbcbsalomon@google.com gpu->setClip(clipCopy); 857411dad0630913fc07f2412b4be17acfbfd914fbcbsalomon@google.com // recusive draws would have disabled this since they drew with 858411dad0630913fc07f2412b4be17acfbfd914fbcbsalomon@google.com // the clip bounds as clip. 859411dad0630913fc07f2412b4be17acfbfd914fbcbsalomon@google.com fClipMaskInStencil = true; 860411dad0630913fc07f2412b4be17acfbfd914fbcbsalomon@google.com } 861411dad0630913fc07f2412b4be17acfbfd914fbcbsalomon@google.com 862411dad0630913fc07f2412b4be17acfbfd914fbcbsalomon@google.com return true; 863411dad0630913fc07f2412b4be17acfbfd914fbcbsalomon@google.com} 864411dad0630913fc07f2412b4be17acfbfd914fbcbsalomon@google.com 865411dad0630913fc07f2412b4be17acfbfd914fbcbsalomon@google.comnamespace { 866411dad0630913fc07f2412b4be17acfbfd914fbcbsalomon@google.com 867411dad0630913fc07f2412b4be17acfbfd914fbcbsalomon@google.comGrPathFill invert_fill(GrPathFill fill) { 868a320194e4242ef0e5e758aea896bfd52bcb3dac7bsalomon@google.com static const GrPathFill gInvertedFillTable[] = { 869a320194e4242ef0e5e758aea896bfd52bcb3dac7bsalomon@google.com kInverseWinding_PathFill, // kWinding_PathFill 870a320194e4242ef0e5e758aea896bfd52bcb3dac7bsalomon@google.com kInverseEvenOdd_PathFill, // kEvenOdd_PathFill 871a320194e4242ef0e5e758aea896bfd52bcb3dac7bsalomon@google.com kWinding_PathFill, // kInverseWinding_PathFill 872a320194e4242ef0e5e758aea896bfd52bcb3dac7bsalomon@google.com kEvenOdd_PathFill, // kInverseEvenOdd_PathFill 873a320194e4242ef0e5e758aea896bfd52bcb3dac7bsalomon@google.com kHairLine_PathFill, // kHairLine_PathFill 874a320194e4242ef0e5e758aea896bfd52bcb3dac7bsalomon@google.com }; 875a320194e4242ef0e5e758aea896bfd52bcb3dac7bsalomon@google.com GR_STATIC_ASSERT(0 == kWinding_PathFill); 876a320194e4242ef0e5e758aea896bfd52bcb3dac7bsalomon@google.com GR_STATIC_ASSERT(1 == kEvenOdd_PathFill); 877a320194e4242ef0e5e758aea896bfd52bcb3dac7bsalomon@google.com GR_STATIC_ASSERT(2 == kInverseWinding_PathFill); 878a320194e4242ef0e5e758aea896bfd52bcb3dac7bsalomon@google.com GR_STATIC_ASSERT(3 == kInverseEvenOdd_PathFill); 879fbfcd5602128ec010c82cb733c9cdc0a3254f9f3rmistry@google.com GR_STATIC_ASSERT(4 == kHairLine_PathFill); 880a320194e4242ef0e5e758aea896bfd52bcb3dac7bsalomon@google.com GR_STATIC_ASSERT(5 == kPathFillCount); 881a320194e4242ef0e5e758aea896bfd52bcb3dac7bsalomon@google.com return gInvertedFillTable[fill]; 882a320194e4242ef0e5e758aea896bfd52bcb3dac7bsalomon@google.com} 883a320194e4242ef0e5e758aea896bfd52bcb3dac7bsalomon@google.com 8848dd688b7569df569a672a8a67b2db86a9d376cfcegdaniel} 8858dd688b7569df569a672a8a67b2db86a9d376cfcegdaniel 886a320194e4242ef0e5e758aea896bfd52bcb3dac7bsalomon@google.com//////////////////////////////////////////////////////////////////////////////// 887a320194e4242ef0e5e758aea896bfd52bcb3dac7bsalomon@google.combool GrClipMaskManager::createSoftwareClipMask(GrGpu* gpu, 888a320194e4242ef0e5e758aea896bfd52bcb3dac7bsalomon@google.com const GrClip& clipIn, 889a320194e4242ef0e5e758aea896bfd52bcb3dac7bsalomon@google.com GrTexture** result, 890a320194e4242ef0e5e758aea896bfd52bcb3dac7bsalomon@google.com GrIRect *resultBounds) { 891a320194e4242ef0e5e758aea896bfd52bcb3dac7bsalomon@google.com 892a320194e4242ef0e5e758aea896bfd52bcb3dac7bsalomon@google.com if (this->clipMaskPreamble(gpu, clipIn, result, resultBounds)) { 893a320194e4242ef0e5e758aea896bfd52bcb3dac7bsalomon@google.com return true; 8949853ccef19c200be93a6211f32589fa82a53067cjoshualitt } 895a320194e4242ef0e5e758aea896bfd52bcb3dac7bsalomon@google.com 896a320194e4242ef0e5e758aea896bfd52bcb3dac7bsalomon@google.com GrTexture* accum = fAACache.getLastMask(); 8978dd688b7569df569a672a8a67b2db86a9d376cfcegdaniel if (NULL == accum) { 8987a6184fdf717a1da0c6e1e37b942b17fdaa236d3joshualitt fClipMaskInAlpha = false; 899a320194e4242ef0e5e758aea896bfd52bcb3dac7bsalomon@google.com fAACache.reset(); 900a320194e4242ef0e5e758aea896bfd52bcb3dac7bsalomon@google.com return false; 901a320194e4242ef0e5e758aea896bfd52bcb3dac7bsalomon@google.com } 902a320194e4242ef0e5e758aea896bfd52bcb3dac7bsalomon@google.com 903a320194e4242ef0e5e758aea896bfd52bcb3dac7bsalomon@google.com GrSWMaskHelper helper(this->getContext()); 9048dd688b7569df569a672a8a67b2db86a9d376cfcegdaniel 905a320194e4242ef0e5e758aea896bfd52bcb3dac7bsalomon@google.com helper.init(*resultBounds, NULL, false); 906a320194e4242ef0e5e758aea896bfd52bcb3dac7bsalomon@google.com 907a320194e4242ef0e5e758aea896bfd52bcb3dac7bsalomon@google.com int count = clipIn.getElementCount(); 9086bc1b5fab8554a9cb643277b4867965dd4535cd6bsalomon 9096bc1b5fab8554a9cb643277b4867965dd4535cd6bsalomon bool clearToInside; 91049f085dddff10473b6ebf832a974288300224e60bsalomon SkRegion::Op startOp = SkRegion::kReplace_Op; // suppress warning 911a320194e4242ef0e5e758aea896bfd52bcb3dac7bsalomon@google.com int start = process_initial_clip_elements(clipIn, 912a320194e4242ef0e5e758aea896bfd52bcb3dac7bsalomon@google.com *resultBounds, 913a320194e4242ef0e5e758aea896bfd52bcb3dac7bsalomon@google.com &clearToInside, 914329bf4862e9d5e05363c2b071d8ca475a0ef1952joshualitt &startOp); 915329bf4862e9d5e05363c2b071d8ca475a0ef1952joshualitt 9167a6184fdf717a1da0c6e1e37b942b17fdaa236d3joshualitt helper.clear(clearToInside ? SK_ColorWHITE : 0x00000000); 9178dd688b7569df569a672a8a67b2db86a9d376cfcegdaniel 9188dd688b7569df569a672a8a67b2db86a9d376cfcegdaniel for (int i = start; i < count; ++i) { 919a320194e4242ef0e5e758aea896bfd52bcb3dac7bsalomon@google.com 920a320194e4242ef0e5e758aea896bfd52bcb3dac7bsalomon@google.com SkRegion::Op op = (i == start) ? startOp : clipIn.getOp(i); 921a320194e4242ef0e5e758aea896bfd52bcb3dac7bsalomon@google.com 922a320194e4242ef0e5e758aea896bfd52bcb3dac7bsalomon@google.com if (SkRegion::kIntersect_Op == op || 923a320194e4242ef0e5e758aea896bfd52bcb3dac7bsalomon@google.com SkRegion::kReverseDifference_Op == op) { 924f6de475e5cbd143f348ff7738919e397b7fe7f57tfarina@chromium.org // Intersect and reverse difference require modifying pixels 925411dad0630913fc07f2412b4be17acfbfd914fbcbsalomon@google.com // outside of the geometry that is being "drawn". In both cases 926411dad0630913fc07f2412b4be17acfbfd914fbcbsalomon@google.com // we erase all the pixels outside of the geometry but 927a320194e4242ef0e5e758aea896bfd52bcb3dac7bsalomon@google.com // leave the pixels inside the geometry alone. For reverse 928a320194e4242ef0e5e758aea896bfd52bcb3dac7bsalomon@google.com // difference we invert all the pixels before clearing the ones 929a320194e4242ef0e5e758aea896bfd52bcb3dac7bsalomon@google.com // outside the geometry. 930411dad0630913fc07f2412b4be17acfbfd914fbcbsalomon@google.com if (SkRegion::kReverseDifference_Op == op) { 931a320194e4242ef0e5e758aea896bfd52bcb3dac7bsalomon@google.com SkRect temp = SkRect::MakeLTRB( 932411dad0630913fc07f2412b4be17acfbfd914fbcbsalomon@google.com SkIntToScalar(resultBounds->left()), 933411dad0630913fc07f2412b4be17acfbfd914fbcbsalomon@google.com SkIntToScalar(resultBounds->top()), 934411dad0630913fc07f2412b4be17acfbfd914fbcbsalomon@google.com SkIntToScalar(resultBounds->right()), 935a320194e4242ef0e5e758aea896bfd52bcb3dac7bsalomon@google.com SkIntToScalar(resultBounds->bottom())); 936329bf4862e9d5e05363c2b071d8ca475a0ef1952joshualitt 937a320194e4242ef0e5e758aea896bfd52bcb3dac7bsalomon@google.com // invert the entire scene 938a320194e4242ef0e5e758aea896bfd52bcb3dac7bsalomon@google.com helper.draw(temp, SkRegion::kXOR_Op, false, SK_ColorWHITE); 939a320194e4242ef0e5e758aea896bfd52bcb3dac7bsalomon@google.com } 940a320194e4242ef0e5e758aea896bfd52bcb3dac7bsalomon@google.com 941a320194e4242ef0e5e758aea896bfd52bcb3dac7bsalomon@google.com if (kRect_ClipType == clipIn.getElementType(i)) { 942a320194e4242ef0e5e758aea896bfd52bcb3dac7bsalomon@google.com 943a320194e4242ef0e5e758aea896bfd52bcb3dac7bsalomon@google.com // convert the rect to a path so we can invert the fill 944a320194e4242ef0e5e758aea896bfd52bcb3dac7bsalomon@google.com SkPath temp; 945f6de475e5cbd143f348ff7738919e397b7fe7f57tfarina@chromium.org temp.addRect(clipIn.getRect(i)); 946a320194e4242ef0e5e758aea896bfd52bcb3dac7bsalomon@google.com 947a320194e4242ef0e5e758aea896bfd52bcb3dac7bsalomon@google.com helper.draw(temp, SkRegion::kReplace_Op, 948a320194e4242ef0e5e758aea896bfd52bcb3dac7bsalomon@google.com kInverseEvenOdd_PathFill, clipIn.getDoAA(i), 949a320194e4242ef0e5e758aea896bfd52bcb3dac7bsalomon@google.com 0x00000000); 950a320194e4242ef0e5e758aea896bfd52bcb3dac7bsalomon@google.com } else { 951a320194e4242ef0e5e758aea896bfd52bcb3dac7bsalomon@google.com GrAssert(kPath_ClipType == clipIn.getElementType(i)); 952a320194e4242ef0e5e758aea896bfd52bcb3dac7bsalomon@google.com 953f6de475e5cbd143f348ff7738919e397b7fe7f57tfarina@chromium.org helper.draw(clipIn.getPath(i), 954a320194e4242ef0e5e758aea896bfd52bcb3dac7bsalomon@google.com SkRegion::kReplace_Op, 955a320194e4242ef0e5e758aea896bfd52bcb3dac7bsalomon@google.com invert_fill(clipIn.getPathFill(i)), 956a320194e4242ef0e5e758aea896bfd52bcb3dac7bsalomon@google.com clipIn.getDoAA(i), 957a320194e4242ef0e5e758aea896bfd52bcb3dac7bsalomon@google.com 0x00000000); 958a320194e4242ef0e5e758aea896bfd52bcb3dac7bsalomon@google.com } 959a320194e4242ef0e5e758aea896bfd52bcb3dac7bsalomon@google.com 960a320194e4242ef0e5e758aea896bfd52bcb3dac7bsalomon@google.com continue; 961a320194e4242ef0e5e758aea896bfd52bcb3dac7bsalomon@google.com } 962a320194e4242ef0e5e758aea896bfd52bcb3dac7bsalomon@google.com 963a320194e4242ef0e5e758aea896bfd52bcb3dac7bsalomon@google.com // The other ops (union, xor, diff) only affect pixels inside 964a320194e4242ef0e5e758aea896bfd52bcb3dac7bsalomon@google.com // the geometry so they can just be drawn normally 965a320194e4242ef0e5e758aea896bfd52bcb3dac7bsalomon@google.com if (kRect_ClipType == clipIn.getElementType(i)) { 966a320194e4242ef0e5e758aea896bfd52bcb3dac7bsalomon@google.com 967a320194e4242ef0e5e758aea896bfd52bcb3dac7bsalomon@google.com helper.draw(clipIn.getRect(i), 968a320194e4242ef0e5e758aea896bfd52bcb3dac7bsalomon@google.com op, 969a320194e4242ef0e5e758aea896bfd52bcb3dac7bsalomon@google.com clipIn.getDoAA(i), SK_ColorWHITE); 97088cb22b6b4816c7a9ca6c5b795965b4606f9eb7bcommit-bot@chromium.org 971a320194e4242ef0e5e758aea896bfd52bcb3dac7bsalomon@google.com } else { 972a320194e4242ef0e5e758aea896bfd52bcb3dac7bsalomon@google.com GrAssert(kPath_ClipType == clipIn.getElementType(i)); 973a320194e4242ef0e5e758aea896bfd52bcb3dac7bsalomon@google.com 974a320194e4242ef0e5e758aea896bfd52bcb3dac7bsalomon@google.com helper.draw(clipIn.getPath(i), 975411dad0630913fc07f2412b4be17acfbfd914fbcbsalomon@google.com op, 976fbfcd5602128ec010c82cb733c9cdc0a3254f9f3rmistry@google.com clipIn.getPathFill(i), 977a320194e4242ef0e5e758aea896bfd52bcb3dac7bsalomon@google.com clipIn.getDoAA(i), SK_ColorWHITE); 978a320194e4242ef0e5e758aea896bfd52bcb3dac7bsalomon@google.com } 979f6de475e5cbd143f348ff7738919e397b7fe7f57tfarina@chromium.org } 980411dad0630913fc07f2412b4be17acfbfd914fbcbsalomon@google.com 981a320194e4242ef0e5e758aea896bfd52bcb3dac7bsalomon@google.com // Because we are using the scratch texture cache, "accum" may be 982a320194e4242ef0e5e758aea896bfd52bcb3dac7bsalomon@google.com // larger than expected and have some cruft in the areas we aren't using. 983411dad0630913fc07f2412b4be17acfbfd914fbcbsalomon@google.com // Clear it out. 984a320194e4242ef0e5e758aea896bfd52bcb3dac7bsalomon@google.com 985a320194e4242ef0e5e758aea896bfd52bcb3dac7bsalomon@google.com // TODO: need a simpler way to clear the texture - can we combine 986a320194e4242ef0e5e758aea896bfd52bcb3dac7bsalomon@google.com // the clear and the writePixels (inside toTexture) 987a320194e4242ef0e5e758aea896bfd52bcb3dac7bsalomon@google.com GrDrawState* drawState = gpu->drawState(); 988a320194e4242ef0e5e758aea896bfd52bcb3dac7bsalomon@google.com GrAssert(NULL != drawState); 989a320194e4242ef0e5e758aea896bfd52bcb3dac7bsalomon@google.com GrRenderTarget* temp = drawState->getRenderTarget(); 990a320194e4242ef0e5e758aea896bfd52bcb3dac7bsalomon@google.com clear(gpu, accum, 0x00000000); 991a320194e4242ef0e5e758aea896bfd52bcb3dac7bsalomon@google.com // can't leave the accum bound as a rendertarget 992a320194e4242ef0e5e758aea896bfd52bcb3dac7bsalomon@google.com drawState->setRenderTarget(temp); 993a320194e4242ef0e5e758aea896bfd52bcb3dac7bsalomon@google.com 994a320194e4242ef0e5e758aea896bfd52bcb3dac7bsalomon@google.com helper.toTexture(accum); 995a320194e4242ef0e5e758aea896bfd52bcb3dac7bsalomon@google.com 996a320194e4242ef0e5e758aea896bfd52bcb3dac7bsalomon@google.com *result = accum; 997a320194e4242ef0e5e758aea896bfd52bcb3dac7bsalomon@google.com 998a320194e4242ef0e5e758aea896bfd52bcb3dac7bsalomon@google.com return true; 999411dad0630913fc07f2412b4be17acfbfd914fbcbsalomon@google.com} 1000411dad0630913fc07f2412b4be17acfbfd914fbcbsalomon@google.com 1001411dad0630913fc07f2412b4be17acfbfd914fbcbsalomon@google.com//////////////////////////////////////////////////////////////////////////////// 1002411dad0630913fc07f2412b4be17acfbfd914fbcbsalomon@google.comvoid GrClipMaskManager::releaseResources() { 1003d3e5842db0cb169e10d6da1e62c94ba5cf182bb4commit-bot@chromium.org fAACache.releaseResources(); 10044c2443e36fdc6c095b17e90baa4a2f26a6f00b08bsalomon@google.com} 10054c2443e36fdc6c095b17e90baa4a2f26a6f00b08bsalomon@google.com