GrClipMaskManager.cpp revision 5acc0e36d987dff3172fd45a14b66c52a51d49e4
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"
16a72eef322c686954cdffa849dc26d8133b802f1drobertphillips@google.com
17a72eef322c686954cdffa849dc26d8133b802f1drobertphillips@google.com//#define GR_AA_CLIP 1
186b70a7bd3328ea0a12be47b1a7f835c905f16147robertphillips@google.com//#define GR_SW_CLIP 1
19a72eef322c686954cdffa849dc26d8133b802f1drobertphillips@google.com
20f294b773f0b2b9f05eb45b52dd3cb4d97b96af06robertphillips@google.com////////////////////////////////////////////////////////////////////////////////
211e945b7e708c633d4aed937ebfce57d52ba21d83robertphillips@google.comvoid ScissoringSettings::setupScissoring(GrGpu* gpu) {
221e945b7e708c633d4aed937ebfce57d52ba21d83robertphillips@google.com    if (!fEnableScissoring) {
231e945b7e708c633d4aed937ebfce57d52ba21d83robertphillips@google.com        gpu->disableScissor();
241e945b7e708c633d4aed937ebfce57d52ba21d83robertphillips@google.com        return;
251e945b7e708c633d4aed937ebfce57d52ba21d83robertphillips@google.com    }
261e945b7e708c633d4aed937ebfce57d52ba21d83robertphillips@google.com
271e945b7e708c633d4aed937ebfce57d52ba21d83robertphillips@google.com    gpu->enableScissoring(fScissorRect);
281e945b7e708c633d4aed937ebfce57d52ba21d83robertphillips@google.com}
291e945b7e708c633d4aed937ebfce57d52ba21d83robertphillips@google.com
30a72eef322c686954cdffa849dc26d8133b802f1drobertphillips@google.comnamespace {
31a72eef322c686954cdffa849dc26d8133b802f1drobertphillips@google.com// set up the draw state to enable the aa clipping mask. Besides setting up the
32a72eef322c686954cdffa849dc26d8133b802f1drobertphillips@google.com// sampler matrix this also alters the vertex layout
336b70a7bd3328ea0a12be47b1a7f835c905f16147robertphillips@google.comvoid setup_drawstate_aaclip(GrGpu* gpu,
346b70a7bd3328ea0a12be47b1a7f835c905f16147robertphillips@google.com                            GrTexture* result,
356623fcd1ee33b35fa18e304e9c76272faa603cbfrobertphillips@google.com                            const GrIRect &bound) {
36a72eef322c686954cdffa849dc26d8133b802f1drobertphillips@google.com    GrDrawState* drawState = gpu->drawState();
37a72eef322c686954cdffa849dc26d8133b802f1drobertphillips@google.com    GrAssert(drawState);
38a72eef322c686954cdffa849dc26d8133b802f1drobertphillips@google.com
39a72eef322c686954cdffa849dc26d8133b802f1drobertphillips@google.com    static const int maskStage = GrPaint::kTotalStages+1;
40a72eef322c686954cdffa849dc26d8133b802f1drobertphillips@google.com
41a72eef322c686954cdffa849dc26d8133b802f1drobertphillips@google.com    GrMatrix mat;
42a72eef322c686954cdffa849dc26d8133b802f1drobertphillips@google.com    mat.setIDiv(result->width(), result->height());
436623fcd1ee33b35fa18e304e9c76272faa603cbfrobertphillips@google.com    mat.preTranslate(SkIntToScalar(-bound.fLeft), SkIntToScalar(-bound.fTop));
44a72eef322c686954cdffa849dc26d8133b802f1drobertphillips@google.com    mat.preConcat(drawState->getViewMatrix());
45a72eef322c686954cdffa849dc26d8133b802f1drobertphillips@google.com
46a72eef322c686954cdffa849dc26d8133b802f1drobertphillips@google.com    drawState->sampler(maskStage)->reset(GrSamplerState::kClamp_WrapMode,
47a72eef322c686954cdffa849dc26d8133b802f1drobertphillips@google.com                                         GrSamplerState::kNearest_Filter,
48a72eef322c686954cdffa849dc26d8133b802f1drobertphillips@google.com                                         mat);
49a72eef322c686954cdffa849dc26d8133b802f1drobertphillips@google.com
50a72eef322c686954cdffa849dc26d8133b802f1drobertphillips@google.com    drawState->setTexture(maskStage, result);
51a72eef322c686954cdffa849dc26d8133b802f1drobertphillips@google.com
52a72eef322c686954cdffa849dc26d8133b802f1drobertphillips@google.com    // The AA clipping determination happens long after the geometry has
53a72eef322c686954cdffa849dc26d8133b802f1drobertphillips@google.com    // been set up to draw. Here we directly enable the AA clip mask stage
54a72eef322c686954cdffa849dc26d8133b802f1drobertphillips@google.com    gpu->addToVertexLayout(
55a72eef322c686954cdffa849dc26d8133b802f1drobertphillips@google.com                GrDrawTarget::StagePosAsTexCoordVertexLayoutBit(maskStage));
56a72eef322c686954cdffa849dc26d8133b802f1drobertphillips@google.com}
57a72eef322c686954cdffa849dc26d8133b802f1drobertphillips@google.com
586b70a7bd3328ea0a12be47b1a7f835c905f16147robertphillips@google.combool create_mask_in_sw() {
596b70a7bd3328ea0a12be47b1a7f835c905f16147robertphillips@google.com    return false;
606b70a7bd3328ea0a12be47b1a7f835c905f16147robertphillips@google.com}
616b70a7bd3328ea0a12be47b1a7f835c905f16147robertphillips@google.com
62a72eef322c686954cdffa849dc26d8133b802f1drobertphillips@google.com}
63a72eef322c686954cdffa849dc26d8133b802f1drobertphillips@google.com
64f294b773f0b2b9f05eb45b52dd3cb4d97b96af06robertphillips@google.com////////////////////////////////////////////////////////////////////////////////
656b70a7bd3328ea0a12be47b1a7f835c905f16147robertphillips@google.com// sort out what kind of clip mask needs to be created: alpha, stencil,
666b70a7bd3328ea0a12be47b1a7f835c905f16147robertphillips@google.com// scissor, or entirely software
671e945b7e708c633d4aed937ebfce57d52ba21d83robertphillips@google.combool GrClipMaskManager::createClipMask(GrGpu* gpu,
681e945b7e708c633d4aed937ebfce57d52ba21d83robertphillips@google.com                                       const GrClip& clipIn,
691e945b7e708c633d4aed937ebfce57d52ba21d83robertphillips@google.com                                       ScissoringSettings* scissorSettings) {
701e945b7e708c633d4aed937ebfce57d52ba21d83robertphillips@google.com
711e945b7e708c633d4aed937ebfce57d52ba21d83robertphillips@google.com    GrAssert(scissorSettings);
721e945b7e708c633d4aed937ebfce57d52ba21d83robertphillips@google.com
731e945b7e708c633d4aed937ebfce57d52ba21d83robertphillips@google.com    scissorSettings->fEnableScissoring = false;
741e945b7e708c633d4aed937ebfce57d52ba21d83robertphillips@google.com    fClipMaskInStencil = false;
75f294b773f0b2b9f05eb45b52dd3cb4d97b96af06robertphillips@google.com    fClipMaskInAlpha = false;
761e945b7e708c633d4aed937ebfce57d52ba21d83robertphillips@google.com
771e945b7e708c633d4aed937ebfce57d52ba21d83robertphillips@google.com    GrDrawState* drawState = gpu->drawState();
781e945b7e708c633d4aed937ebfce57d52ba21d83robertphillips@google.com    if (!drawState->isClipState()) {
791e945b7e708c633d4aed937ebfce57d52ba21d83robertphillips@google.com        return true;
801e945b7e708c633d4aed937ebfce57d52ba21d83robertphillips@google.com    }
811e945b7e708c633d4aed937ebfce57d52ba21d83robertphillips@google.com
821e945b7e708c633d4aed937ebfce57d52ba21d83robertphillips@google.com    GrRenderTarget* rt = drawState->getRenderTarget();
831e945b7e708c633d4aed937ebfce57d52ba21d83robertphillips@google.com
841e945b7e708c633d4aed937ebfce57d52ba21d83robertphillips@google.com    // GrDrawTarget should have filtered this for us
851e945b7e708c633d4aed937ebfce57d52ba21d83robertphillips@google.com    GrAssert(NULL != rt);
861e945b7e708c633d4aed937ebfce57d52ba21d83robertphillips@google.com
876b70a7bd3328ea0a12be47b1a7f835c905f16147robertphillips@google.com#if GR_SW_CLIP
886b70a7bd3328ea0a12be47b1a7f835c905f16147robertphillips@google.com    if (create_mask_in_sw()) {
896b70a7bd3328ea0a12be47b1a7f835c905f16147robertphillips@google.com        // The clip geometry is complex enough that it will be more
906b70a7bd3328ea0a12be47b1a7f835c905f16147robertphillips@google.com        // efficient to create it entirely in software
916b70a7bd3328ea0a12be47b1a7f835c905f16147robertphillips@google.com        GrTexture* result = NULL;
926623fcd1ee33b35fa18e304e9c76272faa603cbfrobertphillips@google.com        GrIRect bound;
936b70a7bd3328ea0a12be47b1a7f835c905f16147robertphillips@google.com        if (this->createSoftwareClipMask(gpu, clipIn, &result, &bound)) {
946b70a7bd3328ea0a12be47b1a7f835c905f16147robertphillips@google.com            fClipMaskInAlpha = true;
956b70a7bd3328ea0a12be47b1a7f835c905f16147robertphillips@google.com
966b70a7bd3328ea0a12be47b1a7f835c905f16147robertphillips@google.com            setup_drawstate_aaclip(gpu, result, bound);
976b70a7bd3328ea0a12be47b1a7f835c905f16147robertphillips@google.com            return true;
986b70a7bd3328ea0a12be47b1a7f835c905f16147robertphillips@google.com        }
996b70a7bd3328ea0a12be47b1a7f835c905f16147robertphillips@google.com    }
1006b70a7bd3328ea0a12be47b1a7f835c905f16147robertphillips@google.com#endif
1016b70a7bd3328ea0a12be47b1a7f835c905f16147robertphillips@google.com
102f294b773f0b2b9f05eb45b52dd3cb4d97b96af06robertphillips@google.com#if GR_AA_CLIP
103f294b773f0b2b9f05eb45b52dd3cb4d97b96af06robertphillips@google.com    // If MSAA is enabled use the (faster) stencil path for AA clipping
104f294b773f0b2b9f05eb45b52dd3cb4d97b96af06robertphillips@google.com    // otherwise the alpha clip mask is our only option
105f294b773f0b2b9f05eb45b52dd3cb4d97b96af06robertphillips@google.com    if (clipIn.requiresAA() && 0 == rt->numSamples()) {
106f294b773f0b2b9f05eb45b52dd3cb4d97b96af06robertphillips@google.com        // Since we are going to create a destination texture of the correct
107f294b773f0b2b9f05eb45b52dd3cb4d97b96af06robertphillips@google.com        // size for the mask (rather than being bound by the size of the
108f294b773f0b2b9f05eb45b52dd3cb4d97b96af06robertphillips@google.com        // render target) we aren't going to use scissoring like the stencil
109f294b773f0b2b9f05eb45b52dd3cb4d97b96af06robertphillips@google.com        // path does (see scissorSettings below)
110a72eef322c686954cdffa849dc26d8133b802f1drobertphillips@google.com        GrTexture* result = NULL;
1116623fcd1ee33b35fa18e304e9c76272faa603cbfrobertphillips@google.com        GrIRect bound;
112a72eef322c686954cdffa849dc26d8133b802f1drobertphillips@google.com        if (this->createAlphaClipMask(gpu, clipIn, &result, &bound)) {
113f294b773f0b2b9f05eb45b52dd3cb4d97b96af06robertphillips@google.com            fClipMaskInAlpha = true;
114a72eef322c686954cdffa849dc26d8133b802f1drobertphillips@google.com
1156b70a7bd3328ea0a12be47b1a7f835c905f16147robertphillips@google.com            setup_drawstate_aaclip(gpu, result, bound);
116f294b773f0b2b9f05eb45b52dd3cb4d97b96af06robertphillips@google.com            return true;
117f294b773f0b2b9f05eb45b52dd3cb4d97b96af06robertphillips@google.com        }
118f294b773f0b2b9f05eb45b52dd3cb4d97b96af06robertphillips@google.com
119f294b773f0b2b9f05eb45b52dd3cb4d97b96af06robertphillips@google.com        // if alpha clip mask creation fails fall through to the stencil
120f294b773f0b2b9f05eb45b52dd3cb4d97b96af06robertphillips@google.com        // buffer method
121f294b773f0b2b9f05eb45b52dd3cb4d97b96af06robertphillips@google.com    }
122f294b773f0b2b9f05eb45b52dd3cb4d97b96af06robertphillips@google.com#endif // GR_AA_CLIP
123f294b773f0b2b9f05eb45b52dd3cb4d97b96af06robertphillips@google.com
1245acc0e36d987dff3172fd45a14b66c52a51d49e4robertphillips@google.com    // Either a hard (stencil buffer) clip was explicitly requested or
1255acc0e36d987dff3172fd45a14b66c52a51d49e4robertphillips@google.com    // an antialiased clip couldn't be created. In either case, free up
1265acc0e36d987dff3172fd45a14b66c52a51d49e4robertphillips@google.com    // the texture in the antialiased mask cache.
1275acc0e36d987dff3172fd45a14b66c52a51d49e4robertphillips@google.com    // TODO: this may require more investigation. Ganesh performs a lot of
1285acc0e36d987dff3172fd45a14b66c52a51d49e4robertphillips@google.com    // utility draws (e.g., clears, InOderDrawBuffer playbacks) that hit
1295acc0e36d987dff3172fd45a14b66c52a51d49e4robertphillips@google.com    // the stencil buffer path. These may be incorrectly messing up the
1305acc0e36d987dff3172fd45a14b66c52a51d49e4robertphillips@google.com    // AA cache.
1315acc0e36d987dff3172fd45a14b66c52a51d49e4robertphillips@google.com    fAACache.reset();
1325acc0e36d987dff3172fd45a14b66c52a51d49e4robertphillips@google.com
1331e945b7e708c633d4aed937ebfce57d52ba21d83robertphillips@google.com    GrRect bounds;
1341e945b7e708c633d4aed937ebfce57d52ba21d83robertphillips@google.com    GrRect rtRect;
1351e945b7e708c633d4aed937ebfce57d52ba21d83robertphillips@google.com    rtRect.setLTRB(0, 0,
1361e945b7e708c633d4aed937ebfce57d52ba21d83robertphillips@google.com                    GrIntToScalar(rt->width()), GrIntToScalar(rt->height()));
1371e945b7e708c633d4aed937ebfce57d52ba21d83robertphillips@google.com    if (clipIn.hasConservativeBounds()) {
1381e945b7e708c633d4aed937ebfce57d52ba21d83robertphillips@google.com        bounds = clipIn.getConservativeBounds();
1391e945b7e708c633d4aed937ebfce57d52ba21d83robertphillips@google.com        if (!bounds.intersect(rtRect)) {
1401e945b7e708c633d4aed937ebfce57d52ba21d83robertphillips@google.com            bounds.setEmpty();
1411e945b7e708c633d4aed937ebfce57d52ba21d83robertphillips@google.com        }
1421e945b7e708c633d4aed937ebfce57d52ba21d83robertphillips@google.com    } else {
1431e945b7e708c633d4aed937ebfce57d52ba21d83robertphillips@google.com        bounds = rtRect;
1441e945b7e708c633d4aed937ebfce57d52ba21d83robertphillips@google.com    }
1451e945b7e708c633d4aed937ebfce57d52ba21d83robertphillips@google.com
1461e945b7e708c633d4aed937ebfce57d52ba21d83robertphillips@google.com    bounds.roundOut(&scissorSettings->fScissorRect);
1471e945b7e708c633d4aed937ebfce57d52ba21d83robertphillips@google.com    if  (scissorSettings->fScissorRect.isEmpty()) {
1481e945b7e708c633d4aed937ebfce57d52ba21d83robertphillips@google.com        scissorSettings->fScissorRect.setLTRB(0,0,0,0);
1491e945b7e708c633d4aed937ebfce57d52ba21d83robertphillips@google.com        // TODO: I think we can do an early exit here - after refactoring try:
1501e945b7e708c633d4aed937ebfce57d52ba21d83robertphillips@google.com        //  set fEnableScissoring to true but leave fClipMaskInStencil false
1511e945b7e708c633d4aed937ebfce57d52ba21d83robertphillips@google.com        //  and return - everything is going to be scissored away anyway!
1521e945b7e708c633d4aed937ebfce57d52ba21d83robertphillips@google.com    }
1531e945b7e708c633d4aed937ebfce57d52ba21d83robertphillips@google.com    scissorSettings->fEnableScissoring = true;
1541e945b7e708c633d4aed937ebfce57d52ba21d83robertphillips@google.com
1551e945b7e708c633d4aed937ebfce57d52ba21d83robertphillips@google.com    // use the stencil clip if we can't represent the clip as a rectangle.
1561e945b7e708c633d4aed937ebfce57d52ba21d83robertphillips@google.com    fClipMaskInStencil = !clipIn.isRect() && !clipIn.isEmpty() &&
1571e945b7e708c633d4aed937ebfce57d52ba21d83robertphillips@google.com                         !bounds.isEmpty();
1581e945b7e708c633d4aed937ebfce57d52ba21d83robertphillips@google.com
1591e945b7e708c633d4aed937ebfce57d52ba21d83robertphillips@google.com    if (fClipMaskInStencil) {
1601e945b7e708c633d4aed937ebfce57d52ba21d83robertphillips@google.com        return this->createStencilClipMask(gpu, clipIn, bounds, scissorSettings);
1611e945b7e708c633d4aed937ebfce57d52ba21d83robertphillips@google.com    }
1621e945b7e708c633d4aed937ebfce57d52ba21d83robertphillips@google.com
1631e945b7e708c633d4aed937ebfce57d52ba21d83robertphillips@google.com    return true;
1641e945b7e708c633d4aed937ebfce57d52ba21d83robertphillips@google.com}
1651e945b7e708c633d4aed937ebfce57d52ba21d83robertphillips@google.com
1661e945b7e708c633d4aed937ebfce57d52ba21d83robertphillips@google.com#define VISUALIZE_COMPLEX_CLIP 0
1671e945b7e708c633d4aed937ebfce57d52ba21d83robertphillips@google.com
1681e945b7e708c633d4aed937ebfce57d52ba21d83robertphillips@google.com#if VISUALIZE_COMPLEX_CLIP
1691e945b7e708c633d4aed937ebfce57d52ba21d83robertphillips@google.com    #include "GrRandom.h"
1701e945b7e708c633d4aed937ebfce57d52ba21d83robertphillips@google.com    GrRandom gRandom;
1711e945b7e708c633d4aed937ebfce57d52ba21d83robertphillips@google.com    #define SET_RANDOM_COLOR drawState->setColor(0xff000000 | gRandom.nextU());
1721e945b7e708c633d4aed937ebfce57d52ba21d83robertphillips@google.com#else
1731e945b7e708c633d4aed937ebfce57d52ba21d83robertphillips@google.com    #define SET_RANDOM_COLOR
1741e945b7e708c633d4aed937ebfce57d52ba21d83robertphillips@google.com#endif
1751e945b7e708c633d4aed937ebfce57d52ba21d83robertphillips@google.com
1761e945b7e708c633d4aed937ebfce57d52ba21d83robertphillips@google.comnamespace {
1776623fcd1ee33b35fa18e304e9c76272faa603cbfrobertphillips@google.com/**
1786623fcd1ee33b35fa18e304e9c76272faa603cbfrobertphillips@google.com * Does "container" contain "containee"? If either is empty then
1796623fcd1ee33b35fa18e304e9c76272faa603cbfrobertphillips@google.com * no containment is possible.
1806623fcd1ee33b35fa18e304e9c76272faa603cbfrobertphillips@google.com */
1816623fcd1ee33b35fa18e304e9c76272faa603cbfrobertphillips@google.combool contains(const SkRect& container, const SkIRect& containee) {
1826623fcd1ee33b35fa18e304e9c76272faa603cbfrobertphillips@google.com    return  !containee.isEmpty() && !container.isEmpty() &&
1836623fcd1ee33b35fa18e304e9c76272faa603cbfrobertphillips@google.com            container.fLeft <= SkIntToScalar(containee.fLeft) &&
1846623fcd1ee33b35fa18e304e9c76272faa603cbfrobertphillips@google.com            container.fTop <= SkIntToScalar(containee.fTop) &&
1856623fcd1ee33b35fa18e304e9c76272faa603cbfrobertphillips@google.com            container.fRight >= SkIntToScalar(containee.fRight) &&
1866623fcd1ee33b35fa18e304e9c76272faa603cbfrobertphillips@google.com            container.fBottom >= SkIntToScalar(containee.fBottom);
1876623fcd1ee33b35fa18e304e9c76272faa603cbfrobertphillips@google.com}
1886623fcd1ee33b35fa18e304e9c76272faa603cbfrobertphillips@google.com
1896623fcd1ee33b35fa18e304e9c76272faa603cbfrobertphillips@google.com
190f294b773f0b2b9f05eb45b52dd3cb4d97b96af06robertphillips@google.com////////////////////////////////////////////////////////////////////////////////
1911e945b7e708c633d4aed937ebfce57d52ba21d83robertphillips@google.com// determines how many elements at the head of the clip can be skipped and
1921e945b7e708c633d4aed937ebfce57d52ba21d83robertphillips@google.com// whether the initial clear should be to the inside- or outside-the-clip value,
1931e945b7e708c633d4aed937ebfce57d52ba21d83robertphillips@google.com// and what op should be used to draw the first element that isn't skipped.
1941e945b7e708c633d4aed937ebfce57d52ba21d83robertphillips@google.comint process_initial_clip_elements(const GrClip& clip,
1956623fcd1ee33b35fa18e304e9c76272faa603cbfrobertphillips@google.com                                  const GrIRect& bounds,
1961e945b7e708c633d4aed937ebfce57d52ba21d83robertphillips@google.com                                  bool* clearToInside,
1970f191f30af7c067883c97b034baf70bfd92f5ea0robertphillips@google.com                                  SkRegion::Op* startOp) {
1981e945b7e708c633d4aed937ebfce57d52ba21d83robertphillips@google.com
1991e945b7e708c633d4aed937ebfce57d52ba21d83robertphillips@google.com    // logically before the first element of the clip stack is
2001e945b7e708c633d4aed937ebfce57d52ba21d83robertphillips@google.com    // processed the clip is entirely open. However, depending on the
2011e945b7e708c633d4aed937ebfce57d52ba21d83robertphillips@google.com    // first set op we may prefer to clear to 0 for performance. We may
2021e945b7e708c633d4aed937ebfce57d52ba21d83robertphillips@google.com    // also be able to skip the initial clip paths/rects. We loop until
2031e945b7e708c633d4aed937ebfce57d52ba21d83robertphillips@google.com    // we cannot skip an element.
2041e945b7e708c633d4aed937ebfce57d52ba21d83robertphillips@google.com    int curr;
2051e945b7e708c633d4aed937ebfce57d52ba21d83robertphillips@google.com    bool done = false;
2061e945b7e708c633d4aed937ebfce57d52ba21d83robertphillips@google.com    *clearToInside = true;
2071e945b7e708c633d4aed937ebfce57d52ba21d83robertphillips@google.com    int count = clip.getElementCount();
2081e945b7e708c633d4aed937ebfce57d52ba21d83robertphillips@google.com
2091e945b7e708c633d4aed937ebfce57d52ba21d83robertphillips@google.com    for (curr = 0; curr < count && !done; ++curr) {
2101e945b7e708c633d4aed937ebfce57d52ba21d83robertphillips@google.com        switch (clip.getOp(curr)) {
2110f191f30af7c067883c97b034baf70bfd92f5ea0robertphillips@google.com            case SkRegion::kReplace_Op:
2121e945b7e708c633d4aed937ebfce57d52ba21d83robertphillips@google.com                // replace ignores everything previous
2130f191f30af7c067883c97b034baf70bfd92f5ea0robertphillips@google.com                *startOp = SkRegion::kReplace_Op;
2141e945b7e708c633d4aed937ebfce57d52ba21d83robertphillips@google.com                *clearToInside = false;
2151e945b7e708c633d4aed937ebfce57d52ba21d83robertphillips@google.com                done = true;
2161e945b7e708c633d4aed937ebfce57d52ba21d83robertphillips@google.com                break;
2170f191f30af7c067883c97b034baf70bfd92f5ea0robertphillips@google.com            case SkRegion::kIntersect_Op:
2181e945b7e708c633d4aed937ebfce57d52ba21d83robertphillips@google.com                // if this element contains the entire bounds then we
2191e945b7e708c633d4aed937ebfce57d52ba21d83robertphillips@google.com                // can skip it.
2201e945b7e708c633d4aed937ebfce57d52ba21d83robertphillips@google.com                if (kRect_ClipType == clip.getElementType(curr)
2216623fcd1ee33b35fa18e304e9c76272faa603cbfrobertphillips@google.com                    && contains(clip.getRect(curr), bounds)) {
2221e945b7e708c633d4aed937ebfce57d52ba21d83robertphillips@google.com                    break;
2231e945b7e708c633d4aed937ebfce57d52ba21d83robertphillips@google.com                }
2241e945b7e708c633d4aed937ebfce57d52ba21d83robertphillips@google.com                // if everything is initially clearToInside then intersect is
2251e945b7e708c633d4aed937ebfce57d52ba21d83robertphillips@google.com                // same as clear to 0 and treat as a replace. Otherwise,
2261e945b7e708c633d4aed937ebfce57d52ba21d83robertphillips@google.com                // set stays empty.
2271e945b7e708c633d4aed937ebfce57d52ba21d83robertphillips@google.com                if (*clearToInside) {
2280f191f30af7c067883c97b034baf70bfd92f5ea0robertphillips@google.com                    *startOp = SkRegion::kReplace_Op;
2291e945b7e708c633d4aed937ebfce57d52ba21d83robertphillips@google.com                    *clearToInside = false;
2301e945b7e708c633d4aed937ebfce57d52ba21d83robertphillips@google.com                    done = true;
2311e945b7e708c633d4aed937ebfce57d52ba21d83robertphillips@google.com                }
2321e945b7e708c633d4aed937ebfce57d52ba21d83robertphillips@google.com                break;
2331e945b7e708c633d4aed937ebfce57d52ba21d83robertphillips@google.com                // we can skip a leading union.
2340f191f30af7c067883c97b034baf70bfd92f5ea0robertphillips@google.com            case SkRegion::kUnion_Op:
2351e945b7e708c633d4aed937ebfce57d52ba21d83robertphillips@google.com                // if everything is initially outside then union is
2361e945b7e708c633d4aed937ebfce57d52ba21d83robertphillips@google.com                // same as replace. Otherwise, every pixel is still
2371e945b7e708c633d4aed937ebfce57d52ba21d83robertphillips@google.com                // clearToInside
2381e945b7e708c633d4aed937ebfce57d52ba21d83robertphillips@google.com                if (!*clearToInside) {
2390f191f30af7c067883c97b034baf70bfd92f5ea0robertphillips@google.com                    *startOp = SkRegion::kReplace_Op;
2401e945b7e708c633d4aed937ebfce57d52ba21d83robertphillips@google.com                    done = true;
2411e945b7e708c633d4aed937ebfce57d52ba21d83robertphillips@google.com                }
2421e945b7e708c633d4aed937ebfce57d52ba21d83robertphillips@google.com                break;
2430f191f30af7c067883c97b034baf70bfd92f5ea0robertphillips@google.com            case SkRegion::kXOR_Op:
2441e945b7e708c633d4aed937ebfce57d52ba21d83robertphillips@google.com                // xor is same as difference or replace both of which
2451e945b7e708c633d4aed937ebfce57d52ba21d83robertphillips@google.com                // can be 1-pass instead of 2 for xor.
2461e945b7e708c633d4aed937ebfce57d52ba21d83robertphillips@google.com                if (*clearToInside) {
2470f191f30af7c067883c97b034baf70bfd92f5ea0robertphillips@google.com                    *startOp = SkRegion::kDifference_Op;
2481e945b7e708c633d4aed937ebfce57d52ba21d83robertphillips@google.com                } else {
2490f191f30af7c067883c97b034baf70bfd92f5ea0robertphillips@google.com                    *startOp = SkRegion::kReplace_Op;
2501e945b7e708c633d4aed937ebfce57d52ba21d83robertphillips@google.com                }
2511e945b7e708c633d4aed937ebfce57d52ba21d83robertphillips@google.com                done = true;
2521e945b7e708c633d4aed937ebfce57d52ba21d83robertphillips@google.com                break;
2530f191f30af7c067883c97b034baf70bfd92f5ea0robertphillips@google.com            case SkRegion::kDifference_Op:
2541e945b7e708c633d4aed937ebfce57d52ba21d83robertphillips@google.com                // if all pixels are clearToInside then we have to process the
2551e945b7e708c633d4aed937ebfce57d52ba21d83robertphillips@google.com                // difference, otherwise it has no effect and all pixels
2561e945b7e708c633d4aed937ebfce57d52ba21d83robertphillips@google.com                // remain outside.
2571e945b7e708c633d4aed937ebfce57d52ba21d83robertphillips@google.com                if (*clearToInside) {
2580f191f30af7c067883c97b034baf70bfd92f5ea0robertphillips@google.com                    *startOp = SkRegion::kDifference_Op;
2591e945b7e708c633d4aed937ebfce57d52ba21d83robertphillips@google.com                    done = true;
2601e945b7e708c633d4aed937ebfce57d52ba21d83robertphillips@google.com                }
2611e945b7e708c633d4aed937ebfce57d52ba21d83robertphillips@google.com                break;
2620f191f30af7c067883c97b034baf70bfd92f5ea0robertphillips@google.com            case SkRegion::kReverseDifference_Op:
2631e945b7e708c633d4aed937ebfce57d52ba21d83robertphillips@google.com                // if all pixels are clearToInside then reverse difference
2641e945b7e708c633d4aed937ebfce57d52ba21d83robertphillips@google.com                // produces empty set. Otherise it is same as replace
2651e945b7e708c633d4aed937ebfce57d52ba21d83robertphillips@google.com                if (*clearToInside) {
2661e945b7e708c633d4aed937ebfce57d52ba21d83robertphillips@google.com                    *clearToInside = false;
2671e945b7e708c633d4aed937ebfce57d52ba21d83robertphillips@google.com                } else {
2680f191f30af7c067883c97b034baf70bfd92f5ea0robertphillips@google.com                    *startOp = SkRegion::kReplace_Op;
2691e945b7e708c633d4aed937ebfce57d52ba21d83robertphillips@google.com                    done = true;
2701e945b7e708c633d4aed937ebfce57d52ba21d83robertphillips@google.com                }
2711e945b7e708c633d4aed937ebfce57d52ba21d83robertphillips@google.com                break;
2721e945b7e708c633d4aed937ebfce57d52ba21d83robertphillips@google.com            default:
2731e945b7e708c633d4aed937ebfce57d52ba21d83robertphillips@google.com                GrCrash("Unknown set op.");
2741e945b7e708c633d4aed937ebfce57d52ba21d83robertphillips@google.com        }
2751e945b7e708c633d4aed937ebfce57d52ba21d83robertphillips@google.com    }
2761e945b7e708c633d4aed937ebfce57d52ba21d83robertphillips@google.com    return done ? curr-1 : count;
2771e945b7e708c633d4aed937ebfce57d52ba21d83robertphillips@google.com}
278f294b773f0b2b9f05eb45b52dd3cb4d97b96af06robertphillips@google.com
279f294b773f0b2b9f05eb45b52dd3cb4d97b96af06robertphillips@google.com}
280f294b773f0b2b9f05eb45b52dd3cb4d97b96af06robertphillips@google.com
281f294b773f0b2b9f05eb45b52dd3cb4d97b96af06robertphillips@google.com
282f294b773f0b2b9f05eb45b52dd3cb4d97b96af06robertphillips@google.comnamespace {
283f294b773f0b2b9f05eb45b52dd3cb4d97b96af06robertphillips@google.com
284f294b773f0b2b9f05eb45b52dd3cb4d97b96af06robertphillips@google.com////////////////////////////////////////////////////////////////////////////////
285f294b773f0b2b9f05eb45b52dd3cb4d97b96af06robertphillips@google.com// set up the OpenGL blend function to perform the specified
286f294b773f0b2b9f05eb45b52dd3cb4d97b96af06robertphillips@google.com// boolean operation for alpha clip mask creation
2876b70a7bd3328ea0a12be47b1a7f835c905f16147robertphillips@google.comvoid setup_boolean_blendcoeffs(GrDrawState* drawState, SkRegion::Op op) {
288f294b773f0b2b9f05eb45b52dd3cb4d97b96af06robertphillips@google.com
289f294b773f0b2b9f05eb45b52dd3cb4d97b96af06robertphillips@google.com    switch (op) {
290f294b773f0b2b9f05eb45b52dd3cb4d97b96af06robertphillips@google.com        case SkRegion::kReplace_Op:
291f294b773f0b2b9f05eb45b52dd3cb4d97b96af06robertphillips@google.com            drawState->setBlendFunc(kOne_BlendCoeff, kZero_BlendCoeff);
292f294b773f0b2b9f05eb45b52dd3cb4d97b96af06robertphillips@google.com            break;
293f294b773f0b2b9f05eb45b52dd3cb4d97b96af06robertphillips@google.com        case SkRegion::kIntersect_Op:
294f294b773f0b2b9f05eb45b52dd3cb4d97b96af06robertphillips@google.com            drawState->setBlendFunc(kDC_BlendCoeff, kZero_BlendCoeff);
295f294b773f0b2b9f05eb45b52dd3cb4d97b96af06robertphillips@google.com            break;
296f294b773f0b2b9f05eb45b52dd3cb4d97b96af06robertphillips@google.com        case SkRegion::kUnion_Op:
297f294b773f0b2b9f05eb45b52dd3cb4d97b96af06robertphillips@google.com            drawState->setBlendFunc(kOne_BlendCoeff, kISC_BlendCoeff);
298f294b773f0b2b9f05eb45b52dd3cb4d97b96af06robertphillips@google.com            break;
299f294b773f0b2b9f05eb45b52dd3cb4d97b96af06robertphillips@google.com        case SkRegion::kXOR_Op:
300f294b773f0b2b9f05eb45b52dd3cb4d97b96af06robertphillips@google.com            drawState->setBlendFunc(kIDC_BlendCoeff, kISC_BlendCoeff);
301f294b773f0b2b9f05eb45b52dd3cb4d97b96af06robertphillips@google.com            break;
302f294b773f0b2b9f05eb45b52dd3cb4d97b96af06robertphillips@google.com        case SkRegion::kDifference_Op:
303f294b773f0b2b9f05eb45b52dd3cb4d97b96af06robertphillips@google.com            drawState->setBlendFunc(kZero_BlendCoeff, kISC_BlendCoeff);
304f294b773f0b2b9f05eb45b52dd3cb4d97b96af06robertphillips@google.com            break;
305f294b773f0b2b9f05eb45b52dd3cb4d97b96af06robertphillips@google.com        case SkRegion::kReverseDifference_Op:
306f294b773f0b2b9f05eb45b52dd3cb4d97b96af06robertphillips@google.com            drawState->setBlendFunc(kIDC_BlendCoeff, kZero_BlendCoeff);
307f294b773f0b2b9f05eb45b52dd3cb4d97b96af06robertphillips@google.com            break;
308f294b773f0b2b9f05eb45b52dd3cb4d97b96af06robertphillips@google.com        default:
309f294b773f0b2b9f05eb45b52dd3cb4d97b96af06robertphillips@google.com            GrAssert(false);
310f294b773f0b2b9f05eb45b52dd3cb4d97b96af06robertphillips@google.com            break;
311f294b773f0b2b9f05eb45b52dd3cb4d97b96af06robertphillips@google.com    }
312f294b773f0b2b9f05eb45b52dd3cb4d97b96af06robertphillips@google.com}
313f294b773f0b2b9f05eb45b52dd3cb4d97b96af06robertphillips@google.com
314f294b773f0b2b9f05eb45b52dd3cb4d97b96af06robertphillips@google.com}
315f294b773f0b2b9f05eb45b52dd3cb4d97b96af06robertphillips@google.com
316f294b773f0b2b9f05eb45b52dd3cb4d97b96af06robertphillips@google.com////////////////////////////////////////////////////////////////////////////////
317f294b773f0b2b9f05eb45b52dd3cb4d97b96af06robertphillips@google.combool GrClipMaskManager::drawPath(GrGpu* gpu,
3188d033a1b125886c62906d975b5cc28a382064526bsalomon@google.com                                 const SkPath& path,
319f294b773f0b2b9f05eb45b52dd3cb4d97b96af06robertphillips@google.com                                 GrPathFill fill,
320f294b773f0b2b9f05eb45b52dd3cb4d97b96af06robertphillips@google.com                                 bool doAA) {
321f294b773f0b2b9f05eb45b52dd3cb4d97b96af06robertphillips@google.com
322f294b773f0b2b9f05eb45b52dd3cb4d97b96af06robertphillips@google.com    GrPathRenderer* pr = this->getClipPathRenderer(gpu, path, fill, doAA);
323f294b773f0b2b9f05eb45b52dd3cb4d97b96af06robertphillips@google.com    if (NULL == pr) {
324f294b773f0b2b9f05eb45b52dd3cb4d97b96af06robertphillips@google.com        return false;
325f294b773f0b2b9f05eb45b52dd3cb4d97b96af06robertphillips@google.com    }
326f294b773f0b2b9f05eb45b52dd3cb4d97b96af06robertphillips@google.com
327f294b773f0b2b9f05eb45b52dd3cb4d97b96af06robertphillips@google.com    pr->drawPath(path, fill, NULL, gpu, 0, doAA);
328f294b773f0b2b9f05eb45b52dd3cb4d97b96af06robertphillips@google.com    return true;
329f294b773f0b2b9f05eb45b52dd3cb4d97b96af06robertphillips@google.com}
330f294b773f0b2b9f05eb45b52dd3cb4d97b96af06robertphillips@google.com
331f294b773f0b2b9f05eb45b52dd3cb4d97b96af06robertphillips@google.com////////////////////////////////////////////////////////////////////////////////
332f294b773f0b2b9f05eb45b52dd3cb4d97b96af06robertphillips@google.combool GrClipMaskManager::drawClipShape(GrGpu* gpu,
333f294b773f0b2b9f05eb45b52dd3cb4d97b96af06robertphillips@google.com                                      GrTexture* target,
334f294b773f0b2b9f05eb45b52dd3cb4d97b96af06robertphillips@google.com                                      const GrClip& clipIn,
335f294b773f0b2b9f05eb45b52dd3cb4d97b96af06robertphillips@google.com                                      int index) {
336f294b773f0b2b9f05eb45b52dd3cb4d97b96af06robertphillips@google.com    GrDrawState* drawState = gpu->drawState();
337f294b773f0b2b9f05eb45b52dd3cb4d97b96af06robertphillips@google.com    GrAssert(NULL != drawState);
338f294b773f0b2b9f05eb45b52dd3cb4d97b96af06robertphillips@google.com
339f294b773f0b2b9f05eb45b52dd3cb4d97b96af06robertphillips@google.com    drawState->setRenderTarget(target->asRenderTarget());
340f294b773f0b2b9f05eb45b52dd3cb4d97b96af06robertphillips@google.com
341f294b773f0b2b9f05eb45b52dd3cb4d97b96af06robertphillips@google.com    if (kRect_ClipType == clipIn.getElementType(index)) {
342f294b773f0b2b9f05eb45b52dd3cb4d97b96af06robertphillips@google.com        if (clipIn.getDoAA(index)) {
343f294b773f0b2b9f05eb45b52dd3cb4d97b96af06robertphillips@google.com            // convert the rect to a path for AA
344f294b773f0b2b9f05eb45b52dd3cb4d97b96af06robertphillips@google.com            SkPath temp;
345f294b773f0b2b9f05eb45b52dd3cb4d97b96af06robertphillips@google.com            temp.addRect(clipIn.getRect(index));
346f294b773f0b2b9f05eb45b52dd3cb4d97b96af06robertphillips@google.com
347f294b773f0b2b9f05eb45b52dd3cb4d97b96af06robertphillips@google.com            return this->drawPath(gpu, temp,
348f294b773f0b2b9f05eb45b52dd3cb4d97b96af06robertphillips@google.com                                  kEvenOdd_PathFill, clipIn.getDoAA(index));
349f294b773f0b2b9f05eb45b52dd3cb4d97b96af06robertphillips@google.com        } else {
350f294b773f0b2b9f05eb45b52dd3cb4d97b96af06robertphillips@google.com            gpu->drawSimpleRect(clipIn.getRect(index), NULL, 0);
351f294b773f0b2b9f05eb45b52dd3cb4d97b96af06robertphillips@google.com        }
352f294b773f0b2b9f05eb45b52dd3cb4d97b96af06robertphillips@google.com    } else {
353f294b773f0b2b9f05eb45b52dd3cb4d97b96af06robertphillips@google.com        return this->drawPath(gpu,
354f294b773f0b2b9f05eb45b52dd3cb4d97b96af06robertphillips@google.com                              clipIn.getPath(index),
355f294b773f0b2b9f05eb45b52dd3cb4d97b96af06robertphillips@google.com                              clipIn.getPathFill(index),
356f294b773f0b2b9f05eb45b52dd3cb4d97b96af06robertphillips@google.com                              clipIn.getDoAA(index));
357f294b773f0b2b9f05eb45b52dd3cb4d97b96af06robertphillips@google.com    }
358f294b773f0b2b9f05eb45b52dd3cb4d97b96af06robertphillips@google.com    return true;
359f294b773f0b2b9f05eb45b52dd3cb4d97b96af06robertphillips@google.com}
360f294b773f0b2b9f05eb45b52dd3cb4d97b96af06robertphillips@google.com
361f294b773f0b2b9f05eb45b52dd3cb4d97b96af06robertphillips@google.comvoid GrClipMaskManager::drawTexture(GrGpu* gpu,
362f294b773f0b2b9f05eb45b52dd3cb4d97b96af06robertphillips@google.com                                    GrTexture* target,
363f294b773f0b2b9f05eb45b52dd3cb4d97b96af06robertphillips@google.com                                    GrTexture* texture) {
364f294b773f0b2b9f05eb45b52dd3cb4d97b96af06robertphillips@google.com    GrDrawState* drawState = gpu->drawState();
365f294b773f0b2b9f05eb45b52dd3cb4d97b96af06robertphillips@google.com    GrAssert(NULL != drawState);
366f294b773f0b2b9f05eb45b52dd3cb4d97b96af06robertphillips@google.com
367f294b773f0b2b9f05eb45b52dd3cb4d97b96af06robertphillips@google.com    // no AA here since it is encoded in the texture
368f294b773f0b2b9f05eb45b52dd3cb4d97b96af06robertphillips@google.com    drawState->setRenderTarget(target->asRenderTarget());
369f294b773f0b2b9f05eb45b52dd3cb4d97b96af06robertphillips@google.com
370f294b773f0b2b9f05eb45b52dd3cb4d97b96af06robertphillips@google.com    GrMatrix sampleM;
371f294b773f0b2b9f05eb45b52dd3cb4d97b96af06robertphillips@google.com    sampleM.setIDiv(texture->width(), texture->height());
372f294b773f0b2b9f05eb45b52dd3cb4d97b96af06robertphillips@google.com    drawState->setTexture(0, texture);
373f294b773f0b2b9f05eb45b52dd3cb4d97b96af06robertphillips@google.com
374f294b773f0b2b9f05eb45b52dd3cb4d97b96af06robertphillips@google.com    drawState->sampler(0)->reset(GrSamplerState::kClamp_WrapMode,
375f294b773f0b2b9f05eb45b52dd3cb4d97b96af06robertphillips@google.com                                 GrSamplerState::kNearest_Filter,
376f294b773f0b2b9f05eb45b52dd3cb4d97b96af06robertphillips@google.com                                 sampleM);
377f294b773f0b2b9f05eb45b52dd3cb4d97b96af06robertphillips@google.com
378f105b109264f71dfb0bfd9977e6a5dd0a5a12f57robertphillips@google.com    GrRect rect = GrRect::MakeWH(SkIntToScalar(target->width()),
379f105b109264f71dfb0bfd9977e6a5dd0a5a12f57robertphillips@google.com                                 SkIntToScalar(target->height()));
380f105b109264f71dfb0bfd9977e6a5dd0a5a12f57robertphillips@google.com
381f294b773f0b2b9f05eb45b52dd3cb4d97b96af06robertphillips@google.com    gpu->drawSimpleRect(rect, NULL, 1 << 0);
382f294b773f0b2b9f05eb45b52dd3cb4d97b96af06robertphillips@google.com
383f294b773f0b2b9f05eb45b52dd3cb4d97b96af06robertphillips@google.com    drawState->setTexture(0, NULL);
384f294b773f0b2b9f05eb45b52dd3cb4d97b96af06robertphillips@google.com}
385f294b773f0b2b9f05eb45b52dd3cb4d97b96af06robertphillips@google.com
386f294b773f0b2b9f05eb45b52dd3cb4d97b96af06robertphillips@google.comnamespace {
387f294b773f0b2b9f05eb45b52dd3cb4d97b96af06robertphillips@google.com
388f294b773f0b2b9f05eb45b52dd3cb4d97b96af06robertphillips@google.comvoid clear(GrGpu* gpu,
389f294b773f0b2b9f05eb45b52dd3cb4d97b96af06robertphillips@google.com           GrTexture* target,
390f294b773f0b2b9f05eb45b52dd3cb4d97b96af06robertphillips@google.com           GrColor color) {
391f294b773f0b2b9f05eb45b52dd3cb4d97b96af06robertphillips@google.com    GrDrawState* drawState = gpu->drawState();
392f294b773f0b2b9f05eb45b52dd3cb4d97b96af06robertphillips@google.com    GrAssert(NULL != drawState);
393f294b773f0b2b9f05eb45b52dd3cb4d97b96af06robertphillips@google.com
394f294b773f0b2b9f05eb45b52dd3cb4d97b96af06robertphillips@google.com    // zap entire target to specified color
395f294b773f0b2b9f05eb45b52dd3cb4d97b96af06robertphillips@google.com    drawState->setRenderTarget(target->asRenderTarget());
396f294b773f0b2b9f05eb45b52dd3cb4d97b96af06robertphillips@google.com    gpu->clear(NULL, color);
397f294b773f0b2b9f05eb45b52dd3cb4d97b96af06robertphillips@google.com}
398f294b773f0b2b9f05eb45b52dd3cb4d97b96af06robertphillips@google.com
399f105b109264f71dfb0bfd9977e6a5dd0a5a12f57robertphillips@google.com}
400f105b109264f71dfb0bfd9977e6a5dd0a5a12f57robertphillips@google.com
4016d62df404bf420bedff4d7b5edd061740a673d44robertphillips@google.com// get a texture to act as a temporary buffer for AA clip boolean operations
4026d62df404bf420bedff4d7b5edd061740a673d44robertphillips@google.com// TODO: given the expense of createTexture we may want to just cache this too
4036623fcd1ee33b35fa18e304e9c76272faa603cbfrobertphillips@google.comvoid GrClipMaskManager::getTemp(const GrIRect& bounds,
404f105b109264f71dfb0bfd9977e6a5dd0a5a12f57robertphillips@google.com                                GrAutoScratchTexture* temp) {
405f105b109264f71dfb0bfd9977e6a5dd0a5a12f57robertphillips@google.com    if (NULL != temp->texture()) {
4066d62df404bf420bedff4d7b5edd061740a673d44robertphillips@google.com        // we've already allocated the temp texture
4076d62df404bf420bedff4d7b5edd061740a673d44robertphillips@google.com        return;
4086d62df404bf420bedff4d7b5edd061740a673d44robertphillips@google.com    }
4096d62df404bf420bedff4d7b5edd061740a673d44robertphillips@google.com
4106b70a7bd3328ea0a12be47b1a7f835c905f16147robertphillips@google.com    const GrTextureDesc desc = {
4116b70a7bd3328ea0a12be47b1a7f835c905f16147robertphillips@google.com        kRenderTarget_GrTextureFlagBit|kNoStencil_GrTextureFlagBit,
4126623fcd1ee33b35fa18e304e9c76272faa603cbfrobertphillips@google.com        bounds.width(),
4136623fcd1ee33b35fa18e304e9c76272faa603cbfrobertphillips@google.com        bounds.height(),
4146b70a7bd3328ea0a12be47b1a7f835c905f16147robertphillips@google.com        kAlpha_8_GrPixelConfig,
4156b70a7bd3328ea0a12be47b1a7f835c905f16147robertphillips@google.com        0           // samples
4166b70a7bd3328ea0a12be47b1a7f835c905f16147robertphillips@google.com    };
4176b70a7bd3328ea0a12be47b1a7f835c905f16147robertphillips@google.com
418f105b109264f71dfb0bfd9977e6a5dd0a5a12f57robertphillips@google.com    temp->set(fAACache.getContext(), desc);
4196d62df404bf420bedff4d7b5edd061740a673d44robertphillips@google.com}
4206d62df404bf420bedff4d7b5edd061740a673d44robertphillips@google.com
4216d62df404bf420bedff4d7b5edd061740a673d44robertphillips@google.com
422f105b109264f71dfb0bfd9977e6a5dd0a5a12f57robertphillips@google.comvoid GrClipMaskManager::setupCache(const GrClip& clipIn,
4236623fcd1ee33b35fa18e304e9c76272faa603cbfrobertphillips@google.com                                   const GrIRect& bounds) {
424f105b109264f71dfb0bfd9977e6a5dd0a5a12f57robertphillips@google.com    // Since we are setting up the cache we know the last lookup was a miss
425f105b109264f71dfb0bfd9977e6a5dd0a5a12f57robertphillips@google.com    // Free up the currently cached mask so it can be reused
426f105b109264f71dfb0bfd9977e6a5dd0a5a12f57robertphillips@google.com    fAACache.reset();
4276d62df404bf420bedff4d7b5edd061740a673d44robertphillips@google.com
428f105b109264f71dfb0bfd9977e6a5dd0a5a12f57robertphillips@google.com    const GrTextureDesc desc = {
429f105b109264f71dfb0bfd9977e6a5dd0a5a12f57robertphillips@google.com        kRenderTarget_GrTextureFlagBit|kNoStencil_GrTextureFlagBit,
4306623fcd1ee33b35fa18e304e9c76272faa603cbfrobertphillips@google.com        bounds.width(),
4316623fcd1ee33b35fa18e304e9c76272faa603cbfrobertphillips@google.com        bounds.height(),
432f105b109264f71dfb0bfd9977e6a5dd0a5a12f57robertphillips@google.com        kAlpha_8_GrPixelConfig,
433f105b109264f71dfb0bfd9977e6a5dd0a5a12f57robertphillips@google.com        0           // samples
434f105b109264f71dfb0bfd9977e6a5dd0a5a12f57robertphillips@google.com    };
435f294b773f0b2b9f05eb45b52dd3cb4d97b96af06robertphillips@google.com
436f105b109264f71dfb0bfd9977e6a5dd0a5a12f57robertphillips@google.com    fAACache.acquireMask(clipIn, desc, bounds);
437f105b109264f71dfb0bfd9977e6a5dd0a5a12f57robertphillips@google.com}
438f294b773f0b2b9f05eb45b52dd3cb4d97b96af06robertphillips@google.com
4396b70a7bd3328ea0a12be47b1a7f835c905f16147robertphillips@google.com////////////////////////////////////////////////////////////////////////////////
4406b70a7bd3328ea0a12be47b1a7f835c905f16147robertphillips@google.com// Shared preamble between gpu and SW-only AA clip mask creation paths.
4416b70a7bd3328ea0a12be47b1a7f835c905f16147robertphillips@google.com// Handles caching, determination of clip mask bound & allocation (if needed)
4426b70a7bd3328ea0a12be47b1a7f835c905f16147robertphillips@google.com// of the result texture
4436b70a7bd3328ea0a12be47b1a7f835c905f16147robertphillips@google.com// Returns true if there is no more work to be done (i.e., we got a cache hit)
4446b70a7bd3328ea0a12be47b1a7f835c905f16147robertphillips@google.combool GrClipMaskManager::clipMaskPreamble(GrGpu* gpu,
4456b70a7bd3328ea0a12be47b1a7f835c905f16147robertphillips@google.com                                         const GrClip& clipIn,
4466b70a7bd3328ea0a12be47b1a7f835c905f16147robertphillips@google.com                                         GrTexture** result,
4476623fcd1ee33b35fa18e304e9c76272faa603cbfrobertphillips@google.com                                         GrIRect *resultBounds) {
448f294b773f0b2b9f05eb45b52dd3cb4d97b96af06robertphillips@google.com    GrDrawState* origDrawState = gpu->drawState();
449f294b773f0b2b9f05eb45b52dd3cb4d97b96af06robertphillips@google.com    GrAssert(origDrawState->isClipState());
450f294b773f0b2b9f05eb45b52dd3cb4d97b96af06robertphillips@google.com
451f294b773f0b2b9f05eb45b52dd3cb4d97b96af06robertphillips@google.com    GrRenderTarget* rt = origDrawState->getRenderTarget();
452f294b773f0b2b9f05eb45b52dd3cb4d97b96af06robertphillips@google.com    GrAssert(NULL != rt);
453f294b773f0b2b9f05eb45b52dd3cb4d97b96af06robertphillips@google.com
454f294b773f0b2b9f05eb45b52dd3cb4d97b96af06robertphillips@google.com    GrRect rtRect;
455f294b773f0b2b9f05eb45b52dd3cb4d97b96af06robertphillips@google.com    rtRect.setLTRB(0, 0,
456f294b773f0b2b9f05eb45b52dd3cb4d97b96af06robertphillips@google.com                    GrIntToScalar(rt->width()), GrIntToScalar(rt->height()));
457f294b773f0b2b9f05eb45b52dd3cb4d97b96af06robertphillips@google.com
458f294b773f0b2b9f05eb45b52dd3cb4d97b96af06robertphillips@google.com    // unlike the stencil path the alpha path is not bound to the size of the
459f294b773f0b2b9f05eb45b52dd3cb4d97b96af06robertphillips@google.com    // render target - determine the minimum size required for the mask
460f294b773f0b2b9f05eb45b52dd3cb4d97b96af06robertphillips@google.com    GrRect bounds;
461f294b773f0b2b9f05eb45b52dd3cb4d97b96af06robertphillips@google.com
462f294b773f0b2b9f05eb45b52dd3cb4d97b96af06robertphillips@google.com    if (clipIn.hasConservativeBounds()) {
463f294b773f0b2b9f05eb45b52dd3cb4d97b96af06robertphillips@google.com        bounds = clipIn.getConservativeBounds();
464f294b773f0b2b9f05eb45b52dd3cb4d97b96af06robertphillips@google.com        if (!bounds.intersect(rtRect)) {
465f294b773f0b2b9f05eb45b52dd3cb4d97b96af06robertphillips@google.com            // the mask will be empty in this case
466f294b773f0b2b9f05eb45b52dd3cb4d97b96af06robertphillips@google.com            GrAssert(false);
467f294b773f0b2b9f05eb45b52dd3cb4d97b96af06robertphillips@google.com            bounds.setEmpty();
468f294b773f0b2b9f05eb45b52dd3cb4d97b96af06robertphillips@google.com        }
469f294b773f0b2b9f05eb45b52dd3cb4d97b96af06robertphillips@google.com    } else {
470f294b773f0b2b9f05eb45b52dd3cb4d97b96af06robertphillips@google.com        // still locked to the size of the render target
471f294b773f0b2b9f05eb45b52dd3cb4d97b96af06robertphillips@google.com        bounds = rtRect;
472f294b773f0b2b9f05eb45b52dd3cb4d97b96af06robertphillips@google.com    }
473f294b773f0b2b9f05eb45b52dd3cb4d97b96af06robertphillips@google.com
4746623fcd1ee33b35fa18e304e9c76272faa603cbfrobertphillips@google.com    GrIRect intBounds;
4756623fcd1ee33b35fa18e304e9c76272faa603cbfrobertphillips@google.com    bounds.roundOut(&intBounds);
476f294b773f0b2b9f05eb45b52dd3cb4d97b96af06robertphillips@google.com
477f294b773f0b2b9f05eb45b52dd3cb4d97b96af06robertphillips@google.com    // need to outset a pixel since the standard bounding box computation
478f294b773f0b2b9f05eb45b52dd3cb4d97b96af06robertphillips@google.com    // path doesn't leave any room for antialiasing (esp. w.r.t. rects)
4796623fcd1ee33b35fa18e304e9c76272faa603cbfrobertphillips@google.com    intBounds.outset(1, 1);
480f294b773f0b2b9f05eb45b52dd3cb4d97b96af06robertphillips@google.com
481a72eef322c686954cdffa849dc26d8133b802f1drobertphillips@google.com    // TODO: make sure we don't outset if bounds are still 0,0 @ min
482a72eef322c686954cdffa849dc26d8133b802f1drobertphillips@google.com
4838fff356c8505f2ac78e1fc9dc17c1192e3a608e4robertphillips@google.com    if (fAACache.canReuse(clipIn,
4846623fcd1ee33b35fa18e304e9c76272faa603cbfrobertphillips@google.com                          intBounds.width(),
4856623fcd1ee33b35fa18e304e9c76272faa603cbfrobertphillips@google.com                          intBounds.height())) {
4868fff356c8505f2ac78e1fc9dc17c1192e3a608e4robertphillips@google.com        *result = fAACache.getLastMask();
4878fff356c8505f2ac78e1fc9dc17c1192e3a608e4robertphillips@google.com        fAACache.getLastBound(resultBounds);
4888fff356c8505f2ac78e1fc9dc17c1192e3a608e4robertphillips@google.com        return true;
4898fff356c8505f2ac78e1fc9dc17c1192e3a608e4robertphillips@google.com    }
4908fff356c8505f2ac78e1fc9dc17c1192e3a608e4robertphillips@google.com
4916623fcd1ee33b35fa18e304e9c76272faa603cbfrobertphillips@google.com    this->setupCache(clipIn, intBounds);
492f105b109264f71dfb0bfd9977e6a5dd0a5a12f57robertphillips@google.com
4936623fcd1ee33b35fa18e304e9c76272faa603cbfrobertphillips@google.com    *resultBounds = intBounds;
4946b70a7bd3328ea0a12be47b1a7f835c905f16147robertphillips@google.com    return false;
4956b70a7bd3328ea0a12be47b1a7f835c905f16147robertphillips@google.com}
496f294b773f0b2b9f05eb45b52dd3cb4d97b96af06robertphillips@google.com
4976b70a7bd3328ea0a12be47b1a7f835c905f16147robertphillips@google.com////////////////////////////////////////////////////////////////////////////////
4986b70a7bd3328ea0a12be47b1a7f835c905f16147robertphillips@google.com// Create a 8-bit clip mask in alpha
4996b70a7bd3328ea0a12be47b1a7f835c905f16147robertphillips@google.combool GrClipMaskManager::createAlphaClipMask(GrGpu* gpu,
5006b70a7bd3328ea0a12be47b1a7f835c905f16147robertphillips@google.com                                            const GrClip& clipIn,
5016b70a7bd3328ea0a12be47b1a7f835c905f16147robertphillips@google.com                                            GrTexture** result,
5026623fcd1ee33b35fa18e304e9c76272faa603cbfrobertphillips@google.com                                            GrIRect *resultBounds) {
5036b70a7bd3328ea0a12be47b1a7f835c905f16147robertphillips@google.com
504f105b109264f71dfb0bfd9977e6a5dd0a5a12f57robertphillips@google.com    if (this->clipMaskPreamble(gpu, clipIn, result, resultBounds)) {
5056b70a7bd3328ea0a12be47b1a7f835c905f16147robertphillips@google.com        return true;
5066b70a7bd3328ea0a12be47b1a7f835c905f16147robertphillips@google.com    }
507f294b773f0b2b9f05eb45b52dd3cb4d97b96af06robertphillips@google.com
508f105b109264f71dfb0bfd9977e6a5dd0a5a12f57robertphillips@google.com    GrTexture* accum = fAACache.getLastMask();
5096d62df404bf420bedff4d7b5edd061740a673d44robertphillips@google.com    if (NULL == accum) {
510f294b773f0b2b9f05eb45b52dd3cb4d97b96af06robertphillips@google.com        fClipMaskInAlpha = false;
511f105b109264f71dfb0bfd9977e6a5dd0a5a12f57robertphillips@google.com        fAACache.reset();
512f294b773f0b2b9f05eb45b52dd3cb4d97b96af06robertphillips@google.com        return false;
513f294b773f0b2b9f05eb45b52dd3cb4d97b96af06robertphillips@google.com    }
514f294b773f0b2b9f05eb45b52dd3cb4d97b96af06robertphillips@google.com
515f294b773f0b2b9f05eb45b52dd3cb4d97b96af06robertphillips@google.com    GrDrawTarget::AutoStateRestore asr(gpu, GrDrawTarget::kReset_ASRInit);
516f294b773f0b2b9f05eb45b52dd3cb4d97b96af06robertphillips@google.com    GrDrawState* drawState = gpu->drawState();
517f294b773f0b2b9f05eb45b52dd3cb4d97b96af06robertphillips@google.com
518f294b773f0b2b9f05eb45b52dd3cb4d97b96af06robertphillips@google.com    GrDrawTarget::AutoGeometryPush agp(gpu);
519f294b773f0b2b9f05eb45b52dd3cb4d97b96af06robertphillips@google.com
520f294b773f0b2b9f05eb45b52dd3cb4d97b96af06robertphillips@google.com    int count = clipIn.getElementCount();
521f294b773f0b2b9f05eb45b52dd3cb4d97b96af06robertphillips@google.com
5226b70a7bd3328ea0a12be47b1a7f835c905f16147robertphillips@google.com    if (0 != resultBounds->fTop || 0 != resultBounds->fLeft) {
523f294b773f0b2b9f05eb45b52dd3cb4d97b96af06robertphillips@google.com        // if we were able to trim down the size of the mask we need to
524f294b773f0b2b9f05eb45b52dd3cb4d97b96af06robertphillips@google.com        // offset the paths & rects that will be used to compute it
525f294b773f0b2b9f05eb45b52dd3cb4d97b96af06robertphillips@google.com        GrMatrix m;
526f294b773f0b2b9f05eb45b52dd3cb4d97b96af06robertphillips@google.com
5276623fcd1ee33b35fa18e304e9c76272faa603cbfrobertphillips@google.com        m.setTranslate(SkIntToScalar(-resultBounds->fLeft),
5286623fcd1ee33b35fa18e304e9c76272faa603cbfrobertphillips@google.com                       SkIntToScalar(-resultBounds->fTop));
529f294b773f0b2b9f05eb45b52dd3cb4d97b96af06robertphillips@google.com
5306d62df404bf420bedff4d7b5edd061740a673d44robertphillips@google.com        drawState->setViewMatrix(m);
531f294b773f0b2b9f05eb45b52dd3cb4d97b96af06robertphillips@google.com    }
532f294b773f0b2b9f05eb45b52dd3cb4d97b96af06robertphillips@google.com
533f294b773f0b2b9f05eb45b52dd3cb4d97b96af06robertphillips@google.com    bool clearToInside;
534f294b773f0b2b9f05eb45b52dd3cb4d97b96af06robertphillips@google.com    SkRegion::Op startOp = SkRegion::kReplace_Op; // suppress warning
535f294b773f0b2b9f05eb45b52dd3cb4d97b96af06robertphillips@google.com    int start = process_initial_clip_elements(clipIn,
5366b70a7bd3328ea0a12be47b1a7f835c905f16147robertphillips@google.com                                              *resultBounds,
537f294b773f0b2b9f05eb45b52dd3cb4d97b96af06robertphillips@google.com                                              &clearToInside,
538f294b773f0b2b9f05eb45b52dd3cb4d97b96af06robertphillips@google.com                                              &startOp);
539f294b773f0b2b9f05eb45b52dd3cb4d97b96af06robertphillips@google.com
5406d62df404bf420bedff4d7b5edd061740a673d44robertphillips@google.com    clear(gpu, accum, clearToInside ? 0xffffffff : 0x00000000);
541f294b773f0b2b9f05eb45b52dd3cb4d97b96af06robertphillips@google.com
542f105b109264f71dfb0bfd9977e6a5dd0a5a12f57robertphillips@google.com    GrAutoScratchTexture temp;
5436b70a7bd3328ea0a12be47b1a7f835c905f16147robertphillips@google.com
544f294b773f0b2b9f05eb45b52dd3cb4d97b96af06robertphillips@google.com    // walk through each clip element and perform its set op
545f294b773f0b2b9f05eb45b52dd3cb4d97b96af06robertphillips@google.com    for (int c = start; c < count; ++c) {
546f294b773f0b2b9f05eb45b52dd3cb4d97b96af06robertphillips@google.com
547f294b773f0b2b9f05eb45b52dd3cb4d97b96af06robertphillips@google.com        SkRegion::Op op = (c == start) ? startOp : clipIn.getOp(c);
548f294b773f0b2b9f05eb45b52dd3cb4d97b96af06robertphillips@google.com
549f294b773f0b2b9f05eb45b52dd3cb4d97b96af06robertphillips@google.com        if (SkRegion::kReplace_Op == op) {
550f294b773f0b2b9f05eb45b52dd3cb4d97b96af06robertphillips@google.com            // TODO: replace is actually a lot faster then intersection
551f294b773f0b2b9f05eb45b52dd3cb4d97b96af06robertphillips@google.com            // for this path - refactor the stencil path so it can handle
552f294b773f0b2b9f05eb45b52dd3cb4d97b96af06robertphillips@google.com            // replace ops and alter GrClip to allow them through
553f294b773f0b2b9f05eb45b52dd3cb4d97b96af06robertphillips@google.com
554f294b773f0b2b9f05eb45b52dd3cb4d97b96af06robertphillips@google.com            // clear the accumulator and draw the new object directly into it
5556d62df404bf420bedff4d7b5edd061740a673d44robertphillips@google.com            clear(gpu, accum, 0x00000000);
556f294b773f0b2b9f05eb45b52dd3cb4d97b96af06robertphillips@google.com
5576b70a7bd3328ea0a12be47b1a7f835c905f16147robertphillips@google.com            setup_boolean_blendcoeffs(drawState, op);
558f294b773f0b2b9f05eb45b52dd3cb4d97b96af06robertphillips@google.com            this->drawClipShape(gpu, accum, clipIn, c);
559f294b773f0b2b9f05eb45b52dd3cb4d97b96af06robertphillips@google.com
560f294b773f0b2b9f05eb45b52dd3cb4d97b96af06robertphillips@google.com        } else if (SkRegion::kReverseDifference_Op == op ||
561f294b773f0b2b9f05eb45b52dd3cb4d97b96af06robertphillips@google.com                   SkRegion::kIntersect_Op == op) {
562f294b773f0b2b9f05eb45b52dd3cb4d97b96af06robertphillips@google.com            // there is no point in intersecting a screen filling rectangle.
563f294b773f0b2b9f05eb45b52dd3cb4d97b96af06robertphillips@google.com            if (SkRegion::kIntersect_Op == op &&
564f294b773f0b2b9f05eb45b52dd3cb4d97b96af06robertphillips@google.com                kRect_ClipType == clipIn.getElementType(c) &&
5656623fcd1ee33b35fa18e304e9c76272faa603cbfrobertphillips@google.com                contains(clipIn.getRect(c), *resultBounds)) {
566f294b773f0b2b9f05eb45b52dd3cb4d97b96af06robertphillips@google.com                continue;
567f294b773f0b2b9f05eb45b52dd3cb4d97b96af06robertphillips@google.com            }
568f294b773f0b2b9f05eb45b52dd3cb4d97b96af06robertphillips@google.com
569f105b109264f71dfb0bfd9977e6a5dd0a5a12f57robertphillips@google.com            getTemp(*resultBounds, &temp);
570f105b109264f71dfb0bfd9977e6a5dd0a5a12f57robertphillips@google.com            if (NULL == temp.texture()) {
5716d62df404bf420bedff4d7b5edd061740a673d44robertphillips@google.com                fClipMaskInAlpha = false;
572f105b109264f71dfb0bfd9977e6a5dd0a5a12f57robertphillips@google.com                fAACache.reset();
5736d62df404bf420bedff4d7b5edd061740a673d44robertphillips@google.com                return false;
5746d62df404bf420bedff4d7b5edd061740a673d44robertphillips@google.com            }
5756d62df404bf420bedff4d7b5edd061740a673d44robertphillips@google.com
576f294b773f0b2b9f05eb45b52dd3cb4d97b96af06robertphillips@google.com            // clear the temp target & draw into it
577f105b109264f71dfb0bfd9977e6a5dd0a5a12f57robertphillips@google.com            clear(gpu, temp.texture(), 0x00000000);
578f294b773f0b2b9f05eb45b52dd3cb4d97b96af06robertphillips@google.com
5796b70a7bd3328ea0a12be47b1a7f835c905f16147robertphillips@google.com            setup_boolean_blendcoeffs(drawState, SkRegion::kReplace_Op);
580f105b109264f71dfb0bfd9977e6a5dd0a5a12f57robertphillips@google.com            this->drawClipShape(gpu, temp.texture(), clipIn, c);
581f294b773f0b2b9f05eb45b52dd3cb4d97b96af06robertphillips@google.com
582f294b773f0b2b9f05eb45b52dd3cb4d97b96af06robertphillips@google.com            // TODO: rather than adding these two translations here
583f294b773f0b2b9f05eb45b52dd3cb4d97b96af06robertphillips@google.com            // compute the bounding box needed to render the texture
584f294b773f0b2b9f05eb45b52dd3cb4d97b96af06robertphillips@google.com            // into temp
5856b70a7bd3328ea0a12be47b1a7f835c905f16147robertphillips@google.com            if (0 != resultBounds->fTop || 0 != resultBounds->fLeft) {
586f294b773f0b2b9f05eb45b52dd3cb4d97b96af06robertphillips@google.com                GrMatrix m;
587f294b773f0b2b9f05eb45b52dd3cb4d97b96af06robertphillips@google.com
5886623fcd1ee33b35fa18e304e9c76272faa603cbfrobertphillips@google.com                m.setTranslate(SkIntToScalar(resultBounds->fLeft),
5896623fcd1ee33b35fa18e304e9c76272faa603cbfrobertphillips@google.com                               SkIntToScalar(resultBounds->fTop));
590f294b773f0b2b9f05eb45b52dd3cb4d97b96af06robertphillips@google.com
591f294b773f0b2b9f05eb45b52dd3cb4d97b96af06robertphillips@google.com                drawState->preConcatViewMatrix(m);
592f294b773f0b2b9f05eb45b52dd3cb4d97b96af06robertphillips@google.com            }
593f294b773f0b2b9f05eb45b52dd3cb4d97b96af06robertphillips@google.com
594f294b773f0b2b9f05eb45b52dd3cb4d97b96af06robertphillips@google.com            // Now draw into the accumulator using the real operation
595f294b773f0b2b9f05eb45b52dd3cb4d97b96af06robertphillips@google.com            // and the temp buffer as a texture
5966b70a7bd3328ea0a12be47b1a7f835c905f16147robertphillips@google.com            setup_boolean_blendcoeffs(drawState, op);
597f105b109264f71dfb0bfd9977e6a5dd0a5a12f57robertphillips@google.com            this->drawTexture(gpu, accum, temp.texture());
598f294b773f0b2b9f05eb45b52dd3cb4d97b96af06robertphillips@google.com
5996b70a7bd3328ea0a12be47b1a7f835c905f16147robertphillips@google.com            if (0 != resultBounds->fTop || 0 != resultBounds->fLeft) {
600f294b773f0b2b9f05eb45b52dd3cb4d97b96af06robertphillips@google.com                GrMatrix m;
601f294b773f0b2b9f05eb45b52dd3cb4d97b96af06robertphillips@google.com
6026623fcd1ee33b35fa18e304e9c76272faa603cbfrobertphillips@google.com                m.setTranslate(SkIntToScalar(-resultBounds->fLeft),
6036623fcd1ee33b35fa18e304e9c76272faa603cbfrobertphillips@google.com                               SkIntToScalar(-resultBounds->fTop));
604f294b773f0b2b9f05eb45b52dd3cb4d97b96af06robertphillips@google.com
605f294b773f0b2b9f05eb45b52dd3cb4d97b96af06robertphillips@google.com                drawState->preConcatViewMatrix(m);
606f294b773f0b2b9f05eb45b52dd3cb4d97b96af06robertphillips@google.com            }
607f294b773f0b2b9f05eb45b52dd3cb4d97b96af06robertphillips@google.com
608f294b773f0b2b9f05eb45b52dd3cb4d97b96af06robertphillips@google.com        } else {
609f294b773f0b2b9f05eb45b52dd3cb4d97b96af06robertphillips@google.com            // all the remaining ops can just be directly draw into
610f294b773f0b2b9f05eb45b52dd3cb4d97b96af06robertphillips@google.com            // the accumulation buffer
6116b70a7bd3328ea0a12be47b1a7f835c905f16147robertphillips@google.com            setup_boolean_blendcoeffs(drawState, op);
612f294b773f0b2b9f05eb45b52dd3cb4d97b96af06robertphillips@google.com            this->drawClipShape(gpu, accum, clipIn, c);
613f294b773f0b2b9f05eb45b52dd3cb4d97b96af06robertphillips@google.com        }
614f294b773f0b2b9f05eb45b52dd3cb4d97b96af06robertphillips@google.com    }
615f294b773f0b2b9f05eb45b52dd3cb4d97b96af06robertphillips@google.com
616a72eef322c686954cdffa849dc26d8133b802f1drobertphillips@google.com    *result = accum;
6176d62df404bf420bedff4d7b5edd061740a673d44robertphillips@google.com
618f294b773f0b2b9f05eb45b52dd3cb4d97b96af06robertphillips@google.com    return true;
6191e945b7e708c633d4aed937ebfce57d52ba21d83robertphillips@google.com}
6201e945b7e708c633d4aed937ebfce57d52ba21d83robertphillips@google.com
621f294b773f0b2b9f05eb45b52dd3cb4d97b96af06robertphillips@google.com////////////////////////////////////////////////////////////////////////////////
6221e945b7e708c633d4aed937ebfce57d52ba21d83robertphillips@google.com// Create a 1-bit clip mask in the stencil buffer
6231e945b7e708c633d4aed937ebfce57d52ba21d83robertphillips@google.combool GrClipMaskManager::createStencilClipMask(GrGpu* gpu,
6241e945b7e708c633d4aed937ebfce57d52ba21d83robertphillips@google.com                                              const GrClip& clipIn,
6251e945b7e708c633d4aed937ebfce57d52ba21d83robertphillips@google.com                                              const GrRect& bounds,
6261e945b7e708c633d4aed937ebfce57d52ba21d83robertphillips@google.com                                              ScissoringSettings* scissorSettings) {
6271e945b7e708c633d4aed937ebfce57d52ba21d83robertphillips@google.com
6281e945b7e708c633d4aed937ebfce57d52ba21d83robertphillips@google.com    GrAssert(fClipMaskInStencil);
6291e945b7e708c633d4aed937ebfce57d52ba21d83robertphillips@google.com
6301e945b7e708c633d4aed937ebfce57d52ba21d83robertphillips@google.com    GrDrawState* drawState = gpu->drawState();
6311e945b7e708c633d4aed937ebfce57d52ba21d83robertphillips@google.com    GrAssert(drawState->isClipState());
6321e945b7e708c633d4aed937ebfce57d52ba21d83robertphillips@google.com
6331e945b7e708c633d4aed937ebfce57d52ba21d83robertphillips@google.com    GrRenderTarget* rt = drawState->getRenderTarget();
6341e945b7e708c633d4aed937ebfce57d52ba21d83robertphillips@google.com    GrAssert(NULL != rt);
6351e945b7e708c633d4aed937ebfce57d52ba21d83robertphillips@google.com
6361e945b7e708c633d4aed937ebfce57d52ba21d83robertphillips@google.com    // TODO: dynamically attach a SB when needed.
6371e945b7e708c633d4aed937ebfce57d52ba21d83robertphillips@google.com    GrStencilBuffer* stencilBuffer = rt->getStencilBuffer();
6381e945b7e708c633d4aed937ebfce57d52ba21d83robertphillips@google.com    if (NULL == stencilBuffer) {
6391e945b7e708c633d4aed937ebfce57d52ba21d83robertphillips@google.com        return false;
6401e945b7e708c633d4aed937ebfce57d52ba21d83robertphillips@google.com    }
6411e945b7e708c633d4aed937ebfce57d52ba21d83robertphillips@google.com
6421e945b7e708c633d4aed937ebfce57d52ba21d83robertphillips@google.com    if (stencilBuffer->mustRenderClip(clipIn, rt->width(), rt->height())) {
6431e945b7e708c633d4aed937ebfce57d52ba21d83robertphillips@google.com
6441e945b7e708c633d4aed937ebfce57d52ba21d83robertphillips@google.com        stencilBuffer->setLastClip(clipIn, rt->width(), rt->height());
6451e945b7e708c633d4aed937ebfce57d52ba21d83robertphillips@google.com
6461e945b7e708c633d4aed937ebfce57d52ba21d83robertphillips@google.com        // we set the current clip to the bounds so that our recursive
6471e945b7e708c633d4aed937ebfce57d52ba21d83robertphillips@google.com        // draws are scissored to them. We use the copy of the complex clip
6481e945b7e708c633d4aed937ebfce57d52ba21d83robertphillips@google.com        // we just stashed on the SB to render from. We set it back after
6491e945b7e708c633d4aed937ebfce57d52ba21d83robertphillips@google.com        // we finish drawing it into the stencil.
6501e945b7e708c633d4aed937ebfce57d52ba21d83robertphillips@google.com        const GrClip& clipCopy = stencilBuffer->getLastClip();
6511e945b7e708c633d4aed937ebfce57d52ba21d83robertphillips@google.com        gpu->setClip(GrClip(bounds));
6521e945b7e708c633d4aed937ebfce57d52ba21d83robertphillips@google.com
6531e945b7e708c633d4aed937ebfce57d52ba21d83robertphillips@google.com        GrDrawTarget::AutoStateRestore asr(gpu, GrDrawTarget::kReset_ASRInit);
6541e945b7e708c633d4aed937ebfce57d52ba21d83robertphillips@google.com        drawState = gpu->drawState();
6551e945b7e708c633d4aed937ebfce57d52ba21d83robertphillips@google.com        drawState->setRenderTarget(rt);
6561e945b7e708c633d4aed937ebfce57d52ba21d83robertphillips@google.com        GrDrawTarget::AutoGeometryPush agp(gpu);
6571e945b7e708c633d4aed937ebfce57d52ba21d83robertphillips@google.com
6581e945b7e708c633d4aed937ebfce57d52ba21d83robertphillips@google.com        gpu->disableScissor();
6591e945b7e708c633d4aed937ebfce57d52ba21d83robertphillips@google.com#if !VISUALIZE_COMPLEX_CLIP
6601e945b7e708c633d4aed937ebfce57d52ba21d83robertphillips@google.com        drawState->enableState(GrDrawState::kNoColorWrites_StateBit);
6611e945b7e708c633d4aed937ebfce57d52ba21d83robertphillips@google.com#endif
6621e945b7e708c633d4aed937ebfce57d52ba21d83robertphillips@google.com
6631e945b7e708c633d4aed937ebfce57d52ba21d83robertphillips@google.com        int count = clipCopy.getElementCount();
6641e945b7e708c633d4aed937ebfce57d52ba21d83robertphillips@google.com        int clipBit = stencilBuffer->bits();
6651e945b7e708c633d4aed937ebfce57d52ba21d83robertphillips@google.com        SkASSERT((clipBit <= 16) &&
6661e945b7e708c633d4aed937ebfce57d52ba21d83robertphillips@google.com                    "Ganesh only handles 16b or smaller stencil buffers");
6671e945b7e708c633d4aed937ebfce57d52ba21d83robertphillips@google.com        clipBit = (1 << (clipBit-1));
6681e945b7e708c633d4aed937ebfce57d52ba21d83robertphillips@google.com
6696623fcd1ee33b35fa18e304e9c76272faa603cbfrobertphillips@google.com        GrIRect rtRect = GrIRect::MakeWH(rt->width(), rt->height());
6701e945b7e708c633d4aed937ebfce57d52ba21d83robertphillips@google.com
6711e945b7e708c633d4aed937ebfce57d52ba21d83robertphillips@google.com        bool clearToInside;
6720f191f30af7c067883c97b034baf70bfd92f5ea0robertphillips@google.com        SkRegion::Op startOp = SkRegion::kReplace_Op; // suppress warning
6731e945b7e708c633d4aed937ebfce57d52ba21d83robertphillips@google.com        int start = process_initial_clip_elements(clipCopy,
6741e945b7e708c633d4aed937ebfce57d52ba21d83robertphillips@google.com                                                    rtRect,
6751e945b7e708c633d4aed937ebfce57d52ba21d83robertphillips@google.com                                                    &clearToInside,
6761e945b7e708c633d4aed937ebfce57d52ba21d83robertphillips@google.com                                                    &startOp);
6771e945b7e708c633d4aed937ebfce57d52ba21d83robertphillips@google.com
6781e945b7e708c633d4aed937ebfce57d52ba21d83robertphillips@google.com        gpu->clearStencilClip(scissorSettings->fScissorRect, clearToInside);
6791e945b7e708c633d4aed937ebfce57d52ba21d83robertphillips@google.com
6801e945b7e708c633d4aed937ebfce57d52ba21d83robertphillips@google.com        // walk through each clip element and perform its set op
6811e945b7e708c633d4aed937ebfce57d52ba21d83robertphillips@google.com        // with the existing clip.
6821e945b7e708c633d4aed937ebfce57d52ba21d83robertphillips@google.com        for (int c = start; c < count; ++c) {
6831e945b7e708c633d4aed937ebfce57d52ba21d83robertphillips@google.com            GrPathFill fill;
6841e945b7e708c633d4aed937ebfce57d52ba21d83robertphillips@google.com            bool fillInverted;
6851e945b7e708c633d4aed937ebfce57d52ba21d83robertphillips@google.com            // enabled at bottom of loop
6861e945b7e708c633d4aed937ebfce57d52ba21d83robertphillips@google.com            drawState->disableState(GrGpu::kModifyStencilClip_StateBit);
6871e945b7e708c633d4aed937ebfce57d52ba21d83robertphillips@google.com
6881e945b7e708c633d4aed937ebfce57d52ba21d83robertphillips@google.com            bool canRenderDirectToStencil; // can the clip element be drawn
6896b70a7bd3328ea0a12be47b1a7f835c905f16147robertphillips@google.com                                           // directly to the stencil buffer
6906b70a7bd3328ea0a12be47b1a7f835c905f16147robertphillips@google.com                                           // with a non-inverted fill rule
6916b70a7bd3328ea0a12be47b1a7f835c905f16147robertphillips@google.com                                           // without extra passes to
6926b70a7bd3328ea0a12be47b1a7f835c905f16147robertphillips@google.com                                           // resolve in/out status.
6931e945b7e708c633d4aed937ebfce57d52ba21d83robertphillips@google.com
694f294b773f0b2b9f05eb45b52dd3cb4d97b96af06robertphillips@google.com            SkRegion::Op op = (c == start) ? startOp : clipCopy.getOp(c);
695f294b773f0b2b9f05eb45b52dd3cb4d97b96af06robertphillips@google.com
6961e945b7e708c633d4aed937ebfce57d52ba21d83robertphillips@google.com            GrPathRenderer* pr = NULL;
6978d033a1b125886c62906d975b5cc28a382064526bsalomon@google.com            const SkPath* clipPath = NULL;
6981e945b7e708c633d4aed937ebfce57d52ba21d83robertphillips@google.com            if (kRect_ClipType == clipCopy.getElementType(c)) {
6991e945b7e708c633d4aed937ebfce57d52ba21d83robertphillips@google.com                canRenderDirectToStencil = true;
7001e945b7e708c633d4aed937ebfce57d52ba21d83robertphillips@google.com                fill = kEvenOdd_PathFill;
7011e945b7e708c633d4aed937ebfce57d52ba21d83robertphillips@google.com                fillInverted = false;
7021e945b7e708c633d4aed937ebfce57d52ba21d83robertphillips@google.com                // there is no point in intersecting a screen filling
7031e945b7e708c633d4aed937ebfce57d52ba21d83robertphillips@google.com                // rectangle.
704f294b773f0b2b9f05eb45b52dd3cb4d97b96af06robertphillips@google.com                if (SkRegion::kIntersect_Op == op &&
7056623fcd1ee33b35fa18e304e9c76272faa603cbfrobertphillips@google.com                    contains(clipCopy.getRect(c), rtRect)) {
7061e945b7e708c633d4aed937ebfce57d52ba21d83robertphillips@google.com                    continue;
7071e945b7e708c633d4aed937ebfce57d52ba21d83robertphillips@google.com                }
7081e945b7e708c633d4aed937ebfce57d52ba21d83robertphillips@google.com            } else {
7091e945b7e708c633d4aed937ebfce57d52ba21d83robertphillips@google.com                fill = clipCopy.getPathFill(c);
7101e945b7e708c633d4aed937ebfce57d52ba21d83robertphillips@google.com                fillInverted = GrIsFillInverted(fill);
7111e945b7e708c633d4aed937ebfce57d52ba21d83robertphillips@google.com                fill = GrNonInvertedFill(fill);
7121e945b7e708c633d4aed937ebfce57d52ba21d83robertphillips@google.com                clipPath = &clipCopy.getPath(c);
713f294b773f0b2b9f05eb45b52dd3cb4d97b96af06robertphillips@google.com                pr = this->getClipPathRenderer(gpu, *clipPath, fill, false);
7141e945b7e708c633d4aed937ebfce57d52ba21d83robertphillips@google.com                if (NULL == pr) {
7151e945b7e708c633d4aed937ebfce57d52ba21d83robertphillips@google.com                    fClipMaskInStencil = false;
7161e945b7e708c633d4aed937ebfce57d52ba21d83robertphillips@google.com                    gpu->setClip(clipCopy);     // restore to the original
7171e945b7e708c633d4aed937ebfce57d52ba21d83robertphillips@google.com                    return false;
7181e945b7e708c633d4aed937ebfce57d52ba21d83robertphillips@google.com                }
7191e945b7e708c633d4aed937ebfce57d52ba21d83robertphillips@google.com                canRenderDirectToStencil =
7201e945b7e708c633d4aed937ebfce57d52ba21d83robertphillips@google.com                    !pr->requiresStencilPass(*clipPath, fill, gpu);
7211e945b7e708c633d4aed937ebfce57d52ba21d83robertphillips@google.com            }
7221e945b7e708c633d4aed937ebfce57d52ba21d83robertphillips@google.com
7231e945b7e708c633d4aed937ebfce57d52ba21d83robertphillips@google.com            int passes;
7241e945b7e708c633d4aed937ebfce57d52ba21d83robertphillips@google.com            GrStencilSettings stencilSettings[GrStencilSettings::kMaxStencilClipPasses];
7251e945b7e708c633d4aed937ebfce57d52ba21d83robertphillips@google.com
7261e945b7e708c633d4aed937ebfce57d52ba21d83robertphillips@google.com            bool canDrawDirectToClip; // Given the renderer, the element,
7271e945b7e708c633d4aed937ebfce57d52ba21d83robertphillips@google.com                                        // fill rule, and set operation can
7281e945b7e708c633d4aed937ebfce57d52ba21d83robertphillips@google.com                                        // we render the element directly to
7291e945b7e708c633d4aed937ebfce57d52ba21d83robertphillips@google.com                                        // stencil bit used for clipping.
7301e945b7e708c633d4aed937ebfce57d52ba21d83robertphillips@google.com            canDrawDirectToClip =
7311e945b7e708c633d4aed937ebfce57d52ba21d83robertphillips@google.com                GrStencilSettings::GetClipPasses(op,
7321e945b7e708c633d4aed937ebfce57d52ba21d83robertphillips@google.com                                                    canRenderDirectToStencil,
7331e945b7e708c633d4aed937ebfce57d52ba21d83robertphillips@google.com                                                    clipBit,
7341e945b7e708c633d4aed937ebfce57d52ba21d83robertphillips@google.com                                                    fillInverted,
7351e945b7e708c633d4aed937ebfce57d52ba21d83robertphillips@google.com                                                    &passes, stencilSettings);
7361e945b7e708c633d4aed937ebfce57d52ba21d83robertphillips@google.com
7371e945b7e708c633d4aed937ebfce57d52ba21d83robertphillips@google.com            // draw the element to the client stencil bits if necessary
7381e945b7e708c633d4aed937ebfce57d52ba21d83robertphillips@google.com            if (!canDrawDirectToClip) {
7391e945b7e708c633d4aed937ebfce57d52ba21d83robertphillips@google.com                GR_STATIC_CONST_SAME_STENCIL(gDrawToStencil,
7401e945b7e708c633d4aed937ebfce57d52ba21d83robertphillips@google.com                    kIncClamp_StencilOp,
7411e945b7e708c633d4aed937ebfce57d52ba21d83robertphillips@google.com                    kIncClamp_StencilOp,
7421e945b7e708c633d4aed937ebfce57d52ba21d83robertphillips@google.com                    kAlways_StencilFunc,
7431e945b7e708c633d4aed937ebfce57d52ba21d83robertphillips@google.com                    0xffff,
7441e945b7e708c633d4aed937ebfce57d52ba21d83robertphillips@google.com                    0x0000,
7451e945b7e708c633d4aed937ebfce57d52ba21d83robertphillips@google.com                    0xffff);
7461e945b7e708c633d4aed937ebfce57d52ba21d83robertphillips@google.com                SET_RANDOM_COLOR
7471e945b7e708c633d4aed937ebfce57d52ba21d83robertphillips@google.com                if (kRect_ClipType == clipCopy.getElementType(c)) {
7481e945b7e708c633d4aed937ebfce57d52ba21d83robertphillips@google.com                    *drawState->stencil() = gDrawToStencil;
7491e945b7e708c633d4aed937ebfce57d52ba21d83robertphillips@google.com                    gpu->drawSimpleRect(clipCopy.getRect(c), NULL, 0);
7501e945b7e708c633d4aed937ebfce57d52ba21d83robertphillips@google.com                } else {
7511e945b7e708c633d4aed937ebfce57d52ba21d83robertphillips@google.com                    if (canRenderDirectToStencil) {
7521e945b7e708c633d4aed937ebfce57d52ba21d83robertphillips@google.com                        *drawState->stencil() = gDrawToStencil;
7531e945b7e708c633d4aed937ebfce57d52ba21d83robertphillips@google.com                        pr->drawPath(*clipPath, fill, NULL, gpu, 0, false);
7541e945b7e708c633d4aed937ebfce57d52ba21d83robertphillips@google.com                    } else {
7551e945b7e708c633d4aed937ebfce57d52ba21d83robertphillips@google.com                        pr->drawPathToStencil(*clipPath, fill, gpu);
7561e945b7e708c633d4aed937ebfce57d52ba21d83robertphillips@google.com                    }
7571e945b7e708c633d4aed937ebfce57d52ba21d83robertphillips@google.com                }
7581e945b7e708c633d4aed937ebfce57d52ba21d83robertphillips@google.com            }
7591e945b7e708c633d4aed937ebfce57d52ba21d83robertphillips@google.com
7601e945b7e708c633d4aed937ebfce57d52ba21d83robertphillips@google.com            // now we modify the clip bit by rendering either the clip
7611e945b7e708c633d4aed937ebfce57d52ba21d83robertphillips@google.com            // element directly or a bounding rect of the entire clip.
7621e945b7e708c633d4aed937ebfce57d52ba21d83robertphillips@google.com            drawState->enableState(GrGpu::kModifyStencilClip_StateBit);
7631e945b7e708c633d4aed937ebfce57d52ba21d83robertphillips@google.com            for (int p = 0; p < passes; ++p) {
7641e945b7e708c633d4aed937ebfce57d52ba21d83robertphillips@google.com                *drawState->stencil() = stencilSettings[p];
7651e945b7e708c633d4aed937ebfce57d52ba21d83robertphillips@google.com                if (canDrawDirectToClip) {
7661e945b7e708c633d4aed937ebfce57d52ba21d83robertphillips@google.com                    if (kRect_ClipType == clipCopy.getElementType(c)) {
7671e945b7e708c633d4aed937ebfce57d52ba21d83robertphillips@google.com                        SET_RANDOM_COLOR
7681e945b7e708c633d4aed937ebfce57d52ba21d83robertphillips@google.com                        gpu->drawSimpleRect(clipCopy.getRect(c), NULL, 0);
7691e945b7e708c633d4aed937ebfce57d52ba21d83robertphillips@google.com                    } else {
7701e945b7e708c633d4aed937ebfce57d52ba21d83robertphillips@google.com                        SET_RANDOM_COLOR
7711e945b7e708c633d4aed937ebfce57d52ba21d83robertphillips@google.com                        pr->drawPath(*clipPath, fill, NULL, gpu, 0, false);
7721e945b7e708c633d4aed937ebfce57d52ba21d83robertphillips@google.com                    }
7731e945b7e708c633d4aed937ebfce57d52ba21d83robertphillips@google.com                } else {
7741e945b7e708c633d4aed937ebfce57d52ba21d83robertphillips@google.com                    SET_RANDOM_COLOR
7751e945b7e708c633d4aed937ebfce57d52ba21d83robertphillips@google.com                    gpu->drawSimpleRect(bounds, NULL, 0);
7761e945b7e708c633d4aed937ebfce57d52ba21d83robertphillips@google.com                }
7771e945b7e708c633d4aed937ebfce57d52ba21d83robertphillips@google.com            }
7781e945b7e708c633d4aed937ebfce57d52ba21d83robertphillips@google.com        }
7791e945b7e708c633d4aed937ebfce57d52ba21d83robertphillips@google.com        // restore clip
7801e945b7e708c633d4aed937ebfce57d52ba21d83robertphillips@google.com        gpu->setClip(clipCopy);
7811e945b7e708c633d4aed937ebfce57d52ba21d83robertphillips@google.com        // recusive draws would have disabled this since they drew with
7821e945b7e708c633d4aed937ebfce57d52ba21d83robertphillips@google.com        // the clip bounds as clip.
7831e945b7e708c633d4aed937ebfce57d52ba21d83robertphillips@google.com        fClipMaskInStencil = true;
7841e945b7e708c633d4aed937ebfce57d52ba21d83robertphillips@google.com    }
7851e945b7e708c633d4aed937ebfce57d52ba21d83robertphillips@google.com
7861e945b7e708c633d4aed937ebfce57d52ba21d83robertphillips@google.com    return true;
7871e945b7e708c633d4aed937ebfce57d52ba21d83robertphillips@google.com}
7881e945b7e708c633d4aed937ebfce57d52ba21d83robertphillips@google.com
789f294b773f0b2b9f05eb45b52dd3cb4d97b96af06robertphillips@google.com////////////////////////////////////////////////////////////////////////////////
7906b70a7bd3328ea0a12be47b1a7f835c905f16147robertphillips@google.combool GrClipMaskManager::createSoftwareClipMask(GrGpu* gpu,
7916b70a7bd3328ea0a12be47b1a7f835c905f16147robertphillips@google.com                                               const GrClip& clipIn,
7926b70a7bd3328ea0a12be47b1a7f835c905f16147robertphillips@google.com                                               GrTexture** result,
7936623fcd1ee33b35fa18e304e9c76272faa603cbfrobertphillips@google.com                                               GrIRect *resultBounds) {
7946b70a7bd3328ea0a12be47b1a7f835c905f16147robertphillips@google.com
795f105b109264f71dfb0bfd9977e6a5dd0a5a12f57robertphillips@google.com    if (this->clipMaskPreamble(gpu, clipIn, result, resultBounds)) {
7966b70a7bd3328ea0a12be47b1a7f835c905f16147robertphillips@google.com        return true;
7976b70a7bd3328ea0a12be47b1a7f835c905f16147robertphillips@google.com    }
7986b70a7bd3328ea0a12be47b1a7f835c905f16147robertphillips@google.com
799f105b109264f71dfb0bfd9977e6a5dd0a5a12f57robertphillips@google.com    GrTexture* accum = fAACache.getLastMask();
8006b70a7bd3328ea0a12be47b1a7f835c905f16147robertphillips@google.com    if (NULL == accum) {
8016b70a7bd3328ea0a12be47b1a7f835c905f16147robertphillips@google.com        fClipMaskInAlpha = false;
802f105b109264f71dfb0bfd9977e6a5dd0a5a12f57robertphillips@google.com        fAACache.reset();
8036b70a7bd3328ea0a12be47b1a7f835c905f16147robertphillips@google.com        return false;
8046b70a7bd3328ea0a12be47b1a7f835c905f16147robertphillips@google.com    }
8056b70a7bd3328ea0a12be47b1a7f835c905f16147robertphillips@google.com
8066b70a7bd3328ea0a12be47b1a7f835c905f16147robertphillips@google.com#if 0
8076b70a7bd3328ea0a12be47b1a7f835c905f16147robertphillips@google.com    SkRasterClip rasterClip;
8086b70a7bd3328ea0a12be47b1a7f835c905f16147robertphillips@google.com
8096b70a7bd3328ea0a12be47b1a7f835c905f16147robertphillips@google.com    // TODO: refactor GrClip out of existance and use SkCanvas's ClipVisitor
8106b70a7bd3328ea0a12be47b1a7f835c905f16147robertphillips@google.com    //      - may have to move it to SkClipStack
8116b70a7bd3328ea0a12be47b1a7f835c905f16147robertphillips@google.com    for (int i = 0; i < clipIn.getElementCount(); ++i) {
8126b70a7bd3328ea0a12be47b1a7f835c905f16147robertphillips@google.com        if (kRect_ClipType == clipIn.getElementType(i)) {
8136b70a7bd3328ea0a12be47b1a7f835c905f16147robertphillips@google.com            rasterClip.op(clipIn.getRect(i), clipIn.getOp(i), clipIn.getDoAA(i));
8146b70a7bd3328ea0a12be47b1a7f835c905f16147robertphillips@google.com        } else {
8156b70a7bd3328ea0a12be47b1a7f835c905f16147robertphillips@google.com            GrAssert(kPath_ClipType == clipIn.getElementType(i));
8166b70a7bd3328ea0a12be47b1a7f835c905f16147robertphillips@google.com
8176b70a7bd3328ea0a12be47b1a7f835c905f16147robertphillips@google.com            SkIPoint deviceSize = SkIPoint::Make(resultBounds->width(),
8186b70a7bd3328ea0a12be47b1a7f835c905f16147robertphillips@google.com                                                 resultBounds->height());
8196b70a7bd3328ea0a12be47b1a7f835c905f16147robertphillips@google.com
8206b70a7bd3328ea0a12be47b1a7f835c905f16147robertphillips@google.com            SkRasterClip::clipPathHelper(&rasterClip,
8216b70a7bd3328ea0a12be47b1a7f835c905f16147robertphillips@google.com                                         clipIn.getPath(i),
8226b70a7bd3328ea0a12be47b1a7f835c905f16147robertphillips@google.com                                         clipIn.getOp(i),
8236b70a7bd3328ea0a12be47b1a7f835c905f16147robertphillips@google.com                                         clipIn.getDoAA(i),
8246b70a7bd3328ea0a12be47b1a7f835c905f16147robertphillips@google.com                                         deviceSize);
8256b70a7bd3328ea0a12be47b1a7f835c905f16147robertphillips@google.com        }
8266b70a7bd3328ea0a12be47b1a7f835c905f16147robertphillips@google.com    }
8276b70a7bd3328ea0a12be47b1a7f835c905f16147robertphillips@google.com
8286b70a7bd3328ea0a12be47b1a7f835c905f16147robertphillips@google.com    // TODO: need to get pixels out of SkRasterClip & into the texture!
8296b70a7bd3328ea0a12be47b1a7f835c905f16147robertphillips@google.com#endif
8306b70a7bd3328ea0a12be47b1a7f835c905f16147robertphillips@google.com
8316b70a7bd3328ea0a12be47b1a7f835c905f16147robertphillips@google.com    *result = accum;
8326b70a7bd3328ea0a12be47b1a7f835c905f16147robertphillips@google.com
8336b70a7bd3328ea0a12be47b1a7f835c905f16147robertphillips@google.com    return true;
8346b70a7bd3328ea0a12be47b1a7f835c905f16147robertphillips@google.com}
8356b70a7bd3328ea0a12be47b1a7f835c905f16147robertphillips@google.com
8366b70a7bd3328ea0a12be47b1a7f835c905f16147robertphillips@google.com
8376b70a7bd3328ea0a12be47b1a7f835c905f16147robertphillips@google.com////////////////////////////////////////////////////////////////////////////////
8381e945b7e708c633d4aed937ebfce57d52ba21d83robertphillips@google.comGrPathRenderer* GrClipMaskManager::getClipPathRenderer(GrGpu* gpu,
8398d033a1b125886c62906d975b5cc28a382064526bsalomon@google.com                                                       const SkPath& path,
840f294b773f0b2b9f05eb45b52dd3cb4d97b96af06robertphillips@google.com                                                       GrPathFill fill,
841f294b773f0b2b9f05eb45b52dd3cb4d97b96af06robertphillips@google.com                                                       bool antiAlias) {
8421e945b7e708c633d4aed937ebfce57d52ba21d83robertphillips@google.com    if (NULL == fPathRendererChain) {
8431e945b7e708c633d4aed937ebfce57d52ba21d83robertphillips@google.com        fPathRendererChain =
8441e945b7e708c633d4aed937ebfce57d52ba21d83robertphillips@google.com            new GrPathRendererChain(gpu->getContext(),
845f294b773f0b2b9f05eb45b52dd3cb4d97b96af06robertphillips@google.com                                    GrPathRendererChain::kNone_UsageFlag);
8461e945b7e708c633d4aed937ebfce57d52ba21d83robertphillips@google.com    }
847f294b773f0b2b9f05eb45b52dd3cb4d97b96af06robertphillips@google.com    return fPathRendererChain->getPathRenderer(path, fill, gpu, antiAlias);
8481e945b7e708c633d4aed937ebfce57d52ba21d83robertphillips@google.com}
8491e945b7e708c633d4aed937ebfce57d52ba21d83robertphillips@google.com
850f294b773f0b2b9f05eb45b52dd3cb4d97b96af06robertphillips@google.com////////////////////////////////////////////////////////////////////////////////
851f105b109264f71dfb0bfd9977e6a5dd0a5a12f57robertphillips@google.comvoid GrClipMaskManager::releaseResources() {
8521e945b7e708c633d4aed937ebfce57d52ba21d83robertphillips@google.com    // in case path renderer has any GrResources, start from scratch
8531e945b7e708c633d4aed937ebfce57d52ba21d83robertphillips@google.com    GrSafeSetNull(fPathRendererChain);
854f105b109264f71dfb0bfd9977e6a5dd0a5a12f57robertphillips@google.com    fAACache.releaseResources();
8551e945b7e708c633d4aed937ebfce57d52ba21d83robertphillips@google.com}
856