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 "GrBufferAllocPool.h"
     13 #include "GrClipIterator.h"
     14 #include "GrGpu.h"
     15 #include "GrIndexBuffer.h"
     16 #include "GrInOrderDrawBuffer.h"
     17 #include "GrPathRenderer.h"
     18 #include "GrPathUtils.h"
     19 #include "GrResourceCache.h"
     20 #include "GrStencilBuffer.h"
     21 #include "GrTextStrike.h"
     22 #include "SkTLazy.h"
     23 #include "SkTrace.h"
     24 
     25 #define DEFER_TEXT_RENDERING 1
     26 
     27 #define BATCH_RECT_TO_RECT (1 && !GR_STATIC_RECT_VB)
     28 
     29 // When we're using coverage AA but the blend is incompatible (given gpu
     30 // limitations) should we disable AA or draw wrong?
     31 #define DISABLE_COVERAGE_AA_FOR_BLEND 1
     32 
     33 static const size_t MAX_TEXTURE_CACHE_COUNT = 256;
     34 static const size_t MAX_TEXTURE_CACHE_BYTES = 16 * 1024 * 1024;
     35 
     36 static const size_t DRAW_BUFFER_VBPOOL_BUFFER_SIZE = 1 << 18;
     37 static const int DRAW_BUFFER_VBPOOL_PREALLOC_BUFFERS = 4;
     38 
     39 // We are currently only batching Text and drawRectToRect, both
     40 // of which use the quad index buffer.
     41 static const size_t DRAW_BUFFER_IBPOOL_BUFFER_SIZE = 0;
     42 static const int DRAW_BUFFER_IBPOOL_PREALLOC_BUFFERS = 0;
     43 
     44 #define ASSERT_OWNED_RESOURCE(R) GrAssert(!(R) || (R)->getContext() == this)
     45 
     46 GrContext* GrContext::Create(GrEngine engine,
     47                              GrPlatform3DContext context3D) {
     48     GrContext* ctx = NULL;
     49     GrGpu* fGpu = GrGpu::Create(engine, context3D);
     50     if (NULL != fGpu) {
     51         ctx = new GrContext(fGpu);
     52         fGpu->unref();
     53     }
     54     return ctx;
     55 }
     56 
     57 GrContext::~GrContext() {
     58     this->flush();
     59     delete fTextureCache;
     60     delete fFontCache;
     61     delete fDrawBuffer;
     62     delete fDrawBufferVBAllocPool;
     63     delete fDrawBufferIBAllocPool;
     64 
     65     GrSafeUnref(fAAFillRectIndexBuffer);
     66     GrSafeUnref(fAAStrokeRectIndexBuffer);
     67     fGpu->unref();
     68     GrSafeUnref(fPathRendererChain);
     69 }
     70 
     71 void GrContext::contextLost() {
     72     contextDestroyed();
     73     this->setupDrawBuffer();
     74 }
     75 
     76 void GrContext::contextDestroyed() {
     77     // abandon first to so destructors
     78     // don't try to free the resources in the API.
     79     fGpu->abandonResources();
     80 
     81     // a path renderer may be holding onto resources that
     82     // are now unusable
     83     GrSafeSetNull(fPathRendererChain);
     84 
     85     delete fDrawBuffer;
     86     fDrawBuffer = NULL;
     87 
     88     delete fDrawBufferVBAllocPool;
     89     fDrawBufferVBAllocPool = NULL;
     90 
     91     delete fDrawBufferIBAllocPool;
     92     fDrawBufferIBAllocPool = NULL;
     93 
     94     GrSafeSetNull(fAAFillRectIndexBuffer);
     95     GrSafeSetNull(fAAStrokeRectIndexBuffer);
     96 
     97     fTextureCache->removeAll();
     98     fFontCache->freeAll();
     99     fGpu->markContextDirty();
    100 }
    101 
    102 void GrContext::resetContext() {
    103     fGpu->markContextDirty();
    104 }
    105 
    106 void GrContext::freeGpuResources() {
    107     this->flush();
    108     fTextureCache->removeAll();
    109     fFontCache->freeAll();
    110     // a path renderer may be holding onto resources
    111     GrSafeSetNull(fPathRendererChain);
    112 }
    113 
    114 size_t GrContext::getGpuTextureCacheBytes() const {
    115   return fTextureCache->getCachedResourceBytes();
    116 }
    117 
    118 ////////////////////////////////////////////////////////////////////////////////
    119 
    120 int GrContext::PaintStageVertexLayoutBits(
    121                             const GrPaint& paint,
    122                             const bool hasTexCoords[GrPaint::kTotalStages]) {
    123     int stageMask = paint.getActiveStageMask();
    124     int layout = 0;
    125     for (int i = 0; i < GrPaint::kTotalStages; ++i) {
    126         if ((1 << i) & stageMask) {
    127             if (NULL != hasTexCoords && hasTexCoords[i]) {
    128                 layout |= GrDrawTarget::StageTexCoordVertexLayoutBit(i, i);
    129             } else {
    130                 layout |= GrDrawTarget::StagePosAsTexCoordVertexLayoutBit(i);
    131             }
    132         }
    133     }
    134     return layout;
    135 }
    136 
    137 
    138 ////////////////////////////////////////////////////////////////////////////////
    139 
    140 enum {
    141     // flags for textures
    142     kNPOTBit            = 0x1,
    143     kFilterBit          = 0x2,
    144     kScratchBit         = 0x4,
    145 
    146     // resource type
    147     kTextureBit         = 0x8,
    148     kStencilBufferBit   = 0x10
    149 };
    150 
    151 GrTexture* GrContext::TextureCacheEntry::texture() const {
    152     if (NULL == fEntry) {
    153         return NULL;
    154     } else {
    155         return (GrTexture*) fEntry->resource();
    156     }
    157 }
    158 
    159 namespace {
    160 // returns true if this is a "special" texture because of gpu NPOT limitations
    161 bool gen_texture_key_values(const GrGpu* gpu,
    162                             const GrSamplerState* sampler,
    163                             GrContext::TextureKey clientKey,
    164                             int width,
    165                             int height,
    166                             int sampleCnt,
    167                             bool scratch,
    168                             uint32_t v[4]) {
    169     GR_STATIC_ASSERT(sizeof(GrContext::TextureKey) == sizeof(uint64_t));
    170     // we assume we only need 16 bits of width and height
    171     // assert that texture creation will fail anyway if this assumption
    172     // would cause key collisions.
    173     GrAssert(gpu->getCaps().fMaxTextureSize <= SK_MaxU16);
    174     v[0] = clientKey & 0xffffffffUL;
    175     v[1] = (clientKey >> 32) & 0xffffffffUL;
    176     v[2] = width | (height << 16);
    177 
    178     v[3] = (sampleCnt << 24);
    179     GrAssert(sampleCnt >= 0 && sampleCnt < 256);
    180 
    181     if (!gpu->getCaps().fNPOTTextureTileSupport) {
    182         bool isPow2 = GrIsPow2(width) && GrIsPow2(height);
    183 
    184         bool tiled = NULL != sampler &&
    185                      ((sampler->getWrapX() != GrSamplerState::kClamp_WrapMode) ||
    186                       (sampler->getWrapY() != GrSamplerState::kClamp_WrapMode));
    187 
    188         if (tiled && !isPow2) {
    189             v[3] |= kNPOTBit;
    190             if (GrSamplerState::kNearest_Filter != sampler->getFilter()) {
    191                 v[3] |= kFilterBit;
    192             }
    193         }
    194     }
    195 
    196     if (scratch) {
    197         v[3] |= kScratchBit;
    198     }
    199 
    200     v[3] |= kTextureBit;
    201 
    202     return v[3] & kNPOTBit;
    203 }
    204 
    205 // we should never have more than one stencil buffer with same combo of
    206 // (width,height,samplecount)
    207 void gen_stencil_key_values(int width, int height,
    208                             int sampleCnt, uint32_t v[4]) {
    209     v[0] = width;
    210     v[1] = height;
    211     v[2] = sampleCnt;
    212     v[3] = kStencilBufferBit;
    213 }
    214 
    215 void gen_stencil_key_values(const GrStencilBuffer* sb,
    216                             uint32_t v[4]) {
    217     gen_stencil_key_values(sb->width(), sb->height(),
    218                            sb->numSamples(), v);
    219 }
    220 
    221 }
    222 
    223 GrContext::TextureCacheEntry GrContext::findAndLockTexture(
    224         TextureKey key,
    225         int width,
    226         int height,
    227         const GrSamplerState* sampler) {
    228     uint32_t v[4];
    229     gen_texture_key_values(fGpu, sampler, key, width, height, 0, false, v);
    230     GrResourceKey resourceKey(v);
    231     return TextureCacheEntry(fTextureCache->findAndLock(resourceKey,
    232                                             GrResourceCache::kNested_LockType));
    233 }
    234 
    235 bool GrContext::isTextureInCache(TextureKey key,
    236                                  int width,
    237                                  int height,
    238                                  const GrSamplerState* sampler) const {
    239     uint32_t v[4];
    240     gen_texture_key_values(fGpu, sampler, key, width, height, 0, false, v);
    241     GrResourceKey resourceKey(v);
    242     return fTextureCache->hasKey(resourceKey);
    243 }
    244 
    245 GrResourceEntry* GrContext::addAndLockStencilBuffer(GrStencilBuffer* sb) {
    246     ASSERT_OWNED_RESOURCE(sb);
    247     uint32_t v[4];
    248     gen_stencil_key_values(sb, v);
    249     GrResourceKey resourceKey(v);
    250     return fTextureCache->createAndLock(resourceKey, sb);
    251 }
    252 
    253 GrStencilBuffer* GrContext::findStencilBuffer(int width, int height,
    254                                               int sampleCnt) {
    255     uint32_t v[4];
    256     gen_stencil_key_values(width, height, sampleCnt, v);
    257     GrResourceKey resourceKey(v);
    258     GrResourceEntry* entry = fTextureCache->findAndLock(resourceKey,
    259                                             GrResourceCache::kSingle_LockType);
    260     if (NULL != entry) {
    261         GrStencilBuffer* sb = (GrStencilBuffer*) entry->resource();
    262         return sb;
    263     } else {
    264         return NULL;
    265     }
    266 }
    267 
    268 void GrContext::unlockStencilBuffer(GrResourceEntry* sbEntry) {
    269     ASSERT_OWNED_RESOURCE(sbEntry->resource());
    270     fTextureCache->unlock(sbEntry);
    271 }
    272 
    273 static void stretchImage(void* dst,
    274                          int dstW,
    275                          int dstH,
    276                          void* src,
    277                          int srcW,
    278                          int srcH,
    279                          int bpp) {
    280     GrFixed dx = (srcW << 16) / dstW;
    281     GrFixed dy = (srcH << 16) / dstH;
    282 
    283     GrFixed y = dy >> 1;
    284 
    285     int dstXLimit = dstW*bpp;
    286     for (int j = 0; j < dstH; ++j) {
    287         GrFixed x = dx >> 1;
    288         void* srcRow = (uint8_t*)src + (y>>16)*srcW*bpp;
    289         void* dstRow = (uint8_t*)dst + j*dstW*bpp;
    290         for (int i = 0; i < dstXLimit; i += bpp) {
    291             memcpy((uint8_t*) dstRow + i,
    292                    (uint8_t*) srcRow + (x>>16)*bpp,
    293                    bpp);
    294             x += dx;
    295         }
    296         y += dy;
    297     }
    298 }
    299 
    300 GrContext::TextureCacheEntry GrContext::createAndLockTexture(
    301         TextureKey key,
    302         const GrSamplerState* sampler,
    303         const GrTextureDesc& desc,
    304         void* srcData,
    305         size_t rowBytes) {
    306     SK_TRACE_EVENT0("GrContext::createAndLockTexture");
    307 
    308 #if GR_DUMP_TEXTURE_UPLOAD
    309     GrPrintf("GrContext::createAndLockTexture [%d %d]\n", desc.fWidth, desc.fHeight);
    310 #endif
    311 
    312     TextureCacheEntry entry;
    313     uint32_t v[4];
    314     bool special = gen_texture_key_values(fGpu, sampler, key,
    315                                           desc.fWidth, desc.fHeight,
    316                                           desc.fSampleCnt, false, v);
    317     GrResourceKey resourceKey(v);
    318 
    319     if (special) {
    320         GrAssert(NULL != sampler);
    321         TextureCacheEntry clampEntry = this->findAndLockTexture(key,
    322                                                                 desc.fWidth,
    323                                                                 desc.fHeight,
    324                                                                 NULL);
    325 
    326         if (NULL == clampEntry.texture()) {
    327             clampEntry = this->createAndLockTexture(key, NULL, desc,
    328                                                     srcData, rowBytes);
    329             GrAssert(NULL != clampEntry.texture());
    330             if (NULL == clampEntry.texture()) {
    331                 return entry;
    332             }
    333         }
    334         GrTextureDesc rtDesc = desc;
    335         rtDesc.fFlags =  rtDesc.fFlags |
    336                          kRenderTarget_GrTextureFlagBit |
    337                          kNoStencil_GrTextureFlagBit;
    338         rtDesc.fWidth  = GrNextPow2(GrMax(desc.fWidth, 64));
    339         rtDesc.fHeight = GrNextPow2(GrMax(desc.fHeight, 64));
    340 
    341         GrTexture* texture = fGpu->createTexture(rtDesc, NULL, 0);
    342 
    343         if (NULL != texture) {
    344             GrDrawTarget::AutoStateRestore asr(fGpu);
    345             GrDrawState* drawState = fGpu->drawState();
    346             drawState->reset();
    347             drawState->setRenderTarget(texture->asRenderTarget());
    348             drawState->setTexture(0, clampEntry.texture());
    349 
    350             GrSamplerState::Filter filter;
    351             // if filtering is not desired then we want to ensure all
    352             // texels in the resampled image are copies of texels from
    353             // the original.
    354             if (GrSamplerState::kNearest_Filter == sampler->getFilter()) {
    355                 filter = GrSamplerState::kNearest_Filter;
    356             } else {
    357                 filter = GrSamplerState::kBilinear_Filter;
    358             }
    359             drawState->sampler(0)->reset(GrSamplerState::kClamp_WrapMode,
    360                                          filter);
    361 
    362             static const GrVertexLayout layout =
    363                                 GrDrawTarget::StageTexCoordVertexLayoutBit(0,0);
    364             GrDrawTarget::AutoReleaseGeometry arg(fGpu, layout, 4, 0);
    365 
    366             if (arg.succeeded()) {
    367                 GrPoint* verts = (GrPoint*) arg.vertices();
    368                 verts[0].setIRectFan(0, 0,
    369                                      texture->width(),
    370                                      texture->height(),
    371                                      2*sizeof(GrPoint));
    372                 verts[1].setIRectFan(0, 0, 1, 1, 2*sizeof(GrPoint));
    373                 fGpu->drawNonIndexed(kTriangleFan_PrimitiveType,
    374                                      0, 4);
    375                 entry.set(fTextureCache->createAndLock(resourceKey, texture));
    376             }
    377             texture->releaseRenderTarget();
    378         } else {
    379             // TODO: Our CPU stretch doesn't filter. But we create separate
    380             // stretched textures when the sampler state is either filtered or
    381             // not. Either implement filtered stretch blit on CPU or just create
    382             // one when FBO case fails.
    383 
    384             rtDesc.fFlags = kNone_GrTextureFlags;
    385             // no longer need to clamp at min RT size.
    386             rtDesc.fWidth  = GrNextPow2(desc.fWidth);
    387             rtDesc.fHeight = GrNextPow2(desc.fHeight);
    388             int bpp = GrBytesPerPixel(desc.fConfig);
    389             SkAutoSMalloc<128*128*4> stretchedPixels(bpp *
    390                                                      rtDesc.fWidth *
    391                                                      rtDesc.fHeight);
    392             stretchImage(stretchedPixels.get(), rtDesc.fWidth, rtDesc.fHeight,
    393                          srcData, desc.fWidth, desc.fHeight, bpp);
    394 
    395             size_t stretchedRowBytes = rtDesc.fWidth * bpp;
    396 
    397             GrTexture* texture = fGpu->createTexture(rtDesc,
    398                                                      stretchedPixels.get(),
    399                                                      stretchedRowBytes);
    400             GrAssert(NULL != texture);
    401             entry.set(fTextureCache->createAndLock(resourceKey, texture));
    402         }
    403         fTextureCache->unlock(clampEntry.cacheEntry());
    404 
    405     } else {
    406         GrTexture* texture = fGpu->createTexture(desc, srcData, rowBytes);
    407         if (NULL != texture) {
    408             entry.set(fTextureCache->createAndLock(resourceKey, texture));
    409         }
    410     }
    411     return entry;
    412 }
    413 
    414 namespace {
    415 inline void gen_scratch_tex_key_values(const GrGpu* gpu,
    416                                        const GrTextureDesc& desc,
    417                                        uint32_t v[4]) {
    418     // Instead of a client-provided key of the texture contents
    419     // we create a key of from the descriptor.
    420     GrContext::TextureKey descKey = (desc.fFlags << 8) |
    421                                     ((uint64_t) desc.fConfig << 32);
    422     // this code path isn't friendly to tiling with NPOT restricitons
    423     // We just pass ClampNoFilter()
    424     gen_texture_key_values(gpu, NULL, descKey, desc.fWidth,
    425                            desc.fHeight, desc.fSampleCnt, true, v);
    426 }
    427 }
    428 
    429 GrContext::TextureCacheEntry GrContext::lockScratchTexture(
    430                                                 const GrTextureDesc& inDesc,
    431                                                 ScratchTexMatch match) {
    432 
    433     GrTextureDesc desc = inDesc;
    434     if (kExact_ScratchTexMatch != match) {
    435         // bin by pow2 with a reasonable min
    436         static const int MIN_SIZE = 256;
    437         desc.fWidth  = GrMax(MIN_SIZE, GrNextPow2(desc.fWidth));
    438         desc.fHeight = GrMax(MIN_SIZE, GrNextPow2(desc.fHeight));
    439     }
    440 
    441     GrResourceEntry* entry;
    442     int origWidth = desc.fWidth;
    443     int origHeight = desc.fHeight;
    444     bool doubledW = false;
    445     bool doubledH = false;
    446 
    447     do {
    448         uint32_t v[4];
    449         gen_scratch_tex_key_values(fGpu, desc, v);
    450         GrResourceKey key(v);
    451         entry = fTextureCache->findAndLock(key,
    452                                            GrResourceCache::kNested_LockType);
    453         // if we miss, relax the fit of the flags...
    454         // then try doubling width... then height.
    455         if (NULL != entry || kExact_ScratchTexMatch == match) {
    456             break;
    457         }
    458         if (!(desc.fFlags & kRenderTarget_GrTextureFlagBit)) {
    459             desc.fFlags = desc.fFlags | kRenderTarget_GrTextureFlagBit;
    460         } else if (desc.fFlags & kNoStencil_GrTextureFlagBit) {
    461             desc.fFlags = desc.fFlags & ~kNoStencil_GrTextureFlagBit;
    462         } else if (!doubledW) {
    463             desc.fFlags = inDesc.fFlags;
    464             desc.fWidth *= 2;
    465             doubledW = true;
    466         } else if (!doubledH) {
    467             desc.fFlags = inDesc.fFlags;
    468             desc.fWidth = origWidth;
    469             desc.fHeight *= 2;
    470             doubledH = true;
    471         } else {
    472             break;
    473         }
    474 
    475     } while (true);
    476 
    477     if (NULL == entry) {
    478         desc.fFlags = inDesc.fFlags;
    479         desc.fWidth = origWidth;
    480         desc.fHeight = origHeight;
    481         GrTexture* texture = fGpu->createTexture(desc, NULL, 0);
    482         if (NULL != texture) {
    483             uint32_t v[4];
    484             gen_scratch_tex_key_values(fGpu, desc, v);
    485             GrResourceKey key(v);
    486             entry = fTextureCache->createAndLock(key, texture);
    487         }
    488     }
    489 
    490     // If the caller gives us the same desc/sampler twice we don't want
    491     // to return the same texture the second time (unless it was previously
    492     // released). So we detach the entry from the cache and reattach at release.
    493     if (NULL != entry) {
    494         fTextureCache->detach(entry);
    495     }
    496     return TextureCacheEntry(entry);
    497 }
    498 
    499 void GrContext::unlockTexture(TextureCacheEntry entry) {
    500     ASSERT_OWNED_RESOURCE(entry.texture());
    501     // If this is a scratch texture we detached it from the cache
    502     // while it was locked (to avoid two callers simultaneously getting
    503     // the same texture).
    504     if (kScratchBit & entry.cacheEntry()->key().getValue32(3)) {
    505         fTextureCache->reattachAndUnlock(entry.cacheEntry());
    506     } else {
    507         fTextureCache->unlock(entry.cacheEntry());
    508     }
    509 }
    510 
    511 GrTexture* GrContext::createUncachedTexture(const GrTextureDesc& desc,
    512                                             void* srcData,
    513                                             size_t rowBytes) {
    514     return fGpu->createTexture(desc, srcData, rowBytes);
    515 }
    516 
    517 void GrContext::getTextureCacheLimits(int* maxTextures,
    518                                       size_t* maxTextureBytes) const {
    519     fTextureCache->getLimits(maxTextures, maxTextureBytes);
    520 }
    521 
    522 void GrContext::setTextureCacheLimits(int maxTextures, size_t maxTextureBytes) {
    523     fTextureCache->setLimits(maxTextures, maxTextureBytes);
    524 }
    525 
    526 int GrContext::getMaxTextureSize() const {
    527     return fGpu->getCaps().fMaxTextureSize;
    528 }
    529 
    530 int GrContext::getMaxRenderTargetSize() const {
    531     return fGpu->getCaps().fMaxRenderTargetSize;
    532 }
    533 
    534 ///////////////////////////////////////////////////////////////////////////////
    535 
    536 GrTexture* GrContext::createPlatformTexture(const GrPlatformTextureDesc& desc) {
    537     return fGpu->createPlatformTexture(desc);
    538 }
    539 
    540 GrRenderTarget* GrContext::createPlatformRenderTarget(const GrPlatformRenderTargetDesc& desc) {
    541     return fGpu->createPlatformRenderTarget(desc);
    542 }
    543 
    544 ///////////////////////////////////////////////////////////////////////////////
    545 
    546 bool GrContext::supportsIndex8PixelConfig(const GrSamplerState* sampler,
    547                                           int width, int height) const {
    548     const GrDrawTarget::Caps& caps = fGpu->getCaps();
    549     if (!caps.f8BitPaletteSupport) {
    550         return false;
    551     }
    552 
    553     bool isPow2 = GrIsPow2(width) && GrIsPow2(height);
    554 
    555     if (!isPow2) {
    556         bool tiled = NULL != sampler &&
    557                      (sampler->getWrapX() != GrSamplerState::kClamp_WrapMode ||
    558                       sampler->getWrapY() != GrSamplerState::kClamp_WrapMode);
    559         if (tiled && !caps.fNPOTTextureTileSupport) {
    560             return false;
    561         }
    562     }
    563     return true;
    564 }
    565 
    566 ////////////////////////////////////////////////////////////////////////////////
    567 
    568 const GrClip& GrContext::getClip() const { return fGpu->getClip(); }
    569 
    570 void GrContext::setClip(const GrClip& clip) {
    571     fGpu->setClip(clip);
    572     fGpu->drawState()->enableState(GrDrawState::kClip_StateBit);
    573 }
    574 
    575 void GrContext::setClip(const GrIRect& rect) {
    576     GrClip clip;
    577     clip.setFromIRect(rect);
    578     fGpu->setClip(clip);
    579 }
    580 
    581 ////////////////////////////////////////////////////////////////////////////////
    582 
    583 void GrContext::clear(const GrIRect* rect, const GrColor color) {
    584     this->flush();
    585     fGpu->clear(rect, color);
    586 }
    587 
    588 void GrContext::drawPaint(const GrPaint& paint) {
    589     // set rect to be big enough to fill the space, but not super-huge, so we
    590     // don't overflow fixed-point implementations
    591     GrRect r;
    592     r.setLTRB(0, 0,
    593               GrIntToScalar(getRenderTarget()->width()),
    594               GrIntToScalar(getRenderTarget()->height()));
    595     GrMatrix inverse;
    596     SkTLazy<GrPaint> tmpPaint;
    597     const GrPaint* p = &paint;
    598     GrDrawState* drawState = fGpu->drawState();
    599     GrAutoMatrix am;
    600 
    601     // We attempt to map r by the inverse matrix and draw that. mapRect will
    602     // map the four corners and bound them with a new rect. This will not
    603     // produce a correct result for some perspective matrices.
    604     if (!this->getMatrix().hasPerspective()) {
    605         if (!drawState->getViewInverse(&inverse)) {
    606             GrPrintf("Could not invert matrix");
    607             return;
    608         }
    609         inverse.mapRect(&r);
    610     } else {
    611         if (paint.getActiveMaskStageMask() || paint.getActiveStageMask()) {
    612             if (!drawState->getViewInverse(&inverse)) {
    613                 GrPrintf("Could not invert matrix");
    614                 return;
    615             }
    616             tmpPaint.set(paint);
    617             tmpPaint.get()->preConcatActiveSamplerMatrices(inverse);
    618             p = tmpPaint.get();
    619         }
    620         am.set(this, GrMatrix::I());
    621     }
    622     // by definition this fills the entire clip, no need for AA
    623     if (paint.fAntiAlias) {
    624         if (!tmpPaint.isValid()) {
    625             tmpPaint.set(paint);
    626             p = tmpPaint.get();
    627         }
    628         GrAssert(p == tmpPaint.get());
    629         tmpPaint.get()->fAntiAlias = false;
    630     }
    631     this->drawRect(*p, r);
    632 }
    633 
    634 ////////////////////////////////////////////////////////////////////////////////
    635 
    636 namespace {
    637 inline bool disable_coverage_aa_for_blend(GrDrawTarget* target) {
    638     return DISABLE_COVERAGE_AA_FOR_BLEND && !target->canApplyCoverage();
    639 }
    640 }
    641 
    642 ////////////////////////////////////////////////////////////////////////////////
    643 
    644 /*  create a triangle strip that strokes the specified triangle. There are 8
    645  unique vertices, but we repreat the last 2 to close up. Alternatively we
    646  could use an indices array, and then only send 8 verts, but not sure that
    647  would be faster.
    648  */
    649 static void setStrokeRectStrip(GrPoint verts[10], GrRect rect,
    650                                GrScalar width) {
    651     const GrScalar rad = GrScalarHalf(width);
    652     rect.sort();
    653 
    654     verts[0].set(rect.fLeft + rad, rect.fTop + rad);
    655     verts[1].set(rect.fLeft - rad, rect.fTop - rad);
    656     verts[2].set(rect.fRight - rad, rect.fTop + rad);
    657     verts[3].set(rect.fRight + rad, rect.fTop - rad);
    658     verts[4].set(rect.fRight - rad, rect.fBottom - rad);
    659     verts[5].set(rect.fRight + rad, rect.fBottom + rad);
    660     verts[6].set(rect.fLeft + rad, rect.fBottom - rad);
    661     verts[7].set(rect.fLeft - rad, rect.fBottom + rad);
    662     verts[8] = verts[0];
    663     verts[9] = verts[1];
    664 }
    665 
    666 static void setInsetFan(GrPoint* pts, size_t stride,
    667                         const GrRect& r, GrScalar dx, GrScalar dy) {
    668     pts->setRectFan(r.fLeft + dx, r.fTop + dy, r.fRight - dx, r.fBottom - dy, stride);
    669 }
    670 
    671 static const uint16_t gFillAARectIdx[] = {
    672     0, 1, 5, 5, 4, 0,
    673     1, 2, 6, 6, 5, 1,
    674     2, 3, 7, 7, 6, 2,
    675     3, 0, 4, 4, 7, 3,
    676     4, 5, 6, 6, 7, 4,
    677 };
    678 
    679 int GrContext::aaFillRectIndexCount() const {
    680     return GR_ARRAY_COUNT(gFillAARectIdx);
    681 }
    682 
    683 GrIndexBuffer* GrContext::aaFillRectIndexBuffer() {
    684     if (NULL == fAAFillRectIndexBuffer) {
    685         fAAFillRectIndexBuffer = fGpu->createIndexBuffer(sizeof(gFillAARectIdx),
    686                                                          false);
    687         if (NULL != fAAFillRectIndexBuffer) {
    688     #if GR_DEBUG
    689             bool updated =
    690     #endif
    691             fAAFillRectIndexBuffer->updateData(gFillAARectIdx,
    692                                                sizeof(gFillAARectIdx));
    693             GR_DEBUGASSERT(updated);
    694         }
    695     }
    696     return fAAFillRectIndexBuffer;
    697 }
    698 
    699 static const uint16_t gStrokeAARectIdx[] = {
    700     0 + 0, 1 + 0, 5 + 0, 5 + 0, 4 + 0, 0 + 0,
    701     1 + 0, 2 + 0, 6 + 0, 6 + 0, 5 + 0, 1 + 0,
    702     2 + 0, 3 + 0, 7 + 0, 7 + 0, 6 + 0, 2 + 0,
    703     3 + 0, 0 + 0, 4 + 0, 4 + 0, 7 + 0, 3 + 0,
    704 
    705     0 + 4, 1 + 4, 5 + 4, 5 + 4, 4 + 4, 0 + 4,
    706     1 + 4, 2 + 4, 6 + 4, 6 + 4, 5 + 4, 1 + 4,
    707     2 + 4, 3 + 4, 7 + 4, 7 + 4, 6 + 4, 2 + 4,
    708     3 + 4, 0 + 4, 4 + 4, 4 + 4, 7 + 4, 3 + 4,
    709 
    710     0 + 8, 1 + 8, 5 + 8, 5 + 8, 4 + 8, 0 + 8,
    711     1 + 8, 2 + 8, 6 + 8, 6 + 8, 5 + 8, 1 + 8,
    712     2 + 8, 3 + 8, 7 + 8, 7 + 8, 6 + 8, 2 + 8,
    713     3 + 8, 0 + 8, 4 + 8, 4 + 8, 7 + 8, 3 + 8,
    714 };
    715 
    716 int GrContext::aaStrokeRectIndexCount() const {
    717     return GR_ARRAY_COUNT(gStrokeAARectIdx);
    718 }
    719 
    720 GrIndexBuffer* GrContext::aaStrokeRectIndexBuffer() {
    721     if (NULL == fAAStrokeRectIndexBuffer) {
    722         fAAStrokeRectIndexBuffer = fGpu->createIndexBuffer(sizeof(gStrokeAARectIdx),
    723                                                            false);
    724         if (NULL != fAAStrokeRectIndexBuffer) {
    725     #if GR_DEBUG
    726             bool updated =
    727     #endif
    728             fAAStrokeRectIndexBuffer->updateData(gStrokeAARectIdx,
    729                                                  sizeof(gStrokeAARectIdx));
    730             GR_DEBUGASSERT(updated);
    731         }
    732     }
    733     return fAAStrokeRectIndexBuffer;
    734 }
    735 
    736 static GrVertexLayout aa_rect_layout(const GrDrawTarget* target,
    737                                      bool useCoverage) {
    738     GrVertexLayout layout = 0;
    739     for (int s = 0; s < GrDrawState::kNumStages; ++s) {
    740         if (NULL != target->getDrawState().getTexture(s)) {
    741             layout |= GrDrawTarget::StagePosAsTexCoordVertexLayoutBit(s);
    742         }
    743     }
    744     if (useCoverage) {
    745         layout |= GrDrawTarget::kCoverage_VertexLayoutBit;
    746     } else {
    747         layout |= GrDrawTarget::kColor_VertexLayoutBit;
    748     }
    749     return layout;
    750 }
    751 
    752 void GrContext::fillAARect(GrDrawTarget* target,
    753                            const GrRect& devRect,
    754                            bool useVertexCoverage) {
    755     GrVertexLayout layout = aa_rect_layout(target, useVertexCoverage);
    756 
    757     size_t vsize = GrDrawTarget::VertexSize(layout);
    758 
    759     GrDrawTarget::AutoReleaseGeometry geo(target, layout, 8, 0);
    760     if (!geo.succeeded()) {
    761         GrPrintf("Failed to get space for vertices!\n");
    762         return;
    763     }
    764     GrIndexBuffer* indexBuffer = this->aaFillRectIndexBuffer();
    765     if (NULL == indexBuffer) {
    766         GrPrintf("Failed to create index buffer!\n");
    767         return;
    768     }
    769 
    770     intptr_t verts = reinterpret_cast<intptr_t>(geo.vertices());
    771 
    772     GrPoint* fan0Pos = reinterpret_cast<GrPoint*>(verts);
    773     GrPoint* fan1Pos = reinterpret_cast<GrPoint*>(verts + 4 * vsize);
    774 
    775     setInsetFan(fan0Pos, vsize, devRect, -GR_ScalarHalf, -GR_ScalarHalf);
    776     setInsetFan(fan1Pos, vsize, devRect,  GR_ScalarHalf,  GR_ScalarHalf);
    777 
    778     verts += sizeof(GrPoint);
    779     for (int i = 0; i < 4; ++i) {
    780         *reinterpret_cast<GrColor*>(verts + i * vsize) = 0;
    781     }
    782 
    783     GrColor innerColor;
    784     if (useVertexCoverage) {
    785         innerColor = 0xffffffff;
    786     } else {
    787         innerColor = target->getDrawState().getColor();
    788     }
    789 
    790     verts += 4 * vsize;
    791     for (int i = 0; i < 4; ++i) {
    792         *reinterpret_cast<GrColor*>(verts + i * vsize) = innerColor;
    793     }
    794 
    795     target->setIndexSourceToBuffer(indexBuffer);
    796 
    797     target->drawIndexed(kTriangles_PrimitiveType, 0,
    798                          0, 8, this->aaFillRectIndexCount());
    799 }
    800 
    801 void GrContext::strokeAARect(GrDrawTarget* target,
    802                              const GrRect& devRect,
    803                              const GrVec& devStrokeSize,
    804                              bool useVertexCoverage) {
    805     const GrScalar& dx = devStrokeSize.fX;
    806     const GrScalar& dy = devStrokeSize.fY;
    807     const GrScalar rx = GrMul(dx, GR_ScalarHalf);
    808     const GrScalar ry = GrMul(dy, GR_ScalarHalf);
    809 
    810     GrScalar spare;
    811     {
    812         GrScalar w = devRect.width() - dx;
    813         GrScalar h = devRect.height() - dy;
    814         spare = GrMin(w, h);
    815     }
    816 
    817     if (spare <= 0) {
    818         GrRect r(devRect);
    819         r.inset(-rx, -ry);
    820         fillAARect(target, r, useVertexCoverage);
    821         return;
    822     }
    823     GrVertexLayout layout = aa_rect_layout(target, useVertexCoverage);
    824     size_t vsize = GrDrawTarget::VertexSize(layout);
    825 
    826     GrDrawTarget::AutoReleaseGeometry geo(target, layout, 16, 0);
    827     if (!geo.succeeded()) {
    828         GrPrintf("Failed to get space for vertices!\n");
    829         return;
    830     }
    831     GrIndexBuffer* indexBuffer = this->aaStrokeRectIndexBuffer();
    832     if (NULL == indexBuffer) {
    833         GrPrintf("Failed to create index buffer!\n");
    834         return;
    835     }
    836 
    837     intptr_t verts = reinterpret_cast<intptr_t>(geo.vertices());
    838 
    839     GrPoint* fan0Pos = reinterpret_cast<GrPoint*>(verts);
    840     GrPoint* fan1Pos = reinterpret_cast<GrPoint*>(verts + 4 * vsize);
    841     GrPoint* fan2Pos = reinterpret_cast<GrPoint*>(verts + 8 * vsize);
    842     GrPoint* fan3Pos = reinterpret_cast<GrPoint*>(verts + 12 * vsize);
    843 
    844     setInsetFan(fan0Pos, vsize, devRect, -rx - GR_ScalarHalf, -ry - GR_ScalarHalf);
    845     setInsetFan(fan1Pos, vsize, devRect, -rx + GR_ScalarHalf, -ry + GR_ScalarHalf);
    846     setInsetFan(fan2Pos, vsize, devRect,  rx - GR_ScalarHalf,  ry - GR_ScalarHalf);
    847     setInsetFan(fan3Pos, vsize, devRect,  rx + GR_ScalarHalf,  ry + GR_ScalarHalf);
    848 
    849     verts += sizeof(GrPoint);
    850     for (int i = 0; i < 4; ++i) {
    851         *reinterpret_cast<GrColor*>(verts + i * vsize) = 0;
    852     }
    853 
    854     GrColor innerColor;
    855     if (useVertexCoverage) {
    856         innerColor = 0xffffffff;
    857     } else {
    858         innerColor = target->getDrawState().getColor();
    859     }
    860     verts += 4 * vsize;
    861     for (int i = 0; i < 8; ++i) {
    862         *reinterpret_cast<GrColor*>(verts + i * vsize) = innerColor;
    863     }
    864 
    865     verts += 8 * vsize;
    866     for (int i = 0; i < 8; ++i) {
    867         *reinterpret_cast<GrColor*>(verts + i * vsize) = 0;
    868     }
    869 
    870     target->setIndexSourceToBuffer(indexBuffer);
    871     target->drawIndexed(kTriangles_PrimitiveType,
    872                         0, 0, 16, aaStrokeRectIndexCount());
    873 }
    874 
    875 /**
    876  * Returns true if the rects edges are integer-aligned.
    877  */
    878 static bool isIRect(const GrRect& r) {
    879     return GrScalarIsInt(r.fLeft) && GrScalarIsInt(r.fTop) &&
    880            GrScalarIsInt(r.fRight) && GrScalarIsInt(r.fBottom);
    881 }
    882 
    883 static bool apply_aa_to_rect(GrDrawTarget* target,
    884                              const GrRect& rect,
    885                              GrScalar width,
    886                              const GrMatrix* matrix,
    887                              GrMatrix* combinedMatrix,
    888                              GrRect* devRect,
    889                              bool* useVertexCoverage) {
    890     // we use a simple coverage ramp to do aa on axis-aligned rects
    891     // we check if the rect will be axis-aligned, and the rect won't land on
    892     // integer coords.
    893 
    894     // we are keeping around the "tweak the alpha" trick because
    895     // it is our only hope for the fixed-pipe implementation.
    896     // In a shader implementation we can give a separate coverage input
    897     // TODO: remove this ugliness when we drop the fixed-pipe impl
    898     *useVertexCoverage = false;
    899     if (!target->canTweakAlphaForCoverage()) {
    900         if (disable_coverage_aa_for_blend(target)) {
    901 #if GR_DEBUG
    902             //GrPrintf("Turning off AA to correctly apply blend.\n");
    903 #endif
    904             return false;
    905         } else {
    906             *useVertexCoverage = true;
    907         }
    908     }
    909     const GrDrawState& drawState = target->getDrawState();
    910     if (drawState.getRenderTarget()->isMultisampled()) {
    911         return false;
    912     }
    913 
    914     if (0 == width && target->willUseHWAALines()) {
    915         return false;
    916     }
    917 
    918     if (!drawState.getViewMatrix().preservesAxisAlignment()) {
    919         return false;
    920     }
    921 
    922     if (NULL != matrix &&
    923         !matrix->preservesAxisAlignment()) {
    924         return false;
    925     }
    926 
    927     *combinedMatrix = drawState.getViewMatrix();
    928     if (NULL != matrix) {
    929         combinedMatrix->preConcat(*matrix);
    930         GrAssert(combinedMatrix->preservesAxisAlignment());
    931     }
    932 
    933     combinedMatrix->mapRect(devRect, rect);
    934     devRect->sort();
    935 
    936     if (width < 0) {
    937         return !isIRect(*devRect);
    938     } else {
    939         return true;
    940     }
    941 }
    942 
    943 void GrContext::drawRect(const GrPaint& paint,
    944                          const GrRect& rect,
    945                          GrScalar width,
    946                          const GrMatrix* matrix) {
    947     SK_TRACE_EVENT0("GrContext::drawRect");
    948 
    949     GrDrawTarget* target = this->prepareToDraw(paint, kUnbuffered_DrawCategory);
    950     int stageMask = paint.getActiveStageMask();
    951 
    952     GrRect devRect = rect;
    953     GrMatrix combinedMatrix;
    954     bool useVertexCoverage;
    955     bool needAA = paint.fAntiAlias &&
    956                   !this->getRenderTarget()->isMultisampled();
    957     bool doAA = needAA && apply_aa_to_rect(target, rect, width, matrix,
    958                                            &combinedMatrix, &devRect,
    959                                            &useVertexCoverage);
    960 
    961     if (doAA) {
    962         GrDrawTarget::AutoDeviceCoordDraw adcd(target, stageMask);
    963         if (width >= 0) {
    964             GrVec strokeSize;;
    965             if (width > 0) {
    966                 strokeSize.set(width, width);
    967                 combinedMatrix.mapVectors(&strokeSize, 1);
    968                 strokeSize.setAbs(strokeSize);
    969             } else {
    970                 strokeSize.set(GR_Scalar1, GR_Scalar1);
    971             }
    972             strokeAARect(target, devRect, strokeSize, useVertexCoverage);
    973         } else {
    974             fillAARect(target, devRect, useVertexCoverage);
    975         }
    976         return;
    977     }
    978 
    979     if (width >= 0) {
    980         // TODO: consider making static vertex buffers for these cases.
    981         // Hairline could be done by just adding closing vertex to
    982         // unitSquareVertexBuffer()
    983         GrVertexLayout layout =  PaintStageVertexLayoutBits(paint, NULL);
    984 
    985         static const int worstCaseVertCount = 10;
    986         GrDrawTarget::AutoReleaseGeometry geo(target, layout, worstCaseVertCount, 0);
    987 
    988         if (!geo.succeeded()) {
    989             GrPrintf("Failed to get space for vertices!\n");
    990             return;
    991         }
    992 
    993         GrPrimitiveType primType;
    994         int vertCount;
    995         GrPoint* vertex = geo.positions();
    996 
    997         if (width > 0) {
    998             vertCount = 10;
    999             primType = kTriangleStrip_PrimitiveType;
   1000             setStrokeRectStrip(vertex, rect, width);
   1001         } else {
   1002             // hairline
   1003             vertCount = 5;
   1004             primType = kLineStrip_PrimitiveType;
   1005             vertex[0].set(rect.fLeft, rect.fTop);
   1006             vertex[1].set(rect.fRight, rect.fTop);
   1007             vertex[2].set(rect.fRight, rect.fBottom);
   1008             vertex[3].set(rect.fLeft, rect.fBottom);
   1009             vertex[4].set(rect.fLeft, rect.fTop);
   1010         }
   1011 
   1012         GrDrawState::AutoViewMatrixRestore avmr;
   1013         if (NULL != matrix) {
   1014             GrDrawState* drawState = target->drawState();
   1015             avmr.set(drawState);
   1016             drawState->preConcatViewMatrix(*matrix);
   1017             drawState->preConcatSamplerMatrices(stageMask, *matrix);
   1018         }
   1019 
   1020         target->drawNonIndexed(primType, 0, vertCount);
   1021     } else {
   1022 #if GR_STATIC_RECT_VB
   1023             GrVertexLayout layout = PaintStageVertexLayoutBits(paint, NULL);
   1024             const GrVertexBuffer* sqVB = fGpu->getUnitSquareVertexBuffer();
   1025             if (NULL == sqVB) {
   1026                 GrPrintf("Failed to create static rect vb.\n");
   1027                 return;
   1028             }
   1029             target->setVertexSourceToBuffer(layout, sqVB);
   1030             GrDrawState* drawState = target->drawState();
   1031             GrDrawState::AutoViewMatrixRestore avmr(drawState);
   1032             GrMatrix m;
   1033             m.setAll(rect.width(),    0,             rect.fLeft,
   1034                         0,            rect.height(), rect.fTop,
   1035                         0,            0,             GrMatrix::I()[8]);
   1036 
   1037             if (NULL != matrix) {
   1038                 m.postConcat(*matrix);
   1039             }
   1040             drawState->preConcatViewMatrix(m);
   1041             drawState->preConcatSamplerMatrices(stageMask, m);
   1042 
   1043             target->drawNonIndexed(kTriangleFan_PrimitiveType, 0, 4);
   1044 #else
   1045             target->drawSimpleRect(rect, matrix, stageMask);
   1046 #endif
   1047     }
   1048 }
   1049 
   1050 void GrContext::drawRectToRect(const GrPaint& paint,
   1051                                const GrRect& dstRect,
   1052                                const GrRect& srcRect,
   1053                                const GrMatrix* dstMatrix,
   1054                                const GrMatrix* srcMatrix) {
   1055     SK_TRACE_EVENT0("GrContext::drawRectToRect");
   1056 
   1057     // srcRect refers to paint's first texture
   1058     if (NULL == paint.getTexture(0)) {
   1059         drawRect(paint, dstRect, -1, dstMatrix);
   1060         return;
   1061     }
   1062 
   1063     GR_STATIC_ASSERT(!BATCH_RECT_TO_RECT || !GR_STATIC_RECT_VB);
   1064 
   1065 #if GR_STATIC_RECT_VB
   1066     GrDrawTarget* target = this->prepareToDraw(paint, kUnbuffered_DrawCategory);
   1067     GrDrawState* drawState = target->drawState();
   1068     GrVertexLayout layout = PaintStageVertexLayoutBits(paint, NULL);
   1069     GrDrawState::AutoViewMatrixRestore avmr(drawState);
   1070 
   1071     GrMatrix m;
   1072 
   1073     m.setAll(dstRect.width(), 0,                dstRect.fLeft,
   1074              0,               dstRect.height(), dstRect.fTop,
   1075              0,               0,                GrMatrix::I()[8]);
   1076     if (NULL != dstMatrix) {
   1077         m.postConcat(*dstMatrix);
   1078     }
   1079     drawState->preConcatViewMatrix(m);
   1080 
   1081     // srcRect refers to first stage
   1082     int otherStageMask = paint.getActiveStageMask() &
   1083                          (~(1 << GrPaint::kFirstTextureStage));
   1084     if (otherStageMask) {
   1085         drawState->preConcatSamplerMatrices(otherStageMask, m);
   1086     }
   1087 
   1088     m.setAll(srcRect.width(), 0,                srcRect.fLeft,
   1089              0,               srcRect.height(), srcRect.fTop,
   1090              0,               0,                GrMatrix::I()[8]);
   1091     if (NULL != srcMatrix) {
   1092         m.postConcat(*srcMatrix);
   1093     }
   1094     drawState->sampler(GrPaint::kFirstTextureStage)->preConcatMatrix(m);
   1095 
   1096     const GrVertexBuffer* sqVB = fGpu->getUnitSquareVertexBuffer();
   1097     if (NULL == sqVB) {
   1098         GrPrintf("Failed to create static rect vb.\n");
   1099         return;
   1100     }
   1101     target->setVertexSourceToBuffer(layout, sqVB);
   1102     target->drawNonIndexed(kTriangleFan_PrimitiveType, 0, 4);
   1103 #else
   1104 
   1105     GrDrawTarget* target;
   1106 #if BATCH_RECT_TO_RECT
   1107     target = this->prepareToDraw(paint, kBuffered_DrawCategory);
   1108 #else
   1109     target = this->prepareToDraw(paint, kUnbuffered_DrawCategory);
   1110 #endif
   1111 
   1112     const GrRect* srcRects[GrDrawState::kNumStages] = {NULL};
   1113     const GrMatrix* srcMatrices[GrDrawState::kNumStages] = {NULL};
   1114     srcRects[0] = &srcRect;
   1115     srcMatrices[0] = srcMatrix;
   1116 
   1117     target->drawRect(dstRect, dstMatrix, 1, srcRects, srcMatrices);
   1118 #endif
   1119 }
   1120 
   1121 void GrContext::drawVertices(const GrPaint& paint,
   1122                              GrPrimitiveType primitiveType,
   1123                              int vertexCount,
   1124                              const GrPoint positions[],
   1125                              const GrPoint texCoords[],
   1126                              const GrColor colors[],
   1127                              const uint16_t indices[],
   1128                              int indexCount) {
   1129     SK_TRACE_EVENT0("GrContext::drawVertices");
   1130 
   1131     GrDrawTarget::AutoReleaseGeometry geo;
   1132 
   1133     GrDrawTarget* target = this->prepareToDraw(paint, kUnbuffered_DrawCategory);
   1134 
   1135     bool hasTexCoords[GrPaint::kTotalStages] = {
   1136         NULL != texCoords,   // texCoordSrc provides explicit stage 0 coords
   1137         0                    // remaining stages use positions
   1138     };
   1139 
   1140     GrVertexLayout layout = PaintStageVertexLayoutBits(paint, hasTexCoords);
   1141 
   1142     if (NULL != colors) {
   1143         layout |= GrDrawTarget::kColor_VertexLayoutBit;
   1144     }
   1145     int vertexSize = GrDrawTarget::VertexSize(layout);
   1146 
   1147     if (sizeof(GrPoint) != vertexSize) {
   1148         if (!geo.set(target, layout, vertexCount, 0)) {
   1149             GrPrintf("Failed to get space for vertices!\n");
   1150             return;
   1151         }
   1152         int texOffsets[GrDrawState::kMaxTexCoords];
   1153         int colorOffset;
   1154         GrDrawTarget::VertexSizeAndOffsetsByIdx(layout,
   1155                                                 texOffsets,
   1156                                                 &colorOffset,
   1157                                                 NULL,
   1158                                                 NULL);
   1159         void* curVertex = geo.vertices();
   1160 
   1161         for (int i = 0; i < vertexCount; ++i) {
   1162             *((GrPoint*)curVertex) = positions[i];
   1163 
   1164             if (texOffsets[0] > 0) {
   1165                 *(GrPoint*)((intptr_t)curVertex + texOffsets[0]) = texCoords[i];
   1166             }
   1167             if (colorOffset > 0) {
   1168                 *(GrColor*)((intptr_t)curVertex + colorOffset) = colors[i];
   1169             }
   1170             curVertex = (void*)((intptr_t)curVertex + vertexSize);
   1171         }
   1172     } else {
   1173         target->setVertexSourceToArray(layout, positions, vertexCount);
   1174     }
   1175 
   1176     // we don't currently apply offscreen AA to this path. Need improved
   1177     // management of GrDrawTarget's geometry to avoid copying points per-tile.
   1178 
   1179     if (NULL != indices) {
   1180         target->setIndexSourceToArray(indices, indexCount);
   1181         target->drawIndexed(primitiveType, 0, 0, vertexCount, indexCount);
   1182     } else {
   1183         target->drawNonIndexed(primitiveType, 0, vertexCount);
   1184     }
   1185 }
   1186 
   1187 ///////////////////////////////////////////////////////////////////////////////
   1188 #include "SkDraw.h"
   1189 #include "SkRasterClip.h"
   1190 
   1191 namespace {
   1192 
   1193 SkPath::FillType gr_fill_to_sk_fill(GrPathFill fill) {
   1194     switch (fill) {
   1195         case kWinding_PathFill:
   1196             return SkPath::kWinding_FillType;
   1197         case kEvenOdd_PathFill:
   1198             return SkPath::kEvenOdd_FillType;
   1199         case kInverseWinding_PathFill:
   1200             return SkPath::kInverseWinding_FillType;
   1201         case kInverseEvenOdd_PathFill:
   1202             return SkPath::kInverseEvenOdd_FillType;
   1203         default:
   1204             GrCrash("Unexpected fill.");
   1205             return SkPath::kWinding_FillType;
   1206     }
   1207 }
   1208 
   1209 // gets device coord bounds of path (not considering the fill) and clip. The
   1210 // path bounds will be a subset of the clip bounds. returns false if path bounds
   1211 // would be empty.
   1212 bool get_path_and_clip_bounds(const GrDrawTarget* target,
   1213                               const GrPath& path,
   1214                               const GrVec* translate,
   1215                               GrIRect* pathBounds,
   1216                               GrIRect* clipBounds) {
   1217     // compute bounds as intersection of rt size, clip, and path
   1218     const GrRenderTarget* rt = target->getDrawState().getRenderTarget();
   1219     if (NULL == rt) {
   1220         return false;
   1221     }
   1222     *pathBounds = GrIRect::MakeWH(rt->width(), rt->height());
   1223     const GrClip& clip = target->getClip();
   1224     if (clip.hasConservativeBounds()) {
   1225         clip.getConservativeBounds().roundOut(clipBounds);
   1226         if (!pathBounds->intersect(*clipBounds)) {
   1227             return false;
   1228         }
   1229     } else {
   1230         // pathBounds is currently the rt extent, set clip bounds to that rect.
   1231         *clipBounds = *pathBounds;
   1232     }
   1233     GrRect pathSBounds = path.getBounds();
   1234     if (!pathSBounds.isEmpty()) {
   1235         if (NULL != translate) {
   1236             pathSBounds.offset(*translate);
   1237         }
   1238         target->getDrawState().getViewMatrix().mapRect(&pathSBounds,
   1239                                                         pathSBounds);
   1240         GrIRect pathIBounds;
   1241         pathSBounds.roundOut(&pathIBounds);
   1242         if (!pathBounds->intersect(pathIBounds)) {
   1243             return false;
   1244         }
   1245     } else {
   1246         return false;
   1247     }
   1248     return true;
   1249 }
   1250 
   1251 /**
   1252  * sw rasterizes path to A8 mask using the context's matrix and uploads to a
   1253  * scratch texture.
   1254  */
   1255 
   1256 bool sw_draw_path_to_mask_texture(const GrPath& clientPath,
   1257                                   const GrIRect& pathDevBounds,
   1258                                   GrPathFill fill,
   1259                                   GrContext* context,
   1260                                   const GrPoint* translate,
   1261                                   GrAutoScratchTexture* tex) {
   1262     SkPaint paint;
   1263     SkPath tmpPath;
   1264     const SkPath* pathToDraw = &clientPath;
   1265     if (kHairLine_PathFill == fill) {
   1266         paint.setStyle(SkPaint::kStroke_Style);
   1267         paint.setStrokeWidth(SK_Scalar1);
   1268     } else {
   1269         paint.setStyle(SkPaint::kFill_Style);
   1270         SkPath::FillType skfill = gr_fill_to_sk_fill(fill);
   1271         if (skfill != pathToDraw->getFillType()) {
   1272             tmpPath = *pathToDraw;
   1273             tmpPath.setFillType(skfill);
   1274             pathToDraw = &tmpPath;
   1275         }
   1276     }
   1277     paint.setAntiAlias(true);
   1278     paint.setColor(SK_ColorWHITE);
   1279 
   1280     GrMatrix matrix = context->getMatrix();
   1281     if (NULL != translate) {
   1282         matrix.postTranslate(translate->fX, translate->fY);
   1283     }
   1284 
   1285     matrix.postTranslate(-pathDevBounds.fLeft * SK_Scalar1,
   1286                          -pathDevBounds.fTop * SK_Scalar1);
   1287     GrIRect bounds = GrIRect::MakeWH(pathDevBounds.width(),
   1288                                      pathDevBounds.height());
   1289 
   1290     SkBitmap bm;
   1291     bm.setConfig(SkBitmap::kA8_Config, bounds.fRight, bounds.fBottom);
   1292     if (!bm.allocPixels()) {
   1293         return false;
   1294     }
   1295     sk_bzero(bm.getPixels(), bm.getSafeSize());
   1296 
   1297     SkDraw  draw;
   1298     sk_bzero(&draw, sizeof(draw));
   1299     SkRasterClip rc(bounds);
   1300     draw.fRC    = &rc;
   1301     draw.fClip  = &rc.bwRgn();
   1302     draw.fMatrix = &matrix;
   1303     draw.fBitmap = &bm;
   1304     draw.drawPath(*pathToDraw, paint);
   1305 
   1306     const GrTextureDesc desc = {
   1307         kNone_GrTextureFlags,
   1308         bounds.fRight,
   1309         bounds.fBottom,
   1310         kAlpha_8_GrPixelConfig,
   1311         {0} // samples
   1312     };
   1313 
   1314     tex->set(context, desc);
   1315     GrTexture* texture = tex->texture();
   1316 
   1317     if (NULL == texture) {
   1318         return false;
   1319     }
   1320     SkAutoLockPixels alp(bm);
   1321     texture->writePixels(0, 0, desc.fWidth, desc.fHeight, desc.fConfig,
   1322                          bm.getPixels(), bm.rowBytes());
   1323     return true;
   1324 }
   1325 
   1326 void draw_around_inv_path(GrDrawTarget* target,
   1327                           GrDrawState::StageMask stageMask,
   1328                           const GrIRect& clipBounds,
   1329                           const GrIRect& pathBounds) {
   1330     GrDrawTarget::AutoDeviceCoordDraw adcd(target, stageMask);
   1331     GrRect rect;
   1332     if (clipBounds.fTop < pathBounds.fTop) {
   1333         rect.iset(clipBounds.fLeft, clipBounds.fTop,
   1334                     clipBounds.fRight, pathBounds.fTop);
   1335         target->drawSimpleRect(rect, NULL, stageMask);
   1336     }
   1337     if (clipBounds.fLeft < pathBounds.fLeft) {
   1338         rect.iset(clipBounds.fLeft, pathBounds.fTop,
   1339                     pathBounds.fLeft, pathBounds.fBottom);
   1340         target->drawSimpleRect(rect, NULL, stageMask);
   1341     }
   1342     if (clipBounds.fRight > pathBounds.fRight) {
   1343         rect.iset(pathBounds.fRight, pathBounds.fTop,
   1344                     clipBounds.fRight, pathBounds.fBottom);
   1345         target->drawSimpleRect(rect, NULL, stageMask);
   1346     }
   1347     if (clipBounds.fBottom > pathBounds.fBottom) {
   1348         rect.iset(clipBounds.fLeft, pathBounds.fBottom,
   1349                     clipBounds.fRight, clipBounds.fBottom);
   1350         target->drawSimpleRect(rect, NULL, stageMask);
   1351     }
   1352 }
   1353 
   1354 }
   1355 
   1356 void GrContext::drawPath(const GrPaint& paint, const GrPath& path,
   1357                          GrPathFill fill, const GrPoint* translate) {
   1358 
   1359     if (path.isEmpty()) {
   1360        if (GrIsFillInverted(fill)) {
   1361            this->drawPaint(paint);
   1362        }
   1363        return;
   1364     }
   1365 
   1366     GrDrawTarget* target = this->prepareToDraw(paint, kUnbuffered_DrawCategory);
   1367     GrDrawState::StageMask stageMask = paint.getActiveStageMask();
   1368 
   1369     bool prAA = paint.fAntiAlias && !this->getRenderTarget()->isMultisampled();
   1370 
   1371     // An Assumption here is that path renderer would use some form of tweaking
   1372     // the src color (either the input alpha or in the frag shader) to implement
   1373     // aa. If we have some future driver-mojo path AA that can do the right
   1374     // thing WRT to the blend then we'll need some query on the PR.
   1375     if (disable_coverage_aa_for_blend(target)) {
   1376 #if GR_DEBUG
   1377         //GrPrintf("Turning off AA to correctly apply blend.\n");
   1378 #endif
   1379         prAA = false;
   1380     }
   1381 
   1382     GrPathRenderer* pr = NULL;
   1383     if (prAA) {
   1384         pr = this->getPathRenderer(path, fill, target, true);
   1385         if (NULL == pr) {
   1386             GrAutoScratchTexture ast;
   1387             GrIRect pathBounds, clipBounds;
   1388             if (!get_path_and_clip_bounds(target, path, translate,
   1389                                           &pathBounds, &clipBounds)) {
   1390                 return;
   1391             }
   1392             if (NULL == pr && sw_draw_path_to_mask_texture(path, pathBounds,
   1393                                                            fill, this,
   1394                                                            translate, &ast)) {
   1395                 GrTexture* texture = ast.texture();
   1396                 GrAssert(NULL != texture);
   1397                 GrDrawTarget::AutoDeviceCoordDraw adcd(target, stageMask);
   1398                 enum {
   1399                     kPathMaskStage = GrPaint::kTotalStages,
   1400                 };
   1401                 target->drawState()->setTexture(kPathMaskStage, texture);
   1402                 target->drawState()->sampler(kPathMaskStage)->reset();
   1403                 GrScalar w = GrIntToScalar(pathBounds.width());
   1404                 GrScalar h = GrIntToScalar(pathBounds.height());
   1405                 GrRect maskRect = GrRect::MakeWH(w / texture->width(),
   1406                                                  h / texture->height());
   1407                 const GrRect* srcRects[GrDrawState::kNumStages] = {NULL};
   1408                 srcRects[kPathMaskStage] = &maskRect;
   1409                 stageMask |= 1 << kPathMaskStage;
   1410                 GrRect dstRect = GrRect::MakeLTRB(
   1411                     SK_Scalar1* pathBounds.fLeft,
   1412                     SK_Scalar1* pathBounds.fTop,
   1413                     SK_Scalar1* pathBounds.fRight,
   1414                     SK_Scalar1* pathBounds.fBottom);
   1415                 target->drawRect(dstRect, NULL, stageMask, srcRects, NULL);
   1416                 target->drawState()->setTexture(kPathMaskStage, NULL);
   1417                 if (GrIsFillInverted(fill)) {
   1418                     draw_around_inv_path(target, stageMask,
   1419                                          clipBounds, pathBounds);
   1420                 }
   1421                 return;
   1422             }
   1423         }
   1424     } else {
   1425         pr = this->getPathRenderer(path, fill, target, false);
   1426     }
   1427 
   1428     if (NULL == pr) {
   1429 #if GR_DEBUG
   1430         GrPrintf("Unable to find path renderer compatible with path.\n");
   1431 #endif
   1432         return;
   1433     }
   1434 
   1435     pr->drawPath(path, fill, translate, target, stageMask, prAA);
   1436 }
   1437 
   1438 ////////////////////////////////////////////////////////////////////////////////
   1439 
   1440 void GrContext::flush(int flagsBitfield) {
   1441     if (kDiscard_FlushBit & flagsBitfield) {
   1442         fDrawBuffer->reset();
   1443     } else {
   1444         this->flushDrawBuffer();
   1445     }
   1446     if (kForceCurrentRenderTarget_FlushBit & flagsBitfield) {
   1447         fGpu->forceRenderTargetFlush();
   1448     }
   1449 }
   1450 
   1451 void GrContext::flushText() {
   1452     if (kText_DrawCategory == fLastDrawCategory) {
   1453         flushDrawBuffer();
   1454     }
   1455 }
   1456 
   1457 void GrContext::flushDrawBuffer() {
   1458 #if BATCH_RECT_TO_RECT || DEFER_TEXT_RENDERING
   1459     if (fDrawBuffer) {
   1460         fDrawBuffer->playback(fGpu);
   1461         fDrawBuffer->reset();
   1462     }
   1463 #endif
   1464 }
   1465 
   1466 void GrContext::internalWriteTexturePixels(GrTexture* texture,
   1467                                            int left, int top,
   1468                                            int width, int height,
   1469                                            GrPixelConfig config,
   1470                                            const void* buffer,
   1471                                            size_t rowBytes,
   1472                                            uint32_t flags) {
   1473     SK_TRACE_EVENT0("GrContext::writeTexturePixels");
   1474     ASSERT_OWNED_RESOURCE(texture);
   1475 
   1476     if (!(kDontFlush_PixelOpsFlag & flags)) {
   1477         this->flush();
   1478     }
   1479     // TODO: use scratch texture to perform conversion
   1480     if (GrPixelConfigIsUnpremultiplied(texture->config()) !=
   1481         GrPixelConfigIsUnpremultiplied(config)) {
   1482         return;
   1483     }
   1484 
   1485     fGpu->writeTexturePixels(texture, left, top, width, height,
   1486                              config, buffer, rowBytes);
   1487 }
   1488 
   1489 bool GrContext::internalReadTexturePixels(GrTexture* texture,
   1490                                           int left, int top,
   1491                                           int width, int height,
   1492                                           GrPixelConfig config,
   1493                                           void* buffer,
   1494                                           size_t rowBytes,
   1495                                           uint32_t flags) {
   1496     SK_TRACE_EVENT0("GrContext::readTexturePixels");
   1497     ASSERT_OWNED_RESOURCE(texture);
   1498 
   1499     // TODO: code read pixels for textures that aren't also rendertargets
   1500     GrRenderTarget* target = texture->asRenderTarget();
   1501     if (NULL != target) {
   1502         return this->internalReadRenderTargetPixels(target,
   1503                                                     left, top, width, height,
   1504                                                     config, buffer, rowBytes,
   1505                                                     flags);
   1506     } else {
   1507         return false;
   1508     }
   1509 }
   1510 
   1511 #include "SkConfig8888.h"
   1512 
   1513 namespace {
   1514 /**
   1515  * Converts a GrPixelConfig to a SkCanvas::Config8888. Only byte-per-channel
   1516  * formats are representable as Config8888 and so the function returns false
   1517  * if the GrPixelConfig has no equivalent Config8888.
   1518  */
   1519 bool grconfig_to_config8888(GrPixelConfig config,
   1520                             SkCanvas::Config8888* config8888) {
   1521     switch (config) {
   1522         case kRGBA_8888_PM_GrPixelConfig:
   1523             *config8888 = SkCanvas::kRGBA_Premul_Config8888;
   1524             return true;
   1525         case kRGBA_8888_UPM_GrPixelConfig:
   1526             *config8888 = SkCanvas::kRGBA_Unpremul_Config8888;
   1527             return true;
   1528         case kBGRA_8888_PM_GrPixelConfig:
   1529             *config8888 = SkCanvas::kBGRA_Premul_Config8888;
   1530             return true;
   1531         case kBGRA_8888_UPM_GrPixelConfig:
   1532             *config8888 = SkCanvas::kBGRA_Unpremul_Config8888;
   1533             return true;
   1534         default:
   1535             return false;
   1536     }
   1537 }
   1538 }
   1539 
   1540 bool GrContext::internalReadRenderTargetPixels(GrRenderTarget* target,
   1541                                                int left, int top,
   1542                                                int width, int height,
   1543                                                GrPixelConfig config,
   1544                                                void* buffer,
   1545                                                size_t rowBytes,
   1546                                                uint32_t flags) {
   1547     SK_TRACE_EVENT0("GrContext::readRenderTargetPixels");
   1548     ASSERT_OWNED_RESOURCE(target);
   1549 
   1550     if (NULL == target) {
   1551         target = fGpu->drawState()->getRenderTarget();
   1552         if (NULL == target) {
   1553             return false;
   1554         }
   1555     }
   1556 
   1557     if (!(kDontFlush_PixelOpsFlag & flags)) {
   1558         this->flush();
   1559     }
   1560 
   1561     if (!GrPixelConfigIsUnpremultiplied(target->config()) &&
   1562         GrPixelConfigIsUnpremultiplied(config) &&
   1563         !fGpu->canPreserveReadWriteUnpremulPixels()) {
   1564         SkCanvas::Config8888 srcConfig8888, dstConfig8888;
   1565         if (!grconfig_to_config8888(target->config(), &srcConfig8888) ||
   1566             !grconfig_to_config8888(config, &dstConfig8888)) {
   1567             return false;
   1568         }
   1569         // do read back using target's own config
   1570         this->internalReadRenderTargetPixels(target,
   1571                                              left, top,
   1572                                              width, height,
   1573                                              target->config(),
   1574                                              buffer, rowBytes,
   1575                                              kDontFlush_PixelOpsFlag);
   1576         // sw convert the pixels to unpremul config
   1577         uint32_t* pixels = reinterpret_cast<uint32_t*>(buffer);
   1578         SkConvertConfig8888Pixels(pixels, rowBytes, dstConfig8888,
   1579                                   pixels, rowBytes, srcConfig8888,
   1580                                   width, height);
   1581         return true;
   1582     }
   1583 
   1584     GrTexture* src = target->asTexture();
   1585     bool swapRAndB = NULL != src &&
   1586                      fGpu->preferredReadPixelsConfig(config) ==
   1587                      GrPixelConfigSwapRAndB(config);
   1588 
   1589     bool flipY = NULL != src &&
   1590                  fGpu->readPixelsWillPayForYFlip(target, left, top,
   1591                                                  width, height, config,
   1592                                                  rowBytes);
   1593     bool alphaConversion = (!GrPixelConfigIsUnpremultiplied(target->config()) &&
   1594                              GrPixelConfigIsUnpremultiplied(config));
   1595 
   1596     if (NULL == src && alphaConversion) {
   1597         // we should fallback to cpu conversion here. This could happen when
   1598         // we were given an external render target by the client that is not
   1599         // also a texture (e.g. FBO 0 in GL)
   1600         return false;
   1601     }
   1602     // we draw to a scratch texture if any of these conversion are applied
   1603     GrAutoScratchTexture ast;
   1604     if (flipY || swapRAndB || alphaConversion) {
   1605         GrAssert(NULL != src);
   1606         if (swapRAndB) {
   1607             config = GrPixelConfigSwapRAndB(config);
   1608             GrAssert(kUnknown_GrPixelConfig != config);
   1609         }
   1610         // Make the scratch a render target because we don't have a robust
   1611         // readTexturePixels as of yet (it calls this function).
   1612         const GrTextureDesc desc = {
   1613             kRenderTarget_GrTextureFlagBit,
   1614             width, height,
   1615             config,
   1616             {0}, // samples
   1617         };
   1618 
   1619         // When a full readback is faster than a partial we could always make
   1620         // the scratch exactly match the passed rect. However, if we see many
   1621         // different size rectangles we will trash our texture cache and pay the
   1622         // cost of creating and destroying many textures. So, we only request
   1623         // an exact match when the caller is reading an entire RT.
   1624         ScratchTexMatch match = kApprox_ScratchTexMatch;
   1625         if (0 == left &&
   1626             0 == top &&
   1627             target->width() == width &&
   1628             target->height() == height &&
   1629             fGpu->fullReadPixelsIsFasterThanPartial()) {
   1630             match = kExact_ScratchTexMatch;
   1631         }
   1632         ast.set(this, desc, match);
   1633         GrTexture* texture = ast.texture();
   1634         if (!texture) {
   1635             return false;
   1636         }
   1637         target = texture->asRenderTarget();
   1638         GrAssert(NULL != target);
   1639 
   1640         GrDrawTarget::AutoStateRestore asr(fGpu);
   1641         GrDrawState* drawState = fGpu->drawState();
   1642         drawState->reset();
   1643         drawState->setRenderTarget(target);
   1644 
   1645         GrMatrix matrix;
   1646         if (flipY) {
   1647             matrix.setTranslate(SK_Scalar1 * left,
   1648                                 SK_Scalar1 * (top + height));
   1649             matrix.set(GrMatrix::kMScaleY, -GR_Scalar1);
   1650         } else {
   1651             matrix.setTranslate(SK_Scalar1 *left, SK_Scalar1 *top);
   1652         }
   1653         matrix.postIDiv(src->width(), src->height());
   1654         drawState->sampler(0)->reset(matrix);
   1655         drawState->sampler(0)->setRAndBSwap(swapRAndB);
   1656         drawState->setTexture(0, src);
   1657         GrRect rect;
   1658         rect.setXYWH(0, 0, SK_Scalar1 * width, SK_Scalar1 * height);
   1659         fGpu->drawSimpleRect(rect, NULL, 0x1);
   1660         left = 0;
   1661         top = 0;
   1662     }
   1663     return fGpu->readPixels(target,
   1664                             left, top, width, height,
   1665                             config, buffer, rowBytes, flipY);
   1666 }
   1667 
   1668 void GrContext::resolveRenderTarget(GrRenderTarget* target) {
   1669     GrAssert(target);
   1670     ASSERT_OWNED_RESOURCE(target);
   1671     // In the future we may track whether there are any pending draws to this
   1672     // target. We don't today so we always perform a flush. We don't promise
   1673     // this to our clients, though.
   1674     this->flush();
   1675     fGpu->resolveRenderTarget(target);
   1676 }
   1677 
   1678 void GrContext::copyTexture(GrTexture* src, GrRenderTarget* dst) {
   1679     if (NULL == src || NULL == dst) {
   1680         return;
   1681     }
   1682     ASSERT_OWNED_RESOURCE(src);
   1683 
   1684     GrDrawTarget::AutoStateRestore asr(fGpu);
   1685     GrDrawState* drawState = fGpu->drawState();
   1686     drawState->reset();
   1687     drawState->setRenderTarget(dst);
   1688     GrMatrix sampleM;
   1689     sampleM.setIDiv(src->width(), src->height());
   1690     drawState->setTexture(0, src);
   1691     drawState->sampler(0)->reset(sampleM);
   1692     SkRect rect = SkRect::MakeXYWH(0, 0,
   1693                                    SK_Scalar1 * src->width(),
   1694                                    SK_Scalar1 * src->height());
   1695     fGpu->drawSimpleRect(rect, NULL, 1 << 0);
   1696 }
   1697 
   1698 void GrContext::internalWriteRenderTargetPixels(GrRenderTarget* target,
   1699                                                 int left, int top,
   1700                                                 int width, int height,
   1701                                                 GrPixelConfig config,
   1702                                                 const void* buffer,
   1703                                                 size_t rowBytes,
   1704                                                 uint32_t flags) {
   1705     SK_TRACE_EVENT0("GrContext::writeRenderTargetPixels");
   1706     ASSERT_OWNED_RESOURCE(target);
   1707 
   1708     if (NULL == target) {
   1709         target = fGpu->drawState()->getRenderTarget();
   1710         if (NULL == target) {
   1711             return;
   1712         }
   1713     }
   1714 
   1715     // TODO: when underlying api has a direct way to do this we should use it
   1716     // (e.g. glDrawPixels on desktop GL).
   1717 
   1718     // If the RT is also a texture and we don't have to do PM/UPM conversion
   1719     // then take the texture path, which we expect to be at least as fast or
   1720     // faster since it doesn't use an intermediate texture as we do below.
   1721 
   1722 #if !GR_MAC_BUILD
   1723     // At least some drivers on the Mac get confused when glTexImage2D is called
   1724     // on a texture attached to an FBO. The FBO still sees the old image. TODO:
   1725     // determine what OS versions and/or HW is affected.
   1726     if (NULL != target->asTexture() &&
   1727         GrPixelConfigIsUnpremultiplied(target->config()) ==
   1728         GrPixelConfigIsUnpremultiplied(config)) {
   1729 
   1730         this->internalWriteTexturePixels(target->asTexture(),
   1731                                          left, top, width, height,
   1732                                          config, buffer, rowBytes, flags);
   1733         return;
   1734     }
   1735 #endif
   1736     if (!GrPixelConfigIsUnpremultiplied(target->config()) &&
   1737         GrPixelConfigIsUnpremultiplied(config) &&
   1738         !fGpu->canPreserveReadWriteUnpremulPixels()) {
   1739         SkCanvas::Config8888 srcConfig8888, dstConfig8888;
   1740         if (!grconfig_to_config8888(config, &srcConfig8888) ||
   1741             !grconfig_to_config8888(target->config(), &dstConfig8888)) {
   1742             return;
   1743         }
   1744         // allocate a tmp buffer and sw convert the pixels to premul
   1745         SkAutoSTMalloc<128 * 128, uint32_t> tmpPixels(width * height);
   1746         const uint32_t* src = reinterpret_cast<const uint32_t*>(buffer);
   1747         SkConvertConfig8888Pixels(tmpPixels.get(), 4 * width, dstConfig8888,
   1748                                   src, rowBytes, srcConfig8888,
   1749                                   width, height);
   1750         // upload the already premul pixels
   1751         this->internalWriteRenderTargetPixels(target,
   1752                                              left, top,
   1753                                              width, height,
   1754                                              target->config(),
   1755                                              tmpPixels, 4 * width, flags);
   1756         return;
   1757     }
   1758 
   1759     bool swapRAndB = fGpu->preferredReadPixelsConfig(config) ==
   1760                      GrPixelConfigSwapRAndB(config);
   1761     if (swapRAndB) {
   1762         config = GrPixelConfigSwapRAndB(config);
   1763     }
   1764 
   1765     const GrTextureDesc desc = {
   1766         kNone_GrTextureFlags, width, height, config, {0}
   1767     };
   1768     GrAutoScratchTexture ast(this, desc);
   1769     GrTexture* texture = ast.texture();
   1770     if (NULL == texture) {
   1771         return;
   1772     }
   1773     this->internalWriteTexturePixels(texture, 0, 0, width, height,
   1774                                      config, buffer, rowBytes, flags);
   1775 
   1776     GrDrawTarget::AutoStateRestore  asr(fGpu);
   1777     GrDrawState* drawState = fGpu->drawState();
   1778     drawState->reset();
   1779 
   1780     GrMatrix matrix;
   1781     matrix.setTranslate(GrIntToScalar(left), GrIntToScalar(top));
   1782     drawState->setViewMatrix(matrix);
   1783     drawState->setRenderTarget(target);
   1784     drawState->setTexture(0, texture);
   1785 
   1786     matrix.setIDiv(texture->width(), texture->height());
   1787     drawState->sampler(0)->reset(GrSamplerState::kClamp_WrapMode,
   1788                                  GrSamplerState::kNearest_Filter,
   1789                                  matrix);
   1790     drawState->sampler(0)->setRAndBSwap(swapRAndB);
   1791 
   1792     GrVertexLayout layout = GrDrawTarget::StagePosAsTexCoordVertexLayoutBit(0);
   1793     static const int VCOUNT = 4;
   1794     // TODO: Use GrGpu::drawRect here
   1795     GrDrawTarget::AutoReleaseGeometry geo(fGpu, layout, VCOUNT, 0);
   1796     if (!geo.succeeded()) {
   1797         GrPrintf("Failed to get space for vertices!\n");
   1798         return;
   1799     }
   1800     ((GrPoint*)geo.vertices())->setIRectFan(0, 0, width, height);
   1801     fGpu->drawNonIndexed(kTriangleFan_PrimitiveType, 0, VCOUNT);
   1802 }
   1803 ////////////////////////////////////////////////////////////////////////////////
   1804 
   1805 void GrContext::setPaint(const GrPaint& paint, GrDrawTarget* target) {
   1806     GrDrawState* drawState = target->drawState();
   1807 
   1808     for (int i = 0; i < GrPaint::kMaxTextures; ++i) {
   1809         int s = i + GrPaint::kFirstTextureStage;
   1810         drawState->setTexture(s, paint.getTexture(i));
   1811         ASSERT_OWNED_RESOURCE(paint.getTexture(i));
   1812         if (paint.getTexture(i)) {
   1813             *drawState->sampler(s) = paint.getTextureSampler(i);
   1814         }
   1815     }
   1816 
   1817     drawState->setFirstCoverageStage(GrPaint::kFirstMaskStage);
   1818 
   1819     for (int i = 0; i < GrPaint::kMaxMasks; ++i) {
   1820         int s = i + GrPaint::kFirstMaskStage;
   1821         drawState->setTexture(s, paint.getMask(i));
   1822         ASSERT_OWNED_RESOURCE(paint.getMask(i));
   1823         if (paint.getMask(i)) {
   1824             *drawState->sampler(s) = paint.getMaskSampler(i);
   1825         }
   1826     }
   1827 
   1828     drawState->setColor(paint.fColor);
   1829 
   1830     if (paint.fDither) {
   1831         drawState->enableState(GrDrawState::kDither_StateBit);
   1832     } else {
   1833         drawState->disableState(GrDrawState::kDither_StateBit);
   1834     }
   1835     if (paint.fAntiAlias) {
   1836         drawState->enableState(GrDrawState::kHWAntialias_StateBit);
   1837     } else {
   1838         drawState->disableState(GrDrawState::kHWAntialias_StateBit);
   1839     }
   1840     if (paint.fColorMatrixEnabled) {
   1841         drawState->enableState(GrDrawState::kColorMatrix_StateBit);
   1842     } else {
   1843         drawState->disableState(GrDrawState::kColorMatrix_StateBit);
   1844     }
   1845     drawState->setBlendFunc(paint.fSrcBlendCoeff, paint.fDstBlendCoeff);
   1846     drawState->setColorFilter(paint.fColorFilterColor, paint.fColorFilterXfermode);
   1847     drawState->setColorMatrix(paint.fColorMatrix);
   1848     drawState->setCoverage(paint.fCoverage);
   1849 
   1850     if (paint.getActiveMaskStageMask() && !target->canApplyCoverage()) {
   1851         GrPrintf("Partial pixel coverage will be incorrectly blended.\n");
   1852     }
   1853 }
   1854 
   1855 GrDrawTarget* GrContext::prepareToDraw(const GrPaint& paint,
   1856                                        DrawCategory category) {
   1857     if (category != fLastDrawCategory) {
   1858         flushDrawBuffer();
   1859         fLastDrawCategory = category;
   1860     }
   1861     this->setPaint(paint, fGpu);
   1862     GrDrawTarget* target = fGpu;
   1863     switch (category) {
   1864     case kText_DrawCategory:
   1865 #if DEFER_TEXT_RENDERING
   1866         target = fDrawBuffer;
   1867         fDrawBuffer->initializeDrawStateAndClip(*fGpu);
   1868 #else
   1869         target = fGpu;
   1870 #endif
   1871         break;
   1872     case kUnbuffered_DrawCategory:
   1873         target = fGpu;
   1874         break;
   1875     case kBuffered_DrawCategory:
   1876         target = fDrawBuffer;
   1877         fDrawBuffer->initializeDrawStateAndClip(*fGpu);
   1878         break;
   1879     }
   1880     return target;
   1881 }
   1882 
   1883 GrPathRenderer* GrContext::getPathRenderer(const GrPath& path,
   1884                                            GrPathFill fill,
   1885                                            const GrDrawTarget* target,
   1886                                            bool antiAlias) {
   1887     if (NULL == fPathRendererChain) {
   1888         fPathRendererChain =
   1889             new GrPathRendererChain(this, GrPathRendererChain::kNone_UsageFlag);
   1890     }
   1891     return fPathRendererChain->getPathRenderer(path, fill, target, antiAlias);
   1892 }
   1893 
   1894 ////////////////////////////////////////////////////////////////////////////////
   1895 
   1896 void GrContext::setRenderTarget(GrRenderTarget* target) {
   1897     ASSERT_OWNED_RESOURCE(target);
   1898     this->flush(false);
   1899     fGpu->drawState()->setRenderTarget(target);
   1900 }
   1901 
   1902 GrRenderTarget* GrContext::getRenderTarget() {
   1903     return fGpu->drawState()->getRenderTarget();
   1904 }
   1905 
   1906 const GrRenderTarget* GrContext::getRenderTarget() const {
   1907     return fGpu->getDrawState().getRenderTarget();
   1908 }
   1909 
   1910 const GrMatrix& GrContext::getMatrix() const {
   1911     return fGpu->getDrawState().getViewMatrix();
   1912 }
   1913 
   1914 void GrContext::setMatrix(const GrMatrix& m) {
   1915     fGpu->drawState()->setViewMatrix(m);
   1916 }
   1917 
   1918 void GrContext::concatMatrix(const GrMatrix& m) const {
   1919     fGpu->drawState()->preConcatViewMatrix(m);
   1920 }
   1921 
   1922 static inline intptr_t setOrClear(intptr_t bits, int shift, intptr_t pred) {
   1923     intptr_t mask = 1 << shift;
   1924     if (pred) {
   1925         bits |= mask;
   1926     } else {
   1927         bits &= ~mask;
   1928     }
   1929     return bits;
   1930 }
   1931 
   1932 void GrContext::resetStats() {
   1933     fGpu->resetStats();
   1934 }
   1935 
   1936 const GrGpuStats& GrContext::getStats() const {
   1937     return fGpu->getStats();
   1938 }
   1939 
   1940 void GrContext::printStats() const {
   1941     fGpu->printStats();
   1942 }
   1943 
   1944 GrContext::GrContext(GrGpu* gpu) {
   1945     fGpu = gpu;
   1946     fGpu->ref();
   1947     fGpu->setContext(this);
   1948 
   1949     fPathRendererChain = NULL;
   1950 
   1951     fTextureCache = new GrResourceCache(MAX_TEXTURE_CACHE_COUNT,
   1952                                         MAX_TEXTURE_CACHE_BYTES);
   1953     fFontCache = new GrFontCache(fGpu);
   1954 
   1955     fLastDrawCategory = kUnbuffered_DrawCategory;
   1956 
   1957     fDrawBuffer = NULL;
   1958     fDrawBufferVBAllocPool = NULL;
   1959     fDrawBufferIBAllocPool = NULL;
   1960 
   1961     fAAFillRectIndexBuffer = NULL;
   1962     fAAStrokeRectIndexBuffer = NULL;
   1963 
   1964     this->setupDrawBuffer();
   1965 }
   1966 
   1967 void GrContext::setupDrawBuffer() {
   1968 
   1969     GrAssert(NULL == fDrawBuffer);
   1970     GrAssert(NULL == fDrawBufferVBAllocPool);
   1971     GrAssert(NULL == fDrawBufferIBAllocPool);
   1972 
   1973 #if DEFER_TEXT_RENDERING || BATCH_RECT_TO_RECT
   1974     fDrawBufferVBAllocPool =
   1975         new GrVertexBufferAllocPool(fGpu, false,
   1976                                     DRAW_BUFFER_VBPOOL_BUFFER_SIZE,
   1977                                     DRAW_BUFFER_VBPOOL_PREALLOC_BUFFERS);
   1978     fDrawBufferIBAllocPool =
   1979         new GrIndexBufferAllocPool(fGpu, false,
   1980                                    DRAW_BUFFER_IBPOOL_BUFFER_SIZE,
   1981                                    DRAW_BUFFER_IBPOOL_PREALLOC_BUFFERS);
   1982 
   1983     fDrawBuffer = new GrInOrderDrawBuffer(fGpu,
   1984                                           fDrawBufferVBAllocPool,
   1985                                           fDrawBufferIBAllocPool);
   1986 #endif
   1987 
   1988 #if BATCH_RECT_TO_RECT
   1989     fDrawBuffer->setQuadIndexBuffer(this->getQuadIndexBuffer());
   1990 #endif
   1991 }
   1992 
   1993 GrDrawTarget* GrContext::getTextTarget(const GrPaint& paint) {
   1994     GrDrawTarget* target;
   1995 #if DEFER_TEXT_RENDERING
   1996     target = prepareToDraw(paint, kText_DrawCategory);
   1997 #else
   1998     target = prepareToDraw(paint, kUnbuffered_DrawCategory);
   1999 #endif
   2000     this->setPaint(paint, target);
   2001     return target;
   2002 }
   2003 
   2004 const GrIndexBuffer* GrContext::getQuadIndexBuffer() const {
   2005     return fGpu->getQuadIndexBuffer();
   2006 }
   2007 
   2008 void GrContext::convolve(GrTexture* texture,
   2009                          const SkRect& rect,
   2010                          const float* kernel,
   2011                          int kernelWidth,
   2012                          GrSamplerState::FilterDirection direction) {
   2013     ASSERT_OWNED_RESOURCE(texture);
   2014 
   2015     GrDrawTarget::AutoStateRestore asr(fGpu);
   2016     GrDrawState* drawState = fGpu->drawState();
   2017     GrRenderTarget* target = drawState->getRenderTarget();
   2018     drawState->reset();
   2019     drawState->setRenderTarget(target);
   2020     GrMatrix sampleM;
   2021     sampleM.setIDiv(texture->width(), texture->height());
   2022     drawState->sampler(0)->reset(GrSamplerState::kClamp_WrapMode,
   2023                                  GrSamplerState::kConvolution_Filter,
   2024                                  sampleM);
   2025     drawState->sampler(0)->setConvolutionParams(kernelWidth, kernel);
   2026     drawState->sampler(0)->setFilterDirection(direction);
   2027     drawState->setTexture(0, texture);
   2028     fGpu->drawSimpleRect(rect, NULL, 1 << 0);
   2029 }
   2030 
   2031 void GrContext::applyMorphology(GrTexture* texture,
   2032                                 const SkRect& rect,
   2033                                 int radius,
   2034                                 GrSamplerState::Filter filter,
   2035                                 GrSamplerState::FilterDirection direction) {
   2036     ASSERT_OWNED_RESOURCE(texture);
   2037     GrAssert(filter == GrSamplerState::kErode_Filter ||
   2038              filter == GrSamplerState::kDilate_Filter);
   2039 
   2040     GrDrawTarget::AutoStateRestore asr(fGpu);
   2041     GrDrawState* drawState = fGpu->drawState();
   2042     GrRenderTarget* target = drawState->getRenderTarget();
   2043     drawState->reset();
   2044     drawState->setRenderTarget(target);
   2045     GrMatrix sampleM;
   2046     sampleM.setIDiv(texture->width(), texture->height());
   2047     drawState->sampler(0)->reset(GrSamplerState::kClamp_WrapMode,
   2048                                  filter,
   2049                                  sampleM);
   2050     drawState->sampler(0)->setMorphologyRadius(radius);
   2051     drawState->sampler(0)->setFilterDirection(direction);
   2052     drawState->setTexture(0, texture);
   2053     fGpu->drawSimpleRect(rect, NULL, 1 << 0);
   2054 }
   2055 
   2056 ///////////////////////////////////////////////////////////////////////////////
   2057