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