Home | History | Annotate | Download | only in gpu
      1 
      2 /*
      3  * Copyright 2011 Google Inc.
      4  *
      5  * Use of this source code is governed by a BSD-style license that can be
      6  * found in the LICENSE file.
      7  */
      8 
      9 #include "GrContext.h"
     10 
     11 #include "GrAARectRenderer.h"
     12 #include "GrAtlasTextContext.h"
     13 #include "GrBatch.h"
     14 #include "GrBatchFontCache.h"
     15 #include "GrBatchTarget.h"
     16 #include "GrBatchTest.h"
     17 #include "GrDefaultGeoProcFactory.h"
     18 #include "GrGpuResource.h"
     19 #include "GrGpuResourcePriv.h"
     20 #include "GrDrawTargetCaps.h"
     21 #include "GrGpu.h"
     22 #include "GrIndexBuffer.h"
     23 #include "GrInOrderDrawBuffer.h"
     24 #include "GrLayerCache.h"
     25 #include "GrOvalRenderer.h"
     26 #include "GrPathRenderer.h"
     27 #include "GrPathUtils.h"
     28 #include "GrRenderTargetPriv.h"
     29 #include "GrResourceCache.h"
     30 #include "GrResourceProvider.h"
     31 #include "GrSoftwarePathRenderer.h"
     32 #include "GrStencilAndCoverTextContext.h"
     33 #include "GrStrokeInfo.h"
     34 #include "GrSurfacePriv.h"
     35 #include "GrTextBlobCache.h"
     36 #include "GrTexturePriv.h"
     37 #include "GrTraceMarker.h"
     38 #include "GrTracing.h"
     39 #include "GrVertices.h"
     40 #include "SkDashPathPriv.h"
     41 #include "SkConfig8888.h"
     42 #include "SkGr.h"
     43 #include "SkRRect.h"
     44 #include "SkStrokeRec.h"
     45 #include "SkTLazy.h"
     46 #include "SkTLS.h"
     47 #include "SkTraceEvent.h"
     48 
     49 #include "effects/GrConfigConversionEffect.h"
     50 #include "effects/GrDashingEffect.h"
     51 #include "effects/GrSingleTextureEffect.h"
     52 
     53 #define ASSERT_OWNED_RESOURCE(R) SkASSERT(!(R) || (R)->getContext() == this)
     54 #define RETURN_IF_ABANDONED if (!fDrawBuffer) { return; }
     55 #define RETURN_FALSE_IF_ABANDONED if (!fDrawBuffer) { return false; }
     56 #define RETURN_NULL_IF_ABANDONED if (!fDrawBuffer) { return NULL; }
     57 
     58 class GrContext::AutoCheckFlush {
     59 public:
     60     AutoCheckFlush(GrContext* context) : fContext(context) { SkASSERT(context); }
     61 
     62     ~AutoCheckFlush() {
     63         if (fContext->fFlushToReduceCacheSize) {
     64             fContext->flush();
     65         }
     66     }
     67 
     68 private:
     69     GrContext* fContext;
     70 };
     71 
     72 GrContext* GrContext::Create(GrBackend backend, GrBackendContext backendContext,
     73                              const Options* opts) {
     74     GrContext* context;
     75     if (NULL == opts) {
     76         context = SkNEW_ARGS(GrContext, (Options()));
     77     } else {
     78         context = SkNEW_ARGS(GrContext, (*opts));
     79     }
     80 
     81     if (context->init(backend, backendContext)) {
     82         return context;
     83     } else {
     84         context->unref();
     85         return NULL;
     86     }
     87 }
     88 
     89 static int32_t gNextID = 1;
     90 static int32_t next_id() {
     91     int32_t id;
     92     do {
     93         id = sk_atomic_inc(&gNextID);
     94     } while (id == SK_InvalidGenID);
     95     return id;
     96 }
     97 
     98 GrContext::GrContext(const Options& opts) : fOptions(opts), fUniqueID(next_id()) {
     99     fGpu = NULL;
    100     fResourceCache = NULL;
    101     fResourceProvider = NULL;
    102     fPathRendererChain = NULL;
    103     fSoftwarePathRenderer = NULL;
    104     fBatchFontCache = NULL;
    105     fDrawBuffer = NULL;
    106     fFlushToReduceCacheSize = false;
    107     fAARectRenderer = NULL;
    108     fOvalRenderer = NULL;
    109     fMaxTextureSizeOverride = 1 << 20;
    110 }
    111 
    112 bool GrContext::init(GrBackend backend, GrBackendContext backendContext) {
    113     SkASSERT(NULL == fGpu);
    114 
    115     fGpu = GrGpu::Create(backend, backendContext, this);
    116     if (NULL == fGpu) {
    117         return false;
    118     }
    119     this->initCommon();
    120     return true;
    121 }
    122 
    123 void GrContext::initCommon() {
    124     fResourceCache = SkNEW(GrResourceCache);
    125     fResourceCache->setOverBudgetCallback(OverBudgetCB, this);
    126     fResourceProvider = SkNEW_ARGS(GrResourceProvider, (fGpu, fResourceCache));
    127 
    128     fLayerCache.reset(SkNEW_ARGS(GrLayerCache, (this)));
    129 
    130     fAARectRenderer = SkNEW(GrAARectRenderer);
    131     fOvalRenderer = SkNEW(GrOvalRenderer);
    132 
    133     fDidTestPMConversions = false;
    134 
    135     fDrawBuffer = SkNEW_ARGS(GrInOrderDrawBuffer, (this));
    136 
    137     // GrBatchFontCache will eventually replace GrFontCache
    138     fBatchFontCache = SkNEW_ARGS(GrBatchFontCache, (this));
    139 
    140     fTextBlobCache.reset(SkNEW_ARGS(GrTextBlobCache, (TextBlobCacheOverBudgetCB, this)));
    141 }
    142 
    143 GrContext::~GrContext() {
    144     if (NULL == fGpu) {
    145         return;
    146     }
    147 
    148     this->flush();
    149 
    150     for (int i = 0; i < fCleanUpData.count(); ++i) {
    151         (*fCleanUpData[i].fFunc)(this, fCleanUpData[i].fInfo);
    152     }
    153 
    154     SkDELETE(fResourceProvider);
    155     SkDELETE(fResourceCache);
    156     SkDELETE(fBatchFontCache);
    157     SkDELETE(fDrawBuffer);
    158 
    159     fAARectRenderer->unref();
    160     fOvalRenderer->unref();
    161 
    162     fGpu->unref();
    163     SkSafeUnref(fPathRendererChain);
    164     SkSafeUnref(fSoftwarePathRenderer);
    165 }
    166 
    167 void GrContext::abandonContext() {
    168     fResourceProvider->abandon();
    169     // abandon first to so destructors
    170     // don't try to free the resources in the API.
    171     fResourceCache->abandonAll();
    172 
    173     fGpu->contextAbandoned();
    174 
    175     // a path renderer may be holding onto resources that
    176     // are now unusable
    177     SkSafeSetNull(fPathRendererChain);
    178     SkSafeSetNull(fSoftwarePathRenderer);
    179 
    180     SkDELETE(fDrawBuffer);
    181     fDrawBuffer = NULL;
    182 
    183     fBatchFontCache->freeAll();
    184     fLayerCache->freeAll();
    185     fTextBlobCache->freeAll();
    186 }
    187 
    188 void GrContext::resetContext(uint32_t state) {
    189     fGpu->markContextDirty(state);
    190 }
    191 
    192 void GrContext::freeGpuResources() {
    193     this->flush();
    194 
    195     if (fDrawBuffer) {
    196         fDrawBuffer->purgeResources();
    197     }
    198 
    199     fBatchFontCache->freeAll();
    200     fLayerCache->freeAll();
    201     // a path renderer may be holding onto resources
    202     SkSafeSetNull(fPathRendererChain);
    203     SkSafeSetNull(fSoftwarePathRenderer);
    204 
    205     fResourceCache->purgeAllUnlocked();
    206 }
    207 
    208 void GrContext::getResourceCacheUsage(int* resourceCount, size_t* resourceBytes) const {
    209     if (resourceCount) {
    210         *resourceCount = fResourceCache->getBudgetedResourceCount();
    211     }
    212     if (resourceBytes) {
    213         *resourceBytes = fResourceCache->getBudgetedResourceBytes();
    214     }
    215 }
    216 
    217 GrTextContext* GrContext::createTextContext(GrRenderTarget* renderTarget,
    218                                             SkGpuDevice* gpuDevice,
    219                                             const SkDeviceProperties&
    220                                             leakyProperties,
    221                                             bool enableDistanceFieldFonts) {
    222     if (fGpu->caps()->shaderCaps()->pathRenderingSupport() && renderTarget->isMultisampled()) {
    223         GrStencilAttachment* sb = renderTarget->renderTargetPriv().attachStencilAttachment();
    224         if (sb) {
    225             return GrStencilAndCoverTextContext::Create(this, gpuDevice, leakyProperties);
    226         }
    227     }
    228 
    229     return GrAtlasTextContext::Create(this, gpuDevice, leakyProperties, enableDistanceFieldFonts);
    230 }
    231 
    232 ////////////////////////////////////////////////////////////////////////////////
    233 
    234 bool GrContext::isConfigTexturable(GrPixelConfig config) const {
    235     return fGpu->caps()->isConfigTexturable(config);
    236 }
    237 
    238 bool GrContext::npotTextureTileSupport() const {
    239     return fGpu->caps()->npotTextureTileSupport();
    240 }
    241 
    242 void GrContext::OverBudgetCB(void* data) {
    243     SkASSERT(data);
    244 
    245     GrContext* context = reinterpret_cast<GrContext*>(data);
    246 
    247     // Flush the InOrderDrawBuffer to possibly free up some textures
    248     context->fFlushToReduceCacheSize = true;
    249 }
    250 
    251 void GrContext::TextBlobCacheOverBudgetCB(void* data) {
    252     SkASSERT(data);
    253 
    254     // Unlike the GrResourceCache, TextBlobs are drawn at the SkGpuDevice level, therefore they
    255     // cannot use fFlushTorReduceCacheSize because it uses AutoCheckFlush.  The solution is to move
    256     // drawText calls to below the GrContext level, but this is not trivial because they call
    257     // drawPath on SkGpuDevice
    258     GrContext* context = reinterpret_cast<GrContext*>(data);
    259     context->flush();
    260 }
    261 
    262 int GrContext::getMaxTextureSize() const {
    263     return SkTMin(fGpu->caps()->maxTextureSize(), fMaxTextureSizeOverride);
    264 }
    265 
    266 int GrContext::getMaxRenderTargetSize() const {
    267     return fGpu->caps()->maxRenderTargetSize();
    268 }
    269 
    270 int GrContext::getMaxSampleCount() const {
    271     return fGpu->caps()->maxSampleCount();
    272 }
    273 
    274 ///////////////////////////////////////////////////////////////////////////////
    275 
    276 void GrContext::clear(const SkIRect* rect,
    277                       const GrColor color,
    278                       bool canIgnoreRect,
    279                       GrRenderTarget* renderTarget) {
    280     RETURN_IF_ABANDONED
    281     ASSERT_OWNED_RESOURCE(renderTarget);
    282     SkASSERT(renderTarget);
    283 
    284     AutoCheckFlush acf(this);
    285     GR_CREATE_TRACE_MARKER_CONTEXT("GrContext::clear", this);
    286     GrDrawTarget* target = this->prepareToDraw();
    287     if (NULL == target) {
    288         return;
    289     }
    290     target->clear(rect, color, canIgnoreRect, renderTarget);
    291 }
    292 
    293 void GrContext::drawPaint(GrRenderTarget* rt,
    294                           const GrClip& clip,
    295                           const GrPaint& origPaint,
    296                           const SkMatrix& viewMatrix) {
    297     RETURN_IF_ABANDONED
    298     // set rect to be big enough to fill the space, but not super-huge, so we
    299     // don't overflow fixed-point implementations
    300     SkRect r;
    301     r.setLTRB(0, 0,
    302               SkIntToScalar(rt->width()),
    303               SkIntToScalar(rt->height()));
    304     SkTCopyOnFirstWrite<GrPaint> paint(origPaint);
    305 
    306     // by definition this fills the entire clip, no need for AA
    307     if (paint->isAntiAlias()) {
    308         paint.writable()->setAntiAlias(false);
    309     }
    310 
    311     bool isPerspective = viewMatrix.hasPerspective();
    312 
    313     // We attempt to map r by the inverse matrix and draw that. mapRect will
    314     // map the four corners and bound them with a new rect. This will not
    315     // produce a correct result for some perspective matrices.
    316     if (!isPerspective) {
    317         SkMatrix inverse;
    318         if (!viewMatrix.invert(&inverse)) {
    319             SkDebugf("Could not invert matrix\n");
    320             return;
    321         }
    322         inverse.mapRect(&r);
    323         this->drawRect(rt, clip, *paint, viewMatrix, r);
    324     } else {
    325         SkMatrix localMatrix;
    326         if (!viewMatrix.invert(&localMatrix)) {
    327             SkDebugf("Could not invert matrix\n");
    328             return;
    329         }
    330 
    331         AutoCheckFlush acf(this);
    332         GrPipelineBuilder pipelineBuilder;
    333         GrDrawTarget* target = this->prepareToDraw(&pipelineBuilder, rt, clip, paint, &acf);
    334         if (NULL == target) {
    335             return;
    336         }
    337 
    338         GR_CREATE_TRACE_MARKER("GrContext::drawPaintWithPerspective", target);
    339         target->drawRect(&pipelineBuilder,
    340                          paint->getColor(),
    341                          SkMatrix::I(),
    342                          r,
    343                          NULL,
    344                          &localMatrix);
    345     }
    346 }
    347 
    348 ////////////////////////////////////////////////////////////////////////////////
    349 
    350 static inline bool is_irect(const SkRect& r) {
    351   return SkScalarIsInt(r.fLeft)  && SkScalarIsInt(r.fTop) &&
    352          SkScalarIsInt(r.fRight) && SkScalarIsInt(r.fBottom);
    353 }
    354 
    355 static bool apply_aa_to_rect(GrDrawTarget* target,
    356                              GrPipelineBuilder* pipelineBuilder,
    357                              SkRect* devBoundRect,
    358                              const SkRect& rect,
    359                              SkScalar strokeWidth,
    360                              const SkMatrix& combinedMatrix,
    361                              GrColor color) {
    362     if (pipelineBuilder->getRenderTarget()->isMultisampled()) {
    363         return false;
    364     }
    365 
    366 #if defined(SHADER_AA_FILL_RECT) || !defined(IGNORE_ROT_AA_RECT_OPT)
    367     if (strokeWidth >= 0) {
    368 #endif
    369         if (!combinedMatrix.preservesAxisAlignment()) {
    370             return false;
    371         }
    372 
    373 #if defined(SHADER_AA_FILL_RECT) || !defined(IGNORE_ROT_AA_RECT_OPT)
    374     } else {
    375         if (!combinedMatrix.preservesRightAngles()) {
    376             return false;
    377         }
    378     }
    379 #endif
    380 
    381     combinedMatrix.mapRect(devBoundRect, rect);
    382     if (!combinedMatrix.rectStaysRect()) {
    383         return true;
    384     }
    385 
    386     if (strokeWidth < 0) {
    387         return !is_irect(*devBoundRect);
    388     }
    389 
    390     return true;
    391 }
    392 
    393 static inline bool rect_contains_inclusive(const SkRect& rect, const SkPoint& point) {
    394     return point.fX >= rect.fLeft && point.fX <= rect.fRight &&
    395            point.fY >= rect.fTop && point.fY <= rect.fBottom;
    396 }
    397 
    398 class StrokeRectBatch : public GrBatch {
    399 public:
    400     struct Geometry {
    401         GrColor fColor;
    402         SkMatrix fViewMatrix;
    403         SkRect fRect;
    404         SkScalar fStrokeWidth;
    405     };
    406 
    407     static GrBatch* Create(const Geometry& geometry, bool snapToPixelCenters) {
    408         return SkNEW_ARGS(StrokeRectBatch, (geometry, snapToPixelCenters));
    409     }
    410 
    411     const char* name() const override { return "StrokeRectBatch"; }
    412 
    413     void getInvariantOutputColor(GrInitInvariantOutput* out) const override {
    414         // When this is called on a batch, there is only one geometry bundle
    415         out->setKnownFourComponents(fGeoData[0].fColor);
    416     }
    417 
    418     void getInvariantOutputCoverage(GrInitInvariantOutput* out) const override {
    419         out->setKnownSingleComponent(0xff);
    420     }
    421 
    422     void initBatchTracker(const GrPipelineInfo& init) override {
    423         // Handle any color overrides
    424         if (init.fColorIgnored) {
    425             fGeoData[0].fColor = GrColor_ILLEGAL;
    426         } else if (GrColor_ILLEGAL != init.fOverrideColor) {
    427             fGeoData[0].fColor = init.fOverrideColor;
    428         }
    429 
    430         // setup batch properties
    431         fBatch.fColorIgnored = init.fColorIgnored;
    432         fBatch.fColor = fGeoData[0].fColor;
    433         fBatch.fUsesLocalCoords = init.fUsesLocalCoords;
    434         fBatch.fCoverageIgnored = init.fCoverageIgnored;
    435     }
    436 
    437     void generateGeometry(GrBatchTarget* batchTarget, const GrPipeline* pipeline) override {
    438         SkAutoTUnref<const GrGeometryProcessor> gp(
    439                 GrDefaultGeoProcFactory::Create(GrDefaultGeoProcFactory::kPosition_GPType,
    440                                                 this->color(),
    441                                                 this->viewMatrix(),
    442                                                 SkMatrix::I()));
    443 
    444         batchTarget->initDraw(gp, pipeline);
    445 
    446         // TODO this is hacky, but the only way we have to initialize the GP is to use the
    447         // GrPipelineInfo struct so we can generate the correct shader.  Once we have GrBatch
    448         // everywhere we can remove this nastiness
    449         GrPipelineInfo init;
    450         init.fColorIgnored = fBatch.fColorIgnored;
    451         init.fOverrideColor = GrColor_ILLEGAL;
    452         init.fCoverageIgnored = fBatch.fCoverageIgnored;
    453         init.fUsesLocalCoords = this->usesLocalCoords();
    454         gp->initBatchTracker(batchTarget->currentBatchTracker(), init);
    455 
    456         size_t vertexStride = gp->getVertexStride();
    457 
    458         SkASSERT(vertexStride == sizeof(GrDefaultGeoProcFactory::PositionAttr));
    459 
    460         Geometry& args = fGeoData[0];
    461 
    462         int vertexCount = kVertsPerHairlineRect;
    463         if (args.fStrokeWidth > 0) {
    464             vertexCount = kVertsPerStrokeRect;
    465         }
    466 
    467         const GrVertexBuffer* vertexBuffer;
    468         int firstVertex;
    469 
    470         void* verts = batchTarget->makeVertSpace(vertexStride, vertexCount,
    471                                                  &vertexBuffer, &firstVertex);
    472 
    473         if (!verts) {
    474             SkDebugf("Could not allocate vertices\n");
    475             return;
    476         }
    477 
    478         SkPoint* vertex = reinterpret_cast<SkPoint*>(verts);
    479 
    480         GrPrimitiveType primType;
    481 
    482         if (args.fStrokeWidth > 0) {;
    483             primType = kTriangleStrip_GrPrimitiveType;
    484             args.fRect.sort();
    485             this->setStrokeRectStrip(vertex, args.fRect, args.fStrokeWidth);
    486         } else {
    487             // hairline
    488             primType = kLineStrip_GrPrimitiveType;
    489             vertex[0].set(args.fRect.fLeft, args.fRect.fTop);
    490             vertex[1].set(args.fRect.fRight, args.fRect.fTop);
    491             vertex[2].set(args.fRect.fRight, args.fRect.fBottom);
    492             vertex[3].set(args.fRect.fLeft, args.fRect.fBottom);
    493             vertex[4].set(args.fRect.fLeft, args.fRect.fTop);
    494         }
    495 
    496         GrVertices vertices;
    497         vertices.init(primType, vertexBuffer, firstVertex, vertexCount);
    498         batchTarget->draw(vertices);
    499     }
    500 
    501     SkSTArray<1, Geometry, true>* geoData() { return &fGeoData; }
    502 
    503 private:
    504     StrokeRectBatch(const Geometry& geometry, bool snapToPixelCenters) {
    505         this->initClassID<StrokeRectBatch>();
    506 
    507         fBatch.fHairline = geometry.fStrokeWidth == 0;
    508 
    509         fGeoData.push_back(geometry);
    510 
    511         // setup bounds
    512         fBounds = geometry.fRect;
    513         SkScalar rad = SkScalarHalf(geometry.fStrokeWidth);
    514         fBounds.outset(rad, rad);
    515         geometry.fViewMatrix.mapRect(&fBounds);
    516 
    517         // If our caller snaps to pixel centers then we have to round out the bounds
    518         if (snapToPixelCenters) {
    519             fBounds.roundOut();
    520         }
    521     }
    522 
    523     /*  create a triangle strip that strokes the specified rect. There are 8
    524      unique vertices, but we repeat the last 2 to close up. Alternatively we
    525      could use an indices array, and then only send 8 verts, but not sure that
    526      would be faster.
    527      */
    528     void setStrokeRectStrip(SkPoint verts[10], const SkRect& rect, SkScalar width) {
    529         const SkScalar rad = SkScalarHalf(width);
    530         // TODO we should be able to enable this assert, but we'd have to filter these draws
    531         // this is a bug
    532         //SkASSERT(rad < rect.width() / 2 && rad < rect.height() / 2);
    533 
    534         verts[0].set(rect.fLeft + rad, rect.fTop + rad);
    535         verts[1].set(rect.fLeft - rad, rect.fTop - rad);
    536         verts[2].set(rect.fRight - rad, rect.fTop + rad);
    537         verts[3].set(rect.fRight + rad, rect.fTop - rad);
    538         verts[4].set(rect.fRight - rad, rect.fBottom - rad);
    539         verts[5].set(rect.fRight + rad, rect.fBottom + rad);
    540         verts[6].set(rect.fLeft + rad, rect.fBottom - rad);
    541         verts[7].set(rect.fLeft - rad, rect.fBottom + rad);
    542         verts[8] = verts[0];
    543         verts[9] = verts[1];
    544     }
    545 
    546 
    547     GrColor color() const { return fBatch.fColor; }
    548     bool usesLocalCoords() const { return fBatch.fUsesLocalCoords; }
    549     bool colorIgnored() const { return fBatch.fColorIgnored; }
    550     const SkMatrix& viewMatrix() const { return fGeoData[0].fViewMatrix; }
    551     bool hairline() const { return fBatch.fHairline; }
    552 
    553     bool onCombineIfPossible(GrBatch* t) override {
    554         // StrokeRectBatch* that = t->cast<StrokeRectBatch>();
    555 
    556         // NonAA stroke rects cannot batch right now
    557         // TODO make these batchable
    558         return false;
    559     }
    560 
    561     struct BatchTracker {
    562         GrColor fColor;
    563         bool fUsesLocalCoords;
    564         bool fColorIgnored;
    565         bool fCoverageIgnored;
    566         bool fHairline;
    567     };
    568 
    569     const static int kVertsPerHairlineRect = 5;
    570     const static int kVertsPerStrokeRect = 10;
    571 
    572     BatchTracker fBatch;
    573     SkSTArray<1, Geometry, true> fGeoData;
    574 };
    575 
    576 void GrContext::drawRect(GrRenderTarget* rt,
    577                          const GrClip& clip,
    578                          const GrPaint& paint,
    579                          const SkMatrix& viewMatrix,
    580                          const SkRect& rect,
    581                          const GrStrokeInfo* strokeInfo) {
    582     RETURN_IF_ABANDONED
    583     if (strokeInfo && strokeInfo->isDashed()) {
    584         SkPath path;
    585         path.addRect(rect);
    586         this->drawPath(rt, clip, paint, viewMatrix, path, *strokeInfo);
    587         return;
    588     }
    589 
    590     AutoCheckFlush acf(this);
    591     GrPipelineBuilder pipelineBuilder;
    592     GrDrawTarget* target = this->prepareToDraw(&pipelineBuilder, rt, clip, &paint, &acf);
    593     if (NULL == target) {
    594         return;
    595     }
    596 
    597     GR_CREATE_TRACE_MARKER("GrContext::drawRect", target);
    598     SkScalar width = NULL == strokeInfo ? -1 : strokeInfo->getStrokeRec().getWidth();
    599 
    600     // Check if this is a full RT draw and can be replaced with a clear. We don't bother checking
    601     // cases where the RT is fully inside a stroke.
    602     if (width < 0) {
    603         SkRect rtRect;
    604         pipelineBuilder.getRenderTarget()->getBoundsRect(&rtRect);
    605         SkRect clipSpaceRTRect = rtRect;
    606         bool checkClip = GrClip::kWideOpen_ClipType != clip.clipType();
    607         if (checkClip) {
    608             clipSpaceRTRect.offset(SkIntToScalar(clip.origin().fX),
    609                                    SkIntToScalar(clip.origin().fY));
    610         }
    611         // Does the clip contain the entire RT?
    612         if (!checkClip || clip.quickContains(clipSpaceRTRect)) {
    613             SkMatrix invM;
    614             if (!viewMatrix.invert(&invM)) {
    615                 return;
    616             }
    617             // Does the rect bound the RT?
    618             SkPoint srcSpaceRTQuad[4];
    619             invM.mapRectToQuad(srcSpaceRTQuad, rtRect);
    620             if (rect_contains_inclusive(rect, srcSpaceRTQuad[0]) &&
    621                 rect_contains_inclusive(rect, srcSpaceRTQuad[1]) &&
    622                 rect_contains_inclusive(rect, srcSpaceRTQuad[2]) &&
    623                 rect_contains_inclusive(rect, srcSpaceRTQuad[3])) {
    624                 // Will it blend?
    625                 GrColor clearColor;
    626                 if (paint.isOpaqueAndConstantColor(&clearColor)) {
    627                     target->clear(NULL, clearColor, true, rt);
    628                     return;
    629                 }
    630             }
    631         }
    632     }
    633 
    634     GrColor color = paint.getColor();
    635     SkRect devBoundRect;
    636     bool needAA = paint.isAntiAlias() && !pipelineBuilder.getRenderTarget()->isMultisampled();
    637     bool doAA = needAA && apply_aa_to_rect(target, &pipelineBuilder, &devBoundRect, rect, width,
    638                                            viewMatrix, color);
    639 
    640     if (doAA) {
    641         if (width >= 0) {
    642             const SkStrokeRec& strokeRec = strokeInfo->getStrokeRec();
    643             fAARectRenderer->strokeAARect(target,
    644                                           &pipelineBuilder,
    645                                           color,
    646                                           viewMatrix,
    647                                           rect,
    648                                           devBoundRect,
    649                                           strokeRec);
    650         } else {
    651             // filled AA rect
    652             fAARectRenderer->fillAARect(target,
    653                                         &pipelineBuilder,
    654                                         color,
    655                                         viewMatrix,
    656                                         rect,
    657                                         devBoundRect);
    658         }
    659         return;
    660     }
    661 
    662     if (width >= 0) {
    663         StrokeRectBatch::Geometry geometry;
    664         geometry.fViewMatrix = viewMatrix;
    665         geometry.fColor = color;
    666         geometry.fRect = rect;
    667         geometry.fStrokeWidth = width;
    668 
    669         // Non-AA hairlines are snapped to pixel centers to make which pixels are hit deterministic
    670         bool snapToPixelCenters = (0 == width && !rt->isMultisampled());
    671         SkAutoTUnref<GrBatch> batch(StrokeRectBatch::Create(geometry, snapToPixelCenters));
    672 
    673         // Depending on sub-pixel coordinates and the particular GPU, we may lose a corner of
    674         // hairline rects. We jam all the vertices to pixel centers to avoid this, but not when MSAA
    675         // is enabled because it can cause ugly artifacts.
    676         pipelineBuilder.setState(GrPipelineBuilder::kSnapVerticesToPixelCenters_Flag,
    677                                  snapToPixelCenters);
    678         target->drawBatch(&pipelineBuilder, batch);
    679     } else {
    680         // filled BW rect
    681         target->drawSimpleRect(&pipelineBuilder, color, viewMatrix, rect);
    682     }
    683 }
    684 
    685 void GrContext::drawNonAARectToRect(GrRenderTarget* rt,
    686                                     const GrClip& clip,
    687                                     const GrPaint& paint,
    688                                     const SkMatrix& viewMatrix,
    689                                     const SkRect& rectToDraw,
    690                                     const SkRect& localRect,
    691                                     const SkMatrix* localMatrix) {
    692     RETURN_IF_ABANDONED
    693     AutoCheckFlush acf(this);
    694     GrPipelineBuilder pipelineBuilder;
    695     GrDrawTarget* target = this->prepareToDraw(&pipelineBuilder, rt, clip, &paint, &acf);
    696     if (NULL == target) {
    697         return;
    698     }
    699 
    700     GR_CREATE_TRACE_MARKER("GrContext::drawRectToRect", target);
    701 
    702     target->drawRect(&pipelineBuilder,
    703                      paint.getColor(),
    704                      viewMatrix,
    705                      rectToDraw,
    706                      &localRect,
    707                      localMatrix);
    708 }
    709 
    710 static const GrGeometryProcessor* set_vertex_attributes(bool hasLocalCoords,
    711                                                         bool hasColors,
    712                                                         int* colorOffset,
    713                                                         int* texOffset,
    714                                                         GrColor color,
    715                                                         const SkMatrix& viewMatrix) {
    716     *texOffset = -1;
    717     *colorOffset = -1;
    718     uint32_t flags = GrDefaultGeoProcFactory::kPosition_GPType;
    719     if (hasLocalCoords && hasColors) {
    720         *colorOffset = sizeof(SkPoint);
    721         *texOffset = sizeof(SkPoint) + sizeof(GrColor);
    722         flags |= GrDefaultGeoProcFactory::kColor_GPType |
    723                  GrDefaultGeoProcFactory::kLocalCoord_GPType;
    724     } else if (hasLocalCoords) {
    725         *texOffset = sizeof(SkPoint);
    726         flags |= GrDefaultGeoProcFactory::kLocalCoord_GPType;
    727     } else if (hasColors) {
    728         *colorOffset = sizeof(SkPoint);
    729         flags |= GrDefaultGeoProcFactory::kColor_GPType;
    730     }
    731     return GrDefaultGeoProcFactory::Create(flags, color, viewMatrix, SkMatrix::I());
    732 }
    733 
    734 class DrawVerticesBatch : public GrBatch {
    735 public:
    736     struct Geometry {
    737         GrColor fColor;
    738         SkTDArray<SkPoint> fPositions;
    739         SkTDArray<uint16_t> fIndices;
    740         SkTDArray<GrColor> fColors;
    741         SkTDArray<SkPoint> fLocalCoords;
    742     };
    743 
    744     static GrBatch* Create(const Geometry& geometry, GrPrimitiveType primitiveType,
    745                            const SkMatrix& viewMatrix,
    746                            const SkPoint* positions, int vertexCount,
    747                            const uint16_t* indices, int indexCount,
    748                            const GrColor* colors, const SkPoint* localCoords,
    749                            const SkRect& bounds) {
    750         return SkNEW_ARGS(DrawVerticesBatch, (geometry, primitiveType, viewMatrix, positions,
    751                                               vertexCount, indices, indexCount, colors,
    752                                               localCoords, bounds));
    753     }
    754 
    755     const char* name() const override { return "DrawVerticesBatch"; }
    756 
    757     void getInvariantOutputColor(GrInitInvariantOutput* out) const override {
    758         // When this is called on a batch, there is only one geometry bundle
    759         if (this->hasColors()) {
    760             out->setUnknownFourComponents();
    761         } else {
    762             out->setKnownFourComponents(fGeoData[0].fColor);
    763         }
    764     }
    765 
    766     void getInvariantOutputCoverage(GrInitInvariantOutput* out) const override {
    767         out->setKnownSingleComponent(0xff);
    768     }
    769 
    770     void initBatchTracker(const GrPipelineInfo& init) override {
    771         // Handle any color overrides
    772         if (init.fColorIgnored) {
    773             fGeoData[0].fColor = GrColor_ILLEGAL;
    774         } else if (GrColor_ILLEGAL != init.fOverrideColor) {
    775             fGeoData[0].fColor = init.fOverrideColor;
    776         }
    777 
    778         // setup batch properties
    779         fBatch.fColorIgnored = init.fColorIgnored;
    780         fBatch.fColor = fGeoData[0].fColor;
    781         fBatch.fUsesLocalCoords = init.fUsesLocalCoords;
    782         fBatch.fCoverageIgnored = init.fCoverageIgnored;
    783     }
    784 
    785     void generateGeometry(GrBatchTarget* batchTarget, const GrPipeline* pipeline) override {
    786         int colorOffset = -1, texOffset = -1;
    787         SkAutoTUnref<const GrGeometryProcessor> gp(
    788                 set_vertex_attributes(this->hasLocalCoords(), this->hasColors(), &colorOffset,
    789                                       &texOffset, this->color(), this->viewMatrix()));
    790 
    791         batchTarget->initDraw(gp, pipeline);
    792 
    793         // TODO this is hacky, but the only way we have to initialize the GP is to use the
    794         // GrPipelineInfo struct so we can generate the correct shader.  Once we have GrBatch
    795         // everywhere we can remove this nastiness
    796         GrPipelineInfo init;
    797         init.fColorIgnored = fBatch.fColorIgnored;
    798         init.fOverrideColor = GrColor_ILLEGAL;
    799         init.fCoverageIgnored = fBatch.fCoverageIgnored;
    800         init.fUsesLocalCoords = this->usesLocalCoords();
    801         gp->initBatchTracker(batchTarget->currentBatchTracker(), init);
    802 
    803         size_t vertexStride = gp->getVertexStride();
    804 
    805         SkASSERT(vertexStride == sizeof(SkPoint) + (this->hasLocalCoords() ? sizeof(SkPoint) : 0)
    806                                                  + (this->hasColors() ? sizeof(GrColor) : 0));
    807 
    808         int instanceCount = fGeoData.count();
    809 
    810         const GrVertexBuffer* vertexBuffer;
    811         int firstVertex;
    812 
    813         void* verts = batchTarget->makeVertSpace(vertexStride, this->vertexCount(),
    814                                                  &vertexBuffer, &firstVertex);
    815 
    816         if (!verts) {
    817             SkDebugf("Could not allocate vertices\n");
    818             return;
    819         }
    820 
    821         const GrIndexBuffer* indexBuffer = NULL;
    822         int firstIndex = 0;
    823 
    824         uint16_t* indices = NULL;
    825         if (this->hasIndices()) {
    826             indices = batchTarget->makeIndexSpace(this->indexCount(), &indexBuffer, &firstIndex);
    827 
    828             if (!indices) {
    829                 SkDebugf("Could not allocate indices\n");
    830                 return;
    831             }
    832         }
    833 
    834         int indexOffset = 0;
    835         int vertexOffset = 0;
    836         for (int i = 0; i < instanceCount; i++) {
    837             const Geometry& args = fGeoData[i];
    838 
    839             // TODO we can actually cache this interleaved and then just memcopy
    840             if (this->hasIndices()) {
    841                 for (int j = 0; j < args.fIndices.count(); ++j, ++indexOffset) {
    842                     *(indices + indexOffset) = args.fIndices[j] + vertexOffset;
    843                 }
    844             }
    845 
    846             for (int j = 0; j < args.fPositions.count(); ++j) {
    847                 *((SkPoint*)verts) = args.fPositions[j];
    848                 if (this->hasColors()) {
    849                     *(GrColor*)((intptr_t)verts + colorOffset) = args.fColors[j];
    850                 }
    851                 if (this->hasLocalCoords()) {
    852                     *(SkPoint*)((intptr_t)verts + texOffset) = args.fLocalCoords[j];
    853                 }
    854                 verts = (void*)((intptr_t)verts + vertexStride);
    855                 vertexOffset++;
    856             }
    857         }
    858 
    859         GrVertices vertices;
    860         if (this->hasIndices()) {
    861             vertices.initIndexed(this->primitiveType(), vertexBuffer, indexBuffer, firstVertex,
    862                                  firstIndex, this->vertexCount(), this->indexCount());
    863 
    864         } else {
    865             vertices.init(this->primitiveType(), vertexBuffer, firstVertex, this->vertexCount());
    866         }
    867         batchTarget->draw(vertices);
    868     }
    869 
    870     SkSTArray<1, Geometry, true>* geoData() { return &fGeoData; }
    871 
    872 private:
    873     DrawVerticesBatch(const Geometry& geometry, GrPrimitiveType primitiveType,
    874                       const SkMatrix& viewMatrix,
    875                       const SkPoint* positions, int vertexCount,
    876                       const uint16_t* indices, int indexCount,
    877                       const GrColor* colors, const SkPoint* localCoords, const SkRect& bounds) {
    878         this->initClassID<DrawVerticesBatch>();
    879         SkASSERT(positions);
    880 
    881         fBatch.fViewMatrix = viewMatrix;
    882         Geometry& installedGeo = fGeoData.push_back(geometry);
    883 
    884         installedGeo.fPositions.append(vertexCount, positions);
    885         if (indices) {
    886             installedGeo.fIndices.append(indexCount, indices);
    887             fBatch.fHasIndices = true;
    888         } else {
    889             fBatch.fHasIndices = false;
    890         }
    891 
    892         if (colors) {
    893             installedGeo.fColors.append(vertexCount, colors);
    894             fBatch.fHasColors = true;
    895         } else {
    896             fBatch.fHasColors = false;
    897         }
    898 
    899         if (localCoords) {
    900             installedGeo.fLocalCoords.append(vertexCount, localCoords);
    901             fBatch.fHasLocalCoords = true;
    902         } else {
    903             fBatch.fHasLocalCoords = false;
    904         }
    905         fBatch.fVertexCount = vertexCount;
    906         fBatch.fIndexCount = indexCount;
    907         fBatch.fPrimitiveType = primitiveType;
    908 
    909         this->setBounds(bounds);
    910     }
    911 
    912     GrPrimitiveType primitiveType() const { return fBatch.fPrimitiveType; }
    913     bool batchablePrimitiveType() const {
    914         return kTriangles_GrPrimitiveType == fBatch.fPrimitiveType ||
    915                kLines_GrPrimitiveType == fBatch.fPrimitiveType ||
    916                kPoints_GrPrimitiveType == fBatch.fPrimitiveType;
    917     }
    918     GrColor color() const { return fBatch.fColor; }
    919     bool usesLocalCoords() const { return fBatch.fUsesLocalCoords; }
    920     bool colorIgnored() const { return fBatch.fColorIgnored; }
    921     const SkMatrix& viewMatrix() const { return fBatch.fViewMatrix; }
    922     bool hasColors() const { return fBatch.fHasColors; }
    923     bool hasIndices() const { return fBatch.fHasIndices; }
    924     bool hasLocalCoords() const { return fBatch.fHasLocalCoords; }
    925     int vertexCount() const { return fBatch.fVertexCount; }
    926     int indexCount() const { return fBatch.fIndexCount; }
    927 
    928     bool onCombineIfPossible(GrBatch* t) override {
    929         DrawVerticesBatch* that = t->cast<DrawVerticesBatch>();
    930 
    931         if (!this->batchablePrimitiveType() || this->primitiveType() != that->primitiveType()) {
    932             return false;
    933         }
    934 
    935         SkASSERT(this->usesLocalCoords() == that->usesLocalCoords());
    936 
    937         // We currently use a uniform viewmatrix for this batch
    938         if (!this->viewMatrix().cheapEqualTo(that->viewMatrix())) {
    939             return false;
    940         }
    941 
    942         if (this->hasColors() != that->hasColors()) {
    943             return false;
    944         }
    945 
    946         if (this->hasIndices() != that->hasIndices()) {
    947             return false;
    948         }
    949 
    950         if (this->hasLocalCoords() != that->hasLocalCoords()) {
    951             return false;
    952         }
    953 
    954         if (!this->hasColors() && this->color() != that->color()) {
    955             return false;
    956         }
    957 
    958         if (this->color() != that->color()) {
    959             fBatch.fColor = GrColor_ILLEGAL;
    960         }
    961         fGeoData.push_back_n(that->geoData()->count(), that->geoData()->begin());
    962         fBatch.fVertexCount += that->vertexCount();
    963         fBatch.fIndexCount += that->indexCount();
    964 
    965         this->joinBounds(that->bounds());
    966         return true;
    967     }
    968 
    969     struct BatchTracker {
    970         GrPrimitiveType fPrimitiveType;
    971         SkMatrix fViewMatrix;
    972         GrColor fColor;
    973         bool fUsesLocalCoords;
    974         bool fColorIgnored;
    975         bool fCoverageIgnored;
    976         bool fHasColors;
    977         bool fHasIndices;
    978         bool fHasLocalCoords;
    979         int fVertexCount;
    980         int fIndexCount;
    981     };
    982 
    983     BatchTracker fBatch;
    984     SkSTArray<1, Geometry, true> fGeoData;
    985 };
    986 
    987 void GrContext::drawVertices(GrRenderTarget* rt,
    988                              const GrClip& clip,
    989                              const GrPaint& paint,
    990                              const SkMatrix& viewMatrix,
    991                              GrPrimitiveType primitiveType,
    992                              int vertexCount,
    993                              const SkPoint positions[],
    994                              const SkPoint texCoords[],
    995                              const GrColor colors[],
    996                              const uint16_t indices[],
    997                              int indexCount) {
    998     RETURN_IF_ABANDONED
    999     AutoCheckFlush acf(this);
   1000     GrPipelineBuilder pipelineBuilder;
   1001 
   1002     GrDrawTarget* target = this->prepareToDraw(&pipelineBuilder, rt, clip, &paint, &acf);
   1003     if (NULL == target) {
   1004         return;
   1005     }
   1006 
   1007     GR_CREATE_TRACE_MARKER("GrContext::drawVertices", target);
   1008 
   1009     // TODO clients should give us bounds
   1010     SkRect bounds;
   1011     if (!bounds.setBoundsCheck(positions, vertexCount)) {
   1012         SkDebugf("drawVertices call empty bounds\n");
   1013         return;
   1014     }
   1015 
   1016     viewMatrix.mapRect(&bounds);
   1017 
   1018     // If we don't have AA then we outset for a half pixel in each direction to account for
   1019     // snapping
   1020     if (!paint.isAntiAlias()) {
   1021         bounds.outset(0.5f, 0.5f);
   1022     }
   1023 
   1024     DrawVerticesBatch::Geometry geometry;
   1025     geometry.fColor = paint.getColor();
   1026     SkAutoTUnref<GrBatch> batch(DrawVerticesBatch::Create(geometry, primitiveType, viewMatrix,
   1027                                                           positions, vertexCount, indices,
   1028                                                           indexCount, colors, texCoords,
   1029                                                           bounds));
   1030 
   1031     target->drawBatch(&pipelineBuilder, batch);
   1032 }
   1033 
   1034 ///////////////////////////////////////////////////////////////////////////////
   1035 
   1036 void GrContext::drawRRect(GrRenderTarget*rt,
   1037                           const GrClip& clip,
   1038                           const GrPaint& paint,
   1039                           const SkMatrix& viewMatrix,
   1040                           const SkRRect& rrect,
   1041                           const GrStrokeInfo& strokeInfo) {
   1042     RETURN_IF_ABANDONED
   1043     if (rrect.isEmpty()) {
   1044        return;
   1045     }
   1046 
   1047     if (strokeInfo.isDashed()) {
   1048         SkPath path;
   1049         path.addRRect(rrect);
   1050         this->drawPath(rt, clip, paint, viewMatrix, path, strokeInfo);
   1051         return;
   1052     }
   1053 
   1054     AutoCheckFlush acf(this);
   1055     GrPipelineBuilder pipelineBuilder;
   1056     GrDrawTarget* target = this->prepareToDraw(&pipelineBuilder, rt, clip, &paint, &acf);
   1057     if (NULL == target) {
   1058         return;
   1059     }
   1060 
   1061     GR_CREATE_TRACE_MARKER("GrContext::drawRRect", target);
   1062 
   1063     const SkStrokeRec& strokeRec = strokeInfo.getStrokeRec();
   1064 
   1065     GrColor color = paint.getColor();
   1066     if (!fOvalRenderer->drawRRect(target,
   1067                                   &pipelineBuilder,
   1068                                   color,
   1069                                   viewMatrix,
   1070                                   paint.isAntiAlias(),
   1071                                   rrect,
   1072                                   strokeRec)) {
   1073         SkPath path;
   1074         path.addRRect(rrect);
   1075         this->internalDrawPath(target, &pipelineBuilder, viewMatrix, color, paint.isAntiAlias(),
   1076                                path, strokeInfo);
   1077     }
   1078 }
   1079 
   1080 ///////////////////////////////////////////////////////////////////////////////
   1081 
   1082 void GrContext::drawDRRect(GrRenderTarget* rt,
   1083                            const GrClip& clip,
   1084                            const GrPaint& paint,
   1085                            const SkMatrix& viewMatrix,
   1086                            const SkRRect& outer,
   1087                            const SkRRect& inner) {
   1088     RETURN_IF_ABANDONED
   1089     if (outer.isEmpty()) {
   1090        return;
   1091     }
   1092 
   1093     AutoCheckFlush acf(this);
   1094     GrPipelineBuilder pipelineBuilder;
   1095     GrDrawTarget* target = this->prepareToDraw(&pipelineBuilder, rt, clip, &paint, &acf);
   1096 
   1097     GR_CREATE_TRACE_MARKER("GrContext::drawDRRect", target);
   1098 
   1099     GrColor color = paint.getColor();
   1100     if (!fOvalRenderer->drawDRRect(target,
   1101                                    &pipelineBuilder,
   1102                                    color,
   1103                                    viewMatrix,
   1104                                    paint.isAntiAlias(),
   1105                                    outer,
   1106                                    inner)) {
   1107         SkPath path;
   1108         path.addRRect(inner);
   1109         path.addRRect(outer);
   1110         path.setFillType(SkPath::kEvenOdd_FillType);
   1111 
   1112         GrStrokeInfo fillRec(SkStrokeRec::kFill_InitStyle);
   1113         this->internalDrawPath(target, &pipelineBuilder, viewMatrix, color, paint.isAntiAlias(),
   1114                                path, fillRec);
   1115     }
   1116 }
   1117 
   1118 ///////////////////////////////////////////////////////////////////////////////
   1119 
   1120 void GrContext::drawOval(GrRenderTarget* rt,
   1121                          const GrClip& clip,
   1122                          const GrPaint& paint,
   1123                          const SkMatrix& viewMatrix,
   1124                          const SkRect& oval,
   1125                          const GrStrokeInfo& strokeInfo) {
   1126     RETURN_IF_ABANDONED
   1127     if (oval.isEmpty()) {
   1128        return;
   1129     }
   1130 
   1131     if (strokeInfo.isDashed()) {
   1132         SkPath path;
   1133         path.addOval(oval);
   1134         this->drawPath(rt, clip, paint, viewMatrix, path, strokeInfo);
   1135         return;
   1136     }
   1137 
   1138     AutoCheckFlush acf(this);
   1139     GrPipelineBuilder pipelineBuilder;
   1140     GrDrawTarget* target = this->prepareToDraw(&pipelineBuilder, rt, clip, &paint, &acf);
   1141     if (NULL == target) {
   1142         return;
   1143     }
   1144 
   1145     GR_CREATE_TRACE_MARKER("GrContext::drawOval", target);
   1146 
   1147     const SkStrokeRec& strokeRec = strokeInfo.getStrokeRec();
   1148 
   1149     GrColor color = paint.getColor();
   1150     if (!fOvalRenderer->drawOval(target,
   1151                                  &pipelineBuilder,
   1152                                  color,
   1153                                  viewMatrix,
   1154                                  paint.isAntiAlias(),
   1155                                  oval,
   1156                                  strokeRec)) {
   1157         SkPath path;
   1158         path.addOval(oval);
   1159         this->internalDrawPath(target, &pipelineBuilder, viewMatrix, color, paint.isAntiAlias(),
   1160                                path, strokeInfo);
   1161     }
   1162 }
   1163 
   1164 // Can 'path' be drawn as a pair of filled nested rectangles?
   1165 static bool is_nested_rects(GrDrawTarget* target,
   1166                             GrPipelineBuilder* pipelineBuilder,
   1167                             GrColor color,
   1168                             const SkMatrix& viewMatrix,
   1169                             const SkPath& path,
   1170                             const SkStrokeRec& stroke,
   1171                             SkRect rects[2]) {
   1172     SkASSERT(stroke.isFillStyle());
   1173 
   1174     if (path.isInverseFillType()) {
   1175         return false;
   1176     }
   1177 
   1178     // TODO: this restriction could be lifted if we were willing to apply
   1179     // the matrix to all the points individually rather than just to the rect
   1180     if (!viewMatrix.preservesAxisAlignment()) {
   1181         return false;
   1182     }
   1183 
   1184     SkPath::Direction dirs[2];
   1185     if (!path.isNestedFillRects(rects, dirs)) {
   1186         return false;
   1187     }
   1188 
   1189     if (SkPath::kWinding_FillType == path.getFillType() && dirs[0] == dirs[1]) {
   1190         // The two rects need to be wound opposite to each other
   1191         return false;
   1192     }
   1193 
   1194     // Right now, nested rects where the margin is not the same width
   1195     // all around do not render correctly
   1196     const SkScalar* outer = rects[0].asScalars();
   1197     const SkScalar* inner = rects[1].asScalars();
   1198 
   1199     bool allEq = true;
   1200 
   1201     SkScalar margin = SkScalarAbs(outer[0] - inner[0]);
   1202     bool allGoE1 = margin >= SK_Scalar1;
   1203 
   1204     for (int i = 1; i < 4; ++i) {
   1205         SkScalar temp = SkScalarAbs(outer[i] - inner[i]);
   1206         if (temp < SK_Scalar1) {
   1207             allGoE1 = false;
   1208         }
   1209         if (!SkScalarNearlyEqual(margin, temp)) {
   1210             allEq = false;
   1211         }
   1212     }
   1213 
   1214     return allEq || allGoE1;
   1215 }
   1216 
   1217 void GrContext::drawPath(GrRenderTarget* rt,
   1218                          const GrClip& clip,
   1219                          const GrPaint& paint,
   1220                          const SkMatrix& viewMatrix,
   1221                          const SkPath& path,
   1222                          const GrStrokeInfo& strokeInfo) {
   1223     RETURN_IF_ABANDONED
   1224     if (path.isEmpty()) {
   1225        if (path.isInverseFillType()) {
   1226            this->drawPaint(rt, clip, paint, viewMatrix);
   1227        }
   1228        return;
   1229     }
   1230 
   1231     GrColor color = paint.getColor();
   1232 
   1233     // Note that internalDrawPath may sw-rasterize the path into a scratch texture.
   1234     // Scratch textures can be recycled after they are returned to the texture
   1235     // cache. This presents a potential hazard for buffered drawing. However,
   1236     // the writePixels that uploads to the scratch will perform a flush so we're
   1237     // OK.
   1238     AutoCheckFlush acf(this);
   1239     GrPipelineBuilder pipelineBuilder;
   1240     GrDrawTarget* target = this->prepareToDraw(&pipelineBuilder, rt, clip, &paint, &acf);
   1241     if (NULL == target) {
   1242         return;
   1243     }
   1244 
   1245     GR_CREATE_TRACE_MARKER1("GrContext::drawPath", target, "Is Convex", path.isConvex());
   1246 
   1247     if (!strokeInfo.isDashed()) {
   1248         const SkStrokeRec& strokeRec = strokeInfo.getStrokeRec();
   1249         bool useCoverageAA = paint.isAntiAlias() &&
   1250                 !pipelineBuilder.getRenderTarget()->isMultisampled();
   1251 
   1252         if (useCoverageAA && strokeRec.getWidth() < 0 && !path.isConvex()) {
   1253             // Concave AA paths are expensive - try to avoid them for special cases
   1254             SkRect rects[2];
   1255 
   1256             if (is_nested_rects(target, &pipelineBuilder, color, viewMatrix, path, strokeRec,
   1257                                 rects)) {
   1258                 fAARectRenderer->fillAANestedRects(target, &pipelineBuilder, color, viewMatrix,
   1259                                                    rects);
   1260                 return;
   1261             }
   1262         }
   1263         SkRect ovalRect;
   1264         bool isOval = path.isOval(&ovalRect);
   1265 
   1266         if (isOval && !path.isInverseFillType()) {
   1267             if (fOvalRenderer->drawOval(target,
   1268                                         &pipelineBuilder,
   1269                                         color,
   1270                                         viewMatrix,
   1271                                         paint.isAntiAlias(),
   1272                                         ovalRect,
   1273                                         strokeRec)) {
   1274                 return;
   1275             }
   1276         }
   1277     }
   1278     this->internalDrawPath(target, &pipelineBuilder, viewMatrix, color, paint.isAntiAlias(),
   1279                            path, strokeInfo);
   1280 }
   1281 
   1282 void GrContext::internalDrawPath(GrDrawTarget* target,
   1283                                  GrPipelineBuilder* pipelineBuilder,
   1284                                  const SkMatrix& viewMatrix,
   1285                                  GrColor color,
   1286                                  bool useAA,
   1287                                  const SkPath& path,
   1288                                  const GrStrokeInfo& strokeInfo) {
   1289     RETURN_IF_ABANDONED
   1290     SkASSERT(!path.isEmpty());
   1291 
   1292     GR_CREATE_TRACE_MARKER("GrContext::internalDrawPath", target);
   1293 
   1294 
   1295     // An Assumption here is that path renderer would use some form of tweaking
   1296     // the src color (either the input alpha or in the frag shader) to implement
   1297     // aa. If we have some future driver-mojo path AA that can do the right
   1298     // thing WRT to the blend then we'll need some query on the PR.
   1299     bool useCoverageAA = useAA &&
   1300         !pipelineBuilder->getRenderTarget()->isMultisampled();
   1301 
   1302 
   1303     GrPathRendererChain::DrawType type =
   1304         useCoverageAA ? GrPathRendererChain::kColorAntiAlias_DrawType :
   1305                         GrPathRendererChain::kColor_DrawType;
   1306 
   1307     const SkPath* pathPtr = &path;
   1308     SkTLazy<SkPath> tmpPath;
   1309     const GrStrokeInfo* strokeInfoPtr = &strokeInfo;
   1310 
   1311     // Try a 1st time without stroking the path and without allowing the SW renderer
   1312     GrPathRenderer* pr = this->getPathRenderer(target, pipelineBuilder, viewMatrix, *pathPtr,
   1313                                                *strokeInfoPtr, false, type);
   1314 
   1315     GrStrokeInfo dashlessStrokeInfo(strokeInfo, false);
   1316     if (NULL == pr && strokeInfo.isDashed()) {
   1317         // It didn't work above, so try again with dashed stroke converted to a dashless stroke.
   1318         if (!strokeInfo.applyDash(tmpPath.init(), &dashlessStrokeInfo, *pathPtr)) {
   1319             return;
   1320         }
   1321         pathPtr = tmpPath.get();
   1322         if (pathPtr->isEmpty()) {
   1323             return;
   1324         }
   1325         strokeInfoPtr = &dashlessStrokeInfo;
   1326         pr = this->getPathRenderer(target, pipelineBuilder, viewMatrix, *pathPtr, *strokeInfoPtr,
   1327                                    false, type);
   1328     }
   1329 
   1330     if (NULL == pr) {
   1331         if (!GrPathRenderer::IsStrokeHairlineOrEquivalent(*strokeInfoPtr, viewMatrix, NULL) &&
   1332             !strokeInfoPtr->isFillStyle()) {
   1333             // It didn't work above, so try again with stroke converted to a fill.
   1334             if (!tmpPath.isValid()) {
   1335                 tmpPath.init();
   1336             }
   1337             SkStrokeRec* strokeRec = dashlessStrokeInfo.getStrokeRecPtr();
   1338             strokeRec->setResScale(SkScalarAbs(viewMatrix.getMaxScale()));
   1339             if (!strokeRec->applyToPath(tmpPath.get(), *pathPtr)) {
   1340                 return;
   1341             }
   1342             pathPtr = tmpPath.get();
   1343             if (pathPtr->isEmpty()) {
   1344                 return;
   1345             }
   1346             strokeRec->setFillStyle();
   1347             strokeInfoPtr = &dashlessStrokeInfo;
   1348         }
   1349 
   1350         // This time, allow SW renderer
   1351         pr = this->getPathRenderer(target, pipelineBuilder, viewMatrix, *pathPtr, *strokeInfoPtr,
   1352                                    true, type);
   1353     }
   1354 
   1355     if (NULL == pr) {
   1356 #ifdef SK_DEBUG
   1357         SkDebugf("Unable to find path renderer compatible with path.\n");
   1358 #endif
   1359         return;
   1360     }
   1361 
   1362     pr->drawPath(target, pipelineBuilder, color, viewMatrix, *pathPtr, *strokeInfoPtr, useCoverageAA);
   1363 }
   1364 
   1365 ////////////////////////////////////////////////////////////////////////////////
   1366 
   1367 void GrContext::flush(int flagsBitfield) {
   1368     if (NULL == fDrawBuffer) {
   1369         return;
   1370     }
   1371 
   1372     if (kDiscard_FlushBit & flagsBitfield) {
   1373         fDrawBuffer->reset();
   1374     } else {
   1375         fDrawBuffer->flush();
   1376     }
   1377     fResourceCache->notifyFlushOccurred();
   1378     fFlushToReduceCacheSize = false;
   1379 }
   1380 
   1381 bool sw_convert_to_premul(GrPixelConfig srcConfig, int width, int height, size_t inRowBytes,
   1382                           const void* inPixels, size_t outRowBytes, void* outPixels) {
   1383     SkSrcPixelInfo srcPI;
   1384     if (!GrPixelConfig2ColorAndProfileType(srcConfig, &srcPI.fColorType, NULL)) {
   1385         return false;
   1386     }
   1387     srcPI.fAlphaType = kUnpremul_SkAlphaType;
   1388     srcPI.fPixels = inPixels;
   1389     srcPI.fRowBytes = inRowBytes;
   1390 
   1391     SkDstPixelInfo dstPI;
   1392     dstPI.fColorType = srcPI.fColorType;
   1393     dstPI.fAlphaType = kPremul_SkAlphaType;
   1394     dstPI.fPixels = outPixels;
   1395     dstPI.fRowBytes = outRowBytes;
   1396 
   1397     return srcPI.convertPixelsTo(&dstPI, width, height);
   1398 }
   1399 
   1400 bool GrContext::writeSurfacePixels(GrSurface* surface,
   1401                                    int left, int top, int width, int height,
   1402                                    GrPixelConfig srcConfig, const void* buffer, size_t rowBytes,
   1403                                    uint32_t pixelOpsFlags) {
   1404     RETURN_FALSE_IF_ABANDONED
   1405     {
   1406         GrTexture* texture = NULL;
   1407         if (!(kUnpremul_PixelOpsFlag & pixelOpsFlags) && (texture = surface->asTexture()) &&
   1408             fGpu->canWriteTexturePixels(texture, srcConfig)) {
   1409 
   1410             if (!(kDontFlush_PixelOpsFlag & pixelOpsFlags) &&
   1411                 surface->surfacePriv().hasPendingIO()) {
   1412                 this->flush();
   1413             }
   1414             return fGpu->writeTexturePixels(texture, left, top, width, height,
   1415                                             srcConfig, buffer, rowBytes);
   1416             // Don't need to check kFlushWrites_PixelOp here, we just did a direct write so the
   1417             // upload is already flushed.
   1418         }
   1419     }
   1420 
   1421     // If we didn't do a direct texture write then we upload the pixels to a texture and draw.
   1422     GrRenderTarget* renderTarget = surface->asRenderTarget();
   1423     if (NULL == renderTarget) {
   1424         return false;
   1425     }
   1426 
   1427     // We ignore the preferred config unless it is a R/B swap of the src config. In that case
   1428     // we will upload the original src data to a scratch texture but we will spoof it as the swapped
   1429     // config. This scratch will then have R and B swapped. We correct for this by swapping again
   1430     // when drawing the scratch to the dst using a conversion effect.
   1431     bool swapRAndB = false;
   1432     GrPixelConfig writeConfig = srcConfig;
   1433     if (GrPixelConfigSwapRAndB(srcConfig) ==
   1434         fGpu->preferredWritePixelsConfig(srcConfig, renderTarget->config())) {
   1435         writeConfig = GrPixelConfigSwapRAndB(srcConfig);
   1436         swapRAndB = true;
   1437     }
   1438 
   1439     GrSurfaceDesc desc;
   1440     desc.fWidth = width;
   1441     desc.fHeight = height;
   1442     desc.fConfig = writeConfig;
   1443     SkAutoTUnref<GrTexture> texture(this->textureProvider()->refScratchTexture(desc,
   1444         GrTextureProvider::kApprox_ScratchTexMatch));
   1445     if (!texture) {
   1446         return false;
   1447     }
   1448 
   1449     SkAutoTUnref<const GrFragmentProcessor> fp;
   1450     SkMatrix textureMatrix;
   1451     textureMatrix.setIDiv(texture->width(), texture->height());
   1452 
   1453     // allocate a tmp buffer and sw convert the pixels to premul
   1454     SkAutoSTMalloc<128 * 128, uint32_t> tmpPixels(0);
   1455 
   1456     if (kUnpremul_PixelOpsFlag & pixelOpsFlags) {
   1457         if (!GrPixelConfigIs8888(srcConfig)) {
   1458             return false;
   1459         }
   1460         fp.reset(this->createUPMToPMEffect(texture, swapRAndB, textureMatrix));
   1461         // handle the unpremul step on the CPU if we couldn't create an effect to do it.
   1462         if (NULL == fp) {
   1463             size_t tmpRowBytes = 4 * width;
   1464             tmpPixels.reset(width * height);
   1465             if (!sw_convert_to_premul(srcConfig, width, height, rowBytes, buffer, tmpRowBytes,
   1466                                       tmpPixels.get())) {
   1467                 return false;
   1468             }
   1469             rowBytes = tmpRowBytes;
   1470             buffer = tmpPixels.get();
   1471         }
   1472     }
   1473     if (NULL == fp) {
   1474         fp.reset(GrConfigConversionEffect::Create(texture,
   1475                                                   swapRAndB,
   1476                                                   GrConfigConversionEffect::kNone_PMConversion,
   1477                                                   textureMatrix));
   1478     }
   1479 
   1480     // Even if the client told us not to flush, we still flush here. The client may have known that
   1481     // writes to the original surface caused no data hazards, but they can't know that the scratch
   1482     // we just got is safe.
   1483     if (texture->surfacePriv().hasPendingIO()) {
   1484         this->flush();
   1485     }
   1486     if (!fGpu->writeTexturePixels(texture, 0, 0, width, height,
   1487                                   writeConfig, buffer, rowBytes)) {
   1488         return false;
   1489     }
   1490 
   1491     SkMatrix matrix;
   1492     matrix.setTranslate(SkIntToScalar(left), SkIntToScalar(top));
   1493 
   1494     // This function can be called in the midst of drawing another object (e.g., when uploading a
   1495     // SW-rasterized clip while issuing a draw). So we push the current geometry state before
   1496     // drawing a rect to the render target.
   1497     // The bracket ensures we pop the stack if we wind up flushing below.
   1498     {
   1499         GrDrawTarget* drawTarget = this->prepareToDraw();
   1500         if (!drawTarget) {
   1501             return false;
   1502         }
   1503 
   1504         GrPipelineBuilder pipelineBuilder;
   1505         pipelineBuilder.addColorProcessor(fp);
   1506         pipelineBuilder.setRenderTarget(renderTarget);
   1507         drawTarget->drawSimpleRect(&pipelineBuilder,
   1508                                    GrColor_WHITE,
   1509                                    matrix,
   1510                                    SkRect::MakeWH(SkIntToScalar(width), SkIntToScalar(height)));
   1511     }
   1512 
   1513     if (kFlushWrites_PixelOp & pixelOpsFlags) {
   1514         this->flushSurfaceWrites(surface);
   1515     }
   1516 
   1517     return true;
   1518 }
   1519 
   1520 // toggles between RGBA and BGRA
   1521 static SkColorType toggle_colortype32(SkColorType ct) {
   1522     if (kRGBA_8888_SkColorType == ct) {
   1523         return kBGRA_8888_SkColorType;
   1524     } else {
   1525         SkASSERT(kBGRA_8888_SkColorType == ct);
   1526         return kRGBA_8888_SkColorType;
   1527     }
   1528 }
   1529 
   1530 bool GrContext::readRenderTargetPixels(GrRenderTarget* target,
   1531                                        int left, int top, int width, int height,
   1532                                        GrPixelConfig dstConfig, void* buffer, size_t rowBytes,
   1533                                        uint32_t flags) {
   1534     RETURN_FALSE_IF_ABANDONED
   1535     ASSERT_OWNED_RESOURCE(target);
   1536     SkASSERT(target);
   1537 
   1538     if (!(kDontFlush_PixelOpsFlag & flags) && target->surfacePriv().hasPendingWrite()) {
   1539         this->flush();
   1540     }
   1541 
   1542     // Determine which conversions have to be applied: flipY, swapRAnd, and/or unpremul.
   1543 
   1544     // If fGpu->readPixels would incur a y-flip cost then we will read the pixels upside down. We'll
   1545     // either do the flipY by drawing into a scratch with a matrix or on the cpu after the read.
   1546     bool flipY = fGpu->readPixelsWillPayForYFlip(target, left, top,
   1547                                                  width, height, dstConfig,
   1548                                                  rowBytes);
   1549     // We ignore the preferred config if it is different than our config unless it is an R/B swap.
   1550     // In that case we'll perform an R and B swap while drawing to a scratch texture of the swapped
   1551     // config. Then we will call readPixels on the scratch with the swapped config. The swaps during
   1552     // the draw cancels out the fact that we call readPixels with a config that is R/B swapped from
   1553     // dstConfig.
   1554     GrPixelConfig readConfig = dstConfig;
   1555     bool swapRAndB = false;
   1556     if (GrPixelConfigSwapRAndB(dstConfig) ==
   1557         fGpu->preferredReadPixelsConfig(dstConfig, target->config())) {
   1558         readConfig = GrPixelConfigSwapRAndB(readConfig);
   1559         swapRAndB = true;
   1560     }
   1561 
   1562     bool unpremul = SkToBool(kUnpremul_PixelOpsFlag & flags);
   1563 
   1564     if (unpremul && !GrPixelConfigIs8888(dstConfig)) {
   1565         // The unpremul flag is only allowed for these two configs.
   1566         return false;
   1567     }
   1568 
   1569     SkAutoTUnref<GrTexture> tempTexture;
   1570 
   1571     // If the src is a texture and we would have to do conversions after read pixels, we instead
   1572     // do the conversions by drawing the src to a scratch texture. If we handle any of the
   1573     // conversions in the draw we set the corresponding bool to false so that we don't reapply it
   1574     // on the read back pixels.
   1575     GrTexture* src = target->asTexture();
   1576     if (src && (swapRAndB || unpremul || flipY)) {
   1577         // Make the scratch a render so we can read its pixels.
   1578         GrSurfaceDesc desc;
   1579         desc.fFlags = kRenderTarget_GrSurfaceFlag;
   1580         desc.fWidth = width;
   1581         desc.fHeight = height;
   1582         desc.fConfig = readConfig;
   1583         desc.fOrigin = kTopLeft_GrSurfaceOrigin;
   1584 
   1585         // When a full read back is faster than a partial we could always make the scratch exactly
   1586         // match the passed rect. However, if we see many different size rectangles we will trash
   1587         // our texture cache and pay the cost of creating and destroying many textures. So, we only
   1588         // request an exact match when the caller is reading an entire RT.
   1589         GrTextureProvider::ScratchTexMatch match = GrTextureProvider::kApprox_ScratchTexMatch;
   1590         if (0 == left &&
   1591             0 == top &&
   1592             target->width() == width &&
   1593             target->height() == height &&
   1594             fGpu->fullReadPixelsIsFasterThanPartial()) {
   1595             match = GrTextureProvider::kExact_ScratchTexMatch;
   1596         }
   1597         tempTexture.reset(this->textureProvider()->refScratchTexture(desc, match));
   1598         if (tempTexture) {
   1599             // compute a matrix to perform the draw
   1600             SkMatrix textureMatrix;
   1601             textureMatrix.setTranslate(SK_Scalar1 *left, SK_Scalar1 *top);
   1602             textureMatrix.postIDiv(src->width(), src->height());
   1603 
   1604             SkAutoTUnref<const GrFragmentProcessor> fp;
   1605             if (unpremul) {
   1606                 fp.reset(this->createPMToUPMEffect(src, swapRAndB, textureMatrix));
   1607                 if (fp) {
   1608                     unpremul = false; // we no longer need to do this on CPU after the read back.
   1609                 }
   1610             }
   1611             // If we failed to create a PM->UPM effect and have no other conversions to perform then
   1612             // there is no longer any point to using the scratch.
   1613             if (fp || flipY || swapRAndB) {
   1614                 if (!fp) {
   1615                     fp.reset(GrConfigConversionEffect::Create(
   1616                             src, swapRAndB, GrConfigConversionEffect::kNone_PMConversion,
   1617                             textureMatrix));
   1618                 }
   1619                 swapRAndB = false; // we will handle the swap in the draw.
   1620 
   1621                 // We protect the existing geometry here since it may not be
   1622                 // clear to the caller that a draw operation (i.e., drawSimpleRect)
   1623                 // can be invoked in this method
   1624                 {
   1625                     GrPipelineBuilder pipelineBuilder;
   1626                     SkASSERT(fp);
   1627                     pipelineBuilder.addColorProcessor(fp);
   1628 
   1629                     pipelineBuilder.setRenderTarget(tempTexture->asRenderTarget());
   1630                     SkRect rect = SkRect::MakeWH(SkIntToScalar(width), SkIntToScalar(height));
   1631                     fDrawBuffer->drawSimpleRect(&pipelineBuilder,
   1632                                                 GrColor_WHITE,
   1633                                                 SkMatrix::I(),
   1634                                                 rect);
   1635                     // we want to read back from the scratch's origin
   1636                     left = 0;
   1637                     top = 0;
   1638                     target = tempTexture->asRenderTarget();
   1639                 }
   1640                 this->flushSurfaceWrites(target);
   1641             }
   1642         }
   1643     }
   1644 
   1645     if (!fGpu->readPixels(target,
   1646                           left, top, width, height,
   1647                           readConfig, buffer, rowBytes)) {
   1648         return false;
   1649     }
   1650     // Perform any conversions we weren't able to perform using a scratch texture.
   1651     if (unpremul || swapRAndB) {
   1652         SkDstPixelInfo dstPI;
   1653         if (!GrPixelConfig2ColorAndProfileType(dstConfig, &dstPI.fColorType, NULL)) {
   1654             return false;
   1655         }
   1656         dstPI.fAlphaType = kUnpremul_SkAlphaType;
   1657         dstPI.fPixels = buffer;
   1658         dstPI.fRowBytes = rowBytes;
   1659 
   1660         SkSrcPixelInfo srcPI;
   1661         srcPI.fColorType = swapRAndB ? toggle_colortype32(dstPI.fColorType) : dstPI.fColorType;
   1662         srcPI.fAlphaType = kPremul_SkAlphaType;
   1663         srcPI.fPixels = buffer;
   1664         srcPI.fRowBytes = rowBytes;
   1665 
   1666         return srcPI.convertPixelsTo(&dstPI, width, height);
   1667     }
   1668     return true;
   1669 }
   1670 
   1671 void GrContext::prepareSurfaceForExternalRead(GrSurface* surface) {
   1672     RETURN_IF_ABANDONED
   1673     SkASSERT(surface);
   1674     ASSERT_OWNED_RESOURCE(surface);
   1675     if (surface->surfacePriv().hasPendingIO()) {
   1676         this->flush();
   1677     }
   1678     GrRenderTarget* rt = surface->asRenderTarget();
   1679     if (fGpu && rt) {
   1680         fGpu->resolveRenderTarget(rt);
   1681     }
   1682 }
   1683 
   1684 void GrContext::discardRenderTarget(GrRenderTarget* renderTarget) {
   1685     RETURN_IF_ABANDONED
   1686     SkASSERT(renderTarget);
   1687     ASSERT_OWNED_RESOURCE(renderTarget);
   1688     AutoCheckFlush acf(this);
   1689     GrDrawTarget* target = this->prepareToDraw();
   1690     if (NULL == target) {
   1691         return;
   1692     }
   1693     target->discard(renderTarget);
   1694 }
   1695 
   1696 void GrContext::copySurface(GrSurface* dst, GrSurface* src, const SkIRect& srcRect,
   1697                             const SkIPoint& dstPoint, uint32_t pixelOpsFlags) {
   1698     RETURN_IF_ABANDONED
   1699     if (NULL == src || NULL == dst) {
   1700         return;
   1701     }
   1702     ASSERT_OWNED_RESOURCE(src);
   1703     ASSERT_OWNED_RESOURCE(dst);
   1704 
   1705     // Since we're going to the draw target and not GPU, no need to check kNoFlush
   1706     // here.
   1707 
   1708     GrDrawTarget* target = this->prepareToDraw();
   1709     if (NULL == target) {
   1710         return;
   1711     }
   1712     target->copySurface(dst, src, srcRect, dstPoint);
   1713 
   1714     if (kFlushWrites_PixelOp & pixelOpsFlags) {
   1715         this->flush();
   1716     }
   1717 }
   1718 
   1719 void GrContext::flushSurfaceWrites(GrSurface* surface) {
   1720     RETURN_IF_ABANDONED
   1721     if (surface->surfacePriv().hasPendingWrite()) {
   1722         this->flush();
   1723     }
   1724 }
   1725 
   1726 GrDrawTarget* GrContext::prepareToDraw(GrPipelineBuilder* pipelineBuilder,
   1727                                        GrRenderTarget* rt,
   1728                                        const GrClip& clip,
   1729                                        const GrPaint* paint,
   1730                                        const AutoCheckFlush* acf) {
   1731     if (NULL == fGpu || NULL == fDrawBuffer) {
   1732         return NULL;
   1733     }
   1734 
   1735     ASSERT_OWNED_RESOURCE(rt);
   1736     SkASSERT(rt && paint && acf);
   1737     pipelineBuilder->setFromPaint(*paint, rt, clip);
   1738     return fDrawBuffer;
   1739 }
   1740 
   1741 GrDrawTarget* GrContext::prepareToDraw() {
   1742     if (NULL == fGpu) {
   1743         return NULL;
   1744     }
   1745     return fDrawBuffer;
   1746 }
   1747 
   1748 /*
   1749  * This method finds a path renderer that can draw the specified path on
   1750  * the provided target.
   1751  * Due to its expense, the software path renderer has split out so it can
   1752  * can be individually allowed/disallowed via the "allowSW" boolean.
   1753  */
   1754 GrPathRenderer* GrContext::getPathRenderer(const GrDrawTarget* target,
   1755                                            const GrPipelineBuilder* pipelineBuilder,
   1756                                            const SkMatrix& viewMatrix,
   1757                                            const SkPath& path,
   1758                                            const GrStrokeInfo& stroke,
   1759                                            bool allowSW,
   1760                                            GrPathRendererChain::DrawType drawType,
   1761                                            GrPathRendererChain::StencilSupport* stencilSupport) {
   1762 
   1763     if (NULL == fPathRendererChain) {
   1764         fPathRendererChain = SkNEW_ARGS(GrPathRendererChain, (this));
   1765     }
   1766 
   1767     GrPathRenderer* pr = fPathRendererChain->getPathRenderer(target,
   1768                                                              pipelineBuilder,
   1769                                                              viewMatrix,
   1770                                                              path,
   1771                                                              stroke,
   1772                                                              drawType,
   1773                                                              stencilSupport);
   1774 
   1775     if (NULL == pr && allowSW) {
   1776         if (NULL == fSoftwarePathRenderer) {
   1777             fSoftwarePathRenderer = SkNEW_ARGS(GrSoftwarePathRenderer, (this));
   1778         }
   1779         pr = fSoftwarePathRenderer;
   1780     }
   1781 
   1782     return pr;
   1783 }
   1784 
   1785 ////////////////////////////////////////////////////////////////////////////////
   1786 bool GrContext::isConfigRenderable(GrPixelConfig config, bool withMSAA) const {
   1787     return fGpu->caps()->isConfigRenderable(config, withMSAA);
   1788 }
   1789 
   1790 int GrContext::getRecommendedSampleCount(GrPixelConfig config,
   1791                                          SkScalar dpi) const {
   1792     if (!this->isConfigRenderable(config, true)) {
   1793         return 0;
   1794     }
   1795     int chosenSampleCount = 0;
   1796     if (fGpu->caps()->shaderCaps()->pathRenderingSupport()) {
   1797         if (dpi >= 250.0f) {
   1798             chosenSampleCount = 4;
   1799         } else {
   1800             chosenSampleCount = 16;
   1801         }
   1802     }
   1803     return chosenSampleCount <= fGpu->caps()->maxSampleCount() ?
   1804         chosenSampleCount : 0;
   1805 }
   1806 
   1807 GrDrawTarget* GrContext::getTextTarget() {
   1808     return this->prepareToDraw();
   1809 }
   1810 
   1811 namespace {
   1812 void test_pm_conversions(GrContext* ctx, int* pmToUPMValue, int* upmToPMValue) {
   1813     GrConfigConversionEffect::PMConversion pmToUPM;
   1814     GrConfigConversionEffect::PMConversion upmToPM;
   1815     GrConfigConversionEffect::TestForPreservingPMConversions(ctx, &pmToUPM, &upmToPM);
   1816     *pmToUPMValue = pmToUPM;
   1817     *upmToPMValue = upmToPM;
   1818 }
   1819 }
   1820 
   1821 const GrFragmentProcessor* GrContext::createPMToUPMEffect(GrTexture* texture,
   1822                                                           bool swapRAndB,
   1823                                                           const SkMatrix& matrix) {
   1824     if (!fDidTestPMConversions) {
   1825         test_pm_conversions(this, &fPMToUPMConversion, &fUPMToPMConversion);
   1826         fDidTestPMConversions = true;
   1827     }
   1828     GrConfigConversionEffect::PMConversion pmToUPM =
   1829         static_cast<GrConfigConversionEffect::PMConversion>(fPMToUPMConversion);
   1830     if (GrConfigConversionEffect::kNone_PMConversion != pmToUPM) {
   1831         return GrConfigConversionEffect::Create(texture, swapRAndB, pmToUPM, matrix);
   1832     } else {
   1833         return NULL;
   1834     }
   1835 }
   1836 
   1837 const GrFragmentProcessor* GrContext::createUPMToPMEffect(GrTexture* texture,
   1838                                                           bool swapRAndB,
   1839                                                           const SkMatrix& matrix) {
   1840     if (!fDidTestPMConversions) {
   1841         test_pm_conversions(this, &fPMToUPMConversion, &fUPMToPMConversion);
   1842         fDidTestPMConversions = true;
   1843     }
   1844     GrConfigConversionEffect::PMConversion upmToPM =
   1845         static_cast<GrConfigConversionEffect::PMConversion>(fUPMToPMConversion);
   1846     if (GrConfigConversionEffect::kNone_PMConversion != upmToPM) {
   1847         return GrConfigConversionEffect::Create(texture, swapRAndB, upmToPM, matrix);
   1848     } else {
   1849         return NULL;
   1850     }
   1851 }
   1852 
   1853 //////////////////////////////////////////////////////////////////////////////
   1854 
   1855 void GrContext::getResourceCacheLimits(int* maxTextures, size_t* maxTextureBytes) const {
   1856     if (maxTextures) {
   1857         *maxTextures = fResourceCache->getMaxResourceCount();
   1858     }
   1859     if (maxTextureBytes) {
   1860         *maxTextureBytes = fResourceCache->getMaxResourceBytes();
   1861     }
   1862 }
   1863 
   1864 void GrContext::setResourceCacheLimits(int maxTextures, size_t maxTextureBytes) {
   1865     fResourceCache->setLimits(maxTextures, maxTextureBytes);
   1866 }
   1867 
   1868 //////////////////////////////////////////////////////////////////////////////
   1869 
   1870 void GrContext::addGpuTraceMarker(const GrGpuTraceMarker* marker) {
   1871     fGpu->addGpuTraceMarker(marker);
   1872     if (fDrawBuffer) {
   1873         fDrawBuffer->addGpuTraceMarker(marker);
   1874     }
   1875 }
   1876 
   1877 void GrContext::removeGpuTraceMarker(const GrGpuTraceMarker* marker) {
   1878     fGpu->removeGpuTraceMarker(marker);
   1879     if (fDrawBuffer) {
   1880         fDrawBuffer->removeGpuTraceMarker(marker);
   1881     }
   1882 }
   1883 
   1884 ///////////////////////////////////////////////////////////////////////////////////////////////////
   1885 
   1886 #ifdef GR_TEST_UTILS
   1887 
   1888 BATCH_TEST_DEFINE(StrokeRectBatch) {
   1889     StrokeRectBatch::Geometry geometry;
   1890     geometry.fViewMatrix = GrTest::TestMatrix(random);
   1891     geometry.fColor = GrRandomColor(random);
   1892     geometry.fRect = GrTest::TestRect(random);
   1893     geometry.fStrokeWidth = random->nextBool() ? 0.0f : 1.0f;
   1894 
   1895     return StrokeRectBatch::Create(geometry, random->nextBool());
   1896 }
   1897 
   1898 static uint32_t seed_vertices(GrPrimitiveType type) {
   1899     switch (type) {
   1900         case kTriangles_GrPrimitiveType:
   1901         case kTriangleStrip_GrPrimitiveType:
   1902         case kTriangleFan_GrPrimitiveType:
   1903             return 3;
   1904         case kPoints_GrPrimitiveType:
   1905             return 1;
   1906         case kLines_GrPrimitiveType:
   1907         case kLineStrip_GrPrimitiveType:
   1908             return 2;
   1909     }
   1910     SkFAIL("Incomplete switch\n");
   1911     return 0;
   1912 }
   1913 
   1914 static uint32_t primitive_vertices(GrPrimitiveType type) {
   1915     switch (type) {
   1916         case kTriangles_GrPrimitiveType:
   1917             return 3;
   1918         case kLines_GrPrimitiveType:
   1919             return 2;
   1920         case kTriangleStrip_GrPrimitiveType:
   1921         case kTriangleFan_GrPrimitiveType:
   1922         case kPoints_GrPrimitiveType:
   1923         case kLineStrip_GrPrimitiveType:
   1924             return 1;
   1925     }
   1926     SkFAIL("Incomplete switch\n");
   1927     return 0;
   1928 }
   1929 
   1930 static SkPoint random_point(SkRandom* random, SkScalar min, SkScalar max) {
   1931     SkPoint p;
   1932     p.fX = random->nextRangeScalar(min, max);
   1933     p.fY = random->nextRangeScalar(min, max);
   1934     return p;
   1935 }
   1936 
   1937 static void randomize_params(size_t count, size_t maxVertex, SkScalar min, SkScalar max,
   1938                              SkRandom* random,
   1939                              SkTArray<SkPoint>* positions,
   1940                              SkTArray<SkPoint>* texCoords, bool hasTexCoords,
   1941                              SkTArray<GrColor>* colors, bool hasColors,
   1942                              SkTArray<uint16_t>* indices, bool hasIndices) {
   1943     for (uint32_t v = 0; v < count; v++) {
   1944         positions->push_back(random_point(random, min, max));
   1945         if (hasTexCoords) {
   1946             texCoords->push_back(random_point(random, min, max));
   1947         }
   1948         if (hasColors) {
   1949             colors->push_back(GrRandomColor(random));
   1950         }
   1951         if (hasIndices) {
   1952             SkASSERT(maxVertex <= SK_MaxU16);
   1953             indices->push_back(random->nextULessThan((uint16_t)maxVertex));
   1954         }
   1955     }
   1956 }
   1957 
   1958 BATCH_TEST_DEFINE(VerticesBatch) {
   1959     GrPrimitiveType type = GrPrimitiveType(random->nextULessThan(kLast_GrPrimitiveType + 1));
   1960     uint32_t primitiveCount = random->nextRangeU(1, 100);
   1961 
   1962     // TODO make 'sensible' indexbuffers
   1963     SkTArray<SkPoint> positions;
   1964     SkTArray<SkPoint> texCoords;
   1965     SkTArray<GrColor> colors;
   1966     SkTArray<uint16_t> indices;
   1967 
   1968     bool hasTexCoords = random->nextBool();
   1969     bool hasIndices = random->nextBool();
   1970     bool hasColors = random->nextBool();
   1971 
   1972     uint32_t vertexCount = seed_vertices(type) + (primitiveCount - 1) * primitive_vertices(type);
   1973 
   1974     static const SkScalar kMinVertExtent = -100.f;
   1975     static const SkScalar kMaxVertExtent = 100.f;
   1976     randomize_params(seed_vertices(type), vertexCount, kMinVertExtent, kMaxVertExtent,
   1977                      random,
   1978                      &positions,
   1979                      &texCoords, hasTexCoords,
   1980                      &colors, hasColors,
   1981                      &indices, hasIndices);
   1982 
   1983     for (uint32_t i = 1; i < primitiveCount; i++) {
   1984         randomize_params(primitive_vertices(type), vertexCount, kMinVertExtent, kMaxVertExtent,
   1985                          random,
   1986                          &positions,
   1987                          &texCoords, hasTexCoords,
   1988                          &colors, hasColors,
   1989                          &indices, hasIndices);
   1990     }
   1991 
   1992     SkMatrix viewMatrix = GrTest::TestMatrix(random);
   1993     SkRect bounds;
   1994     SkDEBUGCODE(bool result = ) bounds.setBoundsCheck(positions.begin(), vertexCount);
   1995     SkASSERT(result);
   1996 
   1997     viewMatrix.mapRect(&bounds);
   1998 
   1999     DrawVerticesBatch::Geometry geometry;
   2000     geometry.fColor = GrRandomColor(random);
   2001     return DrawVerticesBatch::Create(geometry, type, viewMatrix,
   2002                                      positions.begin(), vertexCount,
   2003                                      indices.begin(), hasIndices ? vertexCount : 0,
   2004                                      colors.begin(),
   2005                                      texCoords.begin(),
   2006                                      bounds);
   2007 }
   2008 
   2009 #endif
   2010