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 
     10 #include "GrContext.h"
     11 
     12 #include "effects/GrConvolutionEffect.h"
     13 #include "effects/GrSingleTextureEffect.h"
     14 #include "effects/GrConfigConversionEffect.h"
     15 
     16 #include "GrBufferAllocPool.h"
     17 #include "GrGpu.h"
     18 #include "GrIndexBuffer.h"
     19 #include "GrInOrderDrawBuffer.h"
     20 #include "GrPathRenderer.h"
     21 #include "GrPathUtils.h"
     22 #include "GrResourceCache.h"
     23 #include "GrSoftwarePathRenderer.h"
     24 #include "GrStencilBuffer.h"
     25 #include "GrTextStrike.h"
     26 #include "SkStrokeRec.h"
     27 #include "SkTLazy.h"
     28 #include "SkTLS.h"
     29 #include "SkTrace.h"
     30 
     31 SK_DEFINE_INST_COUNT(GrContext)
     32 SK_DEFINE_INST_COUNT(GrDrawState)
     33 
     34 // It can be useful to set this to kNo_BufferedDraw to test whether a bug is caused by using the
     35 // InOrderDrawBuffer, to compare performance of using/not using InOrderDrawBuffer, or to make
     36 // debugging easier.
     37 #define DEFAULT_BUFFERING (GR_DISABLE_DRAW_BUFFERING ? kNo_BufferedDraw : kYes_BufferedDraw)
     38 
     39 #define MAX_BLUR_SIGMA 4.0f
     40 
     41 // When we're using coverage AA but the blend is incompatible (given gpu
     42 // limitations) should we disable AA or draw wrong?
     43 #define DISABLE_COVERAGE_AA_FOR_BLEND 1
     44 
     45 #if GR_DEBUG
     46     // change this to a 1 to see notifications when partial coverage fails
     47     #define GR_DEBUG_PARTIAL_COVERAGE_CHECK 0
     48 #else
     49     #define GR_DEBUG_PARTIAL_COVERAGE_CHECK 0
     50 #endif
     51 
     52 static const size_t MAX_TEXTURE_CACHE_COUNT = 2048;
     53 static const size_t MAX_TEXTURE_CACHE_BYTES = GR_DEFAULT_TEXTURE_CACHE_MB_LIMIT * 1024 * 1024;
     54 
     55 static const size_t DRAW_BUFFER_VBPOOL_BUFFER_SIZE = 1 << 15;
     56 static const int DRAW_BUFFER_VBPOOL_PREALLOC_BUFFERS = 4;
     57 
     58 static const size_t DRAW_BUFFER_IBPOOL_BUFFER_SIZE = 1 << 11;
     59 static const int DRAW_BUFFER_IBPOOL_PREALLOC_BUFFERS = 4;
     60 
     61 #define ASSERT_OWNED_RESOURCE(R) GrAssert(!(R) || (R)->getContext() == this)
     62 
     63 GrContext* GrContext::Create(GrBackend backend, GrBackendContext context) {
     64     GrContext* ctx = NULL;
     65     GrGpu* fGpu = GrGpu::Create(backend, context);
     66     if (NULL != fGpu) {
     67         ctx = SkNEW_ARGS(GrContext, (fGpu));
     68         fGpu->unref();
     69     }
     70     return ctx;
     71 }
     72 
     73 namespace {
     74 void* CreateThreadInstanceCount() {
     75     return SkNEW_ARGS(int, (0));
     76 }
     77 void DeleteThreadInstanceCount(void* v) {
     78     delete reinterpret_cast<int*>(v);
     79 }
     80 #define THREAD_INSTANCE_COUNT                                               \
     81     (*reinterpret_cast<int*>(SkTLS::Get(CreateThreadInstanceCount,          \
     82                                         DeleteThreadInstanceCount)))
     83 
     84 }
     85 
     86 int GrContext::GetThreadInstanceCount() {
     87     return THREAD_INSTANCE_COUNT;
     88 }
     89 
     90 GrContext::~GrContext() {
     91     for (int i = 0; i < fCleanUpData.count(); ++i) {
     92         (*fCleanUpData[i].fFunc)(this, fCleanUpData[i].fInfo);
     93     }
     94 
     95     this->flush();
     96 
     97     // Since the gpu can hold scratch textures, give it a chance to let go
     98     // of them before freeing the texture cache
     99     fGpu->purgeResources();
    100 
    101     delete fTextureCache;
    102     fTextureCache = NULL;
    103     delete fFontCache;
    104     delete fDrawBuffer;
    105     delete fDrawBufferVBAllocPool;
    106     delete fDrawBufferIBAllocPool;
    107 
    108     fAARectRenderer->unref();
    109 
    110     fGpu->unref();
    111     GrSafeUnref(fPathRendererChain);
    112     GrSafeUnref(fSoftwarePathRenderer);
    113     fDrawState->unref();
    114 
    115     --THREAD_INSTANCE_COUNT;
    116 }
    117 
    118 void GrContext::contextLost() {
    119     contextDestroyed();
    120     this->setupDrawBuffer();
    121 }
    122 
    123 void GrContext::contextDestroyed() {
    124     // abandon first to so destructors
    125     // don't try to free the resources in the API.
    126     fGpu->abandonResources();
    127 
    128     // a path renderer may be holding onto resources that
    129     // are now unusable
    130     GrSafeSetNull(fPathRendererChain);
    131     GrSafeSetNull(fSoftwarePathRenderer);
    132 
    133     delete fDrawBuffer;
    134     fDrawBuffer = NULL;
    135 
    136     delete fDrawBufferVBAllocPool;
    137     fDrawBufferVBAllocPool = NULL;
    138 
    139     delete fDrawBufferIBAllocPool;
    140     fDrawBufferIBAllocPool = NULL;
    141 
    142     fAARectRenderer->reset();
    143 
    144     fTextureCache->purgeAllUnlocked();
    145     fFontCache->freeAll();
    146     fGpu->markContextDirty();
    147 }
    148 
    149 void GrContext::resetContext() {
    150     fGpu->markContextDirty();
    151 }
    152 
    153 void GrContext::freeGpuResources() {
    154     this->flush();
    155 
    156     fGpu->purgeResources();
    157 
    158     fAARectRenderer->reset();
    159 
    160     fTextureCache->purgeAllUnlocked();
    161     fFontCache->freeAll();
    162     // a path renderer may be holding onto resources
    163     GrSafeSetNull(fPathRendererChain);
    164     GrSafeSetNull(fSoftwarePathRenderer);
    165 }
    166 
    167 size_t GrContext::getGpuTextureCacheBytes() const {
    168   return fTextureCache->getCachedResourceBytes();
    169 }
    170 
    171 ////////////////////////////////////////////////////////////////////////////////
    172 
    173 namespace {
    174 
    175 void scale_rect(SkRect* rect, float xScale, float yScale) {
    176     rect->fLeft = SkScalarMul(rect->fLeft, SkFloatToScalar(xScale));
    177     rect->fTop = SkScalarMul(rect->fTop, SkFloatToScalar(yScale));
    178     rect->fRight = SkScalarMul(rect->fRight, SkFloatToScalar(xScale));
    179     rect->fBottom = SkScalarMul(rect->fBottom, SkFloatToScalar(yScale));
    180 }
    181 
    182 float adjust_sigma(float sigma, int *scaleFactor, int *radius) {
    183     *scaleFactor = 1;
    184     while (sigma > MAX_BLUR_SIGMA) {
    185         *scaleFactor *= 2;
    186         sigma *= 0.5f;
    187     }
    188     *radius = static_cast<int>(ceilf(sigma * 3.0f));
    189     GrAssert(*radius <= GrConvolutionEffect::kMaxKernelRadius);
    190     return sigma;
    191 }
    192 
    193 void convolve_gaussian(GrDrawTarget* target,
    194                        GrTexture* texture,
    195                        const SkRect& rect,
    196                        float sigma,
    197                        int radius,
    198                        Gr1DKernelEffect::Direction direction) {
    199     GrRenderTarget* rt = target->drawState()->getRenderTarget();
    200     GrDrawTarget::AutoStateRestore asr(target, GrDrawTarget::kReset_ASRInit);
    201     GrDrawState* drawState = target->drawState();
    202     drawState->setRenderTarget(rt);
    203     SkAutoTUnref<GrEffectRef> conv(GrConvolutionEffect::CreateGaussian(texture,
    204                                                                        direction,
    205                                                                        radius,
    206                                                                        sigma));
    207     drawState->setEffect(0, conv);
    208     target->drawSimpleRect(rect, NULL);
    209 }
    210 
    211 }
    212 
    213 ////////////////////////////////////////////////////////////////////////////////
    214 
    215 GrTexture* GrContext::findAndRefTexture(const GrTextureDesc& desc,
    216                                         const GrCacheID& cacheID,
    217                                         const GrTextureParams* params) {
    218     GrResourceKey resourceKey = GrTexture::ComputeKey(fGpu, params, desc, cacheID);
    219     GrResource* resource = fTextureCache->find(resourceKey);
    220     SkSafeRef(resource);
    221     return static_cast<GrTexture*>(resource);
    222 }
    223 
    224 bool GrContext::isTextureInCache(const GrTextureDesc& desc,
    225                                  const GrCacheID& cacheID,
    226                                  const GrTextureParams* params) const {
    227     GrResourceKey resourceKey = GrTexture::ComputeKey(fGpu, params, desc, cacheID);
    228     return fTextureCache->hasKey(resourceKey);
    229 }
    230 
    231 void GrContext::addStencilBuffer(GrStencilBuffer* sb) {
    232     ASSERT_OWNED_RESOURCE(sb);
    233 
    234     GrResourceKey resourceKey = GrStencilBuffer::ComputeKey(sb->width(),
    235                                                             sb->height(),
    236                                                             sb->numSamples());
    237     fTextureCache->addResource(resourceKey, sb);
    238 }
    239 
    240 GrStencilBuffer* GrContext::findStencilBuffer(int width, int height,
    241                                               int sampleCnt) {
    242     GrResourceKey resourceKey = GrStencilBuffer::ComputeKey(width,
    243                                                             height,
    244                                                             sampleCnt);
    245     GrResource* resource = fTextureCache->find(resourceKey);
    246     return static_cast<GrStencilBuffer*>(resource);
    247 }
    248 
    249 static void stretchImage(void* dst,
    250                          int dstW,
    251                          int dstH,
    252                          void* src,
    253                          int srcW,
    254                          int srcH,
    255                          int bpp) {
    256     GrFixed dx = (srcW << 16) / dstW;
    257     GrFixed dy = (srcH << 16) / dstH;
    258 
    259     GrFixed y = dy >> 1;
    260 
    261     int dstXLimit = dstW*bpp;
    262     for (int j = 0; j < dstH; ++j) {
    263         GrFixed x = dx >> 1;
    264         void* srcRow = (uint8_t*)src + (y>>16)*srcW*bpp;
    265         void* dstRow = (uint8_t*)dst + j*dstW*bpp;
    266         for (int i = 0; i < dstXLimit; i += bpp) {
    267             memcpy((uint8_t*) dstRow + i,
    268                    (uint8_t*) srcRow + (x>>16)*bpp,
    269                    bpp);
    270             x += dx;
    271         }
    272         y += dy;
    273     }
    274 }
    275 
    276 // The desired texture is NPOT and tiled but that isn't supported by
    277 // the current hardware. Resize the texture to be a POT
    278 GrTexture* GrContext::createResizedTexture(const GrTextureDesc& desc,
    279                                            const GrCacheID& cacheID,
    280                                            void* srcData,
    281                                            size_t rowBytes,
    282                                            bool needsFiltering) {
    283     SkAutoTUnref<GrTexture> clampedTexture(this->findAndRefTexture(desc, cacheID, NULL));
    284     if (NULL == clampedTexture) {
    285         clampedTexture.reset(this->createTexture(NULL, desc, cacheID, srcData, rowBytes));
    286 
    287         if (NULL == clampedTexture) {
    288             return NULL;
    289         }
    290     }
    291 
    292     GrTextureDesc rtDesc = desc;
    293     rtDesc.fFlags =  rtDesc.fFlags |
    294                      kRenderTarget_GrTextureFlagBit |
    295                      kNoStencil_GrTextureFlagBit;
    296     rtDesc.fWidth  = GrNextPow2(GrMax(desc.fWidth, 64));
    297     rtDesc.fHeight = GrNextPow2(GrMax(desc.fHeight, 64));
    298 
    299     GrTexture* texture = fGpu->createTexture(rtDesc, NULL, 0);
    300 
    301     if (NULL != texture) {
    302         GrDrawTarget::AutoStateRestore asr(fGpu, GrDrawTarget::kReset_ASRInit);
    303         GrDrawState* drawState = fGpu->drawState();
    304         drawState->setRenderTarget(texture->asRenderTarget());
    305 
    306         // if filtering is not desired then we want to ensure all
    307         // texels in the resampled image are copies of texels from
    308         // the original.
    309         GrTextureParams params(SkShader::kClamp_TileMode, needsFiltering);
    310         drawState->createTextureEffect(0, clampedTexture, SkMatrix::I(), params);
    311 
    312         static const GrVertexLayout layout = GrDrawState::StageTexCoordVertexLayoutBit(0,0);
    313         GrDrawTarget::AutoReleaseGeometry arg(fGpu, layout, 4, 0);
    314 
    315         if (arg.succeeded()) {
    316             GrPoint* verts = (GrPoint*) arg.vertices();
    317             verts[0].setIRectFan(0, 0, texture->width(), texture->height(), 2 * sizeof(GrPoint));
    318             verts[1].setIRectFan(0, 0, 1, 1, 2 * sizeof(GrPoint));
    319             fGpu->drawNonIndexed(kTriangleFan_GrPrimitiveType, 0, 4);
    320         }
    321         texture->releaseRenderTarget();
    322     } else {
    323         // TODO: Our CPU stretch doesn't filter. But we create separate
    324         // stretched textures when the texture params is either filtered or
    325         // not. Either implement filtered stretch blit on CPU or just create
    326         // one when FBO case fails.
    327 
    328         rtDesc.fFlags = kNone_GrTextureFlags;
    329         // no longer need to clamp at min RT size.
    330         rtDesc.fWidth  = GrNextPow2(desc.fWidth);
    331         rtDesc.fHeight = GrNextPow2(desc.fHeight);
    332         int bpp = GrBytesPerPixel(desc.fConfig);
    333         SkAutoSMalloc<128*128*4> stretchedPixels(bpp * rtDesc.fWidth * rtDesc.fHeight);
    334         stretchImage(stretchedPixels.get(), rtDesc.fWidth, rtDesc.fHeight,
    335                      srcData, desc.fWidth, desc.fHeight, bpp);
    336 
    337         size_t stretchedRowBytes = rtDesc.fWidth * bpp;
    338 
    339         SkDEBUGCODE(GrTexture* texture = )fGpu->createTexture(rtDesc, stretchedPixels.get(), stretchedRowBytes);
    340         GrAssert(NULL != texture);
    341     }
    342 
    343     return texture;
    344 }
    345 
    346 GrTexture* GrContext::createTexture(const GrTextureParams* params,
    347                                     const GrTextureDesc& desc,
    348                                     const GrCacheID& cacheID,
    349                                     void* srcData,
    350                                     size_t rowBytes) {
    351     SK_TRACE_EVENT0("GrContext::createTexture");
    352 
    353 #if GR_DUMP_TEXTURE_UPLOAD
    354     GrPrintf("GrContext::createTexture[%d %d]\n", desc.fWidth, desc.fHeight);
    355 #endif
    356 
    357     GrResourceKey resourceKey = GrTexture::ComputeKey(fGpu, params, desc, cacheID);
    358 
    359     GrTexture* texture;
    360     if (GrTexture::NeedsResizing(resourceKey)) {
    361         texture = this->createResizedTexture(desc, cacheID,
    362                                              srcData, rowBytes,
    363                                              GrTexture::NeedsFiltering(resourceKey));
    364     } else {
    365         texture= fGpu->createTexture(desc, srcData, rowBytes);
    366     }
    367 
    368     if (NULL != texture) {
    369         fTextureCache->addResource(resourceKey, texture);
    370     }
    371 
    372     return texture;
    373 }
    374 
    375 GrTexture* GrContext::lockAndRefScratchTexture(const GrTextureDesc& inDesc, ScratchTexMatch match) {
    376     GrTextureDesc desc = inDesc;
    377 
    378     GrAssert((desc.fFlags & kRenderTarget_GrTextureFlagBit) ||
    379              !(desc.fFlags & kNoStencil_GrTextureFlagBit));
    380 
    381     if (kApprox_ScratchTexMatch == match) {
    382         // bin by pow2 with a reasonable min
    383         static const int MIN_SIZE = 256;
    384         desc.fWidth  = GrMax(MIN_SIZE, GrNextPow2(desc.fWidth));
    385         desc.fHeight = GrMax(MIN_SIZE, GrNextPow2(desc.fHeight));
    386     }
    387 
    388     GrResource* resource = NULL;
    389     int origWidth = desc.fWidth;
    390     int origHeight = desc.fHeight;
    391     bool doubledW = false;
    392     bool doubledH = false;
    393 
    394     do {
    395         GrResourceKey key = GrTexture::ComputeScratchKey(desc);
    396         // Ensure we have exclusive access to the texture so future 'find' calls don't return it
    397         resource = fTextureCache->find(key, GrResourceCache::kHide_OwnershipFlag);
    398         if (NULL != resource) {
    399             resource->ref();
    400             break;
    401         }
    402         if (kExact_ScratchTexMatch == match) {
    403             break;
    404         }
    405         // We had a cache miss and we are in approx mode, relax the fit of the flags... then try
    406         // doubling width... then the height.
    407 
    408         // We no longer try to reuse textures that were previously used as render targets in
    409         // situations where no RT is needed; doing otherwise can confuse the video driver and
    410         // cause significant performance problems in some cases.
    411         if (desc.fFlags & kNoStencil_GrTextureFlagBit) {
    412             desc.fFlags = desc.fFlags & ~kNoStencil_GrTextureFlagBit;
    413         } else if (!doubledW) {
    414             desc.fFlags = inDesc.fFlags;
    415             desc.fWidth *= 2;
    416             doubledW = true;
    417         } else if (!doubledH) {
    418             desc.fFlags = inDesc.fFlags;
    419             desc.fWidth = origWidth;
    420             desc.fHeight *= 2;
    421             doubledH = true;
    422         } else {
    423             break;
    424         }
    425 
    426     } while (true);
    427 
    428     if (NULL == resource) {
    429         desc.fFlags = inDesc.fFlags;
    430         desc.fWidth = origWidth;
    431         desc.fHeight = origHeight;
    432         GrTexture* texture = fGpu->createTexture(desc, NULL, 0);
    433         if (NULL != texture) {
    434             GrResourceKey key = GrTexture::ComputeScratchKey(texture->desc());
    435             // Make the resource exclusive so future 'find' calls don't return it
    436             fTextureCache->addResource(key, texture, GrResourceCache::kHide_OwnershipFlag);
    437             resource = texture;
    438         }
    439     }
    440 
    441     return static_cast<GrTexture*>(resource);
    442 }
    443 
    444 void GrContext::addExistingTextureToCache(GrTexture* texture) {
    445 
    446     if (NULL == texture) {
    447         return;
    448     }
    449 
    450     // This texture should already have a cache entry since it was once
    451     // attached
    452     GrAssert(NULL != texture->getCacheEntry());
    453 
    454     // Conceptually, the cache entry is going to assume responsibility
    455     // for the creation ref.
    456     GrAssert(1 == texture->getRefCnt());
    457 
    458     // Since this texture came from an AutoScratchTexture it should
    459     // still be in the exclusive pile
    460     fTextureCache->makeNonExclusive(texture->getCacheEntry());
    461 
    462     this->purgeCache();
    463 }
    464 
    465 
    466 void GrContext::unlockScratchTexture(GrTexture* texture) {
    467     ASSERT_OWNED_RESOURCE(texture);
    468     GrAssert(NULL != texture->getCacheEntry());
    469 
    470     // If this is a scratch texture we detached it from the cache
    471     // while it was locked (to avoid two callers simultaneously getting
    472     // the same texture).
    473     if (texture->getCacheEntry()->key().isScratch()) {
    474         fTextureCache->makeNonExclusive(texture->getCacheEntry());
    475     }
    476 
    477     this->purgeCache();
    478 }
    479 
    480 void GrContext::purgeCache() {
    481     if (NULL != fTextureCache) {
    482         fTextureCache->purgeAsNeeded();
    483     }
    484 }
    485 
    486 GrTexture* GrContext::createUncachedTexture(const GrTextureDesc& descIn,
    487                                             void* srcData,
    488                                             size_t rowBytes) {
    489     GrTextureDesc descCopy = descIn;
    490     return fGpu->createTexture(descCopy, srcData, rowBytes);
    491 }
    492 
    493 void GrContext::getTextureCacheLimits(int* maxTextures,
    494                                       size_t* maxTextureBytes) const {
    495     fTextureCache->getLimits(maxTextures, maxTextureBytes);
    496 }
    497 
    498 void GrContext::setTextureCacheLimits(int maxTextures, size_t maxTextureBytes) {
    499     fTextureCache->setLimits(maxTextures, maxTextureBytes);
    500 }
    501 
    502 int GrContext::getMaxTextureSize() const {
    503     return fGpu->getCaps().maxTextureSize();
    504 }
    505 
    506 int GrContext::getMaxRenderTargetSize() const {
    507     return fGpu->getCaps().maxRenderTargetSize();
    508 }
    509 
    510 ///////////////////////////////////////////////////////////////////////////////
    511 
    512 GrTexture* GrContext::wrapBackendTexture(const GrBackendTextureDesc& desc) {
    513     return fGpu->wrapBackendTexture(desc);
    514 }
    515 
    516 GrRenderTarget* GrContext::wrapBackendRenderTarget(const GrBackendRenderTargetDesc& desc) {
    517     return fGpu->wrapBackendRenderTarget(desc);
    518 }
    519 
    520 ///////////////////////////////////////////////////////////////////////////////
    521 
    522 bool GrContext::supportsIndex8PixelConfig(const GrTextureParams* params,
    523                                           int width, int height) const {
    524     const GrDrawTarget::Caps& caps = fGpu->getCaps();
    525     if (!caps.eightBitPaletteSupport()) {
    526         return false;
    527     }
    528 
    529     bool isPow2 = GrIsPow2(width) && GrIsPow2(height);
    530 
    531     if (!isPow2) {
    532         bool tiled = NULL != params && params->isTiled();
    533         if (tiled && !caps.npotTextureTileSupport()) {
    534             return false;
    535         }
    536     }
    537     return true;
    538 }
    539 
    540 ////////////////////////////////////////////////////////////////////////////////
    541 
    542 const GrClipData* GrContext::getClip() const {
    543     return fGpu->getClip();
    544 }
    545 
    546 void GrContext::setClip(const GrClipData* clipData) {
    547     fGpu->setClip(clipData);
    548 
    549     fDrawState->setState(GrDrawState::kClip_StateBit,
    550                          clipData && clipData->fClipStack && !clipData->fClipStack->isWideOpen());
    551 }
    552 
    553 ////////////////////////////////////////////////////////////////////////////////
    554 
    555 void GrContext::clear(const GrIRect* rect,
    556                       const GrColor color,
    557                       GrRenderTarget* target) {
    558     this->prepareToDraw(NULL, DEFAULT_BUFFERING)->clear(rect, color, target);
    559 }
    560 
    561 void GrContext::drawPaint(const GrPaint& origPaint) {
    562     // set rect to be big enough to fill the space, but not super-huge, so we
    563     // don't overflow fixed-point implementations
    564     GrRect r;
    565     r.setLTRB(0, 0,
    566               SkIntToScalar(getRenderTarget()->width()),
    567               SkIntToScalar(getRenderTarget()->height()));
    568     SkMatrix inverse;
    569     SkTCopyOnFirstWrite<GrPaint> paint(origPaint);
    570     AutoMatrix am;
    571 
    572     // We attempt to map r by the inverse matrix and draw that. mapRect will
    573     // map the four corners and bound them with a new rect. This will not
    574     // produce a correct result for some perspective matrices.
    575     if (!this->getMatrix().hasPerspective()) {
    576         if (!fDrawState->getViewInverse(&inverse)) {
    577             GrPrintf("Could not invert matrix\n");
    578             return;
    579         }
    580         inverse.mapRect(&r);
    581     } else {
    582         if (!am.setIdentity(this, paint.writable())) {
    583             GrPrintf("Could not invert matrix\n");
    584             return;
    585         }
    586     }
    587     // by definition this fills the entire clip, no need for AA
    588     if (paint->isAntiAlias()) {
    589         paint.writable()->setAntiAlias(false);
    590     }
    591     this->drawRect(*paint, r);
    592 }
    593 
    594 ////////////////////////////////////////////////////////////////////////////////
    595 
    596 namespace {
    597 inline bool disable_coverage_aa_for_blend(GrDrawTarget* target) {
    598     return DISABLE_COVERAGE_AA_FOR_BLEND && !target->canApplyCoverage();
    599 }
    600 }
    601 
    602 ////////////////////////////////////////////////////////////////////////////////
    603 
    604 /*  create a triangle strip that strokes the specified triangle. There are 8
    605  unique vertices, but we repreat the last 2 to close up. Alternatively we
    606  could use an indices array, and then only send 8 verts, but not sure that
    607  would be faster.
    608  */
    609 static void setStrokeRectStrip(GrPoint verts[10], GrRect rect,
    610                                SkScalar width) {
    611     const SkScalar rad = SkScalarHalf(width);
    612     rect.sort();
    613 
    614     verts[0].set(rect.fLeft + rad, rect.fTop + rad);
    615     verts[1].set(rect.fLeft - rad, rect.fTop - rad);
    616     verts[2].set(rect.fRight - rad, rect.fTop + rad);
    617     verts[3].set(rect.fRight + rad, rect.fTop - rad);
    618     verts[4].set(rect.fRight - rad, rect.fBottom - rad);
    619     verts[5].set(rect.fRight + rad, rect.fBottom + rad);
    620     verts[6].set(rect.fLeft + rad, rect.fBottom - rad);
    621     verts[7].set(rect.fLeft - rad, rect.fBottom + rad);
    622     verts[8] = verts[0];
    623     verts[9] = verts[1];
    624 }
    625 
    626 /**
    627  * Returns true if the rects edges are integer-aligned.
    628  */
    629 static bool isIRect(const GrRect& r) {
    630     return SkScalarIsInt(r.fLeft) && SkScalarIsInt(r.fTop) &&
    631            SkScalarIsInt(r.fRight) && SkScalarIsInt(r.fBottom);
    632 }
    633 
    634 static bool apply_aa_to_rect(GrDrawTarget* target,
    635                              const GrRect& rect,
    636                              SkScalar width,
    637                              const SkMatrix* matrix,
    638                              SkMatrix* combinedMatrix,
    639                              GrRect* devRect,
    640                              bool* useVertexCoverage) {
    641     // we use a simple coverage ramp to do aa on axis-aligned rects
    642     // we check if the rect will be axis-aligned, and the rect won't land on
    643     // integer coords.
    644 
    645     // we are keeping around the "tweak the alpha" trick because
    646     // it is our only hope for the fixed-pipe implementation.
    647     // In a shader implementation we can give a separate coverage input
    648     // TODO: remove this ugliness when we drop the fixed-pipe impl
    649     *useVertexCoverage = false;
    650     if (!target->canTweakAlphaForCoverage()) {
    651         if (disable_coverage_aa_for_blend(target)) {
    652 #if GR_DEBUG
    653             //GrPrintf("Turning off AA to correctly apply blend.\n");
    654 #endif
    655             return false;
    656         } else {
    657             *useVertexCoverage = true;
    658         }
    659     }
    660     const GrDrawState& drawState = target->getDrawState();
    661     if (drawState.getRenderTarget()->isMultisampled()) {
    662         return false;
    663     }
    664 
    665     if (0 == width && target->willUseHWAALines()) {
    666         return false;
    667     }
    668 
    669     if (!drawState.getViewMatrix().preservesAxisAlignment()) {
    670         return false;
    671     }
    672 
    673     if (NULL != matrix &&
    674         !matrix->preservesAxisAlignment()) {
    675         return false;
    676     }
    677 
    678     *combinedMatrix = drawState.getViewMatrix();
    679     if (NULL != matrix) {
    680         combinedMatrix->preConcat(*matrix);
    681         GrAssert(combinedMatrix->preservesAxisAlignment());
    682     }
    683 
    684     combinedMatrix->mapRect(devRect, rect);
    685     devRect->sort();
    686 
    687     if (width < 0) {
    688         return !isIRect(*devRect);
    689     } else {
    690         return true;
    691     }
    692 }
    693 
    694 void GrContext::drawRect(const GrPaint& paint,
    695                          const GrRect& rect,
    696                          SkScalar width,
    697                          const SkMatrix* matrix) {
    698     SK_TRACE_EVENT0("GrContext::drawRect");
    699 
    700     GrDrawTarget* target = this->prepareToDraw(&paint, DEFAULT_BUFFERING);
    701     GrDrawState::AutoStageDisable atr(fDrawState);
    702 
    703     GrRect devRect = rect;
    704     SkMatrix combinedMatrix;
    705     bool useVertexCoverage;
    706     bool needAA = paint.isAntiAlias() &&
    707                   !this->getRenderTarget()->isMultisampled();
    708     bool doAA = needAA && apply_aa_to_rect(target, rect, width, matrix,
    709                                            &combinedMatrix, &devRect,
    710                                            &useVertexCoverage);
    711 
    712     if (doAA) {
    713         GrDrawState::AutoDeviceCoordDraw adcd(target->drawState());
    714         if (!adcd.succeeded()) {
    715             return;
    716         }
    717         if (width >= 0) {
    718             GrVec strokeSize;
    719             if (width > 0) {
    720                 strokeSize.set(width, width);
    721                 combinedMatrix.mapVectors(&strokeSize, 1);
    722                 strokeSize.setAbs(strokeSize);
    723             } else {
    724                 strokeSize.set(SK_Scalar1, SK_Scalar1);
    725             }
    726             fAARectRenderer->strokeAARect(this->getGpu(), target, devRect,
    727                                          strokeSize, useVertexCoverage);
    728         } else {
    729             fAARectRenderer->fillAARect(this->getGpu(), target,
    730                                        devRect, useVertexCoverage);
    731         }
    732         return;
    733     }
    734 
    735     if (width >= 0) {
    736         // TODO: consider making static vertex buffers for these cases.
    737         // Hairline could be done by just adding closing vertex to
    738         // unitSquareVertexBuffer()
    739 
    740         static const int worstCaseVertCount = 10;
    741         GrDrawTarget::AutoReleaseGeometry geo(target, 0, worstCaseVertCount, 0);
    742 
    743         if (!geo.succeeded()) {
    744             GrPrintf("Failed to get space for vertices!\n");
    745             return;
    746         }
    747 
    748         GrPrimitiveType primType;
    749         int vertCount;
    750         GrPoint* vertex = geo.positions();
    751 
    752         if (width > 0) {
    753             vertCount = 10;
    754             primType = kTriangleStrip_GrPrimitiveType;
    755             setStrokeRectStrip(vertex, rect, width);
    756         } else {
    757             // hairline
    758             vertCount = 5;
    759             primType = kLineStrip_GrPrimitiveType;
    760             vertex[0].set(rect.fLeft, rect.fTop);
    761             vertex[1].set(rect.fRight, rect.fTop);
    762             vertex[2].set(rect.fRight, rect.fBottom);
    763             vertex[3].set(rect.fLeft, rect.fBottom);
    764             vertex[4].set(rect.fLeft, rect.fTop);
    765         }
    766 
    767         GrDrawState::AutoViewMatrixRestore avmr;
    768         if (NULL != matrix) {
    769             GrDrawState* drawState = target->drawState();
    770             avmr.set(drawState, *matrix);
    771         }
    772 
    773         target->drawNonIndexed(primType, 0, vertCount);
    774     } else {
    775 #if GR_STATIC_RECT_VB
    776             const GrVertexBuffer* sqVB = fGpu->getUnitSquareVertexBuffer();
    777             if (NULL == sqVB) {
    778                 GrPrintf("Failed to create static rect vb.\n");
    779                 return;
    780             }
    781             target->setVertexSourceToBuffer(0, sqVB);
    782             GrDrawState* drawState = target->drawState();
    783             SkMatrix m;
    784             m.setAll(rect.width(),    0,             rect.fLeft,
    785                         0,            rect.height(), rect.fTop,
    786                         0,            0,             SkMatrix::I()[8]);
    787 
    788             if (NULL != matrix) {
    789                 m.postConcat(*matrix);
    790             }
    791             GrDrawState::AutoViewMatrixRestore avmr(drawState, m);
    792 
    793             target->drawNonIndexed(kTriangleFan_GrPrimitiveType, 0, 4);
    794 #else
    795             target->drawSimpleRect(rect, matrix);
    796 #endif
    797     }
    798 }
    799 
    800 void GrContext::drawRectToRect(const GrPaint& paint,
    801                                const GrRect& dstRect,
    802                                const GrRect& srcRect,
    803                                const SkMatrix* dstMatrix,
    804                                const SkMatrix* srcMatrix) {
    805     SK_TRACE_EVENT0("GrContext::drawRectToRect");
    806 
    807     // srcRect refers to paint's first color stage
    808     if (!paint.isColorStageEnabled(0)) {
    809         drawRect(paint, dstRect, -1, dstMatrix);
    810         return;
    811     }
    812 
    813     GrDrawTarget* target = this->prepareToDraw(&paint, DEFAULT_BUFFERING);
    814 
    815 #if GR_STATIC_RECT_VB
    816     GrDrawState::AutoStageDisable atr(fDrawState);
    817     GrDrawState* drawState = target->drawState();
    818 
    819     SkMatrix m;
    820 
    821     m.setAll(dstRect.width(), 0,                dstRect.fLeft,
    822              0,               dstRect.height(), dstRect.fTop,
    823              0,               0,                SkMatrix::I()[8]);
    824     if (NULL != dstMatrix) {
    825         m.postConcat(*dstMatrix);
    826     }
    827 
    828     // The first color stage's coords come from srcRect rather than applying a matrix to dstRect.
    829     // We explicitly compute a matrix for that stage below, no need to adjust here.
    830     static const uint32_t kExplicitCoordMask = 1 << GrPaint::kFirstColorStage;
    831     GrDrawState::AutoViewMatrixRestore avmr(drawState, m, kExplicitCoordMask);
    832 
    833     m.setAll(srcRect.width(), 0,                srcRect.fLeft,
    834              0,               srcRect.height(), srcRect.fTop,
    835              0,               0,                SkMatrix::I()[8]);
    836     if (NULL != srcMatrix) {
    837         m.postConcat(*srcMatrix);
    838     }
    839 
    840     drawState->preConcatStageMatrices(kExplicitCoordMask, m);
    841 
    842     const GrVertexBuffer* sqVB = fGpu->getUnitSquareVertexBuffer();
    843     if (NULL == sqVB) {
    844         GrPrintf("Failed to create static rect vb.\n");
    845         return;
    846     }
    847     target->setVertexSourceToBuffer(0, sqVB);
    848     target->drawNonIndexed(kTriangleFan_GrPrimitiveType, 0, 4);
    849 #else
    850     GrDrawState::AutoStageDisable atr(fDrawState);
    851 
    852     const GrRect* srcRects[GrDrawState::kNumStages] = {NULL};
    853     const SkMatrix* srcMatrices[GrDrawState::kNumStages] = {NULL};
    854     srcRects[0] = &srcRect;
    855     srcMatrices[0] = srcMatrix;
    856 
    857     target->drawRect(dstRect, dstMatrix, srcRects, srcMatrices);
    858 #endif
    859 }
    860 
    861 void GrContext::drawVertices(const GrPaint& paint,
    862                              GrPrimitiveType primitiveType,
    863                              int vertexCount,
    864                              const GrPoint positions[],
    865                              const GrPoint texCoords[],
    866                              const GrColor colors[],
    867                              const uint16_t indices[],
    868                              int indexCount) {
    869     SK_TRACE_EVENT0("GrContext::drawVertices");
    870 
    871     GrDrawTarget::AutoReleaseGeometry geo;
    872 
    873     GrDrawTarget* target = this->prepareToDraw(&paint, DEFAULT_BUFFERING);
    874     GrDrawState::AutoStageDisable atr(fDrawState);
    875 
    876     GrVertexLayout layout = 0;
    877     if (NULL != texCoords) {
    878         layout |= GrDrawState::StageTexCoordVertexLayoutBit(0, 0);
    879     }
    880     if (NULL != colors) {
    881         layout |= GrDrawState::kColor_VertexLayoutBit;
    882     }
    883     int vertexSize = GrDrawState::VertexSize(layout);
    884 
    885     if (sizeof(GrPoint) != vertexSize) {
    886         if (!geo.set(target, layout, vertexCount, 0)) {
    887             GrPrintf("Failed to get space for vertices!\n");
    888             return;
    889         }
    890         int texOffsets[GrDrawState::kMaxTexCoords];
    891         int colorOffset;
    892         GrDrawState::VertexSizeAndOffsetsByIdx(layout,
    893                                                 texOffsets,
    894                                                 &colorOffset,
    895                                                 NULL,
    896                                                 NULL);
    897         void* curVertex = geo.vertices();
    898 
    899         for (int i = 0; i < vertexCount; ++i) {
    900             *((GrPoint*)curVertex) = positions[i];
    901 
    902             if (texOffsets[0] > 0) {
    903                 *(GrPoint*)((intptr_t)curVertex + texOffsets[0]) = texCoords[i];
    904             }
    905             if (colorOffset > 0) {
    906                 *(GrColor*)((intptr_t)curVertex + colorOffset) = colors[i];
    907             }
    908             curVertex = (void*)((intptr_t)curVertex + vertexSize);
    909         }
    910     } else {
    911         target->setVertexSourceToArray(layout, positions, vertexCount);
    912     }
    913 
    914     // we don't currently apply offscreen AA to this path. Need improved
    915     // management of GrDrawTarget's geometry to avoid copying points per-tile.
    916 
    917     if (NULL != indices) {
    918         target->setIndexSourceToArray(indices, indexCount);
    919         target->drawIndexed(primitiveType, 0, 0, vertexCount, indexCount);
    920     } else {
    921         target->drawNonIndexed(primitiveType, 0, vertexCount);
    922     }
    923 }
    924 
    925 ///////////////////////////////////////////////////////////////////////////////
    926 namespace {
    927 
    928 struct CircleVertex {
    929     GrPoint fPos;
    930     GrPoint fCenter;
    931     SkScalar fOuterRadius;
    932     SkScalar fInnerRadius;
    933 };
    934 
    935 inline bool circleStaysCircle(const SkMatrix& m) {
    936     return m.isSimilarity();
    937 }
    938 
    939 }
    940 
    941 void GrContext::drawOval(const GrPaint& paint,
    942                          const GrRect& oval,
    943                          const SkStrokeRec& stroke) {
    944 
    945     if (!canDrawOval(paint, oval, stroke)) {
    946         SkPath path;
    947         path.addOval(oval);
    948         this->drawPath(paint, path, stroke);
    949         return;
    950     }
    951 
    952     internalDrawOval(paint, oval, stroke);
    953 }
    954 
    955 bool GrContext::canDrawOval(const GrPaint& paint, const GrRect& oval, const SkStrokeRec& stroke) const {
    956 
    957     if (!paint.isAntiAlias()) {
    958         return false;
    959     }
    960 
    961     // we can draw circles in any style
    962     bool isCircle = SkScalarNearlyEqual(oval.width(), oval.height())
    963                     && circleStaysCircle(this->getMatrix());
    964     // and for now, axis-aligned ellipses only with fill or stroke-and-fill
    965     SkStrokeRec::Style style = stroke.getStyle();
    966     bool isStroke = (style == SkStrokeRec::kStroke_Style || style == SkStrokeRec::kHairline_Style);
    967     bool isFilledAxisAlignedEllipse = this->getMatrix().rectStaysRect() && !isStroke;
    968 
    969     return isCircle || isFilledAxisAlignedEllipse;
    970 }
    971 
    972 void GrContext::internalDrawOval(const GrPaint& paint,
    973                                  const GrRect& oval,
    974                                  const SkStrokeRec& stroke) {
    975 
    976     SkScalar xRadius = SkScalarHalf(oval.width());
    977     SkScalar yRadius = SkScalarHalf(oval.height());
    978 
    979     SkScalar strokeWidth = stroke.getWidth();
    980     SkStrokeRec::Style style = stroke.getStyle();
    981 
    982     bool isCircle = SkScalarNearlyEqual(xRadius, yRadius) && circleStaysCircle(this->getMatrix());
    983 #ifdef SK_DEBUG
    984     {
    985         // we should have checked for this previously
    986         bool isStroke = (style == SkStrokeRec::kStroke_Style || style == SkStrokeRec::kHairline_Style);
    987         bool isFilledAxisAlignedEllipse = this->getMatrix().rectStaysRect() && !isStroke;
    988         SkASSERT(paint.isAntiAlias() && (isCircle || isFilledAxisAlignedEllipse));
    989     }
    990 #endif
    991 
    992     GrDrawTarget* target = this->prepareToDraw(&paint, DEFAULT_BUFFERING);
    993 
    994     GrDrawState* drawState = target->drawState();
    995     GrDrawState::AutoStageDisable atr(fDrawState);
    996     const SkMatrix vm = drawState->getViewMatrix();
    997 
    998     const GrRenderTarget* rt = drawState->getRenderTarget();
    999     if (NULL == rt) {
   1000         return;
   1001     }
   1002 
   1003     GrDrawState::AutoDeviceCoordDraw adcd(drawState);
   1004     if (!adcd.succeeded()) {
   1005         return;
   1006     }
   1007 
   1008     GrVertexLayout layout = GrDrawState::kEdge_VertexLayoutBit;
   1009     GrAssert(sizeof(CircleVertex) == GrDrawState::VertexSize(layout));
   1010 
   1011     GrDrawTarget::AutoReleaseGeometry geo(target, layout, 4, 0);
   1012     if (!geo.succeeded()) {
   1013         GrPrintf("Failed to get space for vertices!\n");
   1014         return;
   1015     }
   1016 
   1017     CircleVertex* verts = reinterpret_cast<CircleVertex*>(geo.vertices());
   1018 
   1019     GrPoint center = GrPoint::Make(oval.centerX(), oval.centerY());
   1020     vm.mapPoints(&center, 1);
   1021 
   1022     SkScalar L;
   1023     SkScalar R;
   1024     SkScalar T;
   1025     SkScalar B;
   1026 
   1027     if (isCircle) {
   1028         drawState->setVertexEdgeType(GrDrawState::kCircle_EdgeType);
   1029 
   1030         xRadius = vm.mapRadius(xRadius);
   1031 
   1032         SkScalar outerRadius = xRadius;
   1033         SkScalar innerRadius = 0;
   1034         SkScalar halfWidth = 0;
   1035         if (style != SkStrokeRec::kFill_Style) {
   1036             strokeWidth = vm.mapRadius(strokeWidth);
   1037             if (SkScalarNearlyZero(strokeWidth)) {
   1038                 halfWidth = SK_ScalarHalf;
   1039             } else {
   1040                 halfWidth = SkScalarHalf(strokeWidth);
   1041             }
   1042 
   1043             outerRadius += halfWidth;
   1044             if (style == SkStrokeRec::kStroke_Style || style == SkStrokeRec::kHairline_Style) {
   1045                 innerRadius = SkMaxScalar(0, xRadius - halfWidth);
   1046             }
   1047         }
   1048 
   1049         for (int i = 0; i < 4; ++i) {
   1050             verts[i].fCenter = center;
   1051             verts[i].fOuterRadius = outerRadius;
   1052             verts[i].fInnerRadius = innerRadius;
   1053         }
   1054 
   1055         L = -outerRadius;
   1056         R = +outerRadius;
   1057         T = -outerRadius;
   1058         B = +outerRadius;
   1059     } else {  // is axis-aligned ellipse
   1060         drawState->setVertexEdgeType(GrDrawState::kEllipse_EdgeType);
   1061 
   1062         SkRect xformedRect;
   1063         vm.mapRect(&xformedRect, oval);
   1064 
   1065         xRadius = SkScalarHalf(xformedRect.width());
   1066         yRadius = SkScalarHalf(xformedRect.height());
   1067 
   1068         if (style == SkStrokeRec::kStrokeAndFill_Style && strokeWidth > 0.0f) {
   1069             SkScalar halfWidth = SkScalarHalf(strokeWidth);
   1070             // do (potentially) anisotropic mapping
   1071             SkVector scaledStroke;
   1072             scaledStroke.set(halfWidth, halfWidth);
   1073             vm.mapVectors(&scaledStroke, 1);
   1074             // this is legit only if scale & translation (which should be the case at the moment)
   1075             xRadius += scaledStroke.fX;
   1076             yRadius += scaledStroke.fY;
   1077         }
   1078 
   1079         SkScalar ratio = SkScalarDiv(xRadius, yRadius);
   1080 
   1081         for (int i = 0; i < 4; ++i) {
   1082             verts[i].fCenter = center;
   1083             verts[i].fOuterRadius = xRadius;
   1084             verts[i].fInnerRadius = ratio;
   1085         }
   1086 
   1087         L = -xRadius;
   1088         R = +xRadius;
   1089         T = -yRadius;
   1090         B = +yRadius;
   1091     }
   1092 
   1093     // The fragment shader will extend the radius out half a pixel
   1094     // to antialias. Expand the drawn rect here so all the pixels
   1095     // will be captured.
   1096     L += center.fX - SK_ScalarHalf;
   1097     R += center.fX + SK_ScalarHalf;
   1098     T += center.fY - SK_ScalarHalf;
   1099     B += center.fY + SK_ScalarHalf;
   1100 
   1101     verts[0].fPos = SkPoint::Make(L, T);
   1102     verts[1].fPos = SkPoint::Make(R, T);
   1103     verts[2].fPos = SkPoint::Make(L, B);
   1104     verts[3].fPos = SkPoint::Make(R, B);
   1105 
   1106     target->drawNonIndexed(kTriangleStrip_GrPrimitiveType, 0, 4);
   1107 }
   1108 
   1109 void GrContext::drawPath(const GrPaint& paint, const SkPath& path, const SkStrokeRec& stroke) {
   1110 
   1111     if (path.isEmpty()) {
   1112        if (path.isInverseFillType()) {
   1113            this->drawPaint(paint);
   1114        }
   1115        return;
   1116     }
   1117 
   1118     SkRect ovalRect;
   1119     bool isOval = path.isOval(&ovalRect);
   1120 
   1121     if (isOval && !path.isInverseFillType() && this->canDrawOval(paint, ovalRect, stroke)) {
   1122         this->drawOval(paint, ovalRect, stroke);
   1123         return;
   1124     }
   1125 
   1126     this->internalDrawPath(paint, path, stroke);
   1127 }
   1128 
   1129 void GrContext::internalDrawPath(const GrPaint& paint, const SkPath& path, const SkStrokeRec& stroke) {
   1130 
   1131     // Note that below we may sw-rasterize the path into a scratch texture.
   1132     // Scratch textures can be recycled after they are returned to the texture
   1133     // cache. This presents a potential hazard for buffered drawing. However,
   1134     // the writePixels that uploads to the scratch will perform a flush so we're
   1135     // OK.
   1136     GrDrawTarget* target = this->prepareToDraw(&paint, DEFAULT_BUFFERING);
   1137     GrDrawState::AutoStageDisable atr(fDrawState);
   1138 
   1139     bool prAA = paint.isAntiAlias() && !this->getRenderTarget()->isMultisampled();
   1140 
   1141     // An Assumption here is that path renderer would use some form of tweaking
   1142     // the src color (either the input alpha or in the frag shader) to implement
   1143     // aa. If we have some future driver-mojo path AA that can do the right
   1144     // thing WRT to the blend then we'll need some query on the PR.
   1145     if (disable_coverage_aa_for_blend(target)) {
   1146 #if GR_DEBUG
   1147         //GrPrintf("Turning off AA to correctly apply blend.\n");
   1148 #endif
   1149         prAA = false;
   1150     }
   1151 
   1152     GrPathRendererChain::DrawType type = prAA ? GrPathRendererChain::kColorAntiAlias_DrawType :
   1153                                                 GrPathRendererChain::kColor_DrawType;
   1154 
   1155     const SkPath* pathPtr = &path;
   1156     SkPath tmpPath;
   1157     SkStrokeRec strokeRec(stroke);
   1158 
   1159     // Try a 1st time without stroking the path and without allowing the SW renderer
   1160     GrPathRenderer* pr = this->getPathRenderer(*pathPtr, strokeRec, target, false, type);
   1161 
   1162     if (NULL == pr) {
   1163         if (!strokeRec.isHairlineStyle()) {
   1164             // It didn't work the 1st time, so try again with the stroked path
   1165             if (strokeRec.applyToPath(&tmpPath, *pathPtr)) {
   1166                 pathPtr = &tmpPath;
   1167                 strokeRec.setFillStyle();
   1168             }
   1169         }
   1170         // This time, allow SW renderer
   1171         pr = this->getPathRenderer(*pathPtr, strokeRec, target, true, type);
   1172     }
   1173 
   1174     if (NULL == pr) {
   1175 #if GR_DEBUG
   1176         GrPrintf("Unable to find path renderer compatible with path.\n");
   1177 #endif
   1178         return;
   1179     }
   1180 
   1181     pr->drawPath(*pathPtr, strokeRec, target, prAA);
   1182 }
   1183 
   1184 ////////////////////////////////////////////////////////////////////////////////
   1185 
   1186 void GrContext::flush(int flagsBitfield) {
   1187     if (kDiscard_FlushBit & flagsBitfield) {
   1188         fDrawBuffer->reset();
   1189     } else {
   1190         this->flushDrawBuffer();
   1191     }
   1192     if (kForceCurrentRenderTarget_FlushBit & flagsBitfield) {
   1193         fGpu->forceRenderTargetFlush();
   1194     }
   1195 }
   1196 
   1197 void GrContext::flushDrawBuffer() {
   1198     if (fDrawBuffer) {
   1199         // With addition of the AA clip path, flushing the draw buffer can
   1200         // result in the generation of an AA clip mask. During this
   1201         // process the SW path renderer may be invoked which recusively
   1202         // calls this method (via internalWriteTexturePixels) creating
   1203         // infinite recursion
   1204         GrInOrderDrawBuffer* temp = fDrawBuffer;
   1205         fDrawBuffer = NULL;
   1206 
   1207         temp->flushTo(fGpu);
   1208 
   1209         fDrawBuffer = temp;
   1210     }
   1211 }
   1212 
   1213 void GrContext::writeTexturePixels(GrTexture* texture,
   1214                                    int left, int top, int width, int height,
   1215                                    GrPixelConfig config, const void* buffer, size_t rowBytes,
   1216                                    uint32_t flags) {
   1217     SK_TRACE_EVENT0("GrContext::writeTexturePixels");
   1218     ASSERT_OWNED_RESOURCE(texture);
   1219 
   1220     // TODO: use scratch texture to perform conversion
   1221     if (kUnpremul_PixelOpsFlag & flags) {
   1222         return;
   1223     }
   1224     if (!(kDontFlush_PixelOpsFlag & flags)) {
   1225         this->flush();
   1226     }
   1227 
   1228     fGpu->writeTexturePixels(texture, left, top, width, height,
   1229                              config, buffer, rowBytes);
   1230 }
   1231 
   1232 bool GrContext::readTexturePixels(GrTexture* texture,
   1233                                   int left, int top, int width, int height,
   1234                                   GrPixelConfig config, void* buffer, size_t rowBytes,
   1235                                   uint32_t flags) {
   1236     SK_TRACE_EVENT0("GrContext::readTexturePixels");
   1237     ASSERT_OWNED_RESOURCE(texture);
   1238 
   1239     // TODO: code read pixels for textures that aren't also rendertargets
   1240     GrRenderTarget* target = texture->asRenderTarget();
   1241     if (NULL != target) {
   1242         return this->readRenderTargetPixels(target,
   1243                                             left, top, width, height,
   1244                                             config, buffer, rowBytes,
   1245                                             flags);
   1246     } else {
   1247         return false;
   1248     }
   1249 }
   1250 
   1251 #include "SkConfig8888.h"
   1252 
   1253 namespace {
   1254 /**
   1255  * Converts a GrPixelConfig to a SkCanvas::Config8888. Only byte-per-channel
   1256  * formats are representable as Config8888 and so the function returns false
   1257  * if the GrPixelConfig has no equivalent Config8888.
   1258  */
   1259 bool grconfig_to_config8888(GrPixelConfig config,
   1260                             bool unpremul,
   1261                             SkCanvas::Config8888* config8888) {
   1262     switch (config) {
   1263         case kRGBA_8888_GrPixelConfig:
   1264             if (unpremul) {
   1265                 *config8888 = SkCanvas::kRGBA_Unpremul_Config8888;
   1266             } else {
   1267                 *config8888 = SkCanvas::kRGBA_Premul_Config8888;
   1268             }
   1269             return true;
   1270         case kBGRA_8888_GrPixelConfig:
   1271             if (unpremul) {
   1272                 *config8888 = SkCanvas::kBGRA_Unpremul_Config8888;
   1273             } else {
   1274                 *config8888 = SkCanvas::kBGRA_Premul_Config8888;
   1275             }
   1276             return true;
   1277         default:
   1278             return false;
   1279     }
   1280 }
   1281 
   1282 // It returns a configuration with where the byte position of the R & B components are swapped in
   1283 // relation to the input config. This should only be called with the result of
   1284 // grconfig_to_config8888 as it will fail for other configs.
   1285 SkCanvas::Config8888 swap_config8888_red_and_blue(SkCanvas::Config8888 config8888) {
   1286     switch (config8888) {
   1287         case SkCanvas::kBGRA_Premul_Config8888:
   1288             return SkCanvas::kRGBA_Premul_Config8888;
   1289         case SkCanvas::kBGRA_Unpremul_Config8888:
   1290             return SkCanvas::kRGBA_Unpremul_Config8888;
   1291         case SkCanvas::kRGBA_Premul_Config8888:
   1292             return SkCanvas::kBGRA_Premul_Config8888;
   1293         case SkCanvas::kRGBA_Unpremul_Config8888:
   1294             return SkCanvas::kBGRA_Unpremul_Config8888;
   1295         default:
   1296             GrCrash("Unexpected input");
   1297             return SkCanvas::kBGRA_Unpremul_Config8888;;
   1298     }
   1299 }
   1300 }
   1301 
   1302 bool GrContext::readRenderTargetPixels(GrRenderTarget* target,
   1303                                        int left, int top, int width, int height,
   1304                                        GrPixelConfig config, void* buffer, size_t rowBytes,
   1305                                        uint32_t flags) {
   1306     SK_TRACE_EVENT0("GrContext::readRenderTargetPixels");
   1307     ASSERT_OWNED_RESOURCE(target);
   1308 
   1309     if (NULL == target) {
   1310         target = fDrawState->getRenderTarget();
   1311         if (NULL == target) {
   1312             return false;
   1313         }
   1314     }
   1315 
   1316     if (!(kDontFlush_PixelOpsFlag & flags)) {
   1317         this->flush();
   1318     }
   1319 
   1320     // Determine which conversions have to be applied: flipY, swapRAnd, and/or unpremul.
   1321 
   1322     // If fGpu->readPixels would incur a y-flip cost then we will read the pixels upside down. We'll
   1323     // either do the flipY by drawing into a scratch with a matrix or on the cpu after the read.
   1324     bool flipY = fGpu->readPixelsWillPayForYFlip(target, left, top,
   1325                                                  width, height, config,
   1326                                                  rowBytes);
   1327     bool swapRAndB = fGpu->preferredReadPixelsConfig(config) == GrPixelConfigSwapRAndB(config);
   1328 
   1329     bool unpremul = SkToBool(kUnpremul_PixelOpsFlag & flags);
   1330 
   1331     // flipY will get set to false when it is handled below using a scratch. However, in that case
   1332     // we still want to do the read upside down.
   1333     bool readUpsideDown = flipY;
   1334 
   1335     if (unpremul && kRGBA_8888_GrPixelConfig != config && kBGRA_8888_GrPixelConfig != config) {
   1336         // The unpremul flag is only allowed for these two configs.
   1337         return false;
   1338     }
   1339 
   1340     GrPixelConfig readConfig;
   1341     if (swapRAndB) {
   1342         readConfig = GrPixelConfigSwapRAndB(config);
   1343         GrAssert(kUnknown_GrPixelConfig != config);
   1344     } else {
   1345         readConfig = config;
   1346     }
   1347 
   1348     // If the src is a texture and we would have to do conversions after read pixels, we instead
   1349     // do the conversions by drawing the src to a scratch texture. If we handle any of the
   1350     // conversions in the draw we set the corresponding bool to false so that we don't reapply it
   1351     // on the read back pixels.
   1352     GrTexture* src = target->asTexture();
   1353     GrAutoScratchTexture ast;
   1354     if (NULL != src && (swapRAndB || unpremul || flipY)) {
   1355         // Make the scratch a render target because we don't have a robust readTexturePixels as of
   1356         // yet. It calls this function.
   1357         GrTextureDesc desc;
   1358         desc.fFlags = kRenderTarget_GrTextureFlagBit;
   1359         desc.fWidth = width;
   1360         desc.fHeight = height;
   1361         desc.fConfig = readConfig;
   1362 
   1363         // When a full readback is faster than a partial we could always make the scratch exactly
   1364         // match the passed rect. However, if we see many different size rectangles we will trash
   1365         // our texture cache and pay the cost of creating and destroying many textures. So, we only
   1366         // request an exact match when the caller is reading an entire RT.
   1367         ScratchTexMatch match = kApprox_ScratchTexMatch;
   1368         if (0 == left &&
   1369             0 == top &&
   1370             target->width() == width &&
   1371             target->height() == height &&
   1372             fGpu->fullReadPixelsIsFasterThanPartial()) {
   1373             match = kExact_ScratchTexMatch;
   1374         }
   1375         ast.set(this, desc, match);
   1376         GrTexture* texture = ast.texture();
   1377         if (texture) {
   1378             // compute a matrix to perform the draw
   1379             SkMatrix textureMatrix;
   1380             if (flipY) {
   1381                 textureMatrix.setTranslate(SK_Scalar1 * left,
   1382                                     SK_Scalar1 * (top + height));
   1383                 textureMatrix.set(SkMatrix::kMScaleY, -SK_Scalar1);
   1384             } else {
   1385                 textureMatrix.setTranslate(SK_Scalar1 *left, SK_Scalar1 *top);
   1386             }
   1387             textureMatrix.postIDiv(src->width(), src->height());
   1388 
   1389             SkAutoTUnref<const GrEffectRef> effect;
   1390             if (unpremul) {
   1391                 effect.reset(this->createPMToUPMEffect(src, swapRAndB, textureMatrix));
   1392                 if (NULL != effect) {
   1393                     unpremul = false; // we no longer need to do this on CPU after the readback.
   1394                 }
   1395             }
   1396             // If we failed to create a PM->UPM effect and have no other conversions to perform then
   1397             // there is no longer any point to using the scratch.
   1398             if (NULL != effect || flipY || swapRAndB) {
   1399                 if (!effect) {
   1400                     effect.reset(GrConfigConversionEffect::Create(
   1401                                                     src,
   1402                                                     swapRAndB,
   1403                                                     GrConfigConversionEffect::kNone_PMConversion,
   1404                                                     textureMatrix));
   1405                 }
   1406                 swapRAndB = false; // we will handle the swap in the draw.
   1407                 flipY = false; // we already incorporated the y flip in the matrix
   1408 
   1409                 GrDrawTarget::AutoStateRestore asr(fGpu, GrDrawTarget::kReset_ASRInit);
   1410                 GrDrawState* drawState = fGpu->drawState();
   1411                 GrAssert(effect);
   1412                 drawState->setEffect(0, effect);
   1413 
   1414                 drawState->setRenderTarget(texture->asRenderTarget());
   1415                 GrRect rect = GrRect::MakeWH(SkIntToScalar(width), SkIntToScalar(height));
   1416                 fGpu->drawSimpleRect(rect, NULL);
   1417                 // we want to read back from the scratch's origin
   1418                 left = 0;
   1419                 top = 0;
   1420                 target = texture->asRenderTarget();
   1421             }
   1422         }
   1423     }
   1424     if (!fGpu->readPixels(target,
   1425                           left, top, width, height,
   1426                           readConfig, buffer, rowBytes, readUpsideDown)) {
   1427         return false;
   1428     }
   1429     // Perform any conversions we weren't able to perform using a scratch texture.
   1430     if (unpremul || swapRAndB || flipY) {
   1431         // These are initialized to suppress a warning
   1432         SkCanvas::Config8888 srcC8888 = SkCanvas::kNative_Premul_Config8888;
   1433         SkCanvas::Config8888 dstC8888 = SkCanvas::kNative_Premul_Config8888;
   1434 
   1435         bool c8888IsValid = grconfig_to_config8888(config, false, &srcC8888);
   1436         grconfig_to_config8888(config, unpremul, &dstC8888);
   1437 
   1438         if (swapRAndB) {
   1439             GrAssert(c8888IsValid); // we should only do r/b swap on 8888 configs
   1440             srcC8888 = swap_config8888_red_and_blue(srcC8888);
   1441         }
   1442         if (flipY) {
   1443             size_t tightRB = width * GrBytesPerPixel(config);
   1444             if (0 == rowBytes) {
   1445                 rowBytes = tightRB;
   1446             }
   1447             SkAutoSTMalloc<256, uint8_t> tempRow(tightRB);
   1448             intptr_t top = reinterpret_cast<intptr_t>(buffer);
   1449             intptr_t bot = top + (height - 1) * rowBytes;
   1450             while (top < bot) {
   1451                 uint32_t* t = reinterpret_cast<uint32_t*>(top);
   1452                 uint32_t* b = reinterpret_cast<uint32_t*>(bot);
   1453                 uint32_t* temp = reinterpret_cast<uint32_t*>(tempRow.get());
   1454                 memcpy(temp, t, tightRB);
   1455                 if (c8888IsValid) {
   1456                     SkConvertConfig8888Pixels(t, tightRB, dstC8888,
   1457                                               b, tightRB, srcC8888,
   1458                                               width, 1);
   1459                     SkConvertConfig8888Pixels(b, tightRB, dstC8888,
   1460                                               temp, tightRB, srcC8888,
   1461                                               width, 1);
   1462                 } else {
   1463                     memcpy(t, b, tightRB);
   1464                     memcpy(b, temp, tightRB);
   1465                 }
   1466                 top += rowBytes;
   1467                 bot -= rowBytes;
   1468             }
   1469             // The above loop does nothing on the middle row when height is odd.
   1470             if (top == bot && c8888IsValid && dstC8888 != srcC8888) {
   1471                 uint32_t* mid = reinterpret_cast<uint32_t*>(top);
   1472                 SkConvertConfig8888Pixels(mid, tightRB, dstC8888, mid, tightRB, srcC8888, width, 1);
   1473             }
   1474         } else {
   1475             // if we aren't flipping Y then we have no reason to be here other than doing
   1476             // conversions for 8888 (r/b swap or upm).
   1477             GrAssert(c8888IsValid);
   1478             uint32_t* b32 = reinterpret_cast<uint32_t*>(buffer);
   1479             SkConvertConfig8888Pixels(b32, rowBytes, dstC8888,
   1480                                       b32, rowBytes, srcC8888,
   1481                                       width, height);
   1482         }
   1483     }
   1484     return true;
   1485 }
   1486 
   1487 void GrContext::resolveRenderTarget(GrRenderTarget* target) {
   1488     GrAssert(target);
   1489     ASSERT_OWNED_RESOURCE(target);
   1490     // In the future we may track whether there are any pending draws to this
   1491     // target. We don't today so we always perform a flush. We don't promise
   1492     // this to our clients, though.
   1493     this->flush();
   1494     fGpu->resolveRenderTarget(target);
   1495 }
   1496 
   1497 void GrContext::copyTexture(GrTexture* src, GrRenderTarget* dst, const SkIPoint* topLeft) {
   1498     if (NULL == src || NULL == dst) {
   1499         return;
   1500     }
   1501     ASSERT_OWNED_RESOURCE(src);
   1502 
   1503     // Writes pending to the source texture are not tracked, so a flush
   1504     // is required to ensure that the copy captures the most recent contents
   1505     // of the source texture. See similar behavior in
   1506     // GrContext::resolveRenderTarget.
   1507     this->flush();
   1508 
   1509     GrDrawTarget::AutoStateRestore asr(fGpu, GrDrawTarget::kReset_ASRInit);
   1510     GrDrawState* drawState = fGpu->drawState();
   1511     drawState->setRenderTarget(dst);
   1512     SkMatrix sampleM;
   1513     sampleM.setIDiv(src->width(), src->height());
   1514     SkIRect srcRect = SkIRect::MakeWH(dst->width(), dst->height());
   1515     if (NULL != topLeft) {
   1516         srcRect.offset(*topLeft);
   1517     }
   1518     SkIRect srcBounds = SkIRect::MakeWH(src->width(), src->height());
   1519     if (!srcRect.intersect(srcBounds)) {
   1520         return;
   1521     }
   1522     sampleM.preTranslate(SkIntToScalar(srcRect.fLeft), SkIntToScalar(srcRect.fTop));
   1523     drawState->createTextureEffect(0, src, sampleM);
   1524     SkRect dstR = SkRect::MakeWH(SkIntToScalar(srcRect.width()), SkIntToScalar(srcRect.height()));
   1525     fGpu->drawSimpleRect(dstR, NULL);
   1526 }
   1527 
   1528 void GrContext::writeRenderTargetPixels(GrRenderTarget* target,
   1529                                         int left, int top, int width, int height,
   1530                                         GrPixelConfig config,
   1531                                         const void* buffer,
   1532                                         size_t rowBytes,
   1533                                         uint32_t flags) {
   1534     SK_TRACE_EVENT0("GrContext::writeRenderTargetPixels");
   1535     ASSERT_OWNED_RESOURCE(target);
   1536 
   1537     if (NULL == target) {
   1538         target = fDrawState->getRenderTarget();
   1539         if (NULL == target) {
   1540             return;
   1541         }
   1542     }
   1543 
   1544     // TODO: when underlying api has a direct way to do this we should use it (e.g. glDrawPixels on
   1545     // desktop GL).
   1546 
   1547     // We will always call some form of writeTexturePixels and we will pass our flags on to it.
   1548     // Thus, we don't perform a flush here since that call will do it (if the kNoFlush flag isn't
   1549     // set.)
   1550 
   1551     // If the RT is also a texture and we don't have to premultiply then take the texture path.
   1552     // We expect to be at least as fast or faster since it doesn't use an intermediate texture as
   1553     // we do below.
   1554 
   1555 #if !GR_MAC_BUILD
   1556     // At least some drivers on the Mac get confused when glTexImage2D is called on a texture
   1557     // attached to an FBO. The FBO still sees the old image. TODO: determine what OS versions and/or
   1558     // HW is affected.
   1559     if (NULL != target->asTexture() && !(kUnpremul_PixelOpsFlag & flags)) {
   1560         this->writeTexturePixels(target->asTexture(),
   1561                                  left, top, width, height,
   1562                                  config, buffer, rowBytes, flags);
   1563         return;
   1564     }
   1565 #endif
   1566 
   1567     bool swapRAndB = (fGpu->preferredReadPixelsConfig(config) == GrPixelConfigSwapRAndB(config));
   1568 
   1569     GrPixelConfig textureConfig;
   1570     if (swapRAndB) {
   1571         textureConfig = GrPixelConfigSwapRAndB(config);
   1572     } else {
   1573         textureConfig = config;
   1574     }
   1575 
   1576     GrTextureDesc desc;
   1577     desc.fWidth = width;
   1578     desc.fHeight = height;
   1579     desc.fConfig = textureConfig;
   1580     GrAutoScratchTexture ast(this, desc);
   1581     GrTexture* texture = ast.texture();
   1582     if (NULL == texture) {
   1583         return;
   1584     }
   1585 
   1586     SkAutoTUnref<const GrEffectRef> effect;
   1587     SkMatrix textureMatrix;
   1588     textureMatrix.setIDiv(texture->width(), texture->height());
   1589 
   1590     // allocate a tmp buffer and sw convert the pixels to premul
   1591     SkAutoSTMalloc<128 * 128, uint32_t> tmpPixels(0);
   1592 
   1593     if (kUnpremul_PixelOpsFlag & flags) {
   1594         if (kRGBA_8888_GrPixelConfig != config && kBGRA_8888_GrPixelConfig != config) {
   1595             return;
   1596         }
   1597         effect.reset(this->createUPMToPMEffect(texture, swapRAndB, textureMatrix));
   1598         if (NULL == effect) {
   1599             SkCanvas::Config8888 srcConfig8888, dstConfig8888;
   1600             GR_DEBUGCODE(bool success = )
   1601             grconfig_to_config8888(config, true, &srcConfig8888);
   1602             GrAssert(success);
   1603             GR_DEBUGCODE(success = )
   1604             grconfig_to_config8888(config, false, &dstConfig8888);
   1605             GrAssert(success);
   1606             const uint32_t* src = reinterpret_cast<const uint32_t*>(buffer);
   1607             tmpPixels.reset(width * height);
   1608             SkConvertConfig8888Pixels(tmpPixels.get(), 4 * width, dstConfig8888,
   1609                                       src, rowBytes, srcConfig8888,
   1610                                       width, height);
   1611             buffer = tmpPixels.get();
   1612             rowBytes = 4 * width;
   1613         }
   1614     }
   1615     if (NULL == effect) {
   1616         effect.reset(GrConfigConversionEffect::Create(texture,
   1617                                                       swapRAndB,
   1618                                                       GrConfigConversionEffect::kNone_PMConversion,
   1619                                                       textureMatrix));
   1620     }
   1621 
   1622     this->writeTexturePixels(texture,
   1623                              0, 0, width, height,
   1624                              textureConfig, buffer, rowBytes,
   1625                              flags & ~kUnpremul_PixelOpsFlag);
   1626 
   1627     GrDrawTarget::AutoStateRestore  asr(fGpu, GrDrawTarget::kReset_ASRInit);
   1628     GrDrawState* drawState = fGpu->drawState();
   1629     GrAssert(effect);
   1630     drawState->setEffect(0, effect);
   1631 
   1632     SkMatrix matrix;
   1633     matrix.setTranslate(SkIntToScalar(left), SkIntToScalar(top));
   1634     drawState->setViewMatrix(matrix);
   1635     drawState->setRenderTarget(target);
   1636 
   1637     fGpu->drawSimpleRect(GrRect::MakeWH(SkIntToScalar(width), SkIntToScalar(height)), NULL);
   1638 }
   1639 ////////////////////////////////////////////////////////////////////////////////
   1640 
   1641 GrDrawTarget* GrContext::prepareToDraw(const GrPaint* paint, BufferedDraw buffered) {
   1642     if (kNo_BufferedDraw == buffered && kYes_BufferedDraw == fLastDrawWasBuffered) {
   1643         this->flushDrawBuffer();
   1644         fLastDrawWasBuffered = kNo_BufferedDraw;
   1645     }
   1646     if (NULL != paint) {
   1647         GrAssert(fDrawState->stagesDisabled());
   1648         fDrawState->setFromPaint(*paint);
   1649 #if GR_DEBUG_PARTIAL_COVERAGE_CHECK
   1650         if ((paint->hasMask() || 0xff != paint->fCoverage) &&
   1651             !fGpu->canApplyCoverage()) {
   1652             GrPrintf("Partial pixel coverage will be incorrectly blended.\n");
   1653         }
   1654 #endif
   1655     }
   1656     if (kYes_BufferedDraw == buffered) {
   1657         fDrawBuffer->setClip(fGpu->getClip());
   1658         fLastDrawWasBuffered = kYes_BufferedDraw;
   1659         return fDrawBuffer;
   1660     } else {
   1661         GrAssert(kNo_BufferedDraw == buffered);
   1662         return fGpu;
   1663     }
   1664 }
   1665 
   1666 /*
   1667  * This method finds a path renderer that can draw the specified path on
   1668  * the provided target.
   1669  * Due to its expense, the software path renderer has split out so it can
   1670  * can be individually allowed/disallowed via the "allowSW" boolean.
   1671  */
   1672 GrPathRenderer* GrContext::getPathRenderer(const SkPath& path,
   1673                                            const SkStrokeRec& stroke,
   1674                                            const GrDrawTarget* target,
   1675                                            bool allowSW,
   1676                                            GrPathRendererChain::DrawType drawType,
   1677                                            GrPathRendererChain::StencilSupport* stencilSupport) {
   1678 
   1679     if (NULL == fPathRendererChain) {
   1680         fPathRendererChain = SkNEW_ARGS(GrPathRendererChain, (this));
   1681     }
   1682 
   1683     GrPathRenderer* pr = fPathRendererChain->getPathRenderer(path,
   1684                                                              stroke,
   1685                                                              target,
   1686                                                              drawType,
   1687                                                              stencilSupport);
   1688 
   1689     if (NULL == pr && allowSW) {
   1690         if (NULL == fSoftwarePathRenderer) {
   1691             fSoftwarePathRenderer = SkNEW_ARGS(GrSoftwarePathRenderer, (this));
   1692         }
   1693         pr = fSoftwarePathRenderer;
   1694     }
   1695 
   1696     return pr;
   1697 }
   1698 
   1699 ////////////////////////////////////////////////////////////////////////////////
   1700 
   1701 void GrContext::setRenderTarget(GrRenderTarget* target) {
   1702     ASSERT_OWNED_RESOURCE(target);
   1703     fDrawState->setRenderTarget(target);
   1704 }
   1705 
   1706 GrRenderTarget* GrContext::getRenderTarget() {
   1707     return fDrawState->getRenderTarget();
   1708 }
   1709 
   1710 const GrRenderTarget* GrContext::getRenderTarget() const {
   1711     return fDrawState->getRenderTarget();
   1712 }
   1713 
   1714 bool GrContext::isConfigRenderable(GrPixelConfig config) const {
   1715     return fGpu->isConfigRenderable(config);
   1716 }
   1717 
   1718 const SkMatrix& GrContext::getMatrix() const {
   1719     return fDrawState->getViewMatrix();
   1720 }
   1721 
   1722 void GrContext::setMatrix(const SkMatrix& m) {
   1723     fDrawState->setViewMatrix(m);
   1724 }
   1725 
   1726 void GrContext::setIdentityMatrix() {
   1727     fDrawState->viewMatrix()->reset();
   1728 }
   1729 
   1730 void GrContext::concatMatrix(const SkMatrix& m) const {
   1731     fDrawState->preConcatViewMatrix(m);
   1732 }
   1733 
   1734 static inline intptr_t setOrClear(intptr_t bits, int shift, intptr_t pred) {
   1735     intptr_t mask = 1 << shift;
   1736     if (pred) {
   1737         bits |= mask;
   1738     } else {
   1739         bits &= ~mask;
   1740     }
   1741     return bits;
   1742 }
   1743 
   1744 GrContext::GrContext(GrGpu* gpu) {
   1745     ++THREAD_INSTANCE_COUNT;
   1746 
   1747     fGpu = gpu;
   1748     fGpu->ref();
   1749     fGpu->setContext(this);
   1750 
   1751     fDrawState = SkNEW(GrDrawState);
   1752     fGpu->setDrawState(fDrawState);
   1753 
   1754     fPathRendererChain = NULL;
   1755     fSoftwarePathRenderer = NULL;
   1756 
   1757     fTextureCache = SkNEW_ARGS(GrResourceCache,
   1758                                (MAX_TEXTURE_CACHE_COUNT,
   1759                                 MAX_TEXTURE_CACHE_BYTES));
   1760     fFontCache = SkNEW_ARGS(GrFontCache, (fGpu));
   1761 
   1762     fLastDrawWasBuffered = kNo_BufferedDraw;
   1763 
   1764     fDrawBuffer = NULL;
   1765     fDrawBufferVBAllocPool = NULL;
   1766     fDrawBufferIBAllocPool = NULL;
   1767 
   1768     fAARectRenderer = SkNEW(GrAARectRenderer);
   1769 
   1770     fDidTestPMConversions = false;
   1771 
   1772     this->setupDrawBuffer();
   1773 }
   1774 
   1775 void GrContext::setupDrawBuffer() {
   1776 
   1777     GrAssert(NULL == fDrawBuffer);
   1778     GrAssert(NULL == fDrawBufferVBAllocPool);
   1779     GrAssert(NULL == fDrawBufferIBAllocPool);
   1780 
   1781     fDrawBufferVBAllocPool =
   1782         SkNEW_ARGS(GrVertexBufferAllocPool, (fGpu, false,
   1783                                     DRAW_BUFFER_VBPOOL_BUFFER_SIZE,
   1784                                     DRAW_BUFFER_VBPOOL_PREALLOC_BUFFERS));
   1785     fDrawBufferIBAllocPool =
   1786         SkNEW_ARGS(GrIndexBufferAllocPool, (fGpu, false,
   1787                                    DRAW_BUFFER_IBPOOL_BUFFER_SIZE,
   1788                                    DRAW_BUFFER_IBPOOL_PREALLOC_BUFFERS));
   1789 
   1790     fDrawBuffer = SkNEW_ARGS(GrInOrderDrawBuffer, (fGpu,
   1791                                           fDrawBufferVBAllocPool,
   1792                                           fDrawBufferIBAllocPool));
   1793 
   1794     if (fDrawBuffer) {
   1795         fDrawBuffer->setAutoFlushTarget(fGpu);
   1796         fDrawBuffer->setDrawState(fDrawState);
   1797     }
   1798 }
   1799 
   1800 GrDrawTarget* GrContext::getTextTarget(const GrPaint& paint) {
   1801     return prepareToDraw(&paint, DEFAULT_BUFFERING);
   1802 }
   1803 
   1804 const GrIndexBuffer* GrContext::getQuadIndexBuffer() const {
   1805     return fGpu->getQuadIndexBuffer();
   1806 }
   1807 
   1808 namespace {
   1809 void test_pm_conversions(GrContext* ctx, int* pmToUPMValue, int* upmToPMValue) {
   1810     GrConfigConversionEffect::PMConversion pmToUPM;
   1811     GrConfigConversionEffect::PMConversion upmToPM;
   1812     GrConfigConversionEffect::TestForPreservingPMConversions(ctx, &pmToUPM, &upmToPM);
   1813     *pmToUPMValue = pmToUPM;
   1814     *upmToPMValue = upmToPM;
   1815 }
   1816 }
   1817 
   1818 const GrEffectRef* GrContext::createPMToUPMEffect(GrTexture* texture,
   1819                                                   bool swapRAndB,
   1820                                                   const SkMatrix& matrix) {
   1821     if (!fDidTestPMConversions) {
   1822         test_pm_conversions(this, &fPMToUPMConversion, &fUPMToPMConversion);
   1823         fDidTestPMConversions = true;
   1824     }
   1825     GrConfigConversionEffect::PMConversion pmToUPM =
   1826         static_cast<GrConfigConversionEffect::PMConversion>(fPMToUPMConversion);
   1827     if (GrConfigConversionEffect::kNone_PMConversion != pmToUPM) {
   1828         return GrConfigConversionEffect::Create(texture, swapRAndB, pmToUPM, matrix);
   1829     } else {
   1830         return NULL;
   1831     }
   1832 }
   1833 
   1834 const GrEffectRef* GrContext::createUPMToPMEffect(GrTexture* texture,
   1835                                                   bool swapRAndB,
   1836                                                   const SkMatrix& matrix) {
   1837     if (!fDidTestPMConversions) {
   1838         test_pm_conversions(this, &fPMToUPMConversion, &fUPMToPMConversion);
   1839         fDidTestPMConversions = true;
   1840     }
   1841     GrConfigConversionEffect::PMConversion upmToPM =
   1842         static_cast<GrConfigConversionEffect::PMConversion>(fUPMToPMConversion);
   1843     if (GrConfigConversionEffect::kNone_PMConversion != upmToPM) {
   1844         return GrConfigConversionEffect::Create(texture, swapRAndB, upmToPM, matrix);
   1845     } else {
   1846         return NULL;
   1847     }
   1848 }
   1849 
   1850 GrTexture* GrContext::gaussianBlur(GrTexture* srcTexture,
   1851                                    bool canClobberSrc,
   1852                                    const SkRect& rect,
   1853                                    float sigmaX, float sigmaY) {
   1854     ASSERT_OWNED_RESOURCE(srcTexture);
   1855 
   1856     AutoRenderTarget art(this);
   1857 
   1858     AutoMatrix am;
   1859     am.setIdentity(this);
   1860 
   1861     SkIRect clearRect;
   1862     int scaleFactorX, radiusX;
   1863     int scaleFactorY, radiusY;
   1864     sigmaX = adjust_sigma(sigmaX, &scaleFactorX, &radiusX);
   1865     sigmaY = adjust_sigma(sigmaY, &scaleFactorY, &radiusY);
   1866 
   1867     SkRect srcRect(rect);
   1868     scale_rect(&srcRect, 1.0f / scaleFactorX, 1.0f / scaleFactorY);
   1869     srcRect.roundOut();
   1870     scale_rect(&srcRect, static_cast<float>(scaleFactorX),
   1871                          static_cast<float>(scaleFactorY));
   1872 
   1873     AutoClip acs(this, srcRect);
   1874 
   1875     GrAssert(kBGRA_8888_GrPixelConfig == srcTexture->config() ||
   1876              kRGBA_8888_GrPixelConfig == srcTexture->config() ||
   1877              kAlpha_8_GrPixelConfig == srcTexture->config());
   1878 
   1879     GrTextureDesc desc;
   1880     desc.fFlags = kRenderTarget_GrTextureFlagBit | kNoStencil_GrTextureFlagBit;
   1881     desc.fWidth = SkScalarFloorToInt(srcRect.width());
   1882     desc.fHeight = SkScalarFloorToInt(srcRect.height());
   1883     desc.fConfig = srcTexture->config();
   1884 
   1885     GrAutoScratchTexture temp1, temp2;
   1886     GrTexture* dstTexture = temp1.set(this, desc);
   1887     GrTexture* tempTexture = canClobberSrc ? srcTexture : temp2.set(this, desc);
   1888     if (NULL == dstTexture || NULL == tempTexture) {
   1889         return NULL;
   1890     }
   1891 
   1892     GrPaint paint;
   1893     paint.reset();
   1894 
   1895     for (int i = 1; i < scaleFactorX || i < scaleFactorY; i *= 2) {
   1896         SkMatrix matrix;
   1897         matrix.setIDiv(srcTexture->width(), srcTexture->height());
   1898         this->setRenderTarget(dstTexture->asRenderTarget());
   1899         SkRect dstRect(srcRect);
   1900         scale_rect(&dstRect, i < scaleFactorX ? 0.5f : 1.0f,
   1901                              i < scaleFactorY ? 0.5f : 1.0f);
   1902 
   1903         paint.colorStage(0)->setEffect(GrSimpleTextureEffect::Create(srcTexture,
   1904                                                                      matrix,
   1905                                                                      true))->unref();
   1906         this->drawRectToRect(paint, dstRect, srcRect);
   1907         srcRect = dstRect;
   1908         srcTexture = dstTexture;
   1909         SkTSwap(dstTexture, tempTexture);
   1910     }
   1911 
   1912     SkIRect srcIRect;
   1913     srcRect.roundOut(&srcIRect);
   1914 
   1915     if (sigmaX > 0.0f) {
   1916         if (scaleFactorX > 1) {
   1917             // Clear out a radius to the right of the srcRect to prevent the
   1918             // X convolution from reading garbage.
   1919             clearRect = SkIRect::MakeXYWH(srcIRect.fRight, srcIRect.fTop,
   1920                                           radiusX, srcIRect.height());
   1921             this->clear(&clearRect, 0x0);
   1922         }
   1923 
   1924         this->setRenderTarget(dstTexture->asRenderTarget());
   1925         GrDrawTarget* target = this->prepareToDraw(NULL, DEFAULT_BUFFERING);
   1926         convolve_gaussian(target, srcTexture, srcRect, sigmaX, radiusX,
   1927                           Gr1DKernelEffect::kX_Direction);
   1928         srcTexture = dstTexture;
   1929         SkTSwap(dstTexture, tempTexture);
   1930     }
   1931 
   1932     if (sigmaY > 0.0f) {
   1933         if (scaleFactorY > 1 || sigmaX > 0.0f) {
   1934             // Clear out a radius below the srcRect to prevent the Y
   1935             // convolution from reading garbage.
   1936             clearRect = SkIRect::MakeXYWH(srcIRect.fLeft, srcIRect.fBottom,
   1937                                           srcIRect.width(), radiusY);
   1938             this->clear(&clearRect, 0x0);
   1939         }
   1940 
   1941         this->setRenderTarget(dstTexture->asRenderTarget());
   1942         GrDrawTarget* target = this->prepareToDraw(NULL, DEFAULT_BUFFERING);
   1943         convolve_gaussian(target, srcTexture, srcRect, sigmaY, radiusY,
   1944                           Gr1DKernelEffect::kY_Direction);
   1945         srcTexture = dstTexture;
   1946         SkTSwap(dstTexture, tempTexture);
   1947     }
   1948 
   1949     if (scaleFactorX > 1 || scaleFactorY > 1) {
   1950         // Clear one pixel to the right and below, to accommodate bilinear
   1951         // upsampling.
   1952         clearRect = SkIRect::MakeXYWH(srcIRect.fLeft, srcIRect.fBottom,
   1953                                       srcIRect.width() + 1, 1);
   1954         this->clear(&clearRect, 0x0);
   1955         clearRect = SkIRect::MakeXYWH(srcIRect.fRight, srcIRect.fTop,
   1956                                       1, srcIRect.height());
   1957         this->clear(&clearRect, 0x0);
   1958         SkMatrix matrix;
   1959         // FIXME:  This should be mitchell, not bilinear.
   1960         matrix.setIDiv(srcTexture->width(), srcTexture->height());
   1961         this->setRenderTarget(dstTexture->asRenderTarget());
   1962         paint.colorStage(0)->setEffect(GrSimpleTextureEffect::Create(srcTexture,
   1963                                                                      matrix,
   1964                                                                      true))->unref();
   1965         SkRect dstRect(srcRect);
   1966         scale_rect(&dstRect, (float) scaleFactorX, (float) scaleFactorY);
   1967         this->drawRectToRect(paint, dstRect, srcRect);
   1968         srcRect = dstRect;
   1969         srcTexture = dstTexture;
   1970         SkTSwap(dstTexture, tempTexture);
   1971     }
   1972     if (srcTexture == temp1.texture()) {
   1973         return temp1.detach();
   1974     } else if (srcTexture == temp2.texture()) {
   1975         return temp2.detach();
   1976     } else {
   1977         srcTexture->ref();
   1978         return srcTexture;
   1979     }
   1980 }
   1981 
   1982 ///////////////////////////////////////////////////////////////////////////////
   1983 #if GR_CACHE_STATS
   1984 void GrContext::printCacheStats() const {
   1985     fTextureCache->printStats();
   1986 }
   1987 #endif
   1988