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