Home | History | Annotate | Download | only in src
      1 /*
      2     Copyright 2011 Google Inc.
      3 
      4     Licensed under the Apache License, Version 2.0 (the "License");
      5     you may not use this file except in compliance with the License.
      6     You may obtain a copy of the License at
      7 
      8          http://www.apache.org/licenses/LICENSE-2.0
      9 
     10     Unless required by applicable law or agreed to in writing, software
     11     distributed under the License is distributed on an "AS IS" BASIS,
     12     WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
     13     See the License for the specific language governing permissions and
     14     limitations under the License.
     15  */
     16 
     17 #include "GrContext.h"
     18 #include "GrGpu.h"
     19 #include "GrTextureCache.h"
     20 #include "GrTextStrike.h"
     21 #include "GrMemory.h"
     22 #include "GrClipIterator.h"
     23 #include "GrIndexBuffer.h"
     24 #include "GrInOrderDrawBuffer.h"
     25 #include "GrBufferAllocPool.h"
     26 #include "GrPathRenderer.h"
     27 
     28 // larger than this, and we don't AA. set to 0 for no AA
     29 #ifndef GR_MAX_OFFSCREEN_AA_DIM
     30     #define GR_MAX_OFFSCREEN_AA_DIM    0
     31 #endif
     32 
     33 #define DEFER_TEXT_RENDERING 1
     34 
     35 #define BATCH_RECT_TO_RECT (1 && !GR_STATIC_RECT_VB)
     36 
     37 static const size_t MAX_TEXTURE_CACHE_COUNT = 128;
     38 static const size_t MAX_TEXTURE_CACHE_BYTES = 8 * 1024 * 1024;
     39 
     40 static const size_t DRAW_BUFFER_VBPOOL_BUFFER_SIZE = 1 << 18;
     41 static const int DRAW_BUFFER_VBPOOL_PREALLOC_BUFFERS = 4;
     42 
     43 // We are currently only batching Text and drawRectToRect, both
     44 // of which use the quad index buffer.
     45 static const size_t DRAW_BUFFER_IBPOOL_BUFFER_SIZE = 0;
     46 static const int DRAW_BUFFER_IBPOOL_PREALLOC_BUFFERS = 0;
     47 
     48 GrContext* GrContext::Create(GrEngine engine,
     49                              GrPlatform3DContext context3D) {
     50     GrContext* ctx = NULL;
     51     GrGpu* fGpu = GrGpu::Create(engine, context3D);
     52     if (NULL != fGpu) {
     53         ctx = new GrContext(fGpu);
     54         fGpu->unref();
     55     }
     56     return ctx;
     57 }
     58 
     59 GrContext* GrContext::CreateGLShaderContext() {
     60     return GrContext::Create(kOpenGL_Shaders_GrEngine, 0);
     61 }
     62 
     63 GrContext::~GrContext() {
     64     this->flush();
     65     delete fTextureCache;
     66     delete fFontCache;
     67     delete fDrawBuffer;
     68     delete fDrawBufferVBAllocPool;
     69     delete fDrawBufferIBAllocPool;
     70     GrSafeUnref(fCustomPathRenderer);
     71     GrSafeUnref(fAAFillRectIndexBuffer);
     72     GrSafeUnref(fAAStrokeRectIndexBuffer);
     73     fGpu->unref();
     74 }
     75 
     76 void GrContext::contextLost() {
     77     contextDestroyed();
     78     this->setupDrawBuffer();
     79 }
     80 
     81 void GrContext::contextDestroyed() {
     82     // abandon first to so destructors
     83     // don't try to free the resources in the API.
     84     fGpu->abandonResources();
     85 
     86     delete fDrawBuffer;
     87     fDrawBuffer = NULL;
     88 
     89     delete fDrawBufferVBAllocPool;
     90     fDrawBufferVBAllocPool = NULL;
     91 
     92     delete fDrawBufferIBAllocPool;
     93     fDrawBufferIBAllocPool = NULL;
     94 
     95     GrSafeSetNull(fAAFillRectIndexBuffer);
     96     GrSafeSetNull(fAAStrokeRectIndexBuffer);
     97 
     98     fTextureCache->removeAll();
     99     fFontCache->freeAll();
    100     fGpu->markContextDirty();
    101 }
    102 
    103 void GrContext::resetContext() {
    104     fGpu->markContextDirty();
    105 }
    106 
    107 void GrContext::freeGpuResources() {
    108     this->flush();
    109     fTextureCache->removeAll();
    110     fFontCache->freeAll();
    111 }
    112 
    113 ////////////////////////////////////////////////////////////////////////////////
    114 
    115 int GrContext::PaintStageVertexLayoutBits(
    116                             const GrPaint& paint,
    117                             const bool hasTexCoords[GrPaint::kTotalStages]) {
    118     int stageMask = paint.getActiveStageMask();
    119     int layout = 0;
    120     for (int i = 0; i < GrPaint::kTotalStages; ++i) {
    121         if ((1 << i) & stageMask) {
    122             if (NULL != hasTexCoords && hasTexCoords[i]) {
    123                 layout |= GrDrawTarget::StageTexCoordVertexLayoutBit(i, i);
    124             } else {
    125                 layout |= GrDrawTarget::StagePosAsTexCoordVertexLayoutBit(i);
    126             }
    127         }
    128     }
    129     return layout;
    130 }
    131 
    132 
    133 ////////////////////////////////////////////////////////////////////////////////
    134 
    135 enum {
    136     kNPOTBit    = 0x1,
    137     kFilterBit  = 0x2,
    138     kKeylessBit = 0x4,
    139 };
    140 
    141 bool GrContext::finalizeTextureKey(GrTextureKey* key,
    142                                    const GrSamplerState& sampler,
    143                                    bool keyless) const {
    144     uint32_t bits = 0;
    145     uint16_t width = key->width();
    146     uint16_t height = key->height();
    147 
    148     if (!fGpu->npotTextureTileSupport()) {
    149         bool isPow2 = GrIsPow2(width) && GrIsPow2(height);
    150 
    151         bool tiled = (sampler.getWrapX() != GrSamplerState::kClamp_WrapMode) ||
    152                      (sampler.getWrapY() != GrSamplerState::kClamp_WrapMode);
    153 
    154         if (tiled && !isPow2) {
    155             bits |= kNPOTBit;
    156             if (GrSamplerState::kNearest_Filter != sampler.getFilter()) {
    157                 bits |= kFilterBit;
    158             }
    159         }
    160     }
    161 
    162     if (keyless) {
    163         bits |= kKeylessBit;
    164     }
    165     key->finalize(bits);
    166     return 0 != bits;
    167 }
    168 
    169 GrTextureEntry* GrContext::findAndLockTexture(GrTextureKey* key,
    170                                               const GrSamplerState& sampler) {
    171     finalizeTextureKey(key, sampler, false);
    172     return fTextureCache->findAndLock(*key);
    173 }
    174 
    175 static void stretchImage(void* dst,
    176                          int dstW,
    177                          int dstH,
    178                          void* src,
    179                          int srcW,
    180                          int srcH,
    181                          int bpp) {
    182     GrFixed dx = (srcW << 16) / dstW;
    183     GrFixed dy = (srcH << 16) / dstH;
    184 
    185     GrFixed y = dy >> 1;
    186 
    187     int dstXLimit = dstW*bpp;
    188     for (int j = 0; j < dstH; ++j) {
    189         GrFixed x = dx >> 1;
    190         void* srcRow = (uint8_t*)src + (y>>16)*srcW*bpp;
    191         void* dstRow = (uint8_t*)dst + j*dstW*bpp;
    192         for (int i = 0; i < dstXLimit; i += bpp) {
    193             memcpy((uint8_t*) dstRow + i,
    194                    (uint8_t*) srcRow + (x>>16)*bpp,
    195                    bpp);
    196             x += dx;
    197         }
    198         y += dy;
    199     }
    200 }
    201 
    202 GrTextureEntry* GrContext::createAndLockTexture(GrTextureKey* key,
    203                                                 const GrSamplerState& sampler,
    204                                                 const GrTextureDesc& desc,
    205                                                 void* srcData, size_t rowBytes) {
    206     GrAssert(key->width() == desc.fWidth);
    207     GrAssert(key->height() == desc.fHeight);
    208 
    209 #if GR_DUMP_TEXTURE_UPLOAD
    210     GrPrintf("GrContext::createAndLockTexture [%d %d]\n", desc.fWidth, desc.fHeight);
    211 #endif
    212 
    213     GrTextureEntry* entry = NULL;
    214     bool special = finalizeTextureKey(key, sampler, false);
    215     if (special) {
    216         GrTextureEntry* clampEntry;
    217         GrTextureKey clampKey(*key);
    218         clampEntry = findAndLockTexture(&clampKey, GrSamplerState::ClampNoFilter());
    219 
    220         if (NULL == clampEntry) {
    221             clampEntry = createAndLockTexture(&clampKey,
    222                                               GrSamplerState::ClampNoFilter(),
    223                                               desc, srcData, rowBytes);
    224             GrAssert(NULL != clampEntry);
    225             if (NULL == clampEntry) {
    226                 return NULL;
    227             }
    228         }
    229         GrTextureDesc rtDesc = desc;
    230         rtDesc.fFlags =  rtDesc.fFlags |
    231                          kRenderTarget_GrTextureFlagBit |
    232                          kNoStencil_GrTextureFlagBit;
    233         rtDesc.fWidth  = GrNextPow2(GrMax<int>(desc.fWidth,
    234                                                fGpu->minRenderTargetWidth()));
    235         rtDesc.fHeight = GrNextPow2(GrMax<int>(desc.fHeight,
    236                                                fGpu->minRenderTargetHeight()));
    237 
    238         GrTexture* texture = fGpu->createTexture(rtDesc, NULL, 0);
    239 
    240         if (NULL != texture) {
    241             GrDrawTarget::AutoStateRestore asr(fGpu);
    242             fGpu->setRenderTarget(texture->asRenderTarget());
    243             fGpu->setTexture(0, clampEntry->texture());
    244             fGpu->disableStencil();
    245             fGpu->setViewMatrix(GrMatrix::I());
    246             fGpu->setAlpha(0xff);
    247             fGpu->setBlendFunc(kOne_BlendCoeff, kZero_BlendCoeff);
    248             fGpu->disableState(GrDrawTarget::kDither_StateBit |
    249                                GrDrawTarget::kClip_StateBit   |
    250                                GrDrawTarget::kAntialias_StateBit);
    251             GrSamplerState::Filter filter;
    252             // if filtering is not desired then we want to ensure all
    253             // texels in the resampled image are copies of texels from
    254             // the original.
    255             if (GrSamplerState::kNearest_Filter == sampler.getFilter()) {
    256                 filter = GrSamplerState::kNearest_Filter;
    257             } else {
    258                 filter = GrSamplerState::kBilinear_Filter;
    259             }
    260             GrSamplerState stretchSampler(GrSamplerState::kClamp_WrapMode,
    261                                           GrSamplerState::kClamp_WrapMode,
    262                                           filter);
    263             fGpu->setSamplerState(0, stretchSampler);
    264 
    265             static const GrVertexLayout layout =
    266                                 GrDrawTarget::StageTexCoordVertexLayoutBit(0,0);
    267             GrDrawTarget::AutoReleaseGeometry arg(fGpu, layout, 4, 0);
    268 
    269             if (arg.succeeded()) {
    270                 GrPoint* verts = (GrPoint*) arg.vertices();
    271                 verts[0].setIRectFan(0, 0,
    272                                      texture->width(),
    273                                      texture->height(),
    274                                      2*sizeof(GrPoint));
    275                 verts[1].setIRectFan(0, 0, 1, 1, 2*sizeof(GrPoint));
    276                 fGpu->drawNonIndexed(kTriangleFan_PrimitiveType,
    277                                      0, 4);
    278                 entry = fTextureCache->createAndLock(*key, texture);
    279             }
    280             texture->releaseRenderTarget();
    281         } else {
    282             // TODO: Our CPU stretch doesn't filter. But we create separate
    283             // stretched textures when the sampler state is either filtered or
    284             // not. Either implement filtered stretch blit on CPU or just create
    285             // one when FBO case fails.
    286 
    287             rtDesc.fFlags = kNone_GrTextureFlags;
    288             // no longer need to clamp at min RT size.
    289             rtDesc.fWidth  = GrNextPow2(desc.fWidth);
    290             rtDesc.fHeight = GrNextPow2(desc.fHeight);
    291             int bpp = GrBytesPerPixel(desc.fFormat);
    292             GrAutoSMalloc<128*128*4> stretchedPixels(bpp *
    293                                                      rtDesc.fWidth *
    294                                                      rtDesc.fHeight);
    295             stretchImage(stretchedPixels.get(), rtDesc.fWidth, rtDesc.fHeight,
    296                          srcData, desc.fWidth, desc.fHeight, bpp);
    297 
    298             size_t stretchedRowBytes = rtDesc.fWidth * bpp;
    299 
    300             GrTexture* texture = fGpu->createTexture(rtDesc,
    301                                                      stretchedPixels.get(),
    302                                                      stretchedRowBytes);
    303             GrAssert(NULL != texture);
    304             entry = fTextureCache->createAndLock(*key, texture);
    305         }
    306         fTextureCache->unlock(clampEntry);
    307 
    308     } else {
    309         GrTexture* texture = fGpu->createTexture(desc, srcData, rowBytes);
    310         if (NULL != texture) {
    311             entry = fTextureCache->createAndLock(*key, texture);
    312         } else {
    313             entry = NULL;
    314         }
    315     }
    316     return entry;
    317 }
    318 
    319 GrTextureEntry* GrContext::lockKeylessTexture(const GrTextureDesc& desc) {
    320     uint32_t p0 = desc.fFormat;
    321     uint32_t p1 = (desc.fAALevel << 16) | desc.fFlags;
    322     GrTextureKey key(p0, p1, desc.fWidth, desc.fHeight);
    323     this->finalizeTextureKey(&key, GrSamplerState::ClampNoFilter(), true);
    324 
    325     GrTextureEntry* entry = fTextureCache->findAndLock(key);
    326     if (NULL == entry) {
    327         GrTexture* texture = fGpu->createTexture(desc, NULL, 0);
    328         if (NULL != texture) {
    329             entry = fTextureCache->createAndLock(key, texture);
    330         }
    331     }
    332     // If the caller gives us the same desc/sampler twice we don't want
    333     // to return the same texture the second time (unless it was previously
    334     // released). So we detach the entry from the cache and reattach at release.
    335     if (NULL != entry) {
    336         fTextureCache->detach(entry);
    337     }
    338     return entry;
    339 }
    340 
    341 void GrContext::unlockTexture(GrTextureEntry* entry) {
    342     if (kKeylessBit & entry->key().getPrivateBits()) {
    343         fTextureCache->reattachAndUnlock(entry);
    344     } else {
    345         fTextureCache->unlock(entry);
    346     }
    347 }
    348 
    349 GrTexture* GrContext::createUncachedTexture(const GrTextureDesc& desc,
    350                                             void* srcData,
    351                                             size_t rowBytes) {
    352     return fGpu->createTexture(desc, srcData, rowBytes);
    353 }
    354 
    355 void GrContext::getTextureCacheLimits(int* maxTextures,
    356                                       size_t* maxTextureBytes) const {
    357     fTextureCache->getLimits(maxTextures, maxTextureBytes);
    358 }
    359 
    360 void GrContext::setTextureCacheLimits(int maxTextures, size_t maxTextureBytes) {
    361     fTextureCache->setLimits(maxTextures, maxTextureBytes);
    362 }
    363 
    364 int GrContext::getMaxTextureDimension() {
    365     return fGpu->maxTextureDimension();
    366 }
    367 
    368 ///////////////////////////////////////////////////////////////////////////////
    369 
    370 GrResource* GrContext::createPlatformSurface(const GrPlatformSurfaceDesc& desc) {
    371     // validate flags here so that GrGpu subclasses don't have to check
    372     if (kTexture_GrPlatformSurfaceType == desc.fSurfaceType &&
    373         0 != desc.fRenderTargetFlags) {
    374             return NULL;
    375     }
    376     if (!(kIsMultisampled_GrPlatformRenderTargetFlagBit & desc.fRenderTargetFlags) &&
    377         (kGrCanResolve_GrPlatformRenderTargetFlagBit & desc.fRenderTargetFlags)) {
    378             return NULL;
    379     }
    380     if (kTextureRenderTarget_GrPlatformSurfaceType == desc.fSurfaceType &&
    381         (kIsMultisampled_GrPlatformRenderTargetFlagBit & desc.fRenderTargetFlags) &&
    382         !(kGrCanResolve_GrPlatformRenderTargetFlagBit & desc.fRenderTargetFlags)) {
    383         return NULL;
    384     }
    385     return fGpu->createPlatformSurface(desc);
    386 }
    387 
    388 GrRenderTarget* GrContext::createRenderTargetFrom3DApiState() {
    389     return fGpu->createRenderTargetFrom3DApiState();
    390 }
    391 
    392 ///////////////////////////////////////////////////////////////////////////////
    393 
    394 bool GrContext::supportsIndex8PixelConfig(const GrSamplerState& sampler,
    395                                           int width, int height) {
    396     if (!fGpu->supports8BitPalette()) {
    397         return false;
    398     }
    399 
    400 
    401     bool isPow2 = GrIsPow2(width) && GrIsPow2(height);
    402 
    403     if (!isPow2) {
    404         if (!fGpu->npotTextureSupport()) {
    405             return false;
    406         }
    407 
    408         bool tiled = sampler.getWrapX() != GrSamplerState::kClamp_WrapMode ||
    409                      sampler.getWrapY() != GrSamplerState::kClamp_WrapMode;
    410         if (tiled && !fGpu->npotTextureTileSupport()) {
    411             return false;
    412         }
    413     }
    414     return true;
    415 }
    416 
    417 ////////////////////////////////////////////////////////////////////////////////
    418 
    419 const GrClip& GrContext::getClip() const { return fGpu->getClip(); }
    420 
    421 void GrContext::setClip(const GrClip& clip) {
    422     fGpu->setClip(clip);
    423     fGpu->enableState(GrDrawTarget::kClip_StateBit);
    424 }
    425 
    426 void GrContext::setClip(const GrIRect& rect) {
    427     GrClip clip;
    428     clip.setFromIRect(rect);
    429     fGpu->setClip(clip);
    430 }
    431 
    432 ////////////////////////////////////////////////////////////////////////////////
    433 
    434 void GrContext::clear(const GrIRect* rect, const GrColor color) {
    435     this->flush();
    436     fGpu->clear(rect, color);
    437 }
    438 
    439 void GrContext::drawPaint(const GrPaint& paint) {
    440     // set rect to be big enough to fill the space, but not super-huge, so we
    441     // don't overflow fixed-point implementations
    442     GrRect r;
    443     r.setLTRB(0, 0,
    444               GrIntToScalar(getRenderTarget()->width()),
    445               GrIntToScalar(getRenderTarget()->height()));
    446     GrMatrix inverse;
    447     if (fGpu->getViewInverse(&inverse)) {
    448         inverse.mapRect(&r);
    449     } else {
    450         GrPrintf("---- fGpu->getViewInverse failed\n");
    451     }
    452     this->drawRect(paint, r);
    453 }
    454 
    455 ////////////////////////////////////////////////////////////////////////////////
    456 
    457 bool GrContext::doOffscreenAA(GrDrawTarget* target,
    458                               const GrPaint& paint,
    459                               bool isLines) const {
    460 #if GR_MAX_OFFSCREEN_AA_DIM==0
    461     return false;
    462 #else
    463     if (!paint.fAntiAlias) {
    464         return false;
    465     }
    466     if (isLines && fGpu->supportsAALines()) {
    467         return false;
    468     }
    469     if (target->getRenderTarget()->isMultisampled()) {
    470         return false;
    471     }
    472     // we have to be sure that the blend equation is expressible
    473     // as simple src / dst coeffecients when the source
    474     // is already modulated by the coverage fraction.
    475     // We could use dual-source blending to get the correct per-pixel
    476     // dst coeffecient for the remaining cases.
    477     if (kISC_BlendCoeff != paint.fDstBlendCoeff &&
    478         kOne_BlendCoeff != paint.fDstBlendCoeff &&
    479         kISA_BlendCoeff != paint.fDstBlendCoeff) {
    480         return false;
    481     }
    482     return true;
    483 #endif
    484 }
    485 
    486 bool GrContext::setupOffscreenAAPass1(GrDrawTarget* target,
    487                                       bool requireStencil,
    488                                       const GrIRect& boundRect,
    489                                       OffscreenRecord* record) {
    490     GrAssert(GR_MAX_OFFSCREEN_AA_DIM > 0);
    491 
    492     GrAssert(NULL == record->fEntry0);
    493     GrAssert(NULL == record->fEntry1);
    494 
    495     int boundW = boundRect.width();
    496     int boundH = boundRect.height();
    497     int size  = GrMax(64, (int)GrNextPow2(GrMax(boundW, boundH)));
    498 
    499     GrTextureDesc desc;
    500     if (requireStencil) {
    501         desc.fFlags = kRenderTarget_GrTextureFlagBit;
    502     } else {
    503         desc.fFlags = kRenderTarget_GrTextureFlagBit |
    504                       kNoStencil_GrTextureFlagBit;
    505     }
    506 
    507     desc.fFormat = kRGBA_8888_GrPixelConfig;
    508 
    509     int scale;
    510     // Using MSAA seems to be slower for some yet unknown reason.
    511     if (false && fGpu->supportsFullsceneAA()) {
    512         record->fDownsample = OffscreenRecord::kFSAA_Downsample;
    513         scale = GR_Scalar1;
    514         desc.fAALevel = kMed_GrAALevel;
    515     } else {
    516         record->fDownsample = (fGpu->supports4x4DownsampleFilter()) ?
    517                                 OffscreenRecord::k4x4SinglePass_Downsample :
    518                                 OffscreenRecord::k4x4TwoPass_Downsample;
    519         scale = 4;
    520         desc.fAALevel = kNone_GrAALevel;
    521     }
    522 
    523     desc.fWidth = scale * size;
    524     desc.fHeight = scale * size;
    525 
    526     record->fEntry0 = this->lockKeylessTexture(desc);
    527 
    528     if (NULL == record->fEntry0) {
    529         return false;
    530     }
    531 
    532     if (OffscreenRecord::k4x4TwoPass_Downsample == record->fDownsample) {
    533         desc.fWidth /= 2;
    534         desc.fHeight /= 2;
    535         record->fEntry1 = this->lockKeylessTexture(desc);
    536         if (NULL == record->fEntry1) {
    537             this->unlockTexture(record->fEntry0);
    538             record->fEntry0 = NULL;
    539             return false;
    540         }
    541     }
    542 
    543     GrRenderTarget* offRT0 = record->fEntry0->texture()->asRenderTarget();
    544     GrAssert(NULL != offRT0);
    545 
    546     target->saveCurrentDrawState(&record->fSavedState);
    547 
    548     GrPaint tempPaint;
    549     tempPaint.reset();
    550     SetPaint(tempPaint, target);
    551     target->setRenderTarget(offRT0);
    552 
    553     GrMatrix transM;
    554     transM.setTranslate(-boundRect.fLeft, -boundRect.fTop);
    555     target->postConcatViewMatrix(transM);
    556     GrMatrix scaleM;
    557     scaleM.setScale(scale * GR_Scalar1, scale * GR_Scalar1);
    558     target->postConcatViewMatrix(scaleM);
    559 
    560     // clip gets applied in second pass
    561     target->disableState(GrDrawTarget::kClip_StateBit);
    562 
    563     GrIRect clear = SkIRect::MakeWH(scale * boundW, scale * boundH);
    564     target->clear(&clear, 0x0);
    565 
    566     return true;
    567 }
    568 
    569 void GrContext::offscreenAAPass2(GrDrawTarget* target,
    570                                  const GrPaint& paint,
    571                                  const GrIRect& boundRect,
    572                                  OffscreenRecord* record) {
    573 
    574     GrAssert(NULL != record->fEntry0);
    575 
    576     GrSamplerState::Filter filter;
    577     if (OffscreenRecord::k4x4SinglePass_Downsample == record->fDownsample) {
    578         filter = GrSamplerState::k4x4Downsample_Filter;
    579     } else {
    580         filter = GrSamplerState::kBilinear_Filter;
    581     }
    582 
    583     GrMatrix sampleM;
    584     GrSamplerState sampler(GrSamplerState::kClamp_WrapMode,
    585                            GrSamplerState::kClamp_WrapMode, filter);
    586 
    587     GrTexture* src = record->fEntry0->texture();
    588     int scale;
    589 
    590     enum {
    591         kOffscreenStage = GrPaint::kTotalStages,
    592     };
    593 
    594     if (OffscreenRecord::k4x4TwoPass_Downsample == record->fDownsample) {
    595         GrAssert(NULL != record->fEntry1);
    596         scale = 2;
    597         GrRenderTarget* dst = record->fEntry1->texture()->asRenderTarget();
    598 
    599         // Do 2x2 downsample from first to second
    600         target->setTexture(kOffscreenStage, src);
    601         target->setRenderTarget(dst);
    602         target->setViewMatrix(GrMatrix::I());
    603         sampleM.setScale(scale * GR_Scalar1 / src->width(),
    604                          scale * GR_Scalar1 / src->height());
    605         sampler.setMatrix(sampleM);
    606         target->setSamplerState(kOffscreenStage, sampler);
    607         GrRect rect = SkRect::MakeWH(scale * boundRect.width(),
    608                                      scale * boundRect.height());
    609         target->drawSimpleRect(rect, NULL, 1 << kOffscreenStage);
    610 
    611         src = record->fEntry1->texture();
    612     } else if (OffscreenRecord::kFSAA_Downsample == record->fDownsample) {
    613         scale = 1;
    614         GrIRect rect = SkIRect::MakeWH(boundRect.width(), boundRect.height());
    615         src->asRenderTarget()->overrideResolveRect(rect);
    616     } else {
    617         GrAssert(OffscreenRecord::k4x4SinglePass_Downsample ==
    618                  record->fDownsample);
    619         scale = 4;
    620     }
    621 
    622     // setup for draw back to main RT
    623     int stageMask = paint.getActiveStageMask();
    624 
    625     target->restoreDrawState(record->fSavedState);
    626 
    627     if (stageMask) {
    628         GrMatrix invVM;
    629         if (target->getViewInverse(&invVM)) {
    630             target->preConcatSamplerMatrices(stageMask, invVM);
    631         }
    632     }
    633     target->setViewMatrix(GrMatrix::I());
    634 
    635     target->setTexture(kOffscreenStage, src);
    636     sampleM.setScale(scale * GR_Scalar1 / src->width(),
    637                      scale * GR_Scalar1 / src->height());
    638     sampler.setMatrix(sampleM);
    639     sampleM.setTranslate(-boundRect.fLeft, -boundRect.fTop);
    640     sampler.preConcatMatrix(sampleM);
    641     target->setSamplerState(kOffscreenStage, sampler);
    642 
    643     GrRect dstRect;
    644     int stages = (1 << kOffscreenStage) | stageMask;
    645     dstRect.set(boundRect);
    646     target->drawSimpleRect(dstRect, NULL, stages);
    647 
    648     this->unlockTexture(record->fEntry0);
    649     record->fEntry0 = NULL;
    650     if (NULL != record->fEntry1) {
    651         this->unlockTexture(record->fEntry1);
    652         record->fEntry1 = NULL;
    653     }
    654     target->restoreDrawState(record->fSavedState);
    655 }
    656 
    657 ////////////////////////////////////////////////////////////////////////////////
    658 
    659 /*  create a triangle strip that strokes the specified triangle. There are 8
    660  unique vertices, but we repreat the last 2 to close up. Alternatively we
    661  could use an indices array, and then only send 8 verts, but not sure that
    662  would be faster.
    663  */
    664 static void setStrokeRectStrip(GrPoint verts[10], GrRect rect,
    665                                GrScalar width) {
    666     const GrScalar rad = GrScalarHalf(width);
    667     rect.sort();
    668 
    669     verts[0].set(rect.fLeft + rad, rect.fTop + rad);
    670     verts[1].set(rect.fLeft - rad, rect.fTop - rad);
    671     verts[2].set(rect.fRight - rad, rect.fTop + rad);
    672     verts[3].set(rect.fRight + rad, rect.fTop - rad);
    673     verts[4].set(rect.fRight - rad, rect.fBottom - rad);
    674     verts[5].set(rect.fRight + rad, rect.fBottom + rad);
    675     verts[6].set(rect.fLeft + rad, rect.fBottom - rad);
    676     verts[7].set(rect.fLeft - rad, rect.fBottom + rad);
    677     verts[8] = verts[0];
    678     verts[9] = verts[1];
    679 }
    680 
    681 static GrColor getColorForMesh(const GrPaint& paint) {
    682     // FIXME: This was copied from SkGpuDevice, seems like
    683     // we should have already smeared a in caller if that
    684     // is what is desired.
    685     if (paint.hasTexture()) {
    686         unsigned a = GrColorUnpackA(paint.fColor);
    687         return GrColorPackRGBA(a, a, a, a);
    688     } else {
    689         return paint.fColor;
    690     }
    691 }
    692 
    693 static void setInsetFan(GrPoint* pts, size_t stride,
    694                         const GrRect& r, GrScalar dx, GrScalar dy) {
    695     pts->setRectFan(r.fLeft + dx, r.fTop + dy, r.fRight - dx, r.fBottom - dy, stride);
    696 }
    697 
    698 static const uint16_t gFillAARectIdx[] = {
    699     0, 1, 5, 5, 4, 0,
    700     1, 2, 6, 6, 5, 1,
    701     2, 3, 7, 7, 6, 2,
    702     3, 0, 4, 4, 7, 3,
    703     4, 5, 6, 6, 7, 4,
    704 };
    705 
    706 int GrContext::aaFillRectIndexCount() const {
    707     return GR_ARRAY_COUNT(gFillAARectIdx);
    708 }
    709 
    710 GrIndexBuffer* GrContext::aaFillRectIndexBuffer() {
    711     if (NULL == fAAFillRectIndexBuffer) {
    712         fAAFillRectIndexBuffer = fGpu->createIndexBuffer(sizeof(gFillAARectIdx),
    713                                                          false);
    714         GrAssert(NULL != fAAFillRectIndexBuffer);
    715 #if GR_DEBUG
    716         bool updated =
    717 #endif
    718         fAAFillRectIndexBuffer->updateData(gFillAARectIdx,
    719                                            sizeof(gFillAARectIdx));
    720         GR_DEBUGASSERT(updated);
    721     }
    722     return fAAFillRectIndexBuffer;
    723 }
    724 
    725 static const uint16_t gStrokeAARectIdx[] = {
    726     0 + 0, 1 + 0, 5 + 0, 5 + 0, 4 + 0, 0 + 0,
    727     1 + 0, 2 + 0, 6 + 0, 6 + 0, 5 + 0, 1 + 0,
    728     2 + 0, 3 + 0, 7 + 0, 7 + 0, 6 + 0, 2 + 0,
    729     3 + 0, 0 + 0, 4 + 0, 4 + 0, 7 + 0, 3 + 0,
    730 
    731     0 + 4, 1 + 4, 5 + 4, 5 + 4, 4 + 4, 0 + 4,
    732     1 + 4, 2 + 4, 6 + 4, 6 + 4, 5 + 4, 1 + 4,
    733     2 + 4, 3 + 4, 7 + 4, 7 + 4, 6 + 4, 2 + 4,
    734     3 + 4, 0 + 4, 4 + 4, 4 + 4, 7 + 4, 3 + 4,
    735 
    736     0 + 8, 1 + 8, 5 + 8, 5 + 8, 4 + 8, 0 + 8,
    737     1 + 8, 2 + 8, 6 + 8, 6 + 8, 5 + 8, 1 + 8,
    738     2 + 8, 3 + 8, 7 + 8, 7 + 8, 6 + 8, 2 + 8,
    739     3 + 8, 0 + 8, 4 + 8, 4 + 8, 7 + 8, 3 + 8,
    740 };
    741 
    742 int GrContext::aaStrokeRectIndexCount() const {
    743     return GR_ARRAY_COUNT(gStrokeAARectIdx);
    744 }
    745 
    746 GrIndexBuffer* GrContext::aaStrokeRectIndexBuffer() {
    747     if (NULL == fAAStrokeRectIndexBuffer) {
    748         fAAStrokeRectIndexBuffer = fGpu->createIndexBuffer(sizeof(gStrokeAARectIdx),
    749                                                            false);
    750         GrAssert(NULL != fAAStrokeRectIndexBuffer);
    751 #if GR_DEBUG
    752         bool updated =
    753 #endif
    754         fAAStrokeRectIndexBuffer->updateData(gStrokeAARectIdx,
    755                                              sizeof(gStrokeAARectIdx));
    756         GR_DEBUGASSERT(updated);
    757     }
    758     return fAAStrokeRectIndexBuffer;
    759 }
    760 
    761 void GrContext::fillAARect(GrDrawTarget* target,
    762                            const GrPaint& paint,
    763                            const GrRect& devRect) {
    764 
    765     GrVertexLayout layout = PaintStageVertexLayoutBits(paint, NULL) |
    766                             GrDrawTarget::kColor_VertexLayoutBit;
    767 
    768     size_t vsize = GrDrawTarget::VertexSize(layout);
    769 
    770     GrDrawTarget::AutoReleaseGeometry geo(target, layout, 8, 0);
    771 
    772     intptr_t verts = reinterpret_cast<intptr_t>(geo.vertices());
    773 
    774     GrPoint* fan0Pos = reinterpret_cast<GrPoint*>(verts);
    775     GrPoint* fan1Pos = reinterpret_cast<GrPoint*>(verts + 4 * vsize);
    776 
    777     setInsetFan(fan0Pos, vsize, devRect, -GR_ScalarHalf, -GR_ScalarHalf);
    778     setInsetFan(fan1Pos, vsize, devRect,  GR_ScalarHalf,  GR_ScalarHalf);
    779 
    780     verts += sizeof(GrPoint);
    781     for (int i = 0; i < 4; ++i) {
    782         *reinterpret_cast<GrColor*>(verts + i * vsize) = 0;
    783     }
    784 
    785     GrColor innerColor = getColorForMesh(paint);
    786     verts += 4 * vsize;
    787     for (int i = 0; i < 4; ++i) {
    788         *reinterpret_cast<GrColor*>(verts + i * vsize) = innerColor;
    789     }
    790 
    791     target->setIndexSourceToBuffer(this->aaFillRectIndexBuffer());
    792 
    793     target->drawIndexed(kTriangles_PrimitiveType, 0,
    794                          0, 8, this->aaFillRectIndexCount());
    795 }
    796 
    797 void GrContext::strokeAARect(GrDrawTarget* target, const GrPaint& paint,
    798                              const GrRect& devRect, const GrVec& devStrokeSize) {
    799     const GrScalar& dx = devStrokeSize.fX;
    800     const GrScalar& dy = devStrokeSize.fY;
    801     const GrScalar rx = GrMul(dx, GR_ScalarHalf);
    802     const GrScalar ry = GrMul(dy, GR_ScalarHalf);
    803 
    804     GrVertexLayout layout = PaintStageVertexLayoutBits(paint, NULL) |
    805                             GrDrawTarget::kColor_VertexLayoutBit;
    806 
    807     GrScalar spare;
    808     {
    809         GrScalar w = devRect.width() - dx;
    810         GrScalar h = devRect.height() - dy;
    811         spare = GrMin(w, h);
    812     }
    813 
    814     if (spare <= 0) {
    815         GrRect r(devRect);
    816         r.inset(-rx, -ry);
    817         fillAARect(target, paint, r);
    818         return;
    819     }
    820 
    821     size_t vsize = GrDrawTarget::VertexSize(layout);
    822 
    823     GrDrawTarget::AutoReleaseGeometry geo(target, layout, 16, 0);
    824 
    825     intptr_t verts = reinterpret_cast<intptr_t>(geo.vertices());
    826 
    827     GrPoint* fan0Pos = reinterpret_cast<GrPoint*>(verts);
    828     GrPoint* fan1Pos = reinterpret_cast<GrPoint*>(verts + 4 * vsize);
    829     GrPoint* fan2Pos = reinterpret_cast<GrPoint*>(verts + 8 * vsize);
    830     GrPoint* fan3Pos = reinterpret_cast<GrPoint*>(verts + 12 * vsize);
    831 
    832     setInsetFan(fan0Pos, vsize, devRect, -rx - GR_ScalarHalf, -ry - GR_ScalarHalf);
    833     setInsetFan(fan1Pos, vsize, devRect, -rx + GR_ScalarHalf, -ry + GR_ScalarHalf);
    834     setInsetFan(fan2Pos, vsize, devRect,  rx - GR_ScalarHalf,  ry - GR_ScalarHalf);
    835     setInsetFan(fan3Pos, vsize, devRect,  rx + GR_ScalarHalf,  ry + GR_ScalarHalf);
    836 
    837     verts += sizeof(GrPoint);
    838     for (int i = 0; i < 4; ++i) {
    839         *reinterpret_cast<GrColor*>(verts + i * vsize) = 0;
    840     }
    841 
    842     GrColor innerColor = getColorForMesh(paint);
    843     verts += 4 * vsize;
    844     for (int i = 0; i < 8; ++i) {
    845         *reinterpret_cast<GrColor*>(verts + i * vsize) = innerColor;
    846     }
    847 
    848     verts += 8 * vsize;
    849     for (int i = 0; i < 8; ++i) {
    850         *reinterpret_cast<GrColor*>(verts + i * vsize) = 0;
    851     }
    852 
    853     target->setIndexSourceToBuffer(aaStrokeRectIndexBuffer());
    854     target->drawIndexed(kTriangles_PrimitiveType,
    855                         0, 0, 16, aaStrokeRectIndexCount());
    856 }
    857 
    858 /**
    859  * Returns true if the rects edges are integer-aligned.
    860  */
    861 static bool isIRect(const GrRect& r) {
    862     return GrScalarIsInt(r.fLeft) && GrScalarIsInt(r.fTop) &&
    863            GrScalarIsInt(r.fRight) && GrScalarIsInt(r.fBottom);
    864 }
    865 
    866 static bool apply_aa_to_rect(GrDrawTarget* target,
    867                              GrGpu* gpu,
    868                              const GrPaint& paint,
    869                              const GrRect& rect,
    870                              GrScalar width,
    871                              const GrMatrix* matrix,
    872                              GrMatrix* combinedMatrix,
    873                              GrRect* devRect) {
    874     // we use a simple alpha ramp to do aa on axis-aligned rects
    875     // do AA with alpha ramp if the caller requested AA, the rect
    876     // will be axis-aligned,the render target is not
    877     // multisampled, and the rect won't land on integer coords.
    878 
    879     if (!paint.fAntiAlias) {
    880         return false;
    881     }
    882 
    883     if (target->getRenderTarget()->isMultisampled()) {
    884         return false;
    885     }
    886 
    887     if (0 == width && gpu->supportsAALines()) {
    888         return false;
    889     }
    890 
    891     if (!target->getViewMatrix().preservesAxisAlignment()) {
    892         return false;
    893     }
    894 
    895     if (NULL != matrix &&
    896         !matrix->preservesAxisAlignment()) {
    897         return false;
    898     }
    899 
    900     *combinedMatrix = target->getViewMatrix();
    901     if (NULL != matrix) {
    902         combinedMatrix->preConcat(*matrix);
    903         GrAssert(combinedMatrix->preservesAxisAlignment());
    904     }
    905 
    906     combinedMatrix->mapRect(devRect, rect);
    907     devRect->sort();
    908 
    909     if (width < 0) {
    910         return !isIRect(*devRect);
    911     } else {
    912         return true;
    913     }
    914 }
    915 
    916 void GrContext::drawRect(const GrPaint& paint,
    917                          const GrRect& rect,
    918                          GrScalar width,
    919                          const GrMatrix* matrix) {
    920 
    921 
    922     GrDrawTarget* target = this->prepareToDraw(paint, kUnbuffered_DrawCategory);
    923     int stageMask = paint.getActiveStageMask();
    924 
    925     GrRect devRect = rect;
    926     GrMatrix combinedMatrix;
    927     bool doAA = apply_aa_to_rect(target, fGpu, paint, rect, width, matrix,
    928                                  &combinedMatrix, &devRect);
    929 
    930     if (doAA) {
    931         GrDrawTarget::AutoViewMatrixRestore avm(target);
    932         if (stageMask) {
    933             GrMatrix inv;
    934             if (combinedMatrix.invert(&inv)) {
    935                 target->preConcatSamplerMatrices(stageMask, inv);
    936             }
    937         }
    938         target->setViewMatrix(GrMatrix::I());
    939         if (width >= 0) {
    940             GrVec strokeSize;;
    941             if (width > 0) {
    942                 strokeSize.set(width, width);
    943                 combinedMatrix.mapVectors(&strokeSize, 1);
    944                 strokeSize.setAbs(strokeSize);
    945             } else {
    946                 strokeSize.set(GR_Scalar1, GR_Scalar1);
    947             }
    948             strokeAARect(target, paint, devRect, strokeSize);
    949         } else {
    950             fillAARect(target, paint, devRect);
    951         }
    952         return;
    953     }
    954 
    955     if (width >= 0) {
    956         // TODO: consider making static vertex buffers for these cases.
    957         // Hairline could be done by just adding closing vertex to
    958         // unitSquareVertexBuffer()
    959         GrVertexLayout layout =  PaintStageVertexLayoutBits(paint, NULL);
    960 
    961         static const int worstCaseVertCount = 10;
    962         GrDrawTarget::AutoReleaseGeometry geo(target, layout, worstCaseVertCount, 0);
    963 
    964         if (!geo.succeeded()) {
    965             return;
    966         }
    967 
    968         GrPrimitiveType primType;
    969         int vertCount;
    970         GrPoint* vertex = geo.positions();
    971 
    972         if (width > 0) {
    973             vertCount = 10;
    974             primType = kTriangleStrip_PrimitiveType;
    975             setStrokeRectStrip(vertex, rect, width);
    976         } else {
    977             // hairline
    978             vertCount = 5;
    979             primType = kLineStrip_PrimitiveType;
    980             vertex[0].set(rect.fLeft, rect.fTop);
    981             vertex[1].set(rect.fRight, rect.fTop);
    982             vertex[2].set(rect.fRight, rect.fBottom);
    983             vertex[3].set(rect.fLeft, rect.fBottom);
    984             vertex[4].set(rect.fLeft, rect.fTop);
    985         }
    986 
    987         GrDrawTarget::AutoViewMatrixRestore avmr;
    988         if (NULL != matrix) {
    989             avmr.set(target);
    990             target->preConcatViewMatrix(*matrix);
    991             target->preConcatSamplerMatrices(stageMask, *matrix);
    992         }
    993 
    994         target->drawNonIndexed(primType, 0, vertCount);
    995     } else {
    996         #if GR_STATIC_RECT_VB
    997             GrVertexLayout layout = PaintStageVertexLayoutBits(paint, NULL);
    998 
    999             target->setVertexSourceToBuffer(layout,
   1000                                             fGpu->getUnitSquareVertexBuffer());
   1001             GrDrawTarget::AutoViewMatrixRestore avmr(target);
   1002             GrMatrix m;
   1003             m.setAll(rect.width(),    0,             rect.fLeft,
   1004                         0,            rect.height(), rect.fTop,
   1005                         0,            0,             GrMatrix::I()[8]);
   1006 
   1007             if (NULL != matrix) {
   1008                 m.postConcat(*matrix);
   1009             }
   1010 
   1011             target->preConcatViewMatrix(m);
   1012             target->preConcatSamplerMatrices(stageMask, m);
   1013 
   1014             target->drawNonIndexed(kTriangleFan_PrimitiveType, 0, 4);
   1015         #else
   1016             target->drawSimpleRect(rect, matrix, stageMask);
   1017         #endif
   1018     }
   1019 }
   1020 
   1021 void GrContext::drawRectToRect(const GrPaint& paint,
   1022                                const GrRect& dstRect,
   1023                                const GrRect& srcRect,
   1024                                const GrMatrix* dstMatrix,
   1025                                const GrMatrix* srcMatrix) {
   1026 
   1027     // srcRect refers to paint's first texture
   1028     if (NULL == paint.getTexture(0)) {
   1029         drawRect(paint, dstRect, -1, dstMatrix);
   1030         return;
   1031     }
   1032 
   1033     GR_STATIC_ASSERT(!BATCH_RECT_TO_RECT || !GR_STATIC_RECT_VB);
   1034 
   1035 #if GR_STATIC_RECT_VB
   1036     GrDrawTarget* target = this->prepareToDraw(paint, kUnbuffered_DrawCategory);
   1037 
   1038     GrVertexLayout layout = PaintStageVertexLayoutBits(paint, NULL);
   1039     GrDrawTarget::AutoViewMatrixRestore avmr(target);
   1040 
   1041     GrMatrix m;
   1042 
   1043     m.setAll(dstRect.width(), 0,                dstRect.fLeft,
   1044              0,               dstRect.height(), dstRect.fTop,
   1045              0,               0,                GrMatrix::I()[8]);
   1046     if (NULL != dstMatrix) {
   1047         m.postConcat(*dstMatrix);
   1048     }
   1049     target->preConcatViewMatrix(m);
   1050 
   1051     // srcRect refers to first stage
   1052     int otherStageMask = paint.getActiveStageMask() &
   1053                          (~(1 << GrPaint::kFirstTextureStage));
   1054     if (otherStageMask) {
   1055         target->preConcatSamplerMatrices(otherStageMask, m);
   1056     }
   1057 
   1058     m.setAll(srcRect.width(), 0,                srcRect.fLeft,
   1059              0,               srcRect.height(), srcRect.fTop,
   1060              0,               0,                GrMatrix::I()[8]);
   1061     if (NULL != srcMatrix) {
   1062         m.postConcat(*srcMatrix);
   1063     }
   1064     target->preConcatSamplerMatrix(GrPaint::kFirstTextureStage, m);
   1065 
   1066     target->setVertexSourceToBuffer(layout, fGpu->getUnitSquareVertexBuffer());
   1067     target->drawNonIndexed(kTriangleFan_PrimitiveType, 0, 4);
   1068 #else
   1069 
   1070     GrDrawTarget* target;
   1071 #if BATCH_RECT_TO_RECT
   1072     target = this->prepareToDraw(paint, kBuffered_DrawCategory);
   1073 #else
   1074     target = this->prepareToDraw(paint, kUnbuffered_DrawCategory);
   1075 #endif
   1076 
   1077     const GrRect* srcRects[GrDrawTarget::kNumStages] = {NULL};
   1078     const GrMatrix* srcMatrices[GrDrawTarget::kNumStages] = {NULL};
   1079     srcRects[0] = &srcRect;
   1080     srcMatrices[0] = srcMatrix;
   1081 
   1082     target->drawRect(dstRect, dstMatrix, 1, srcRects, srcMatrices);
   1083 #endif
   1084 }
   1085 
   1086 void GrContext::drawVertices(const GrPaint& paint,
   1087                              GrPrimitiveType primitiveType,
   1088                              int vertexCount,
   1089                              const GrPoint positions[],
   1090                              const GrPoint texCoords[],
   1091                              const GrColor colors[],
   1092                              const uint16_t indices[],
   1093                              int indexCount) {
   1094 
   1095     GrDrawTarget::AutoReleaseGeometry geo;
   1096 
   1097     GrDrawTarget* target = this->prepareToDraw(paint, kUnbuffered_DrawCategory);
   1098 
   1099     bool hasTexCoords[GrPaint::kTotalStages] = {
   1100         NULL != texCoords,   // texCoordSrc provides explicit stage 0 coords
   1101         0                    // remaining stages use positions
   1102     };
   1103 
   1104     GrVertexLayout layout = PaintStageVertexLayoutBits(paint, hasTexCoords);
   1105 
   1106     if (NULL != colors) {
   1107         layout |= GrDrawTarget::kColor_VertexLayoutBit;
   1108     }
   1109     int vertexSize = GrDrawTarget::VertexSize(layout);
   1110 
   1111     bool doAA = false;
   1112     OffscreenRecord record;
   1113     GrIRect bounds;
   1114 
   1115     if (sizeof(GrPoint) != vertexSize) {
   1116         if (!geo.set(target, layout, vertexCount, 0)) {
   1117             GrPrintf("Failed to get space for vertices!");
   1118             return;
   1119         }
   1120         int texOffsets[GrDrawTarget::kMaxTexCoords];
   1121         int colorOffset;
   1122         GrDrawTarget::VertexSizeAndOffsetsByIdx(layout,
   1123                                                 texOffsets,
   1124                                                 &colorOffset);
   1125         void* curVertex = geo.vertices();
   1126 
   1127         for (int i = 0; i < vertexCount; ++i) {
   1128             *((GrPoint*)curVertex) = positions[i];
   1129 
   1130             if (texOffsets[0] > 0) {
   1131                 *(GrPoint*)((intptr_t)curVertex + texOffsets[0]) = texCoords[i];
   1132             }
   1133             if (colorOffset > 0) {
   1134                 *(GrColor*)((intptr_t)curVertex + colorOffset) = colors[i];
   1135             }
   1136             curVertex = (void*)((intptr_t)curVertex + vertexSize);
   1137         }
   1138     } else {
   1139         // we don't do offscreen AA when we have per-vertex tex coords or colors
   1140         if (this->doOffscreenAA(target, paint, GrIsPrimTypeLines(primitiveType))) {
   1141             GrRect b;
   1142             b.setBounds(positions, vertexCount);
   1143             target->getViewMatrix().mapRect(&b);
   1144             b.roundOut(&bounds);
   1145 
   1146             if (this->setupOffscreenAAPass1(target, false, bounds, &record)) {
   1147                 doAA = true;
   1148             }
   1149         }
   1150         target->setVertexSourceToArray(layout, positions, vertexCount);
   1151     }
   1152 
   1153     if (NULL != indices) {
   1154         target->setIndexSourceToArray(indices, indexCount);
   1155     }
   1156 
   1157     if (NULL != indices) {
   1158         target->drawIndexed(primitiveType, 0, 0, vertexCount, indexCount);
   1159     } else {
   1160         target->drawNonIndexed(primitiveType, 0, vertexCount);
   1161     }
   1162 
   1163     if (doAA) {
   1164         this->offscreenAAPass2(target, paint, bounds, &record);
   1165     }
   1166 }
   1167 
   1168 
   1169 ///////////////////////////////////////////////////////////////////////////////
   1170 
   1171 void GrContext::drawPath(const GrPaint& paint, const GrPath& path,
   1172                          GrPathFill fill, const GrPoint* translate) {
   1173 
   1174     GrDrawTarget* target = this->prepareToDraw(paint, kUnbuffered_DrawCategory);
   1175     GrPathRenderer* pr = this->getPathRenderer(target, path, fill);
   1176 
   1177     if (!IsFillInverted(fill) && // will be relaxed soon
   1178         !pr->supportsAA(target, path, fill) &&
   1179         this->doOffscreenAA(target, paint, kHairLine_PathFill == fill)) {
   1180 
   1181         OffscreenRecord record;
   1182         bool needsStencil = pr->requiresStencilPass(target, path, fill);
   1183 
   1184         // compute bounds as intersection of rt size, clip, and path
   1185         GrIRect bound = SkIRect::MakeWH(target->getRenderTarget()->width(),
   1186                                         target->getRenderTarget()->height());
   1187         if (target->getClip().hasConservativeBounds()) {
   1188             GrIRect clipIBounds;
   1189             target->getClip().getConservativeBounds().roundOut(&clipIBounds);
   1190             if (!bound.intersect(clipIBounds)) {
   1191                 return;
   1192             }
   1193         }
   1194 
   1195         GrRect pathBounds = path.getBounds();
   1196         GrIRect pathIBounds;
   1197         if (!pathBounds.isEmpty()) {
   1198             if (NULL != translate) {
   1199                 pathBounds.offset(*translate);
   1200             }
   1201             target->getViewMatrix().mapRect(&pathBounds, pathBounds);
   1202             pathBounds.roundOut(&pathIBounds);
   1203             if (!bound.intersect(pathIBounds)) {
   1204                 return;
   1205             }
   1206         }
   1207 
   1208         // for now, abort antialiasing if our bounds are too big, so we don't
   1209         // hit the FBO size limit
   1210         if (pathIBounds.width() > GR_MAX_OFFSCREEN_AA_DIM ||
   1211             pathIBounds.height() > GR_MAX_OFFSCREEN_AA_DIM) {
   1212             goto NO_AA;
   1213         }
   1214 
   1215         if (this->setupOffscreenAAPass1(target, needsStencil, bound, &record)) {
   1216             pr->drawPath(target, 0, path, fill, translate);
   1217             this->offscreenAAPass2(target, paint, bound, &record);
   1218             return;
   1219         }
   1220     }
   1221 
   1222 // we can fall out of the AA section for some reasons, and land here
   1223 NO_AA:
   1224     GrDrawTarget::StageBitfield enabledStages = paint.getActiveStageMask();
   1225 
   1226     pr->drawPath(target, enabledStages, path, fill, translate);
   1227 }
   1228 
   1229 ////////////////////////////////////////////////////////////////////////////////
   1230 
   1231 void GrContext::flush(int flagsBitfield) {
   1232     if (kDiscard_FlushBit & flagsBitfield) {
   1233         fDrawBuffer->reset();
   1234     } else {
   1235         flushDrawBuffer();
   1236     }
   1237 
   1238     if (kForceCurrentRenderTarget_FlushBit & flagsBitfield) {
   1239         fGpu->forceRenderTargetFlush();
   1240     }
   1241 }
   1242 
   1243 void GrContext::flushText() {
   1244     if (kText_DrawCategory == fLastDrawCategory) {
   1245         flushDrawBuffer();
   1246     }
   1247 }
   1248 
   1249 void GrContext::flushDrawBuffer() {
   1250 #if BATCH_RECT_TO_RECT || DEFER_TEXT_RENDERING
   1251     if (fDrawBuffer) {
   1252         fDrawBuffer->playback(fGpu);
   1253         fDrawBuffer->reset();
   1254     }
   1255 #endif
   1256 }
   1257 
   1258 bool GrContext::readTexturePixels(GrTexture* texture,
   1259                                   int left, int top, int width, int height,
   1260                                   GrPixelConfig config, void* buffer) {
   1261 
   1262     // TODO: code read pixels for textures that aren't rendertargets
   1263 
   1264     this->flush();
   1265     GrRenderTarget* target = texture->asRenderTarget();
   1266     if (NULL != target) {
   1267         return fGpu->readPixels(target,
   1268                                 left, top, width, height,
   1269                                 config, buffer);
   1270     } else {
   1271         return false;
   1272     }
   1273 }
   1274 
   1275 bool GrContext::readRenderTargetPixels(GrRenderTarget* target,
   1276                                       int left, int top, int width, int height,
   1277                                       GrPixelConfig config, void* buffer) {
   1278     uint32_t flushFlags = 0;
   1279     if (NULL == target) {
   1280         flushFlags |= GrContext::kForceCurrentRenderTarget_FlushBit;
   1281     }
   1282 
   1283     this->flush(flushFlags);
   1284     return fGpu->readPixels(target,
   1285                             left, top, width, height,
   1286                             config, buffer);
   1287 }
   1288 
   1289 void GrContext::writePixels(int left, int top, int width, int height,
   1290                             GrPixelConfig config, const void* buffer,
   1291                             size_t stride) {
   1292 
   1293     // TODO: when underlying api has a direct way to do this we should use it
   1294     // (e.g. glDrawPixels on desktop GL).
   1295 
   1296     const GrTextureDesc desc = {
   1297         kNone_GrTextureFlags, kNone_GrAALevel, width, height, config
   1298     };
   1299     GrTexture* texture = fGpu->createTexture(desc, buffer, stride);
   1300     if (NULL == texture) {
   1301         return;
   1302     }
   1303 
   1304     this->flush(true);
   1305 
   1306     GrAutoUnref                     aur(texture);
   1307     GrDrawTarget::AutoStateRestore  asr(fGpu);
   1308 
   1309     GrMatrix matrix;
   1310     matrix.setTranslate(GrIntToScalar(left), GrIntToScalar(top));
   1311     fGpu->setViewMatrix(matrix);
   1312 
   1313     fGpu->setColorFilter(0, SkXfermode::kDst_Mode);
   1314     fGpu->disableState(GrDrawTarget::kClip_StateBit);
   1315     fGpu->setAlpha(0xFF);
   1316     fGpu->setBlendFunc(kOne_BlendCoeff,
   1317                        kZero_BlendCoeff);
   1318     fGpu->setTexture(0, texture);
   1319 
   1320     GrSamplerState sampler;
   1321     sampler.setClampNoFilter();
   1322     matrix.setScale(GR_Scalar1 / width, GR_Scalar1 / height);
   1323     sampler.setMatrix(matrix);
   1324     fGpu->setSamplerState(0, sampler);
   1325 
   1326     GrVertexLayout layout = GrDrawTarget::StagePosAsTexCoordVertexLayoutBit(0);
   1327     static const int VCOUNT = 4;
   1328 
   1329     GrDrawTarget::AutoReleaseGeometry geo(fGpu, layout, VCOUNT, 0);
   1330     if (!geo.succeeded()) {
   1331         return;
   1332     }
   1333     ((GrPoint*)geo.vertices())->setIRectFan(0, 0, width, height);
   1334     fGpu->drawNonIndexed(kTriangleFan_PrimitiveType, 0, VCOUNT);
   1335 }
   1336 ////////////////////////////////////////////////////////////////////////////////
   1337 
   1338 void GrContext::SetPaint(const GrPaint& paint, GrDrawTarget* target) {
   1339 
   1340     for (int i = 0; i < GrPaint::kMaxTextures; ++i) {
   1341         int s = i + GrPaint::kFirstTextureStage;
   1342         target->setTexture(s, paint.getTexture(i));
   1343         target->setSamplerState(s, *paint.getTextureSampler(i));
   1344     }
   1345 
   1346     target->setFirstCoverageStage(GrPaint::kFirstMaskStage);
   1347 
   1348     for (int i = 0; i < GrPaint::kMaxMasks; ++i) {
   1349         int s = i + GrPaint::kFirstMaskStage;
   1350         target->setTexture(s, paint.getMask(i));
   1351         target->setSamplerState(s, *paint.getMaskSampler(i));
   1352     }
   1353 
   1354     target->setColor(paint.fColor);
   1355 
   1356     if (paint.fDither) {
   1357         target->enableState(GrDrawTarget::kDither_StateBit);
   1358     } else {
   1359         target->disableState(GrDrawTarget::kDither_StateBit);
   1360     }
   1361     if (paint.fAntiAlias) {
   1362         target->enableState(GrDrawTarget::kAntialias_StateBit);
   1363     } else {
   1364         target->disableState(GrDrawTarget::kAntialias_StateBit);
   1365     }
   1366     target->setBlendFunc(paint.fSrcBlendCoeff, paint.fDstBlendCoeff);
   1367     target->setColorFilter(paint.fColorFilterColor, paint.fColorFilterXfermode);
   1368 }
   1369 
   1370 GrDrawTarget* GrContext::prepareToDraw(const GrPaint& paint,
   1371                                        DrawCategory category) {
   1372     if (category != fLastDrawCategory) {
   1373         flushDrawBuffer();
   1374         fLastDrawCategory = category;
   1375     }
   1376     SetPaint(paint, fGpu);
   1377     GrDrawTarget* target = fGpu;
   1378     switch (category) {
   1379     case kText_DrawCategory:
   1380 #if DEFER_TEXT_RENDERING
   1381         target = fDrawBuffer;
   1382         fDrawBuffer->initializeDrawStateAndClip(*fGpu);
   1383 #else
   1384         target = fGpu;
   1385 #endif
   1386         break;
   1387     case kUnbuffered_DrawCategory:
   1388         target = fGpu;
   1389         break;
   1390     case kBuffered_DrawCategory:
   1391         target = fDrawBuffer;
   1392         fDrawBuffer->initializeDrawStateAndClip(*fGpu);
   1393         break;
   1394     }
   1395     return target;
   1396 }
   1397 
   1398 ////////////////////////////////////////////////////////////////////////////////
   1399 
   1400 void GrContext::setRenderTarget(GrRenderTarget* target) {
   1401     this->flush(false);
   1402     fGpu->setRenderTarget(target);
   1403 }
   1404 
   1405 GrRenderTarget* GrContext::getRenderTarget() {
   1406     return fGpu->getRenderTarget();
   1407 }
   1408 
   1409 const GrRenderTarget* GrContext::getRenderTarget() const {
   1410     return fGpu->getRenderTarget();
   1411 }
   1412 
   1413 const GrMatrix& GrContext::getMatrix() const {
   1414     return fGpu->getViewMatrix();
   1415 }
   1416 
   1417 void GrContext::setMatrix(const GrMatrix& m) {
   1418     fGpu->setViewMatrix(m);
   1419 }
   1420 
   1421 void GrContext::concatMatrix(const GrMatrix& m) const {
   1422     fGpu->preConcatViewMatrix(m);
   1423 }
   1424 
   1425 static inline intptr_t setOrClear(intptr_t bits, int shift, intptr_t pred) {
   1426     intptr_t mask = 1 << shift;
   1427     if (pred) {
   1428         bits |= mask;
   1429     } else {
   1430         bits &= ~mask;
   1431     }
   1432     return bits;
   1433 }
   1434 
   1435 void GrContext::resetStats() {
   1436     fGpu->resetStats();
   1437 }
   1438 
   1439 const GrGpuStats& GrContext::getStats() const {
   1440     return fGpu->getStats();
   1441 }
   1442 
   1443 void GrContext::printStats() const {
   1444     fGpu->printStats();
   1445 }
   1446 
   1447 GrContext::GrContext(GrGpu* gpu) :
   1448     fDefaultPathRenderer(gpu->supportsTwoSidedStencil(),
   1449                          gpu->supportsStencilWrapOps()) {
   1450 
   1451     fGpu = gpu;
   1452     fGpu->ref();
   1453     fGpu->setContext(this);
   1454 
   1455     fCustomPathRenderer = GrPathRenderer::CreatePathRenderer();
   1456     fGpu->setClipPathRenderer(fCustomPathRenderer);
   1457 
   1458     fTextureCache = new GrTextureCache(MAX_TEXTURE_CACHE_COUNT,
   1459                                        MAX_TEXTURE_CACHE_BYTES);
   1460     fFontCache = new GrFontCache(fGpu);
   1461 
   1462     fLastDrawCategory = kUnbuffered_DrawCategory;
   1463 
   1464     fDrawBuffer = NULL;
   1465     fDrawBufferVBAllocPool = NULL;
   1466     fDrawBufferIBAllocPool = NULL;
   1467 
   1468     fAAFillRectIndexBuffer = NULL;
   1469     fAAStrokeRectIndexBuffer = NULL;
   1470 
   1471     this->setupDrawBuffer();
   1472 }
   1473 
   1474 void GrContext::setupDrawBuffer() {
   1475 
   1476     GrAssert(NULL == fDrawBuffer);
   1477     GrAssert(NULL == fDrawBufferVBAllocPool);
   1478     GrAssert(NULL == fDrawBufferIBAllocPool);
   1479 
   1480 #if DEFER_TEXT_RENDERING || BATCH_RECT_TO_RECT
   1481     fDrawBufferVBAllocPool =
   1482         new GrVertexBufferAllocPool(fGpu, false,
   1483                                     DRAW_BUFFER_VBPOOL_BUFFER_SIZE,
   1484                                     DRAW_BUFFER_VBPOOL_PREALLOC_BUFFERS);
   1485     fDrawBufferIBAllocPool =
   1486         new GrIndexBufferAllocPool(fGpu, false,
   1487                                    DRAW_BUFFER_IBPOOL_BUFFER_SIZE,
   1488                                    DRAW_BUFFER_IBPOOL_PREALLOC_BUFFERS);
   1489 
   1490     fDrawBuffer = new GrInOrderDrawBuffer(fDrawBufferVBAllocPool,
   1491                                           fDrawBufferIBAllocPool);
   1492 #endif
   1493 
   1494 #if BATCH_RECT_TO_RECT
   1495     fDrawBuffer->setQuadIndexBuffer(this->getQuadIndexBuffer());
   1496 #endif
   1497 }
   1498 
   1499 GrDrawTarget* GrContext::getTextTarget(const GrPaint& paint) {
   1500     GrDrawTarget* target;
   1501 #if DEFER_TEXT_RENDERING
   1502     target = prepareToDraw(paint, kText_DrawCategory);
   1503 #else
   1504     target = prepareToDraw(paint, kUnbuffered_DrawCategory);
   1505 #endif
   1506     SetPaint(paint, target);
   1507     return target;
   1508 }
   1509 
   1510 const GrIndexBuffer* GrContext::getQuadIndexBuffer() const {
   1511     return fGpu->getQuadIndexBuffer();
   1512 }
   1513 
   1514 GrPathRenderer* GrContext::getPathRenderer(const GrDrawTarget* target,
   1515                                            const GrPath& path,
   1516                                            GrPathFill fill) {
   1517     if (NULL != fCustomPathRenderer &&
   1518         fCustomPathRenderer->canDrawPath(target, path, fill)) {
   1519         return fCustomPathRenderer;
   1520     } else {
   1521         GrAssert(fDefaultPathRenderer.canDrawPath(target, path, fill));
   1522         return &fDefaultPathRenderer;
   1523     }
   1524 }
   1525 
   1526