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