13f30e3a41fc16816105e28e0d4c241eff6d391b4bsalomon@google.com
23f30e3a41fc16816105e28e0d4c241eff6d391b4bsalomon@google.com/*
33f30e3a41fc16816105e28e0d4c241eff6d391b4bsalomon@google.com * Copyright 2011 Google Inc.
43f30e3a41fc16816105e28e0d4c241eff6d391b4bsalomon@google.com *
53f30e3a41fc16816105e28e0d4c241eff6d391b4bsalomon@google.com * Use of this source code is governed by a BSD-style license that can be
63f30e3a41fc16816105e28e0d4c241eff6d391b4bsalomon@google.com * found in the LICENSE file.
73f30e3a41fc16816105e28e0d4c241eff6d391b4bsalomon@google.com */
83f30e3a41fc16816105e28e0d4c241eff6d391b4bsalomon@google.com
93f30e3a41fc16816105e28e0d4c241eff6d391b4bsalomon@google.com
10e4339c1d8b3bdff80969624b9955e11fb6fcf0cbbsalomon@google.com#include "GrContext.h"
11e4339c1d8b3bdff80969624b9955e11fb6fcf0cbbsalomon@google.com
12848d120d9470989a611e6c1d96646d8fa0bdd3f0tomhudson@google.com#include "effects/GrSingleTextureEffect.h"
13f71764d3272e28817cb5025d2b503aa0170ef9b8bsalomon@google.com#include "effects/GrConfigConversionEffect.h"
14ffd9ba72809740cef9d8457a88a946eae3bbb7bdbsalomon@google.com
15d36b83c81d31e1cd58c737e3f7d9d1aeb18526e3jvanverth@google.com#include "GrAARectRenderer.h"
163f30e3a41fc16816105e28e0d4c241eff6d391b4bsalomon@google.com#include "GrBufferAllocPool.h"
173f30e3a41fc16816105e28e0d4c241eff6d391b4bsalomon@google.com#include "GrGpu.h"
18516b4c312ba95ab60863c325482ee6c36618f706bsalomon@google.com#include "GrDrawTargetCaps.h"
193f30e3a41fc16816105e28e0d4c241eff6d391b4bsalomon@google.com#include "GrIndexBuffer.h"
203f30e3a41fc16816105e28e0d4c241eff6d391b4bsalomon@google.com#include "GrInOrderDrawBuffer.h"
2151d94f5635c0744ef6aa4514f0055a88753acfeacommit-bot@chromium.org#include "GrOvalRenderer.h"
223f30e3a41fc16816105e28e0d4c241eff6d391b4bsalomon@google.com#include "GrPathRenderer.h"
233f30e3a41fc16816105e28e0d4c241eff6d391b4bsalomon@google.com#include "GrPathUtils.h"
243f30e3a41fc16816105e28e0d4c241eff6d391b4bsalomon@google.com#include "GrResourceCache.h"
25a1a88ae20406b1cc7eae3d64bc1788d92eaf3816robertphillips@google.com#include "GrSoftwarePathRenderer.h"
263f30e3a41fc16816105e28e0d4c241eff6d391b4bsalomon@google.com#include "GrStencilBuffer.h"
273f30e3a41fc16816105e28e0d4c241eff6d391b4bsalomon@google.com#include "GrTextStrike.h"
2849d843a911c5ad373354bbe871a75a2d1cacebbbbsalomon@google.com#include "SkRTConf.h"
294d077f56281afad5309f6b9ff951bb9d0b9f6f72commit-bot@chromium.org#include "SkRRect.h"
305c2ee5c5d8f8593d40a2a9ffd9ca834653ee6af1sugoi@google.com#include "SkStrokeRec.h"
313f30e3a41fc16816105e28e0d4c241eff6d391b4bsalomon@google.com#include "SkTLazy.h"
324e98b5f7be8218d4a93b21df06a83c74b0942b24bsalomon@google.com#include "SkTLS.h"
333f30e3a41fc16816105e28e0d4c241eff6d391b4bsalomon@google.com#include "SkTrace.h"
343f30e3a41fc16816105e28e0d4c241eff6d391b4bsalomon@google.com
3549d843a911c5ad373354bbe871a75a2d1cacebbbbsalomon@google.com// It can be useful to set this to false to test whether a bug is caused by using the
3673631cc5a64283b9ed285b40739abe9b9a039b2absalomon@google.com// InOrderDrawBuffer, to compare performance of using/not using InOrderDrawBuffer, or to make
3749d843a911c5ad373354bbe871a75a2d1cacebbbbsalomon@google.com// debugging simpler.
38d36543342d0894e354fe82caa73542bb417bcf1cbsalomon@google.comSK_CONF_DECLARE(bool, c_Defer, "gpu.deferContext", true,
39de883c44a7b53cf40b12fab49cd521dcbe18b285jvanverth@google.com                "Defers rendering in GrContext via GrInOrderDrawBuffer.");
4049d843a911c5ad373354bbe871a75a2d1cacebbbbsalomon@google.com
4149d843a911c5ad373354bbe871a75a2d1cacebbbbsalomon@google.com#define BUFFERED_DRAW (c_Defer ? kYes_BufferedDraw : kNo_BufferedDraw)
423f30e3a41fc16816105e28e0d4c241eff6d391b4bsalomon@google.com
430fde04d1de4773e5168a56dbd455b77e1424434acommit-bot@chromium.org#ifdef SK_DEBUG
44b79952d44b66f4275c23dda56cb0c4188569a90areed@google.com    // change this to a 1 to see notifications when partial coverage fails
45b79952d44b66f4275c23dda56cb0c4188569a90areed@google.com    #define GR_DEBUG_PARTIAL_COVERAGE_CHECK 0
46b79952d44b66f4275c23dda56cb0c4188569a90areed@google.com#else
47b79952d44b66f4275c23dda56cb0c4188569a90areed@google.com    #define GR_DEBUG_PARTIAL_COVERAGE_CHECK 0
48b79952d44b66f4275c23dda56cb0c4188569a90areed@google.com#endif
49b79952d44b66f4275c23dda56cb0c4188569a90areed@google.com
50428b26ff1d2e1d8a4b13e690ba693d105fb9377drobertphillips@google.comstatic const size_t MAX_RESOURCE_CACHE_COUNT = GR_DEFAULT_RESOURCE_CACHE_COUNT_LIMIT;
51428b26ff1d2e1d8a4b13e690ba693d105fb9377drobertphillips@google.comstatic const size_t MAX_RESOURCE_CACHE_BYTES = GR_DEFAULT_RESOURCE_CACHE_MB_LIMIT * 1024 * 1024;
523f30e3a41fc16816105e28e0d4c241eff6d391b4bsalomon@google.com
538c569f424e2f35dae25eaaf8f4d7bc1fb24a3893bsalomon@google.comstatic const size_t DRAW_BUFFER_VBPOOL_BUFFER_SIZE = 1 << 15;
543f30e3a41fc16816105e28e0d4c241eff6d391b4bsalomon@google.comstatic const int DRAW_BUFFER_VBPOOL_PREALLOC_BUFFERS = 4;
553f30e3a41fc16816105e28e0d4c241eff6d391b4bsalomon@google.com
5673631cc5a64283b9ed285b40739abe9b9a039b2absalomon@google.comstatic const size_t DRAW_BUFFER_IBPOOL_BUFFER_SIZE = 1 << 11;
5773631cc5a64283b9ed285b40739abe9b9a039b2absalomon@google.comstatic const int DRAW_BUFFER_IBPOOL_PREALLOC_BUFFERS = 4;
583f30e3a41fc16816105e28e0d4c241eff6d391b4bsalomon@google.com
59a91959e0e4997d3a73b38e6d7f0296c566a4b1d0tfarina@chromium.org#define ASSERT_OWNED_RESOURCE(R) SkASSERT(!(R) || (R)->getContext() == this)
60b5ed4edffdba739303dbe834644333b948ecbff9bsalomon@google.com
61860912a0affd82bc6b30ad9006658df856ca1d17bsalomon@google.com// Glorified typedef to avoid including GrDrawState.h in GrContext.h
62860912a0affd82bc6b30ad9006658df856ca1d17bsalomon@google.comclass GrContext::AutoRestoreEffects : public GrDrawState::AutoRestoreEffects {};
63860912a0affd82bc6b30ad9006658df856ca1d17bsalomon@google.com
6421c4256a8eccc702d1c4b561da1a3a3e212d3c23commit-bot@chromium.orgclass GrContext::AutoCheckFlush {
6521c4256a8eccc702d1c4b561da1a3a3e212d3c23commit-bot@chromium.orgpublic:
6621c4256a8eccc702d1c4b561da1a3a3e212d3c23commit-bot@chromium.org    AutoCheckFlush(GrContext* context) : fContext(context) { SkASSERT(NULL != context); }
6721c4256a8eccc702d1c4b561da1a3a3e212d3c23commit-bot@chromium.org
6821c4256a8eccc702d1c4b561da1a3a3e212d3c23commit-bot@chromium.org    ~AutoCheckFlush() {
6921c4256a8eccc702d1c4b561da1a3a3e212d3c23commit-bot@chromium.org        if (fContext->fFlushToReduceCacheSize) {
7021c4256a8eccc702d1c4b561da1a3a3e212d3c23commit-bot@chromium.org            fContext->flush();
7121c4256a8eccc702d1c4b561da1a3a3e212d3c23commit-bot@chromium.org        }
7221c4256a8eccc702d1c4b561da1a3a3e212d3c23commit-bot@chromium.org    }
7321c4256a8eccc702d1c4b561da1a3a3e212d3c23commit-bot@chromium.org
7421c4256a8eccc702d1c4b561da1a3a3e212d3c23commit-bot@chromium.orgprivate:
7521c4256a8eccc702d1c4b561da1a3a3e212d3c23commit-bot@chromium.org    GrContext* fContext;
7621c4256a8eccc702d1c4b561da1a3a3e212d3c23commit-bot@chromium.org};
7721c4256a8eccc702d1c4b561da1a3a3e212d3c23commit-bot@chromium.org
780ad5bd91fd7dc876326ee0832ca8f7947dc1cc24bsalomon@google.comGrContext* GrContext::Create(GrBackend backend, GrBackendContext backendContext) {
790ad5bd91fd7dc876326ee0832ca8f7947dc1cc24bsalomon@google.com    GrContext* context = SkNEW(GrContext);
800ad5bd91fd7dc876326ee0832ca8f7947dc1cc24bsalomon@google.com    if (context->init(backend, backendContext)) {
810ad5bd91fd7dc876326ee0832ca8f7947dc1cc24bsalomon@google.com        return context;
820ad5bd91fd7dc876326ee0832ca8f7947dc1cc24bsalomon@google.com    } else {
830ad5bd91fd7dc876326ee0832ca8f7947dc1cc24bsalomon@google.com        context->unref();
840ad5bd91fd7dc876326ee0832ca8f7947dc1cc24bsalomon@google.com        return NULL;
853f30e3a41fc16816105e28e0d4c241eff6d391b4bsalomon@google.com    }
863f30e3a41fc16816105e28e0d4c241eff6d391b4bsalomon@google.com}
873f30e3a41fc16816105e28e0d4c241eff6d391b4bsalomon@google.com
880ad5bd91fd7dc876326ee0832ca8f7947dc1cc24bsalomon@google.comGrContext::GrContext() {
890ad5bd91fd7dc876326ee0832ca8f7947dc1cc24bsalomon@google.com    fDrawState = NULL;
900ad5bd91fd7dc876326ee0832ca8f7947dc1cc24bsalomon@google.com    fGpu = NULL;
91e1884e6f16a6dd9f457970ffab3887e01f268703commit-bot@chromium.org    fClip = NULL;
920ad5bd91fd7dc876326ee0832ca8f7947dc1cc24bsalomon@google.com    fPathRendererChain = NULL;
930ad5bd91fd7dc876326ee0832ca8f7947dc1cc24bsalomon@google.com    fSoftwarePathRenderer = NULL;
940ad5bd91fd7dc876326ee0832ca8f7947dc1cc24bsalomon@google.com    fTextureCache = NULL;
950ad5bd91fd7dc876326ee0832ca8f7947dc1cc24bsalomon@google.com    fFontCache = NULL;
960ad5bd91fd7dc876326ee0832ca8f7947dc1cc24bsalomon@google.com    fDrawBuffer = NULL;
970ad5bd91fd7dc876326ee0832ca8f7947dc1cc24bsalomon@google.com    fDrawBufferVBAllocPool = NULL;
980ad5bd91fd7dc876326ee0832ca8f7947dc1cc24bsalomon@google.com    fDrawBufferIBAllocPool = NULL;
9921c4256a8eccc702d1c4b561da1a3a3e212d3c23commit-bot@chromium.org    fFlushToReduceCacheSize = false;
1000ad5bd91fd7dc876326ee0832ca8f7947dc1cc24bsalomon@google.com    fAARectRenderer = NULL;
10151d94f5635c0744ef6aa4514f0055a88753acfeacommit-bot@chromium.org    fOvalRenderer = NULL;
102e1884e6f16a6dd9f457970ffab3887e01f268703commit-bot@chromium.org    fViewMatrix.reset();
103b79edfc18351e566f1b395ccb2b9f25bd35bb930robertphillips@google.com    fMaxTextureSizeOverride = 1 << 20;
1040ad5bd91fd7dc876326ee0832ca8f7947dc1cc24bsalomon@google.com}
1050ad5bd91fd7dc876326ee0832ca8f7947dc1cc24bsalomon@google.com
1060ad5bd91fd7dc876326ee0832ca8f7947dc1cc24bsalomon@google.combool GrContext::init(GrBackend backend, GrBackendContext backendContext) {
107a91959e0e4997d3a73b38e6d7f0296c566a4b1d0tfarina@chromium.org    SkASSERT(NULL == fGpu);
1080ad5bd91fd7dc876326ee0832ca8f7947dc1cc24bsalomon@google.com
1090ad5bd91fd7dc876326ee0832ca8f7947dc1cc24bsalomon@google.com    fGpu = GrGpu::Create(backend, backendContext, this);
1100ad5bd91fd7dc876326ee0832ca8f7947dc1cc24bsalomon@google.com    if (NULL == fGpu) {
1110ad5bd91fd7dc876326ee0832ca8f7947dc1cc24bsalomon@google.com        return false;
1120ad5bd91fd7dc876326ee0832ca8f7947dc1cc24bsalomon@google.com    }
1130ad5bd91fd7dc876326ee0832ca8f7947dc1cc24bsalomon@google.com
1140ad5bd91fd7dc876326ee0832ca8f7947dc1cc24bsalomon@google.com    fDrawState = SkNEW(GrDrawState);
1150ad5bd91fd7dc876326ee0832ca8f7947dc1cc24bsalomon@google.com    fGpu->setDrawState(fDrawState);
1160ad5bd91fd7dc876326ee0832ca8f7947dc1cc24bsalomon@google.com
1170ad5bd91fd7dc876326ee0832ca8f7947dc1cc24bsalomon@google.com    fTextureCache = SkNEW_ARGS(GrResourceCache,
118428b26ff1d2e1d8a4b13e690ba693d105fb9377drobertphillips@google.com                               (MAX_RESOURCE_CACHE_COUNT,
119428b26ff1d2e1d8a4b13e690ba693d105fb9377drobertphillips@google.com                                MAX_RESOURCE_CACHE_BYTES));
12048f8f0474fb7f31a97f9b9fc153af8809ac0d40acommit-bot@chromium.org    fTextureCache->setOverbudgetCallback(OverbudgetCB, this);
12148f8f0474fb7f31a97f9b9fc153af8809ac0d40acommit-bot@chromium.org
1220ad5bd91fd7dc876326ee0832ca8f7947dc1cc24bsalomon@google.com    fFontCache = SkNEW_ARGS(GrFontCache, (fGpu));
1230ad5bd91fd7dc876326ee0832ca8f7947dc1cc24bsalomon@google.com
1240ad5bd91fd7dc876326ee0832ca8f7947dc1cc24bsalomon@google.com    fLastDrawWasBuffered = kNo_BufferedDraw;
1250ad5bd91fd7dc876326ee0832ca8f7947dc1cc24bsalomon@google.com
1260ad5bd91fd7dc876326ee0832ca8f7947dc1cc24bsalomon@google.com    fAARectRenderer = SkNEW(GrAARectRenderer);
12751d94f5635c0744ef6aa4514f0055a88753acfeacommit-bot@chromium.org    fOvalRenderer = SkNEW(GrOvalRenderer);
1280ad5bd91fd7dc876326ee0832ca8f7947dc1cc24bsalomon@google.com
1290ad5bd91fd7dc876326ee0832ca8f7947dc1cc24bsalomon@google.com    fDidTestPMConversions = false;
1300ad5bd91fd7dc876326ee0832ca8f7947dc1cc24bsalomon@google.com
1310ad5bd91fd7dc876326ee0832ca8f7947dc1cc24bsalomon@google.com    this->setupDrawBuffer();
1320ad5bd91fd7dc876326ee0832ca8f7947dc1cc24bsalomon@google.com
1330ad5bd91fd7dc876326ee0832ca8f7947dc1cc24bsalomon@google.com    return true;
1344e98b5f7be8218d4a93b21df06a83c74b0942b24bsalomon@google.com}
1354e98b5f7be8218d4a93b21df06a83c74b0942b24bsalomon@google.com
1363f30e3a41fc16816105e28e0d4c241eff6d391b4bsalomon@google.comGrContext::~GrContext() {
137a7dffabef59ae609e5d98c032265700a681cb06ebsalomon@google.com    if (NULL == fGpu) {
138a7dffabef59ae609e5d98c032265700a681cb06ebsalomon@google.com        return;
139a7dffabef59ae609e5d98c032265700a681cb06ebsalomon@google.com    }
140a7dffabef59ae609e5d98c032265700a681cb06ebsalomon@google.com
1413f30e3a41fc16816105e28e0d4c241eff6d391b4bsalomon@google.com    this->flush();
1427ee019c963ed4a2c9eb3d1c8490ba1ee246e0b1arobertphillips@google.com
14389fe2dcf4b11483850e0da098dc87b0cdc80a9b8robertphillips@google.com    for (int i = 0; i < fCleanUpData.count(); ++i) {
14489fe2dcf4b11483850e0da098dc87b0cdc80a9b8robertphillips@google.com        (*fCleanUpData[i].fFunc)(this, fCleanUpData[i].fInfo);
14589fe2dcf4b11483850e0da098dc87b0cdc80a9b8robertphillips@google.com    }
14689fe2dcf4b11483850e0da098dc87b0cdc80a9b8robertphillips@google.com
1477ee019c963ed4a2c9eb3d1c8490ba1ee246e0b1arobertphillips@google.com    // Since the gpu can hold scratch textures, give it a chance to let go
1487ee019c963ed4a2c9eb3d1c8490ba1ee246e0b1arobertphillips@google.com    // of them before freeing the texture cache
1497ee019c963ed4a2c9eb3d1c8490ba1ee246e0b1arobertphillips@google.com    fGpu->purgeResources();
1507ee019c963ed4a2c9eb3d1c8490ba1ee246e0b1arobertphillips@google.com
1513f30e3a41fc16816105e28e0d4c241eff6d391b4bsalomon@google.com    delete fTextureCache;
1527b5b4274da2fcb1e8c56a99e2ae86703f3326fb5robertphillips@google.com    fTextureCache = NULL;
1533f30e3a41fc16816105e28e0d4c241eff6d391b4bsalomon@google.com    delete fFontCache;
1543f30e3a41fc16816105e28e0d4c241eff6d391b4bsalomon@google.com    delete fDrawBuffer;
1553f30e3a41fc16816105e28e0d4c241eff6d391b4bsalomon@google.com    delete fDrawBufferVBAllocPool;
1563f30e3a41fc16816105e28e0d4c241eff6d391b4bsalomon@google.com    delete fDrawBufferIBAllocPool;
1573f30e3a41fc16816105e28e0d4c241eff6d391b4bsalomon@google.com
158fa8749437c07050c8478087ef4eb09069586bf7frobertphillips@google.com    fAARectRenderer->unref();
15951d94f5635c0744ef6aa4514f0055a88753acfeacommit-bot@chromium.org    fOvalRenderer->unref();
160fa8749437c07050c8478087ef4eb09069586bf7frobertphillips@google.com
1613f30e3a41fc16816105e28e0d4c241eff6d391b4bsalomon@google.com    fGpu->unref();
1626afd4a39f8b15b1534c5c716e5de05bcac501b32commit-bot@chromium.org    SkSafeUnref(fPathRendererChain);
1636afd4a39f8b15b1534c5c716e5de05bcac501b32commit-bot@chromium.org    SkSafeUnref(fSoftwarePathRenderer);
1643649448163f693ebcb2cd8308d27e6ba215272eabsalomon@google.com    fDrawState->unref();
1653f30e3a41fc16816105e28e0d4c241eff6d391b4bsalomon@google.com}
1663f30e3a41fc16816105e28e0d4c241eff6d391b4bsalomon@google.com
1673f30e3a41fc16816105e28e0d4c241eff6d391b4bsalomon@google.comvoid GrContext::contextLost() {
1680ad5bd91fd7dc876326ee0832ca8f7947dc1cc24bsalomon@google.com    this->contextDestroyed();
1693f30e3a41fc16816105e28e0d4c241eff6d391b4bsalomon@google.com    this->setupDrawBuffer();
1703f30e3a41fc16816105e28e0d4c241eff6d391b4bsalomon@google.com}
1713f30e3a41fc16816105e28e0d4c241eff6d391b4bsalomon@google.com
1723f30e3a41fc16816105e28e0d4c241eff6d391b4bsalomon@google.comvoid GrContext::contextDestroyed() {
1733f30e3a41fc16816105e28e0d4c241eff6d391b4bsalomon@google.com    // abandon first to so destructors
1743f30e3a41fc16816105e28e0d4c241eff6d391b4bsalomon@google.com    // don't try to free the resources in the API.
1753f30e3a41fc16816105e28e0d4c241eff6d391b4bsalomon@google.com    fGpu->abandonResources();
1763f30e3a41fc16816105e28e0d4c241eff6d391b4bsalomon@google.com
1773f30e3a41fc16816105e28e0d4c241eff6d391b4bsalomon@google.com    // a path renderer may be holding onto resources that
1783f30e3a41fc16816105e28e0d4c241eff6d391b4bsalomon@google.com    // are now unusable
1796afd4a39f8b15b1534c5c716e5de05bcac501b32commit-bot@chromium.org    SkSafeSetNull(fPathRendererChain);
1806afd4a39f8b15b1534c5c716e5de05bcac501b32commit-bot@chromium.org    SkSafeSetNull(fSoftwarePathRenderer);
1813f30e3a41fc16816105e28e0d4c241eff6d391b4bsalomon@google.com
1823f30e3a41fc16816105e28e0d4c241eff6d391b4bsalomon@google.com    delete fDrawBuffer;
1833f30e3a41fc16816105e28e0d4c241eff6d391b4bsalomon@google.com    fDrawBuffer = NULL;
1843f30e3a41fc16816105e28e0d4c241eff6d391b4bsalomon@google.com
1853f30e3a41fc16816105e28e0d4c241eff6d391b4bsalomon@google.com    delete fDrawBufferVBAllocPool;
1863f30e3a41fc16816105e28e0d4c241eff6d391b4bsalomon@google.com    fDrawBufferVBAllocPool = NULL;
1873f30e3a41fc16816105e28e0d4c241eff6d391b4bsalomon@google.com
1883f30e3a41fc16816105e28e0d4c241eff6d391b4bsalomon@google.com    delete fDrawBufferIBAllocPool;
1893f30e3a41fc16816105e28e0d4c241eff6d391b4bsalomon@google.com    fDrawBufferIBAllocPool = NULL;
1903f30e3a41fc16816105e28e0d4c241eff6d391b4bsalomon@google.com
191fa8749437c07050c8478087ef4eb09069586bf7frobertphillips@google.com    fAARectRenderer->reset();
1922487c826e35dd8dfa470913722ea15f73f8fd99fcommit-bot@chromium.org    fOvalRenderer->reset();
1933f30e3a41fc16816105e28e0d4c241eff6d391b4bsalomon@google.com
194f511bc83831d0b7aad6b8b2709593ea305213183bsalomon@google.com    fTextureCache->purgeAllUnlocked();
19509af991708bb73d5e1c8bff9c1e7f8423bde09ddcommit-bot@chromium.org
1963f30e3a41fc16816105e28e0d4c241eff6d391b4bsalomon@google.com    fFontCache->freeAll();
1973f30e3a41fc16816105e28e0d4c241eff6d391b4bsalomon@google.com    fGpu->markContextDirty();
1983f30e3a41fc16816105e28e0d4c241eff6d391b4bsalomon@google.com}
1993f30e3a41fc16816105e28e0d4c241eff6d391b4bsalomon@google.com
200a955749f8bf09cf65154ca8d57a86444ffed85a5bsalomon@google.comvoid GrContext::resetContext(uint32_t state) {
201a955749f8bf09cf65154ca8d57a86444ffed85a5bsalomon@google.com    fGpu->markContextDirty(state);
2023f30e3a41fc16816105e28e0d4c241eff6d391b4bsalomon@google.com}
2033f30e3a41fc16816105e28e0d4c241eff6d391b4bsalomon@google.com
2043f30e3a41fc16816105e28e0d4c241eff6d391b4bsalomon@google.comvoid GrContext::freeGpuResources() {
2053f30e3a41fc16816105e28e0d4c241eff6d391b4bsalomon@google.com    this->flush();
206935e9f4fafdfc64130e6be9ea2bb30e3bafd852armistry@google.com
2072a46d231cee3d3ae87a6090da78b9971078fc9c7robertphillips@google.com    fGpu->purgeResources();
2082a46d231cee3d3ae87a6090da78b9971078fc9c7robertphillips@google.com
209fa8749437c07050c8478087ef4eb09069586bf7frobertphillips@google.com    fAARectRenderer->reset();
2102487c826e35dd8dfa470913722ea15f73f8fd99fcommit-bot@chromium.org    fOvalRenderer->reset();
211fa8749437c07050c8478087ef4eb09069586bf7frobertphillips@google.com
212f511bc83831d0b7aad6b8b2709593ea305213183bsalomon@google.com    fTextureCache->purgeAllUnlocked();
2133f30e3a41fc16816105e28e0d4c241eff6d391b4bsalomon@google.com    fFontCache->freeAll();
2143f30e3a41fc16816105e28e0d4c241eff6d391b4bsalomon@google.com    // a path renderer may be holding onto resources
2156afd4a39f8b15b1534c5c716e5de05bcac501b32commit-bot@chromium.org    SkSafeSetNull(fPathRendererChain);
2166afd4a39f8b15b1534c5c716e5de05bcac501b32commit-bot@chromium.org    SkSafeSetNull(fSoftwarePathRenderer);
2173f30e3a41fc16816105e28e0d4c241eff6d391b4bsalomon@google.com}
2183f30e3a41fc16816105e28e0d4c241eff6d391b4bsalomon@google.com
219a38bcb2cd6c018011060ee5dbe9f0a273c709a23twiz@google.comsize_t GrContext::getGpuTextureCacheBytes() const {
220a38bcb2cd6c018011060ee5dbe9f0a273c709a23twiz@google.com  return fTextureCache->getCachedResourceBytes();
221a38bcb2cd6c018011060ee5dbe9f0a273c709a23twiz@google.com}
222a38bcb2cd6c018011060ee5dbe9f0a273c709a23twiz@google.com
2233f30e3a41fc16816105e28e0d4c241eff6d391b4bsalomon@google.com////////////////////////////////////////////////////////////////////////////////
2243f30e3a41fc16816105e28e0d4c241eff6d391b4bsalomon@google.com
2258f5dc5a363c2e9548f3b48325a1579a5da92e21absalomon@google.comGrTexture* GrContext::findAndRefTexture(const GrTextureDesc& desc,
2268f5dc5a363c2e9548f3b48325a1579a5da92e21absalomon@google.com                                        const GrCacheID& cacheID,
2278f5dc5a363c2e9548f3b48325a1579a5da92e21absalomon@google.com                                        const GrTextureParams* params) {
22898cf2a50d40d9f9b05ba0ea217d9898af474c856bsalomon@google.com    GrResourceKey resourceKey = GrTexture::ComputeKey(fGpu, params, desc, cacheID);
2299addc0ab3020b8d09fae95afe618bb084c1ee7d6robertphillips@google.com    GrResource* resource = fTextureCache->find(resourceKey);
2308f5dc5a363c2e9548f3b48325a1579a5da92e21absalomon@google.com    SkSafeRef(resource);
23107f394de342c79543c2b4f5c5bf18e86ac6e49b0robertphillips@google.com    return static_cast<GrTexture*>(resource);
2323f30e3a41fc16816105e28e0d4c241eff6d391b4bsalomon@google.com}
2333f30e3a41fc16816105e28e0d4c241eff6d391b4bsalomon@google.com
234c937ae9bcbf6bdb6fe7f6b4cdb518a684fb5f1barobertphillips@google.combool GrContext::isTextureInCache(const GrTextureDesc& desc,
23598cf2a50d40d9f9b05ba0ea217d9898af474c856bsalomon@google.com                                 const GrCacheID& cacheID,
23620c50f7c5feda26ad659838c4f3824c47aa36903bsalomon@google.com                                 const GrTextureParams* params) const {
23798cf2a50d40d9f9b05ba0ea217d9898af474c856bsalomon@google.com    GrResourceKey resourceKey = GrTexture::ComputeKey(fGpu, params, desc, cacheID);
238ebdf5650f83c18e13d0188e21c4f7cda9dfda11absalomon@google.com    return fTextureCache->hasKey(resourceKey);
239ebdf5650f83c18e13d0188e21c4f7cda9dfda11absalomon@google.com}
240ebdf5650f83c18e13d0188e21c4f7cda9dfda11absalomon@google.com
2419addc0ab3020b8d09fae95afe618bb084c1ee7d6robertphillips@google.comvoid GrContext::addStencilBuffer(GrStencilBuffer* sb) {
242b5ed4edffdba739303dbe834644333b948ecbff9bsalomon@google.com    ASSERT_OWNED_RESOURCE(sb);
24308e41f3f301dfbbe911c67cd773dba7de0478068robertphillips@google.com
24408e41f3f301dfbbe911c67cd773dba7de0478068robertphillips@google.com    GrResourceKey resourceKey = GrStencilBuffer::ComputeKey(sb->width(),
24508e41f3f301dfbbe911c67cd773dba7de0478068robertphillips@google.com                                                            sb->height(),
24608e41f3f301dfbbe911c67cd773dba7de0478068robertphillips@google.com                                                            sb->numSamples());
24781aa09ceb2fec637188cac56251e25eb1024b46arobertphillips@google.com    fTextureCache->addResource(resourceKey, sb);
2483f30e3a41fc16816105e28e0d4c241eff6d391b4bsalomon@google.com}
2493f30e3a41fc16816105e28e0d4c241eff6d391b4bsalomon@google.com
2509addc0ab3020b8d09fae95afe618bb084c1ee7d6robertphillips@google.comGrStencilBuffer* GrContext::findStencilBuffer(int width, int height,
2513f30e3a41fc16816105e28e0d4c241eff6d391b4bsalomon@google.com                                              int sampleCnt) {
25208e41f3f301dfbbe911c67cd773dba7de0478068robertphillips@google.com    GrResourceKey resourceKey = GrStencilBuffer::ComputeKey(width,
25308e41f3f301dfbbe911c67cd773dba7de0478068robertphillips@google.com                                                            height,
25408e41f3f301dfbbe911c67cd773dba7de0478068robertphillips@google.com                                                            sampleCnt);
2559addc0ab3020b8d09fae95afe618bb084c1ee7d6robertphillips@google.com    GrResource* resource = fTextureCache->find(resourceKey);
25607f394de342c79543c2b4f5c5bf18e86ac6e49b0robertphillips@google.com    return static_cast<GrStencilBuffer*>(resource);
2573f30e3a41fc16816105e28e0d4c241eff6d391b4bsalomon@google.com}
2583f30e3a41fc16816105e28e0d4c241eff6d391b4bsalomon@google.com
2593f30e3a41fc16816105e28e0d4c241eff6d391b4bsalomon@google.comstatic void stretchImage(void* dst,
2603f30e3a41fc16816105e28e0d4c241eff6d391b4bsalomon@google.com                         int dstW,
2613f30e3a41fc16816105e28e0d4c241eff6d391b4bsalomon@google.com                         int dstH,
2623f30e3a41fc16816105e28e0d4c241eff6d391b4bsalomon@google.com                         void* src,
2633f30e3a41fc16816105e28e0d4c241eff6d391b4bsalomon@google.com                         int srcW,
2643f30e3a41fc16816105e28e0d4c241eff6d391b4bsalomon@google.com                         int srcH,
26532b94f845a845a8e150ba2d83f45c2bcd192eb22robertphillips@google.com                         size_t bpp) {
2663f30e3a41fc16816105e28e0d4c241eff6d391b4bsalomon@google.com    GrFixed dx = (srcW << 16) / dstW;
2673f30e3a41fc16816105e28e0d4c241eff6d391b4bsalomon@google.com    GrFixed dy = (srcH << 16) / dstH;
2683f30e3a41fc16816105e28e0d4c241eff6d391b4bsalomon@google.com
2693f30e3a41fc16816105e28e0d4c241eff6d391b4bsalomon@google.com    GrFixed y = dy >> 1;
2703f30e3a41fc16816105e28e0d4c241eff6d391b4bsalomon@google.com
27132b94f845a845a8e150ba2d83f45c2bcd192eb22robertphillips@google.com    size_t dstXLimit = dstW*bpp;
2723f30e3a41fc16816105e28e0d4c241eff6d391b4bsalomon@google.com    for (int j = 0; j < dstH; ++j) {
2733f30e3a41fc16816105e28e0d4c241eff6d391b4bsalomon@google.com        GrFixed x = dx >> 1;
2743f30e3a41fc16816105e28e0d4c241eff6d391b4bsalomon@google.com        void* srcRow = (uint8_t*)src + (y>>16)*srcW*bpp;
2753f30e3a41fc16816105e28e0d4c241eff6d391b4bsalomon@google.com        void* dstRow = (uint8_t*)dst + j*dstW*bpp;
27632b94f845a845a8e150ba2d83f45c2bcd192eb22robertphillips@google.com        for (size_t i = 0; i < dstXLimit; i += bpp) {
2773f30e3a41fc16816105e28e0d4c241eff6d391b4bsalomon@google.com            memcpy((uint8_t*) dstRow + i,
2783f30e3a41fc16816105e28e0d4c241eff6d391b4bsalomon@google.com                   (uint8_t*) srcRow + (x>>16)*bpp,
2793f30e3a41fc16816105e28e0d4c241eff6d391b4bsalomon@google.com                   bpp);
2803f30e3a41fc16816105e28e0d4c241eff6d391b4bsalomon@google.com            x += dx;
2813f30e3a41fc16816105e28e0d4c241eff6d391b4bsalomon@google.com        }
2823f30e3a41fc16816105e28e0d4c241eff6d391b4bsalomon@google.com        y += dy;
2833f30e3a41fc16816105e28e0d4c241eff6d391b4bsalomon@google.com    }
2843f30e3a41fc16816105e28e0d4c241eff6d391b4bsalomon@google.com}
2853f30e3a41fc16816105e28e0d4c241eff6d391b4bsalomon@google.com
286a9f1f61795e9d9019fa13e5ff1f339fc58eb84fdrobertphillips@google.comnamespace {
287a9f1f61795e9d9019fa13e5ff1f339fc58eb84fdrobertphillips@google.com
288a9f1f61795e9d9019fa13e5ff1f339fc58eb84fdrobertphillips@google.com// position + local coordinate
289a9f1f61795e9d9019fa13e5ff1f339fc58eb84fdrobertphillips@google.comextern const GrVertexAttrib gVertexAttribs[] = {
290a9f1f61795e9d9019fa13e5ff1f339fc58eb84fdrobertphillips@google.com    {kVec2f_GrVertexAttribType, 0,               kPosition_GrVertexAttribBinding},
291a9f1f61795e9d9019fa13e5ff1f339fc58eb84fdrobertphillips@google.com    {kVec2f_GrVertexAttribType, sizeof(GrPoint), kLocalCoord_GrVertexAttribBinding}
292a9f1f61795e9d9019fa13e5ff1f339fc58eb84fdrobertphillips@google.com};
293a9f1f61795e9d9019fa13e5ff1f339fc58eb84fdrobertphillips@google.com
294a9f1f61795e9d9019fa13e5ff1f339fc58eb84fdrobertphillips@google.com};
295a9f1f61795e9d9019fa13e5ff1f339fc58eb84fdrobertphillips@google.com
296935e9f4fafdfc64130e6be9ea2bb30e3bafd852armistry@google.com// The desired texture is NPOT and tiled but that isn't supported by
2978abd697592cf7249d2ff55f8aefd2a463091ee19robertphillips@google.com// the current hardware. Resize the texture to be a POT
2988abd697592cf7249d2ff55f8aefd2a463091ee19robertphillips@google.comGrTexture* GrContext::createResizedTexture(const GrTextureDesc& desc,
29998cf2a50d40d9f9b05ba0ea217d9898af474c856bsalomon@google.com                                           const GrCacheID& cacheID,
3008abd697592cf7249d2ff55f8aefd2a463091ee19robertphillips@google.com                                           void* srcData,
3018abd697592cf7249d2ff55f8aefd2a463091ee19robertphillips@google.com                                           size_t rowBytes,
30229ba4805e88962ad40e3ca79c9a768e073f52badhumper@google.com                                           bool filter) {
3038f5dc5a363c2e9548f3b48325a1579a5da92e21absalomon@google.com    SkAutoTUnref<GrTexture> clampedTexture(this->findAndRefTexture(desc, cacheID, NULL));
30407f394de342c79543c2b4f5c5bf18e86ac6e49b0robertphillips@google.com    if (NULL == clampedTexture) {
3058f5dc5a363c2e9548f3b48325a1579a5da92e21absalomon@google.com        clampedTexture.reset(this->createTexture(NULL, desc, cacheID, srcData, rowBytes));
3069addc0ab3020b8d09fae95afe618bb084c1ee7d6robertphillips@google.com
30707f394de342c79543c2b4f5c5bf18e86ac6e49b0robertphillips@google.com        if (NULL == clampedTexture) {
3088abd697592cf7249d2ff55f8aefd2a463091ee19robertphillips@google.com            return NULL;
3098abd697592cf7249d2ff55f8aefd2a463091ee19robertphillips@google.com        }
3108abd697592cf7249d2ff55f8aefd2a463091ee19robertphillips@google.com    }
311b09364450fc79733f5d1629b84ef7c712a8eac55robertphillips@google.com
3128abd697592cf7249d2ff55f8aefd2a463091ee19robertphillips@google.com    GrTextureDesc rtDesc = desc;
3138abd697592cf7249d2ff55f8aefd2a463091ee19robertphillips@google.com    rtDesc.fFlags =  rtDesc.fFlags |
3148abd697592cf7249d2ff55f8aefd2a463091ee19robertphillips@google.com                     kRenderTarget_GrTextureFlagBit |
3158abd697592cf7249d2ff55f8aefd2a463091ee19robertphillips@google.com                     kNoStencil_GrTextureFlagBit;
31604a9a1ce033abe61974016992c2f73441c1c73eecommit-bot@chromium.org    rtDesc.fWidth  = GrNextPow2(desc.fWidth);
31704a9a1ce033abe61974016992c2f73441c1c73eecommit-bot@chromium.org    rtDesc.fHeight = GrNextPow2(desc.fHeight);
3188abd697592cf7249d2ff55f8aefd2a463091ee19robertphillips@google.com
3198abd697592cf7249d2ff55f8aefd2a463091ee19robertphillips@google.com    GrTexture* texture = fGpu->createTexture(rtDesc, NULL, 0);
3208abd697592cf7249d2ff55f8aefd2a463091ee19robertphillips@google.com
3218abd697592cf7249d2ff55f8aefd2a463091ee19robertphillips@google.com    if (NULL != texture) {
3228abd697592cf7249d2ff55f8aefd2a463091ee19robertphillips@google.com        GrDrawTarget::AutoStateRestore asr(fGpu, GrDrawTarget::kReset_ASRInit);
3238abd697592cf7249d2ff55f8aefd2a463091ee19robertphillips@google.com        GrDrawState* drawState = fGpu->drawState();
3248abd697592cf7249d2ff55f8aefd2a463091ee19robertphillips@google.com        drawState->setRenderTarget(texture->asRenderTarget());
3258abd697592cf7249d2ff55f8aefd2a463091ee19robertphillips@google.com
3268abd697592cf7249d2ff55f8aefd2a463091ee19robertphillips@google.com        // if filtering is not desired then we want to ensure all
3278abd697592cf7249d2ff55f8aefd2a463091ee19robertphillips@google.com        // texels in the resampled image are copies of texels from
3288abd697592cf7249d2ff55f8aefd2a463091ee19robertphillips@google.com        // the original.
32929ba4805e88962ad40e3ca79c9a768e073f52badhumper@google.com        GrTextureParams params(SkShader::kClamp_TileMode, filter ? GrTextureParams::kBilerp_FilterMode :
33029ba4805e88962ad40e3ca79c9a768e073f52badhumper@google.com                                                                   GrTextureParams::kNone_FilterMode);
331860912a0affd82bc6b30ad9006658df856ca1d17bsalomon@google.com        drawState->addColorTextureEffect(clampedTexture, SkMatrix::I(), params);
3328abd697592cf7249d2ff55f8aefd2a463091ee19robertphillips@google.com
333a9f1f61795e9d9019fa13e5ff1f339fc58eb84fdrobertphillips@google.com        drawState->setVertexAttribs<gVertexAttribs>(SK_ARRAY_COUNT(gVertexAttribs));
3342419b53383d572e3f3b7adcbcb2574a569bce0dcjvanverth@google.com
3359d8e4b7e65a6b644564e2f2b94730f74b88941e5jvanverth@google.com        GrDrawTarget::AutoReleaseGeometry arg(fGpu, 4, 0);
3368abd697592cf7249d2ff55f8aefd2a463091ee19robertphillips@google.com
3378abd697592cf7249d2ff55f8aefd2a463091ee19robertphillips@google.com        if (arg.succeeded()) {
3388abd697592cf7249d2ff55f8aefd2a463091ee19robertphillips@google.com            GrPoint* verts = (GrPoint*) arg.vertices();
3398f5dc5a363c2e9548f3b48325a1579a5da92e21absalomon@google.com            verts[0].setIRectFan(0, 0, texture->width(), texture->height(), 2 * sizeof(GrPoint));
3408f5dc5a363c2e9548f3b48325a1579a5da92e21absalomon@google.com            verts[1].setIRectFan(0, 0, 1, 1, 2 * sizeof(GrPoint));
3418f5dc5a363c2e9548f3b48325a1579a5da92e21absalomon@google.com            fGpu->drawNonIndexed(kTriangleFan_GrPrimitiveType, 0, 4);
3428abd697592cf7249d2ff55f8aefd2a463091ee19robertphillips@google.com        }
3438abd697592cf7249d2ff55f8aefd2a463091ee19robertphillips@google.com    } else {
3448abd697592cf7249d2ff55f8aefd2a463091ee19robertphillips@google.com        // TODO: Our CPU stretch doesn't filter. But we create separate
3457879945fc341357322f2a19d9a927ff2e6bae4d9bsalomon@google.com        // stretched textures when the texture params is either filtered or
3468abd697592cf7249d2ff55f8aefd2a463091ee19robertphillips@google.com        // not. Either implement filtered stretch blit on CPU or just create
3478abd697592cf7249d2ff55f8aefd2a463091ee19robertphillips@google.com        // one when FBO case fails.
3488abd697592cf7249d2ff55f8aefd2a463091ee19robertphillips@google.com
3498abd697592cf7249d2ff55f8aefd2a463091ee19robertphillips@google.com        rtDesc.fFlags = kNone_GrTextureFlags;
3508abd697592cf7249d2ff55f8aefd2a463091ee19robertphillips@google.com        // no longer need to clamp at min RT size.
3518abd697592cf7249d2ff55f8aefd2a463091ee19robertphillips@google.com        rtDesc.fWidth  = GrNextPow2(desc.fWidth);
3528abd697592cf7249d2ff55f8aefd2a463091ee19robertphillips@google.com        rtDesc.fHeight = GrNextPow2(desc.fHeight);
35332b94f845a845a8e150ba2d83f45c2bcd192eb22robertphillips@google.com        size_t bpp = GrBytesPerPixel(desc.fConfig);
3547879945fc341357322f2a19d9a927ff2e6bae4d9bsalomon@google.com        SkAutoSMalloc<128*128*4> stretchedPixels(bpp * rtDesc.fWidth * rtDesc.fHeight);
3558abd697592cf7249d2ff55f8aefd2a463091ee19robertphillips@google.com        stretchImage(stretchedPixels.get(), rtDesc.fWidth, rtDesc.fHeight,
3567879945fc341357322f2a19d9a927ff2e6bae4d9bsalomon@google.com                     srcData, desc.fWidth, desc.fHeight, bpp);
3578abd697592cf7249d2ff55f8aefd2a463091ee19robertphillips@google.com
3588abd697592cf7249d2ff55f8aefd2a463091ee19robertphillips@google.com        size_t stretchedRowBytes = rtDesc.fWidth * bpp;
3598abd697592cf7249d2ff55f8aefd2a463091ee19robertphillips@google.com
360de883c44a7b53cf40b12fab49cd521dcbe18b285jvanverth@google.com        SkDEBUGCODE(GrTexture* texture = )fGpu->createTexture(rtDesc, stretchedPixels.get(),
361de883c44a7b53cf40b12fab49cd521dcbe18b285jvanverth@google.com                                                              stretchedRowBytes);
362a91959e0e4997d3a73b38e6d7f0296c566a4b1d0tfarina@chromium.org        SkASSERT(NULL != texture);
3638abd697592cf7249d2ff55f8aefd2a463091ee19robertphillips@google.com    }
3648abd697592cf7249d2ff55f8aefd2a463091ee19robertphillips@google.com
3658abd697592cf7249d2ff55f8aefd2a463091ee19robertphillips@google.com    return texture;
3668abd697592cf7249d2ff55f8aefd2a463091ee19robertphillips@google.com}
3678abd697592cf7249d2ff55f8aefd2a463091ee19robertphillips@google.com
3688f5dc5a363c2e9548f3b48325a1579a5da92e21absalomon@google.comGrTexture* GrContext::createTexture(const GrTextureParams* params,
3698f5dc5a363c2e9548f3b48325a1579a5da92e21absalomon@google.com                                    const GrTextureDesc& desc,
3708f5dc5a363c2e9548f3b48325a1579a5da92e21absalomon@google.com                                    const GrCacheID& cacheID,
3718f5dc5a363c2e9548f3b48325a1579a5da92e21absalomon@google.com                                    void* srcData,
3723639a16a353da76b52943e8c1dd9e0dd5edda69dcommit-bot@chromium.org                                    size_t rowBytes,
3733639a16a353da76b52943e8c1dd9e0dd5edda69dcommit-bot@chromium.org                                    GrResourceKey* cacheKey) {
37498cf2a50d40d9f9b05ba0ea217d9898af474c856bsalomon@google.com    SK_TRACE_EVENT0("GrContext::createTexture");
3753f30e3a41fc16816105e28e0d4c241eff6d391b4bsalomon@google.com
37698cf2a50d40d9f9b05ba0ea217d9898af474c856bsalomon@google.com    GrResourceKey resourceKey = GrTexture::ComputeKey(fGpu, params, desc, cacheID);
3776dbbd6c68e3ef02908261880d8dbf52580bfaad9robertphillips@google.com
3788f5dc5a363c2e9548f3b48325a1579a5da92e21absalomon@google.com    GrTexture* texture;
3796dbbd6c68e3ef02908261880d8dbf52580bfaad9robertphillips@google.com    if (GrTexture::NeedsResizing(resourceKey)) {
3808f5dc5a363c2e9548f3b48325a1579a5da92e21absalomon@google.com        texture = this->createResizedTexture(desc, cacheID,
3818f5dc5a363c2e9548f3b48325a1579a5da92e21absalomon@google.com                                             srcData, rowBytes,
38229ba4805e88962ad40e3ca79c9a768e073f52badhumper@google.com                                             GrTexture::NeedsBilerp(resourceKey));
3833f30e3a41fc16816105e28e0d4c241eff6d391b4bsalomon@google.com    } else {
3848f5dc5a363c2e9548f3b48325a1579a5da92e21absalomon@google.com        texture= fGpu->createTexture(desc, srcData, rowBytes);
3858abd697592cf7249d2ff55f8aefd2a463091ee19robertphillips@google.com    }
3868abd697592cf7249d2ff55f8aefd2a463091ee19robertphillips@google.com
3878abd697592cf7249d2ff55f8aefd2a463091ee19robertphillips@google.com    if (NULL != texture) {
388407ee05903b17cc662265a6b7a4ad478655b1794robertphillips@google.com        // Adding a resource could put us overbudget. Try to free up the
389407ee05903b17cc662265a6b7a4ad478655b1794robertphillips@google.com        // necessary space before adding it.
390407ee05903b17cc662265a6b7a4ad478655b1794robertphillips@google.com        fTextureCache->purgeAsNeeded(1, texture->sizeInBytes());
39181aa09ceb2fec637188cac56251e25eb1024b46arobertphillips@google.com        fTextureCache->addResource(resourceKey, texture);
3923639a16a353da76b52943e8c1dd9e0dd5edda69dcommit-bot@chromium.org
3933639a16a353da76b52943e8c1dd9e0dd5edda69dcommit-bot@chromium.org        if (NULL != cacheKey) {
3943639a16a353da76b52943e8c1dd9e0dd5edda69dcommit-bot@chromium.org            *cacheKey = resourceKey;
3953639a16a353da76b52943e8c1dd9e0dd5edda69dcommit-bot@chromium.org        }
3963f30e3a41fc16816105e28e0d4c241eff6d391b4bsalomon@google.com    }
3978abd697592cf7249d2ff55f8aefd2a463091ee19robertphillips@google.com
39807f394de342c79543c2b4f5c5bf18e86ac6e49b0robertphillips@google.com    return texture;
3993f30e3a41fc16816105e28e0d4c241eff6d391b4bsalomon@google.com}
4003f30e3a41fc16816105e28e0d4c241eff6d391b4bsalomon@google.com
4019b2fb91aa9e7228ab8ea0f59e18152fa1cf22fd5skia.committer@gmail.comstatic GrTexture* create_scratch_texture(GrGpu* gpu,
4029b2fb91aa9e7228ab8ea0f59e18152fa1cf22fd5skia.committer@gmail.com                                         GrResourceCache* textureCache,
403db15c207e361418b4a7ff1aaba06d86d5a8bfdb6robertphillips@google.com                                         const GrTextureDesc& desc) {
404db15c207e361418b4a7ff1aaba06d86d5a8bfdb6robertphillips@google.com    GrTexture* texture = gpu->createTexture(desc, NULL, 0);
405db15c207e361418b4a7ff1aaba06d86d5a8bfdb6robertphillips@google.com    if (NULL != texture) {
406db15c207e361418b4a7ff1aaba06d86d5a8bfdb6robertphillips@google.com        GrResourceKey key = GrTexture::ComputeScratchKey(texture->desc());
407db15c207e361418b4a7ff1aaba06d86d5a8bfdb6robertphillips@google.com        // Adding a resource could put us overbudget. Try to free up the
408db15c207e361418b4a7ff1aaba06d86d5a8bfdb6robertphillips@google.com        // necessary space before adding it.
409db15c207e361418b4a7ff1aaba06d86d5a8bfdb6robertphillips@google.com        textureCache->purgeAsNeeded(1, texture->sizeInBytes());
410db15c207e361418b4a7ff1aaba06d86d5a8bfdb6robertphillips@google.com        // Make the resource exclusive so future 'find' calls don't return it
411db15c207e361418b4a7ff1aaba06d86d5a8bfdb6robertphillips@google.com        textureCache->addResource(key, texture, GrResourceCache::kHide_OwnershipFlag);
412db15c207e361418b4a7ff1aaba06d86d5a8bfdb6robertphillips@google.com    }
413db15c207e361418b4a7ff1aaba06d86d5a8bfdb6robertphillips@google.com    return texture;
414db15c207e361418b4a7ff1aaba06d86d5a8bfdb6robertphillips@google.com}
415db15c207e361418b4a7ff1aaba06d86d5a8bfdb6robertphillips@google.com
4168f5dc5a363c2e9548f3b48325a1579a5da92e21absalomon@google.comGrTexture* GrContext::lockAndRefScratchTexture(const GrTextureDesc& inDesc, ScratchTexMatch match) {
417c937ae9bcbf6bdb6fe7f6b4cdb518a684fb5f1barobertphillips@google.com
418a91959e0e4997d3a73b38e6d7f0296c566a4b1d0tfarina@chromium.org    SkASSERT((inDesc.fFlags & kRenderTarget_GrTextureFlagBit) ||
419db15c207e361418b4a7ff1aaba06d86d5a8bfdb6robertphillips@google.com             !(inDesc.fFlags & kNoStencil_GrTextureFlagBit));
420db15c207e361418b4a7ff1aaba06d86d5a8bfdb6robertphillips@google.com
421db15c207e361418b4a7ff1aaba06d86d5a8bfdb6robertphillips@google.com    // Renderable A8 targets are not universally supported (e.g., not on ANGLE)
4221c76f7905778dd7f91bac8fe147b9def90547d53bsalomon@google.com    SkASSERT(this->isConfigRenderable(kAlpha_8_GrPixelConfig, inDesc.fSampleCnt > 0) ||
423db15c207e361418b4a7ff1aaba06d86d5a8bfdb6robertphillips@google.com             !(inDesc.fFlags & kRenderTarget_GrTextureFlagBit) ||
424db15c207e361418b4a7ff1aaba06d86d5a8bfdb6robertphillips@google.com             (inDesc.fConfig != kAlpha_8_GrPixelConfig));
425db15c207e361418b4a7ff1aaba06d86d5a8bfdb6robertphillips@google.com
426d91c9eac7cc13869ffa5e93b9862d1d5ccb6587arobertphillips@google.com    if (!fGpu->caps()->reuseScratchTextures() &&
427d91c9eac7cc13869ffa5e93b9862d1d5ccb6587arobertphillips@google.com        !(inDesc.fFlags & kRenderTarget_GrTextureFlagBit)) {
428d91c9eac7cc13869ffa5e93b9862d1d5ccb6587arobertphillips@google.com        // If we're never recycling this texture we can always make it the right size
429db15c207e361418b4a7ff1aaba06d86d5a8bfdb6robertphillips@google.com        return create_scratch_texture(fGpu, fTextureCache, inDesc);
430db15c207e361418b4a7ff1aaba06d86d5a8bfdb6robertphillips@google.com    }
431db15c207e361418b4a7ff1aaba06d86d5a8bfdb6robertphillips@google.com
432db15c207e361418b4a7ff1aaba06d86d5a8bfdb6robertphillips@google.com    GrTextureDesc desc = inDesc;
4337996019411e2831fd8ecba9695bf87c999825776rileya@google.com
43498cf2a50d40d9f9b05ba0ea217d9898af474c856bsalomon@google.com    if (kApprox_ScratchTexMatch == match) {
4353f30e3a41fc16816105e28e0d4c241eff6d391b4bsalomon@google.com        // bin by pow2 with a reasonable min
436eaf5cf160f64dcb4f0fef8c5bfd9396909b1659absalomon@google.com        static const int MIN_SIZE = 16;
4373f30e3a41fc16816105e28e0d4c241eff6d391b4bsalomon@google.com        desc.fWidth  = GrMax(MIN_SIZE, GrNextPow2(desc.fWidth));
4383f30e3a41fc16816105e28e0d4c241eff6d391b4bsalomon@google.com        desc.fHeight = GrMax(MIN_SIZE, GrNextPow2(desc.fHeight));
4393f30e3a41fc16816105e28e0d4c241eff6d391b4bsalomon@google.com    }
4403f30e3a41fc16816105e28e0d4c241eff6d391b4bsalomon@google.com
44107f394de342c79543c2b4f5c5bf18e86ac6e49b0robertphillips@google.com    GrResource* resource = NULL;
4423f30e3a41fc16816105e28e0d4c241eff6d391b4bsalomon@google.com    int origWidth = desc.fWidth;
4433f30e3a41fc16816105e28e0d4c241eff6d391b4bsalomon@google.com    int origHeight = desc.fHeight;
4443f30e3a41fc16816105e28e0d4c241eff6d391b4bsalomon@google.com
4453f30e3a41fc16816105e28e0d4c241eff6d391b4bsalomon@google.com    do {
44698cf2a50d40d9f9b05ba0ea217d9898af474c856bsalomon@google.com        GrResourceKey key = GrTexture::ComputeScratchKey(desc);
44781aa09ceb2fec637188cac56251e25eb1024b46arobertphillips@google.com        // Ensure we have exclusive access to the texture so future 'find' calls don't return it
44881aa09ceb2fec637188cac56251e25eb1024b46arobertphillips@google.com        resource = fTextureCache->find(key, GrResourceCache::kHide_OwnershipFlag);
4498f5dc5a363c2e9548f3b48325a1579a5da92e21absalomon@google.com        if (NULL != resource) {
4508f5dc5a363c2e9548f3b48325a1579a5da92e21absalomon@google.com            resource->ref();
4518f5dc5a363c2e9548f3b48325a1579a5da92e21absalomon@google.com            break;
4528f5dc5a363c2e9548f3b48325a1579a5da92e21absalomon@google.com        }
4538f5dc5a363c2e9548f3b48325a1579a5da92e21absalomon@google.com        if (kExact_ScratchTexMatch == match) {
4543f30e3a41fc16816105e28e0d4c241eff6d391b4bsalomon@google.com            break;
4553f30e3a41fc16816105e28e0d4c241eff6d391b4bsalomon@google.com        }
456eaf5cf160f64dcb4f0fef8c5bfd9396909b1659absalomon@google.com        // We had a cache miss and we are in approx mode, relax the fit of the flags.
4578f5dc5a363c2e9548f3b48325a1579a5da92e21absalomon@google.com
458935e9f4fafdfc64130e6be9ea2bb30e3bafd852armistry@google.com        // We no longer try to reuse textures that were previously used as render targets in
4597996019411e2831fd8ecba9695bf87c999825776rileya@google.com        // situations where no RT is needed; doing otherwise can confuse the video driver and
4607996019411e2831fd8ecba9695bf87c999825776rileya@google.com        // cause significant performance problems in some cases.
4617996019411e2831fd8ecba9695bf87c999825776rileya@google.com        if (desc.fFlags & kNoStencil_GrTextureFlagBit) {
4623f30e3a41fc16816105e28e0d4c241eff6d391b4bsalomon@google.com            desc.fFlags = desc.fFlags & ~kNoStencil_GrTextureFlagBit;
4633f30e3a41fc16816105e28e0d4c241eff6d391b4bsalomon@google.com        } else {
4643f30e3a41fc16816105e28e0d4c241eff6d391b4bsalomon@google.com            break;
4653f30e3a41fc16816105e28e0d4c241eff6d391b4bsalomon@google.com        }
466935e9f4fafdfc64130e6be9ea2bb30e3bafd852armistry@google.com
4673f30e3a41fc16816105e28e0d4c241eff6d391b4bsalomon@google.com    } while (true);
4683f30e3a41fc16816105e28e0d4c241eff6d391b4bsalomon@google.com
46907f394de342c79543c2b4f5c5bf18e86ac6e49b0robertphillips@google.com    if (NULL == resource) {
4703f30e3a41fc16816105e28e0d4c241eff6d391b4bsalomon@google.com        desc.fFlags = inDesc.fFlags;
4713f30e3a41fc16816105e28e0d4c241eff6d391b4bsalomon@google.com        desc.fWidth = origWidth;
4723f30e3a41fc16816105e28e0d4c241eff6d391b4bsalomon@google.com        desc.fHeight = origHeight;
473db15c207e361418b4a7ff1aaba06d86d5a8bfdb6robertphillips@google.com        resource = create_scratch_texture(fGpu, fTextureCache, desc);
4743f30e3a41fc16816105e28e0d4c241eff6d391b4bsalomon@google.com    }
4753f30e3a41fc16816105e28e0d4c241eff6d391b4bsalomon@google.com
47607f394de342c79543c2b4f5c5bf18e86ac6e49b0robertphillips@google.com    return static_cast<GrTexture*>(resource);
4773f30e3a41fc16816105e28e0d4c241eff6d391b4bsalomon@google.com}
4783f30e3a41fc16816105e28e0d4c241eff6d391b4bsalomon@google.com
479afbadf69c0c56d784da42ff7f48759af501d4e59robertphillips@google.comvoid GrContext::addExistingTextureToCache(GrTexture* texture) {
480afbadf69c0c56d784da42ff7f48759af501d4e59robertphillips@google.com
481afbadf69c0c56d784da42ff7f48759af501d4e59robertphillips@google.com    if (NULL == texture) {
482afbadf69c0c56d784da42ff7f48759af501d4e59robertphillips@google.com        return;
483afbadf69c0c56d784da42ff7f48759af501d4e59robertphillips@google.com    }
484afbadf69c0c56d784da42ff7f48759af501d4e59robertphillips@google.com
485267329d2f29d01bf364f3ffc340cade95b5e4a75robertphillips@google.com    // This texture should already have a cache entry since it was once
486267329d2f29d01bf364f3ffc340cade95b5e4a75robertphillips@google.com    // attached
487a91959e0e4997d3a73b38e6d7f0296c566a4b1d0tfarina@chromium.org    SkASSERT(NULL != texture->getCacheEntry());
488267329d2f29d01bf364f3ffc340cade95b5e4a75robertphillips@google.com
489267329d2f29d01bf364f3ffc340cade95b5e4a75robertphillips@google.com    // Conceptually, the cache entry is going to assume responsibility
4904db4c5c364a5793f471d2ca15f337f800780e9b4robertphillips@google.com    // for the creation ref. Assert refcnt == 1.
491a91959e0e4997d3a73b38e6d7f0296c566a4b1d0tfarina@chromium.org    SkASSERT(texture->unique());
492267329d2f29d01bf364f3ffc340cade95b5e4a75robertphillips@google.com
493d91c9eac7cc13869ffa5e93b9862d1d5ccb6587arobertphillips@google.com    if (fGpu->caps()->reuseScratchTextures() || NULL != texture->asRenderTarget()) {
4944db4c5c364a5793f471d2ca15f337f800780e9b4robertphillips@google.com        // Since this texture came from an AutoScratchTexture it should
4954db4c5c364a5793f471d2ca15f337f800780e9b4robertphillips@google.com        // still be in the exclusive pile. Recycle it.
4964db4c5c364a5793f471d2ca15f337f800780e9b4robertphillips@google.com        fTextureCache->makeNonExclusive(texture->getCacheEntry());
497db15c207e361418b4a7ff1aaba06d86d5a8bfdb6robertphillips@google.com        this->purgeCache();
4984db4c5c364a5793f471d2ca15f337f800780e9b4robertphillips@google.com    } else if (texture->getDeferredRefCount() <= 0) {
499db15c207e361418b4a7ff1aaba06d86d5a8bfdb6robertphillips@google.com        // When we aren't reusing textures we know this scratch texture
500db15c207e361418b4a7ff1aaba06d86d5a8bfdb6robertphillips@google.com        // will never be reused and would be just wasting time in the cache
5014db4c5c364a5793f471d2ca15f337f800780e9b4robertphillips@google.com        fTextureCache->makeNonExclusive(texture->getCacheEntry());
502db15c207e361418b4a7ff1aaba06d86d5a8bfdb6robertphillips@google.com        fTextureCache->deleteResource(texture->getCacheEntry());
5034db4c5c364a5793f471d2ca15f337f800780e9b4robertphillips@google.com    } else {
5044db4c5c364a5793f471d2ca15f337f800780e9b4robertphillips@google.com        // In this case (fDeferredRefCount > 0) but the cache is the only
5054db4c5c364a5793f471d2ca15f337f800780e9b4robertphillips@google.com        // one holding a real ref. Mark the object so when the deferred
5064db4c5c364a5793f471d2ca15f337f800780e9b4robertphillips@google.com        // ref count goes to 0 the texture will be deleted (remember
5074db4c5c364a5793f471d2ca15f337f800780e9b4robertphillips@google.com        // in this code path scratch textures aren't getting reused).
5084db4c5c364a5793f471d2ca15f337f800780e9b4robertphillips@google.com        texture->setNeedsDeferredUnref();
509db15c207e361418b4a7ff1aaba06d86d5a8bfdb6robertphillips@google.com    }
510afbadf69c0c56d784da42ff7f48759af501d4e59robertphillips@google.com}
511afbadf69c0c56d784da42ff7f48759af501d4e59robertphillips@google.com
51286b18b1e3c79ba16461d92c16b8480064ee9e085robertphillips@google.com
5139addc0ab3020b8d09fae95afe618bb084c1ee7d6robertphillips@google.comvoid GrContext::unlockScratchTexture(GrTexture* texture) {
51407f394de342c79543c2b4f5c5bf18e86ac6e49b0robertphillips@google.com    ASSERT_OWNED_RESOURCE(texture);
515a91959e0e4997d3a73b38e6d7f0296c566a4b1d0tfarina@chromium.org    SkASSERT(NULL != texture->getCacheEntry());
51607f394de342c79543c2b4f5c5bf18e86ac6e49b0robertphillips@google.com
5173f30e3a41fc16816105e28e0d4c241eff6d391b4bsalomon@google.com    // If this is a scratch texture we detached it from the cache
5183f30e3a41fc16816105e28e0d4c241eff6d391b4bsalomon@google.com    // while it was locked (to avoid two callers simultaneously getting
5193f30e3a41fc16816105e28e0d4c241eff6d391b4bsalomon@google.com    // the same texture).
52098cf2a50d40d9f9b05ba0ea217d9898af474c856bsalomon@google.com    if (texture->getCacheEntry()->key().isScratch()) {
521d91c9eac7cc13869ffa5e93b9862d1d5ccb6587arobertphillips@google.com        if (fGpu->caps()->reuseScratchTextures() || NULL != texture->asRenderTarget()) {
5224db4c5c364a5793f471d2ca15f337f800780e9b4robertphillips@google.com            fTextureCache->makeNonExclusive(texture->getCacheEntry());
5234db4c5c364a5793f471d2ca15f337f800780e9b4robertphillips@google.com            this->purgeCache();
5244db4c5c364a5793f471d2ca15f337f800780e9b4robertphillips@google.com        } else if (texture->unique() && texture->getDeferredRefCount() <= 0) {
525431d4b7c59fc3346e603618f6608a445ecdd2482skia.committer@gmail.com            // Only the cache now knows about this texture. Since we're never
526431d4b7c59fc3346e603618f6608a445ecdd2482skia.committer@gmail.com            // reusing scratch textures (in this code path) it would just be
5274db4c5c364a5793f471d2ca15f337f800780e9b4robertphillips@google.com            // wasting time sitting in the cache.
5284db4c5c364a5793f471d2ca15f337f800780e9b4robertphillips@google.com            fTextureCache->makeNonExclusive(texture->getCacheEntry());
5294db4c5c364a5793f471d2ca15f337f800780e9b4robertphillips@google.com            fTextureCache->deleteResource(texture->getCacheEntry());
5304db4c5c364a5793f471d2ca15f337f800780e9b4robertphillips@google.com        } else {
5314db4c5c364a5793f471d2ca15f337f800780e9b4robertphillips@google.com            // In this case (fRefCnt > 1 || defRefCnt > 0) but we don't really
532431d4b7c59fc3346e603618f6608a445ecdd2482skia.committer@gmail.com            // want to readd it to the cache (since it will never be reused).
5334db4c5c364a5793f471d2ca15f337f800780e9b4robertphillips@google.com            // Instead, give up the cache's ref and leave the decision up to
5344db4c5c364a5793f471d2ca15f337f800780e9b4robertphillips@google.com            // addExistingTextureToCache once its ref count reaches 0. For
5354db4c5c364a5793f471d2ca15f337f800780e9b4robertphillips@google.com            // this to work we need to leave it in the exclusive list.
5364db4c5c364a5793f471d2ca15f337f800780e9b4robertphillips@google.com            texture->setFlag((GrTextureFlags) GrTexture::kReturnToCache_FlagBit);
5374db4c5c364a5793f471d2ca15f337f800780e9b4robertphillips@google.com            // Give up the cache's ref to the texture
5384db4c5c364a5793f471d2ca15f337f800780e9b4robertphillips@google.com            texture->unref();
5394db4c5c364a5793f471d2ca15f337f800780e9b4robertphillips@google.com        }
5403f30e3a41fc16816105e28e0d4c241eff6d391b4bsalomon@google.com    }
54178eddb84d871e855a878775c1dd0aaf0222bf5eerobertphillips@google.com}
54278eddb84d871e855a878775c1dd0aaf0222bf5eerobertphillips@google.com
54378eddb84d871e855a878775c1dd0aaf0222bf5eerobertphillips@google.comvoid GrContext::purgeCache() {
5447b5b4274da2fcb1e8c56a99e2ae86703f3326fb5robertphillips@google.com    if (NULL != fTextureCache) {
5457b5b4274da2fcb1e8c56a99e2ae86703f3326fb5robertphillips@google.com        fTextureCache->purgeAsNeeded();
5467b5b4274da2fcb1e8c56a99e2ae86703f3326fb5robertphillips@google.com    }
547afbadf69c0c56d784da42ff7f48759af501d4e59robertphillips@google.com}
548afbadf69c0c56d784da42ff7f48759af501d4e59robertphillips@google.com
549dffc62e413056e2ef063fc94c5c74b1bff486d2dcommit-bot@chromium.orgbool GrContext::OverbudgetCB(void* data) {
550a91959e0e4997d3a73b38e6d7f0296c566a4b1d0tfarina@chromium.org    SkASSERT(NULL != data);
551dffc62e413056e2ef063fc94c5c74b1bff486d2dcommit-bot@chromium.org
552dffc62e413056e2ef063fc94c5c74b1bff486d2dcommit-bot@chromium.org    GrContext* context = reinterpret_cast<GrContext*>(data);
553dffc62e413056e2ef063fc94c5c74b1bff486d2dcommit-bot@chromium.org
554dffc62e413056e2ef063fc94c5c74b1bff486d2dcommit-bot@chromium.org    // Flush the InOrderDrawBuffer to possibly free up some textures
55521c4256a8eccc702d1c4b561da1a3a3e212d3c23commit-bot@chromium.org    context->fFlushToReduceCacheSize = true;
556dffc62e413056e2ef063fc94c5c74b1bff486d2dcommit-bot@chromium.org
557dffc62e413056e2ef063fc94c5c74b1bff486d2dcommit-bot@chromium.org    return true;
558dffc62e413056e2ef063fc94c5c74b1bff486d2dcommit-bot@chromium.org}
559dffc62e413056e2ef063fc94c5c74b1bff486d2dcommit-bot@chromium.org
560dffc62e413056e2ef063fc94c5c74b1bff486d2dcommit-bot@chromium.org
561c937ae9bcbf6bdb6fe7f6b4cdb518a684fb5f1barobertphillips@google.comGrTexture* GrContext::createUncachedTexture(const GrTextureDesc& descIn,
5623f30e3a41fc16816105e28e0d4c241eff6d391b4bsalomon@google.com                                            void* srcData,
5633f30e3a41fc16816105e28e0d4c241eff6d391b4bsalomon@google.com                                            size_t rowBytes) {
564c937ae9bcbf6bdb6fe7f6b4cdb518a684fb5f1barobertphillips@google.com    GrTextureDesc descCopy = descIn;
565c937ae9bcbf6bdb6fe7f6b4cdb518a684fb5f1barobertphillips@google.com    return fGpu->createTexture(descCopy, srcData, rowBytes);
5663f30e3a41fc16816105e28e0d4c241eff6d391b4bsalomon@google.com}
5673f30e3a41fc16816105e28e0d4c241eff6d391b4bsalomon@google.com
5689605bac01542206efc8aaf608076a3570f7bfd14bsalomon@google.comvoid GrContext::getTextureCacheLimits(int* maxTextures,
5699605bac01542206efc8aaf608076a3570f7bfd14bsalomon@google.com                                      size_t* maxTextureBytes) const {
5709605bac01542206efc8aaf608076a3570f7bfd14bsalomon@google.com    fTextureCache->getLimits(maxTextures, maxTextureBytes);
5713f30e3a41fc16816105e28e0d4c241eff6d391b4bsalomon@google.com}
5723f30e3a41fc16816105e28e0d4c241eff6d391b4bsalomon@google.com
5739605bac01542206efc8aaf608076a3570f7bfd14bsalomon@google.comvoid GrContext::setTextureCacheLimits(int maxTextures, size_t maxTextureBytes) {
5749605bac01542206efc8aaf608076a3570f7bfd14bsalomon@google.com    fTextureCache->setLimits(maxTextures, maxTextureBytes);
5753f30e3a41fc16816105e28e0d4c241eff6d391b4bsalomon@google.com}
5763f30e3a41fc16816105e28e0d4c241eff6d391b4bsalomon@google.com
5773f30e3a41fc16816105e28e0d4c241eff6d391b4bsalomon@google.comint GrContext::getMaxTextureSize() const {
578b79edfc18351e566f1b395ccb2b9f25bd35bb930robertphillips@google.com    return GrMin(fGpu->caps()->maxTextureSize(), fMaxTextureSizeOverride);
5793f30e3a41fc16816105e28e0d4c241eff6d391b4bsalomon@google.com}
5803f30e3a41fc16816105e28e0d4c241eff6d391b4bsalomon@google.com
5813f30e3a41fc16816105e28e0d4c241eff6d391b4bsalomon@google.comint GrContext::getMaxRenderTargetSize() const {
58259831d70980761e3d9403a122c46e996a5d32543bsalomon@google.com    return fGpu->caps()->maxRenderTargetSize();
5833f30e3a41fc16816105e28e0d4c241eff6d391b4bsalomon@google.com}
5843f30e3a41fc16816105e28e0d4c241eff6d391b4bsalomon@google.com
5853c02eaffc61fc15c1d15d8b7ff947a7276c2fcfabsalomon@google.comint GrContext::getMaxSampleCount() const {
58659831d70980761e3d9403a122c46e996a5d32543bsalomon@google.com    return fGpu->caps()->maxSampleCount();
5873c02eaffc61fc15c1d15d8b7ff947a7276c2fcfabsalomon@google.com}
5883c02eaffc61fc15c1d15d8b7ff947a7276c2fcfabsalomon@google.com
5893f30e3a41fc16816105e28e0d4c241eff6d391b4bsalomon@google.com///////////////////////////////////////////////////////////////////////////////
5903f30e3a41fc16816105e28e0d4c241eff6d391b4bsalomon@google.com
591cff60e9fc895438fae7733789ef0cd02327ca38dbsalomon@google.comGrTexture* GrContext::wrapBackendTexture(const GrBackendTextureDesc& desc) {
592cff60e9fc895438fae7733789ef0cd02327ca38dbsalomon@google.com    return fGpu->wrapBackendTexture(desc);
593015266273f0c3be52f93983d714cb3cd35756b8bbsalomon@google.com}
594015266273f0c3be52f93983d714cb3cd35756b8bbsalomon@google.com
595cff60e9fc895438fae7733789ef0cd02327ca38dbsalomon@google.comGrRenderTarget* GrContext::wrapBackendRenderTarget(const GrBackendRenderTargetDesc& desc) {
596cff60e9fc895438fae7733789ef0cd02327ca38dbsalomon@google.com    return fGpu->wrapBackendRenderTarget(desc);
597015266273f0c3be52f93983d714cb3cd35756b8bbsalomon@google.com}
598015266273f0c3be52f93983d714cb3cd35756b8bbsalomon@google.com
5993f30e3a41fc16816105e28e0d4c241eff6d391b4bsalomon@google.com///////////////////////////////////////////////////////////////////////////////
6003f30e3a41fc16816105e28e0d4c241eff6d391b4bsalomon@google.com
60120c50f7c5feda26ad659838c4f3824c47aa36903bsalomon@google.combool GrContext::supportsIndex8PixelConfig(const GrTextureParams* params,
6023f30e3a41fc16816105e28e0d4c241eff6d391b4bsalomon@google.com                                          int width, int height) const {
603516b4c312ba95ab60863c325482ee6c36618f706bsalomon@google.com    const GrDrawTargetCaps* caps = fGpu->caps();
60459831d70980761e3d9403a122c46e996a5d32543bsalomon@google.com    if (!caps->eightBitPaletteSupport()) {
6053f30e3a41fc16816105e28e0d4c241eff6d391b4bsalomon@google.com        return false;
6063f30e3a41fc16816105e28e0d4c241eff6d391b4bsalomon@google.com    }
6073f30e3a41fc16816105e28e0d4c241eff6d391b4bsalomon@google.com
6083f30e3a41fc16816105e28e0d4c241eff6d391b4bsalomon@google.com    bool isPow2 = GrIsPow2(width) && GrIsPow2(height);
6093f30e3a41fc16816105e28e0d4c241eff6d391b4bsalomon@google.com
6103f30e3a41fc16816105e28e0d4c241eff6d391b4bsalomon@google.com    if (!isPow2) {
61120c50f7c5feda26ad659838c4f3824c47aa36903bsalomon@google.com        bool tiled = NULL != params && params->isTiled();
61259831d70980761e3d9403a122c46e996a5d32543bsalomon@google.com        if (tiled && !caps->npotTextureTileSupport()) {
6133f30e3a41fc16816105e28e0d4c241eff6d391b4bsalomon@google.com            return false;
6143f30e3a41fc16816105e28e0d4c241eff6d391b4bsalomon@google.com        }
6153f30e3a41fc16816105e28e0d4c241eff6d391b4bsalomon@google.com    }
6163f30e3a41fc16816105e28e0d4c241eff6d391b4bsalomon@google.com    return true;
6173f30e3a41fc16816105e28e0d4c241eff6d391b4bsalomon@google.com}
6183f30e3a41fc16816105e28e0d4c241eff6d391b4bsalomon@google.com
6193f30e3a41fc16816105e28e0d4c241eff6d391b4bsalomon@google.com
6203f30e3a41fc16816105e28e0d4c241eff6d391b4bsalomon@google.com////////////////////////////////////////////////////////////////////////////////
6213f30e3a41fc16816105e28e0d4c241eff6d391b4bsalomon@google.com
622a8cbc57c2d74f8024d149370377bd7dcbd8d204ccommit-bot@chromium.orgvoid GrContext::clear(const SkIRect* rect,
6233bf3da2c23cf17d4711ec6ccb6e9965ae74e7b1dbsalomon@google.com                      const GrColor color,
624163b5b016e779d13fa2a4aba29c79acd9387c949robertphillips@google.com                      bool canIgnoreRect,
6251f218673ae464de98d775cfcb4bfd31f8949848brobertphillips@google.com                      GrRenderTarget* target) {
626860912a0affd82bc6b30ad9006658df856ca1d17bsalomon@google.com    AutoRestoreEffects are;
62721c4256a8eccc702d1c4b561da1a3a3e212d3c23commit-bot@chromium.org    AutoCheckFlush acf(this);
6286235b57cdb313411e9e42cbea6c25a858d308455skia.committer@gmail.com    this->prepareToDraw(NULL, BUFFERED_DRAW, &are, &acf)->clear(rect, color,
629163b5b016e779d13fa2a4aba29c79acd9387c949robertphillips@google.com                                                                canIgnoreRect, target);
6303f30e3a41fc16816105e28e0d4c241eff6d391b4bsalomon@google.com}
6313f30e3a41fc16816105e28e0d4c241eff6d391b4bsalomon@google.com
632d87737fd8acef6b668aabb5d406bbd63f417ffbbbsalomon@google.comvoid GrContext::drawPaint(const GrPaint& origPaint) {
6333f30e3a41fc16816105e28e0d4c241eff6d391b4bsalomon@google.com    // set rect to be big enough to fill the space, but not super-huge, so we
6343f30e3a41fc16816105e28e0d4c241eff6d391b4bsalomon@google.com    // don't overflow fixed-point implementations
635a8cbc57c2d74f8024d149370377bd7dcbd8d204ccommit-bot@chromium.org    SkRect r;
6363f30e3a41fc16816105e28e0d4c241eff6d391b4bsalomon@google.com    r.setLTRB(0, 0,
6373a729be1ae6a0bdfb6a8745f1859e8cb7f23baddbsalomon@google.com              SkIntToScalar(getRenderTarget()->width()),
6383a729be1ae6a0bdfb6a8745f1859e8cb7f23baddbsalomon@google.com              SkIntToScalar(getRenderTarget()->height()));
639a4e2f5beb2d73243c15ab871f013d2ba29e8fea3bsalomon@google.com    SkMatrix inverse;
640d87737fd8acef6b668aabb5d406bbd63f417ffbbbsalomon@google.com    SkTCopyOnFirstWrite<GrPaint> paint(origPaint);
6410257ff4808205746950a32a65e03a35e31c987b6robertphillips@google.com    AutoMatrix am;
642c08edffbcbe0eed40d8855f8acfe439c237c43bdbsalomon@google.com
6433f30e3a41fc16816105e28e0d4c241eff6d391b4bsalomon@google.com    // We attempt to map r by the inverse matrix and draw that. mapRect will
6443f30e3a41fc16816105e28e0d4c241eff6d391b4bsalomon@google.com    // map the four corners and bound them with a new rect. This will not
6453f30e3a41fc16816105e28e0d4c241eff6d391b4bsalomon@google.com    // produce a correct result for some perspective matrices.
6463f30e3a41fc16816105e28e0d4c241eff6d391b4bsalomon@google.com    if (!this->getMatrix().hasPerspective()) {
647e1884e6f16a6dd9f457970ffab3887e01f268703commit-bot@chromium.org        if (!fViewMatrix.invert(&inverse)) {
6487cb60d6f6638f4f9866af50615b3972fb99f812fbsalomon@google.com            GrPrintf("Could not invert matrix\n");
6493f30e3a41fc16816105e28e0d4c241eff6d391b4bsalomon@google.com            return;
6503f30e3a41fc16816105e28e0d4c241eff6d391b4bsalomon@google.com        }
6513f30e3a41fc16816105e28e0d4c241eff6d391b4bsalomon@google.com        inverse.mapRect(&r);
6523f30e3a41fc16816105e28e0d4c241eff6d391b4bsalomon@google.com    } else {
6534a8cc154cd99f8c03d606d62685a21a9264272a0bsalomon@google.com        if (!am.setIdentity(this, paint.writable())) {
6544a8cc154cd99f8c03d606d62685a21a9264272a0bsalomon@google.com            GrPrintf("Could not invert matrix\n");
6554a8cc154cd99f8c03d606d62685a21a9264272a0bsalomon@google.com            return;
6563f30e3a41fc16816105e28e0d4c241eff6d391b4bsalomon@google.com        }
6573f30e3a41fc16816105e28e0d4c241eff6d391b4bsalomon@google.com    }
6583f30e3a41fc16816105e28e0d4c241eff6d391b4bsalomon@google.com    // by definition this fills the entire clip, no need for AA
659d87737fd8acef6b668aabb5d406bbd63f417ffbbbsalomon@google.com    if (paint->isAntiAlias()) {
660d87737fd8acef6b668aabb5d406bbd63f417ffbbbsalomon@google.com        paint.writable()->setAntiAlias(false);
6613f30e3a41fc16816105e28e0d4c241eff6d391b4bsalomon@google.com    }
662d87737fd8acef6b668aabb5d406bbd63f417ffbbbsalomon@google.com    this->drawRect(*paint, r);
6633f30e3a41fc16816105e28e0d4c241eff6d391b4bsalomon@google.com}
6643f30e3a41fc16816105e28e0d4c241eff6d391b4bsalomon@google.com
665f241537f949536383a3eadfc8c14b9a682f64f8ccommit-bot@chromium.org#ifdef SK_DEVELOPER
666f241537f949536383a3eadfc8c14b9a682f64f8ccommit-bot@chromium.orgvoid GrContext::dumpFontCache() const {
667f241537f949536383a3eadfc8c14b9a682f64f8ccommit-bot@chromium.org    fFontCache->dump();
668f241537f949536383a3eadfc8c14b9a682f64f8ccommit-bot@chromium.org}
669f241537f949536383a3eadfc8c14b9a682f64f8ccommit-bot@chromium.org#endif
670f241537f949536383a3eadfc8c14b9a682f64f8ccommit-bot@chromium.org
6713f30e3a41fc16816105e28e0d4c241eff6d391b4bsalomon@google.com////////////////////////////////////////////////////////////////////////////////
6723f30e3a41fc16816105e28e0d4c241eff6d391b4bsalomon@google.com
6733f30e3a41fc16816105e28e0d4c241eff6d391b4bsalomon@google.com/*  create a triangle strip that strokes the specified triangle. There are 8
6743f30e3a41fc16816105e28e0d4c241eff6d391b4bsalomon@google.com unique vertices, but we repreat the last 2 to close up. Alternatively we
6753f30e3a41fc16816105e28e0d4c241eff6d391b4bsalomon@google.com could use an indices array, and then only send 8 verts, but not sure that
6763f30e3a41fc16816105e28e0d4c241eff6d391b4bsalomon@google.com would be faster.
6773f30e3a41fc16816105e28e0d4c241eff6d391b4bsalomon@google.com */
678a8cbc57c2d74f8024d149370377bd7dcbd8d204ccommit-bot@chromium.orgstatic void setStrokeRectStrip(GrPoint verts[10], SkRect rect,
6793a729be1ae6a0bdfb6a8745f1859e8cb7f23baddbsalomon@google.com                               SkScalar width) {
6803a729be1ae6a0bdfb6a8745f1859e8cb7f23baddbsalomon@google.com    const SkScalar rad = SkScalarHalf(width);
6813f30e3a41fc16816105e28e0d4c241eff6d391b4bsalomon@google.com    rect.sort();
6823f30e3a41fc16816105e28e0d4c241eff6d391b4bsalomon@google.com
6833f30e3a41fc16816105e28e0d4c241eff6d391b4bsalomon@google.com    verts[0].set(rect.fLeft + rad, rect.fTop + rad);
6843f30e3a41fc16816105e28e0d4c241eff6d391b4bsalomon@google.com    verts[1].set(rect.fLeft - rad, rect.fTop - rad);
6853f30e3a41fc16816105e28e0d4c241eff6d391b4bsalomon@google.com    verts[2].set(rect.fRight - rad, rect.fTop + rad);
6863f30e3a41fc16816105e28e0d4c241eff6d391b4bsalomon@google.com    verts[3].set(rect.fRight + rad, rect.fTop - rad);
6873f30e3a41fc16816105e28e0d4c241eff6d391b4bsalomon@google.com    verts[4].set(rect.fRight - rad, rect.fBottom - rad);
6883f30e3a41fc16816105e28e0d4c241eff6d391b4bsalomon@google.com    verts[5].set(rect.fRight + rad, rect.fBottom + rad);
6893f30e3a41fc16816105e28e0d4c241eff6d391b4bsalomon@google.com    verts[6].set(rect.fLeft + rad, rect.fBottom - rad);
6903f30e3a41fc16816105e28e0d4c241eff6d391b4bsalomon@google.com    verts[7].set(rect.fLeft - rad, rect.fBottom + rad);
6913f30e3a41fc16816105e28e0d4c241eff6d391b4bsalomon@google.com    verts[8] = verts[0];
6923f30e3a41fc16816105e28e0d4c241eff6d391b4bsalomon@google.com    verts[9] = verts[1];
6933f30e3a41fc16816105e28e0d4c241eff6d391b4bsalomon@google.com}
6943f30e3a41fc16816105e28e0d4c241eff6d391b4bsalomon@google.com
695a8cbc57c2d74f8024d149370377bd7dcbd8d204ccommit-bot@chromium.orgstatic bool isIRect(const SkRect& r) {
6964cdd0d47e79464d82e0c49bffd7635eab633e552skia.committer@gmail.com    return SkScalarIsInt(r.fLeft)  && SkScalarIsInt(r.fTop) &&
6974cdd0d47e79464d82e0c49bffd7635eab633e552skia.committer@gmail.com           SkScalarIsInt(r.fRight) && SkScalarIsInt(r.fBottom);
6980d4d39654e55999edb3ef20aa4acbe681045d8e5robertphillips@google.com}
6990d4d39654e55999edb3ef20aa4acbe681045d8e5robertphillips@google.com
7003f30e3a41fc16816105e28e0d4c241eff6d391b4bsalomon@google.comstatic bool apply_aa_to_rect(GrDrawTarget* target,
701a8cbc57c2d74f8024d149370377bd7dcbd8d204ccommit-bot@chromium.org                             const SkRect& rect,
7025b0f4b63c1ecef4655e1cef93a2972c8b0743d08robertphillips@google.com                             SkScalar strokeWidth,
7034bdbb2f0f10b9631e80a19b2b15fa4131cf4d1d9commit-bot@chromium.org                             const SkMatrix& combinedMatrix,
7044bdbb2f0f10b9631e80a19b2b15fa4131cf4d1d9commit-bot@chromium.org                             SkRect* devBoundRect,
7053f30e3a41fc16816105e28e0d4c241eff6d391b4bsalomon@google.com                             bool* useVertexCoverage) {
706561a891178a2db336b6bc2e53be8c82ed9e0fdffbsalomon@google.com    // we use a simple coverage ramp to do aa on axis-aligned rects
707935e9f4fafdfc64130e6be9ea2bb30e3bafd852armistry@google.com    // we check if the rect will be axis-aligned, and the rect won't land on
708561a891178a2db336b6bc2e53be8c82ed9e0fdffbsalomon@google.com    // integer coords.
7093f30e3a41fc16816105e28e0d4c241eff6d391b4bsalomon@google.com
7103f30e3a41fc16816105e28e0d4c241eff6d391b4bsalomon@google.com    // we are keeping around the "tweak the alpha" trick because
7113f30e3a41fc16816105e28e0d4c241eff6d391b4bsalomon@google.com    // it is our only hope for the fixed-pipe implementation.
7123f30e3a41fc16816105e28e0d4c241eff6d391b4bsalomon@google.com    // In a shader implementation we can give a separate coverage input
713f9ba6e3339b8414de3674c55d86267212b99b07fbsalomon@google.com    // TODO: remove this ugliness when we drop the fixed-pipe impl
7143f30e3a41fc16816105e28e0d4c241eff6d391b4bsalomon@google.com    *useVertexCoverage = false;
715f1a7c7962e72d83a3bf733d2c39571b513b2df32bsalomon@google.com    if (!target->getDrawState().canTweakAlphaForCoverage()) {
716f19fb364a079dea27c6f99e5bb3d18cc0e86aa54commit-bot@chromium.org        if (target->shouldDisableCoverageAAForBlend()) {
7170fde04d1de4773e5168a56dbd455b77e1424434acommit-bot@chromium.org#ifdef SK_DEBUG
718561a891178a2db336b6bc2e53be8c82ed9e0fdffbsalomon@google.com            //GrPrintf("Turning off AA to correctly apply blend.\n");
7193f30e3a41fc16816105e28e0d4c241eff6d391b4bsalomon@google.com#endif
7203f30e3a41fc16816105e28e0d4c241eff6d391b4bsalomon@google.com            return false;
721561a891178a2db336b6bc2e53be8c82ed9e0fdffbsalomon@google.com        } else {
722561a891178a2db336b6bc2e53be8c82ed9e0fdffbsalomon@google.com            *useVertexCoverage = true;
7233f30e3a41fc16816105e28e0d4c241eff6d391b4bsalomon@google.com        }
7243f30e3a41fc16816105e28e0d4c241eff6d391b4bsalomon@google.com    }
725c08edffbcbe0eed40d8855f8acfe439c237c43bdbsalomon@google.com    const GrDrawState& drawState = target->getDrawState();
726c08edffbcbe0eed40d8855f8acfe439c237c43bdbsalomon@google.com    if (drawState.getRenderTarget()->isMultisampled()) {
7273f30e3a41fc16816105e28e0d4c241eff6d391b4bsalomon@google.com        return false;
7283f30e3a41fc16816105e28e0d4c241eff6d391b4bsalomon@google.com    }
7293f30e3a41fc16816105e28e0d4c241eff6d391b4bsalomon@google.com
7305b0f4b63c1ecef4655e1cef93a2972c8b0743d08robertphillips@google.com    if (0 == strokeWidth && target->willUseHWAALines()) {
7313f30e3a41fc16816105e28e0d4c241eff6d391b4bsalomon@google.com        return false;
7323f30e3a41fc16816105e28e0d4c241eff6d391b4bsalomon@google.com    }
7333f30e3a41fc16816105e28e0d4c241eff6d391b4bsalomon@google.com
7347867a44b8777a4ce72ab65bdbb0a07bb1a9a7204robertphillips@google.com#if defined(SHADER_AA_FILL_RECT) || !defined(IGNORE_ROT_AA_RECT_OPT)
7355b0f4b63c1ecef4655e1cef93a2972c8b0743d08robertphillips@google.com    if (strokeWidth >= 0) {
7365b0f4b63c1ecef4655e1cef93a2972c8b0743d08robertphillips@google.com#endif
7374bdbb2f0f10b9631e80a19b2b15fa4131cf4d1d9commit-bot@chromium.org        if (!combinedMatrix.preservesAxisAlignment()) {
7385b0f4b63c1ecef4655e1cef93a2972c8b0743d08robertphillips@google.com            return false;
7395b0f4b63c1ecef4655e1cef93a2972c8b0743d08robertphillips@google.com        }
7403f30e3a41fc16816105e28e0d4c241eff6d391b4bsalomon@google.com
7417867a44b8777a4ce72ab65bdbb0a07bb1a9a7204robertphillips@google.com#if defined(SHADER_AA_FILL_RECT) || !defined(IGNORE_ROT_AA_RECT_OPT)
7425b0f4b63c1ecef4655e1cef93a2972c8b0743d08robertphillips@google.com    } else {
7434bdbb2f0f10b9631e80a19b2b15fa4131cf4d1d9commit-bot@chromium.org        if (!combinedMatrix.preservesRightAngles()) {
7445b0f4b63c1ecef4655e1cef93a2972c8b0743d08robertphillips@google.com            return false;
7455b0f4b63c1ecef4655e1cef93a2972c8b0743d08robertphillips@google.com        }
7463f30e3a41fc16816105e28e0d4c241eff6d391b4bsalomon@google.com    }
7475b0f4b63c1ecef4655e1cef93a2972c8b0743d08robertphillips@google.com#endif
7483f30e3a41fc16816105e28e0d4c241eff6d391b4bsalomon@google.com
7494bdbb2f0f10b9631e80a19b2b15fa4131cf4d1d9commit-bot@chromium.org    combinedMatrix.mapRect(devBoundRect, rect);
7500afcae3e5dc0d8ce456272af0ebf9556e8d4165brobertphillips@google.com
7510d4d39654e55999edb3ef20aa4acbe681045d8e5robertphillips@google.com    if (strokeWidth < 0) {
7524bdbb2f0f10b9631e80a19b2b15fa4131cf4d1d9commit-bot@chromium.org        return !isIRect(*devBoundRect);
7530d4d39654e55999edb3ef20aa4acbe681045d8e5robertphillips@google.com    } else {
7540d4d39654e55999edb3ef20aa4acbe681045d8e5robertphillips@google.com        return true;
7550d4d39654e55999edb3ef20aa4acbe681045d8e5robertphillips@google.com    }
7563f30e3a41fc16816105e28e0d4c241eff6d391b4bsalomon@google.com}
7573f30e3a41fc16816105e28e0d4c241eff6d391b4bsalomon@google.com
7584bdbb2f0f10b9631e80a19b2b15fa4131cf4d1d9commit-bot@chromium.orgstatic inline bool rect_contains_inclusive(const SkRect& rect, const SkPoint& point) {
7594bdbb2f0f10b9631e80a19b2b15fa4131cf4d1d9commit-bot@chromium.org    return point.fX >= rect.fLeft && point.fX <= rect.fRight &&
7604bdbb2f0f10b9631e80a19b2b15fa4131cf4d1d9commit-bot@chromium.org           point.fY >= rect.fTop && point.fY <= rect.fBottom;
7614bdbb2f0f10b9631e80a19b2b15fa4131cf4d1d9commit-bot@chromium.org}
7624bdbb2f0f10b9631e80a19b2b15fa4131cf4d1d9commit-bot@chromium.org
7633f30e3a41fc16816105e28e0d4c241eff6d391b4bsalomon@google.comvoid GrContext::drawRect(const GrPaint& paint,
764a8cbc57c2d74f8024d149370377bd7dcbd8d204ccommit-bot@chromium.org                         const SkRect& rect,
7656042c856257ef0bb332f4fa0e7e640660f2183d2commit-bot@chromium.org                         const SkStrokeRec* stroke,
766a4e2f5beb2d73243c15ab871f013d2ba29e8fea3bsalomon@google.com                         const SkMatrix* matrix) {
7673f30e3a41fc16816105e28e0d4c241eff6d391b4bsalomon@google.com    SK_TRACE_EVENT0("GrContext::drawRect");
7683f30e3a41fc16816105e28e0d4c241eff6d391b4bsalomon@google.com
769860912a0affd82bc6b30ad9006658df856ca1d17bsalomon@google.com    AutoRestoreEffects are;
77021c4256a8eccc702d1c4b561da1a3a3e212d3c23commit-bot@chromium.org    AutoCheckFlush acf(this);
77121c4256a8eccc702d1c4b561da1a3a3e212d3c23commit-bot@chromium.org    GrDrawTarget* target = this->prepareToDraw(&paint, BUFFERED_DRAW, &are, &acf);
7723f30e3a41fc16816105e28e0d4c241eff6d391b4bsalomon@google.com
7736042c856257ef0bb332f4fa0e7e640660f2183d2commit-bot@chromium.org    SkScalar width = stroke == NULL ? -1 : stroke->getWidth();
7744bdbb2f0f10b9631e80a19b2b15fa4131cf4d1d9commit-bot@chromium.org    SkMatrix combinedMatrix = target->drawState()->getViewMatrix();
7754bdbb2f0f10b9631e80a19b2b15fa4131cf4d1d9commit-bot@chromium.org    if (NULL != matrix) {
7764bdbb2f0f10b9631e80a19b2b15fa4131cf4d1d9commit-bot@chromium.org        combinedMatrix.preConcat(*matrix);
7774bdbb2f0f10b9631e80a19b2b15fa4131cf4d1d9commit-bot@chromium.org    }
7784bdbb2f0f10b9631e80a19b2b15fa4131cf4d1d9commit-bot@chromium.org
7794bdbb2f0f10b9631e80a19b2b15fa4131cf4d1d9commit-bot@chromium.org    // Check if this is a full RT draw and can be replaced with a clear. We don't bother checking
7804bdbb2f0f10b9631e80a19b2b15fa4131cf4d1d9commit-bot@chromium.org    // cases where the RT is fully inside a stroke.
7814bdbb2f0f10b9631e80a19b2b15fa4131cf4d1d9commit-bot@chromium.org    if (width < 0) {
7824bdbb2f0f10b9631e80a19b2b15fa4131cf4d1d9commit-bot@chromium.org        SkRect rtRect;
7834bdbb2f0f10b9631e80a19b2b15fa4131cf4d1d9commit-bot@chromium.org        target->getDrawState().getRenderTarget()->getBoundsRect(&rtRect);
7844bdbb2f0f10b9631e80a19b2b15fa4131cf4d1d9commit-bot@chromium.org        SkRect clipSpaceRTRect = rtRect;
7854bdbb2f0f10b9631e80a19b2b15fa4131cf4d1d9commit-bot@chromium.org        bool checkClip = false;
7864bdbb2f0f10b9631e80a19b2b15fa4131cf4d1d9commit-bot@chromium.org        if (NULL != this->getClip()) {
7874bdbb2f0f10b9631e80a19b2b15fa4131cf4d1d9commit-bot@chromium.org            checkClip = true;
7884bdbb2f0f10b9631e80a19b2b15fa4131cf4d1d9commit-bot@chromium.org            clipSpaceRTRect.offset(SkIntToScalar(this->getClip()->fOrigin.fX),
7894bdbb2f0f10b9631e80a19b2b15fa4131cf4d1d9commit-bot@chromium.org                                   SkIntToScalar(this->getClip()->fOrigin.fY));
7904bdbb2f0f10b9631e80a19b2b15fa4131cf4d1d9commit-bot@chromium.org        }
7914bdbb2f0f10b9631e80a19b2b15fa4131cf4d1d9commit-bot@chromium.org        // Does the clip contain the entire RT?
7924bdbb2f0f10b9631e80a19b2b15fa4131cf4d1d9commit-bot@chromium.org        if (!checkClip || target->getClip()->fClipStack->quickContains(clipSpaceRTRect)) {
7934bdbb2f0f10b9631e80a19b2b15fa4131cf4d1d9commit-bot@chromium.org            SkMatrix invM;
7944bdbb2f0f10b9631e80a19b2b15fa4131cf4d1d9commit-bot@chromium.org            if (!combinedMatrix.invert(&invM)) {
7954bdbb2f0f10b9631e80a19b2b15fa4131cf4d1d9commit-bot@chromium.org                return;
7964bdbb2f0f10b9631e80a19b2b15fa4131cf4d1d9commit-bot@chromium.org            }
7974bdbb2f0f10b9631e80a19b2b15fa4131cf4d1d9commit-bot@chromium.org            // Does the rect bound the RT?
7984bdbb2f0f10b9631e80a19b2b15fa4131cf4d1d9commit-bot@chromium.org            SkPoint srcSpaceRTQuad[4];
7994bdbb2f0f10b9631e80a19b2b15fa4131cf4d1d9commit-bot@chromium.org            invM.mapRectToQuad(srcSpaceRTQuad, rtRect);
8004bdbb2f0f10b9631e80a19b2b15fa4131cf4d1d9commit-bot@chromium.org            if (rect_contains_inclusive(rect, srcSpaceRTQuad[0]) &&
8014bdbb2f0f10b9631e80a19b2b15fa4131cf4d1d9commit-bot@chromium.org                rect_contains_inclusive(rect, srcSpaceRTQuad[1]) &&
8024bdbb2f0f10b9631e80a19b2b15fa4131cf4d1d9commit-bot@chromium.org                rect_contains_inclusive(rect, srcSpaceRTQuad[2]) &&
8034bdbb2f0f10b9631e80a19b2b15fa4131cf4d1d9commit-bot@chromium.org                rect_contains_inclusive(rect, srcSpaceRTQuad[3])) {
8044bdbb2f0f10b9631e80a19b2b15fa4131cf4d1d9commit-bot@chromium.org                // Will it blend?
8054bdbb2f0f10b9631e80a19b2b15fa4131cf4d1d9commit-bot@chromium.org                GrColor clearColor;
8064bdbb2f0f10b9631e80a19b2b15fa4131cf4d1d9commit-bot@chromium.org                if (paint.isOpaqueAndConstantColor(&clearColor)) {
807163b5b016e779d13fa2a4aba29c79acd9387c949robertphillips@google.com                    target->clear(NULL, clearColor, true);
8084bdbb2f0f10b9631e80a19b2b15fa4131cf4d1d9commit-bot@chromium.org                    return;
8094bdbb2f0f10b9631e80a19b2b15fa4131cf4d1d9commit-bot@chromium.org                }
8104bdbb2f0f10b9631e80a19b2b15fa4131cf4d1d9commit-bot@chromium.org            }
8114bdbb2f0f10b9631e80a19b2b15fa4131cf4d1d9commit-bot@chromium.org        }
8124bdbb2f0f10b9631e80a19b2b15fa4131cf4d1d9commit-bot@chromium.org    }
8134bdbb2f0f10b9631e80a19b2b15fa4131cf4d1d9commit-bot@chromium.org
8144bdbb2f0f10b9631e80a19b2b15fa4131cf4d1d9commit-bot@chromium.org    SkRect devBoundRect;
8153f30e3a41fc16816105e28e0d4c241eff6d391b4bsalomon@google.com    bool useVertexCoverage;
8163b8881bd5fb598fafb295c6a5562115873960f5ebsalomon@google.com    bool needAA = paint.isAntiAlias() &&
817e1884e6f16a6dd9f457970ffab3887e01f268703commit-bot@chromium.org                  !target->getDrawState().getRenderTarget()->isMultisampled();
8184bdbb2f0f10b9631e80a19b2b15fa4131cf4d1d9commit-bot@chromium.org    bool doAA = needAA && apply_aa_to_rect(target, rect, width, combinedMatrix, &devBoundRect,
819f9ba6e3339b8414de3674c55d86267212b99b07fbsalomon@google.com                                           &useVertexCoverage);
8203f30e3a41fc16816105e28e0d4c241eff6d391b4bsalomon@google.com    if (doAA) {
821fbf9f30e11f6dfae9203b152092125fe9b47adb8bsalomon@google.com        GrDrawState::AutoViewMatrixRestore avmr;
822fbf9f30e11f6dfae9203b152092125fe9b47adb8bsalomon@google.com        if (!avmr.setIdentity(target->drawState())) {
8237cb60d6f6638f4f9866af50615b3972fb99f812fbsalomon@google.com            return;
8247cb60d6f6638f4f9866af50615b3972fb99f812fbsalomon@google.com        }
8253f30e3a41fc16816105e28e0d4c241eff6d391b4bsalomon@google.com        if (width >= 0) {
8266042c856257ef0bb332f4fa0e7e640660f2183d2commit-bot@chromium.org            fAARectRenderer->strokeAARect(this->getGpu(), target, rect,
8276042c856257ef0bb332f4fa0e7e640660f2183d2commit-bot@chromium.org                                          combinedMatrix, devBoundRect,
8286042c856257ef0bb332f4fa0e7e640660f2183d2commit-bot@chromium.org                                          stroke, useVertexCoverage);
8293f30e3a41fc16816105e28e0d4c241eff6d391b4bsalomon@google.com        } else {
8305b0f4b63c1ecef4655e1cef93a2972c8b0743d08robertphillips@google.com            // filled AA rect
831935e9f4fafdfc64130e6be9ea2bb30e3bafd852armistry@google.com            fAARectRenderer->fillAARect(this->getGpu(), target,
8324bdbb2f0f10b9631e80a19b2b15fa4131cf4d1d9commit-bot@chromium.org                                        rect, combinedMatrix, devBoundRect,
833b94d10665366901ae9fda0c98d75ffbbd71ff8c4robertphillips@google.com                                        useVertexCoverage);
8343f30e3a41fc16816105e28e0d4c241eff6d391b4bsalomon@google.com        }
8353f30e3a41fc16816105e28e0d4c241eff6d391b4bsalomon@google.com        return;
8363f30e3a41fc16816105e28e0d4c241eff6d391b4bsalomon@google.com    }
8373f30e3a41fc16816105e28e0d4c241eff6d391b4bsalomon@google.com
8383f30e3a41fc16816105e28e0d4c241eff6d391b4bsalomon@google.com    if (width >= 0) {
8393f30e3a41fc16816105e28e0d4c241eff6d391b4bsalomon@google.com        // TODO: consider making static vertex buffers for these cases.
8409b2fd0c3f52229a5618434a4236b96ec4c73dd98bsalomon@google.com        // Hairline could be done by just adding closing vertex to
8419b2fd0c3f52229a5618434a4236b96ec4c73dd98bsalomon@google.com        // unitSquareVertexBuffer()
8423f30e3a41fc16816105e28e0d4c241eff6d391b4bsalomon@google.com
8433f30e3a41fc16816105e28e0d4c241eff6d391b4bsalomon@google.com        static const int worstCaseVertCount = 10;
844768cceef720ead8767ded5f384d880fc9905dc14jvanverth@google.com        target->drawState()->setDefaultVertexAttribs();
8459d8e4b7e65a6b644564e2f2b94730f74b88941e5jvanverth@google.com        GrDrawTarget::AutoReleaseGeometry geo(target, worstCaseVertCount, 0);
8463f30e3a41fc16816105e28e0d4c241eff6d391b4bsalomon@google.com
8473f30e3a41fc16816105e28e0d4c241eff6d391b4bsalomon@google.com        if (!geo.succeeded()) {
8483f30e3a41fc16816105e28e0d4c241eff6d391b4bsalomon@google.com            GrPrintf("Failed to get space for vertices!\n");
8493f30e3a41fc16816105e28e0d4c241eff6d391b4bsalomon@google.com            return;
8503f30e3a41fc16816105e28e0d4c241eff6d391b4bsalomon@google.com        }
8513f30e3a41fc16816105e28e0d4c241eff6d391b4bsalomon@google.com
8523f30e3a41fc16816105e28e0d4c241eff6d391b4bsalomon@google.com        GrPrimitiveType primType;
8533f30e3a41fc16816105e28e0d4c241eff6d391b4bsalomon@google.com        int vertCount;
8543f30e3a41fc16816105e28e0d4c241eff6d391b4bsalomon@google.com        GrPoint* vertex = geo.positions();
8553f30e3a41fc16816105e28e0d4c241eff6d391b4bsalomon@google.com
8563f30e3a41fc16816105e28e0d4c241eff6d391b4bsalomon@google.com        if (width > 0) {
8573f30e3a41fc16816105e28e0d4c241eff6d391b4bsalomon@google.com            vertCount = 10;
8587de94cd88f290887d0c09549902c9f3890265ff2bsalomon@google.com            primType = kTriangleStrip_GrPrimitiveType;
8593f30e3a41fc16816105e28e0d4c241eff6d391b4bsalomon@google.com            setStrokeRectStrip(vertex, rect, width);
8603f30e3a41fc16816105e28e0d4c241eff6d391b4bsalomon@google.com        } else {
8613f30e3a41fc16816105e28e0d4c241eff6d391b4bsalomon@google.com            // hairline
8623f30e3a41fc16816105e28e0d4c241eff6d391b4bsalomon@google.com            vertCount = 5;
8637de94cd88f290887d0c09549902c9f3890265ff2bsalomon@google.com            primType = kLineStrip_GrPrimitiveType;
8643f30e3a41fc16816105e28e0d4c241eff6d391b4bsalomon@google.com            vertex[0].set(rect.fLeft, rect.fTop);
8653f30e3a41fc16816105e28e0d4c241eff6d391b4bsalomon@google.com            vertex[1].set(rect.fRight, rect.fTop);
8663f30e3a41fc16816105e28e0d4c241eff6d391b4bsalomon@google.com            vertex[2].set(rect.fRight, rect.fBottom);
8673f30e3a41fc16816105e28e0d4c241eff6d391b4bsalomon@google.com            vertex[3].set(rect.fLeft, rect.fBottom);
8683f30e3a41fc16816105e28e0d4c241eff6d391b4bsalomon@google.com            vertex[4].set(rect.fLeft, rect.fTop);
8693f30e3a41fc16816105e28e0d4c241eff6d391b4bsalomon@google.com        }
8703f30e3a41fc16816105e28e0d4c241eff6d391b4bsalomon@google.com
871c08edffbcbe0eed40d8855f8acfe439c237c43bdbsalomon@google.com        GrDrawState::AutoViewMatrixRestore avmr;
8723f30e3a41fc16816105e28e0d4c241eff6d391b4bsalomon@google.com        if (NULL != matrix) {
873c08edffbcbe0eed40d8855f8acfe439c237c43bdbsalomon@google.com            GrDrawState* drawState = target->drawState();
87441dcb390a0e517a6f2807b13335def36a0f47802bsalomon@google.com            avmr.set(drawState, *matrix);
8753f30e3a41fc16816105e28e0d4c241eff6d391b4bsalomon@google.com        }
8763f30e3a41fc16816105e28e0d4c241eff6d391b4bsalomon@google.com
8773f30e3a41fc16816105e28e0d4c241eff6d391b4bsalomon@google.com        target->drawNonIndexed(primType, 0, vertCount);
8783f30e3a41fc16816105e28e0d4c241eff6d391b4bsalomon@google.com    } else {
8795b0f4b63c1ecef4655e1cef93a2972c8b0743d08robertphillips@google.com        // filled BW rect
880ff8ff3003b745ab3d0d9a85a74f45ea007eac838robertphillips@google.com        target->drawSimpleRect(rect, matrix);
8813f30e3a41fc16816105e28e0d4c241eff6d391b4bsalomon@google.com    }
8823f30e3a41fc16816105e28e0d4c241eff6d391b4bsalomon@google.com}
8833f30e3a41fc16816105e28e0d4c241eff6d391b4bsalomon@google.com
8843f30e3a41fc16816105e28e0d4c241eff6d391b4bsalomon@google.comvoid GrContext::drawRectToRect(const GrPaint& paint,
885a8cbc57c2d74f8024d149370377bd7dcbd8d204ccommit-bot@chromium.org                               const SkRect& dstRect,
886a8cbc57c2d74f8024d149370377bd7dcbd8d204ccommit-bot@chromium.org                               const SkRect& localRect,
887a4e2f5beb2d73243c15ab871f013d2ba29e8fea3bsalomon@google.com                               const SkMatrix* dstMatrix,
8888bc9236bf27d711cc7fe5cd618b02d29d7c59881bsalomon@google.com                               const SkMatrix* localMatrix) {
8893f30e3a41fc16816105e28e0d4c241eff6d391b4bsalomon@google.com    SK_TRACE_EVENT0("GrContext::drawRectToRect");
890860912a0affd82bc6b30ad9006658df856ca1d17bsalomon@google.com    AutoRestoreEffects are;
89121c4256a8eccc702d1c4b561da1a3a3e212d3c23commit-bot@chromium.org    AutoCheckFlush acf(this);
89221c4256a8eccc702d1c4b561da1a3a3e212d3c23commit-bot@chromium.org    GrDrawTarget* target = this->prepareToDraw(&paint, BUFFERED_DRAW, &are, &acf);
8939b2fd0c3f52229a5618434a4236b96ec4c73dd98bsalomon@google.com
8948bc9236bf27d711cc7fe5cd618b02d29d7c59881bsalomon@google.com    target->drawRect(dstRect, dstMatrix, &localRect, localMatrix);
8953f30e3a41fc16816105e28e0d4c241eff6d391b4bsalomon@google.com}
8963f30e3a41fc16816105e28e0d4c241eff6d391b4bsalomon@google.com
897a9f1f61795e9d9019fa13e5ff1f339fc58eb84fdrobertphillips@google.comnamespace {
898a9f1f61795e9d9019fa13e5ff1f339fc58eb84fdrobertphillips@google.com
899a9f1f61795e9d9019fa13e5ff1f339fc58eb84fdrobertphillips@google.comextern const GrVertexAttrib gPosUVColorAttribs[] = {
900a9f1f61795e9d9019fa13e5ff1f339fc58eb84fdrobertphillips@google.com    {kVec2f_GrVertexAttribType,  0, kPosition_GrVertexAttribBinding },
901a9f1f61795e9d9019fa13e5ff1f339fc58eb84fdrobertphillips@google.com    {kVec2f_GrVertexAttribType,  sizeof(GrPoint), kLocalCoord_GrVertexAttribBinding },
90221ecaf9cc8f36e12ec282d88482d03dfb2271703rmistry@google.com    {kVec4ub_GrVertexAttribType, 2*sizeof(GrPoint), kColor_GrVertexAttribBinding}
903a9f1f61795e9d9019fa13e5ff1f339fc58eb84fdrobertphillips@google.com};
904a9f1f61795e9d9019fa13e5ff1f339fc58eb84fdrobertphillips@google.com
905a9f1f61795e9d9019fa13e5ff1f339fc58eb84fdrobertphillips@google.comextern const GrVertexAttrib gPosColorAttribs[] = {
906a9f1f61795e9d9019fa13e5ff1f339fc58eb84fdrobertphillips@google.com    {kVec2f_GrVertexAttribType,  0, kPosition_GrVertexAttribBinding},
907a9f1f61795e9d9019fa13e5ff1f339fc58eb84fdrobertphillips@google.com    {kVec4ub_GrVertexAttribType, sizeof(GrPoint), kColor_GrVertexAttribBinding},
908a9f1f61795e9d9019fa13e5ff1f339fc58eb84fdrobertphillips@google.com};
909a9f1f61795e9d9019fa13e5ff1f339fc58eb84fdrobertphillips@google.com
910a9f1f61795e9d9019fa13e5ff1f339fc58eb84fdrobertphillips@google.comstatic void set_vertex_attributes(GrDrawState* drawState,
911a9f1f61795e9d9019fa13e5ff1f339fc58eb84fdrobertphillips@google.com                                  const GrPoint* texCoords,
912a9f1f61795e9d9019fa13e5ff1f339fc58eb84fdrobertphillips@google.com                                  const GrColor* colors,
913a9f1f61795e9d9019fa13e5ff1f339fc58eb84fdrobertphillips@google.com                                  int* colorOffset,
914a9f1f61795e9d9019fa13e5ff1f339fc58eb84fdrobertphillips@google.com                                  int* texOffset) {
915a9f1f61795e9d9019fa13e5ff1f339fc58eb84fdrobertphillips@google.com    *texOffset = -1;
916a9f1f61795e9d9019fa13e5ff1f339fc58eb84fdrobertphillips@google.com    *colorOffset = -1;
917a9f1f61795e9d9019fa13e5ff1f339fc58eb84fdrobertphillips@google.com
918a9f1f61795e9d9019fa13e5ff1f339fc58eb84fdrobertphillips@google.com    if (NULL != texCoords && NULL != colors) {
919a9f1f61795e9d9019fa13e5ff1f339fc58eb84fdrobertphillips@google.com        *texOffset = sizeof(GrPoint);
920a9f1f61795e9d9019fa13e5ff1f339fc58eb84fdrobertphillips@google.com        *colorOffset = 2*sizeof(GrPoint);
921a9f1f61795e9d9019fa13e5ff1f339fc58eb84fdrobertphillips@google.com        drawState->setVertexAttribs<gPosUVColorAttribs>(3);
922a9f1f61795e9d9019fa13e5ff1f339fc58eb84fdrobertphillips@google.com    } else if (NULL != texCoords) {
923a9f1f61795e9d9019fa13e5ff1f339fc58eb84fdrobertphillips@google.com        *texOffset = sizeof(GrPoint);
924a9f1f61795e9d9019fa13e5ff1f339fc58eb84fdrobertphillips@google.com        drawState->setVertexAttribs<gPosUVColorAttribs>(2);
925a9f1f61795e9d9019fa13e5ff1f339fc58eb84fdrobertphillips@google.com    } else if (NULL != colors) {
926a9f1f61795e9d9019fa13e5ff1f339fc58eb84fdrobertphillips@google.com        *colorOffset = sizeof(GrPoint);
927a9f1f61795e9d9019fa13e5ff1f339fc58eb84fdrobertphillips@google.com        drawState->setVertexAttribs<gPosColorAttribs>(2);
928a9f1f61795e9d9019fa13e5ff1f339fc58eb84fdrobertphillips@google.com    } else {
929a9f1f61795e9d9019fa13e5ff1f339fc58eb84fdrobertphillips@google.com        drawState->setVertexAttribs<gPosColorAttribs>(1);
930a9f1f61795e9d9019fa13e5ff1f339fc58eb84fdrobertphillips@google.com    }
931a9f1f61795e9d9019fa13e5ff1f339fc58eb84fdrobertphillips@google.com}
932a9f1f61795e9d9019fa13e5ff1f339fc58eb84fdrobertphillips@google.com
933a9f1f61795e9d9019fa13e5ff1f339fc58eb84fdrobertphillips@google.com};
934a9f1f61795e9d9019fa13e5ff1f339fc58eb84fdrobertphillips@google.com
9353f30e3a41fc16816105e28e0d4c241eff6d391b4bsalomon@google.comvoid GrContext::drawVertices(const GrPaint& paint,
9363f30e3a41fc16816105e28e0d4c241eff6d391b4bsalomon@google.com                             GrPrimitiveType primitiveType,
9373f30e3a41fc16816105e28e0d4c241eff6d391b4bsalomon@google.com                             int vertexCount,
9383f30e3a41fc16816105e28e0d4c241eff6d391b4bsalomon@google.com                             const GrPoint positions[],
9393f30e3a41fc16816105e28e0d4c241eff6d391b4bsalomon@google.com                             const GrPoint texCoords[],
9403f30e3a41fc16816105e28e0d4c241eff6d391b4bsalomon@google.com                             const GrColor colors[],
9413f30e3a41fc16816105e28e0d4c241eff6d391b4bsalomon@google.com                             const uint16_t indices[],
9423f30e3a41fc16816105e28e0d4c241eff6d391b4bsalomon@google.com                             int indexCount) {
9433f30e3a41fc16816105e28e0d4c241eff6d391b4bsalomon@google.com    SK_TRACE_EVENT0("GrContext::drawVertices");
9443f30e3a41fc16816105e28e0d4c241eff6d391b4bsalomon@google.com
9453f30e3a41fc16816105e28e0d4c241eff6d391b4bsalomon@google.com    GrDrawTarget::AutoReleaseGeometry geo;
9463f30e3a41fc16816105e28e0d4c241eff6d391b4bsalomon@google.com
947860912a0affd82bc6b30ad9006658df856ca1d17bsalomon@google.com    AutoRestoreEffects are;
94821c4256a8eccc702d1c4b561da1a3a3e212d3c23commit-bot@chromium.org    AutoCheckFlush acf(this);
94921c4256a8eccc702d1c4b561da1a3a3e212d3c23commit-bot@chromium.org    GrDrawTarget* target = this->prepareToDraw(&paint, BUFFERED_DRAW, &are, &acf);
9503f30e3a41fc16816105e28e0d4c241eff6d391b4bsalomon@google.com
951768cceef720ead8767ded5f384d880fc9905dc14jvanverth@google.com    GrDrawState* drawState = target->drawState();
952768cceef720ead8767ded5f384d880fc9905dc14jvanverth@google.com
953768cceef720ead8767ded5f384d880fc9905dc14jvanverth@google.com    int colorOffset = -1, texOffset = -1;
954a9f1f61795e9d9019fa13e5ff1f339fc58eb84fdrobertphillips@google.com    set_vertex_attributes(drawState, texCoords, colors, &colorOffset, &texOffset);
955768cceef720ead8767ded5f384d880fc9905dc14jvanverth@google.com
956768cceef720ead8767ded5f384d880fc9905dc14jvanverth@google.com    size_t vertexSize = drawState->getVertexSize();
9573f30e3a41fc16816105e28e0d4c241eff6d391b4bsalomon@google.com    if (sizeof(GrPoint) != vertexSize) {
9589d8e4b7e65a6b644564e2f2b94730f74b88941e5jvanverth@google.com        if (!geo.set(target, vertexCount, 0)) {
9593f30e3a41fc16816105e28e0d4c241eff6d391b4bsalomon@google.com            GrPrintf("Failed to get space for vertices!\n");
9603f30e3a41fc16816105e28e0d4c241eff6d391b4bsalomon@google.com            return;
9613f30e3a41fc16816105e28e0d4c241eff6d391b4bsalomon@google.com        }
9623f30e3a41fc16816105e28e0d4c241eff6d391b4bsalomon@google.com        void* curVertex = geo.vertices();
9633f30e3a41fc16816105e28e0d4c241eff6d391b4bsalomon@google.com
9643f30e3a41fc16816105e28e0d4c241eff6d391b4bsalomon@google.com        for (int i = 0; i < vertexCount; ++i) {
9653f30e3a41fc16816105e28e0d4c241eff6d391b4bsalomon@google.com            *((GrPoint*)curVertex) = positions[i];
9663f30e3a41fc16816105e28e0d4c241eff6d391b4bsalomon@google.com
967768cceef720ead8767ded5f384d880fc9905dc14jvanverth@google.com            if (texOffset >= 0) {
968992c29694bbefcf9c987ff1e130551b98801a317jvanverth@google.com                *(GrPoint*)((intptr_t)curVertex + texOffset) = texCoords[i];
9693f30e3a41fc16816105e28e0d4c241eff6d391b4bsalomon@google.com            }
970768cceef720ead8767ded5f384d880fc9905dc14jvanverth@google.com            if (colorOffset >= 0) {
9713f30e3a41fc16816105e28e0d4c241eff6d391b4bsalomon@google.com                *(GrColor*)((intptr_t)curVertex + colorOffset) = colors[i];
9723f30e3a41fc16816105e28e0d4c241eff6d391b4bsalomon@google.com            }
9733f30e3a41fc16816105e28e0d4c241eff6d391b4bsalomon@google.com            curVertex = (void*)((intptr_t)curVertex + vertexSize);
9743f30e3a41fc16816105e28e0d4c241eff6d391b4bsalomon@google.com        }
9753f30e3a41fc16816105e28e0d4c241eff6d391b4bsalomon@google.com    } else {
9769d8e4b7e65a6b644564e2f2b94730f74b88941e5jvanverth@google.com        target->setVertexSourceToArray(positions, vertexCount);
9773f30e3a41fc16816105e28e0d4c241eff6d391b4bsalomon@google.com    }
9783f30e3a41fc16816105e28e0d4c241eff6d391b4bsalomon@google.com
979935e9f4fafdfc64130e6be9ea2bb30e3bafd852armistry@google.com    // we don't currently apply offscreen AA to this path. Need improved
9803f30e3a41fc16816105e28e0d4c241eff6d391b4bsalomon@google.com    // management of GrDrawTarget's geometry to avoid copying points per-tile.
9813f30e3a41fc16816105e28e0d4c241eff6d391b4bsalomon@google.com
9823f30e3a41fc16816105e28e0d4c241eff6d391b4bsalomon@google.com    if (NULL != indices) {
9833f30e3a41fc16816105e28e0d4c241eff6d391b4bsalomon@google.com        target->setIndexSourceToArray(indices, indexCount);
9843f30e3a41fc16816105e28e0d4c241eff6d391b4bsalomon@google.com        target->drawIndexed(primitiveType, 0, 0, vertexCount, indexCount);
985bfed24f7c476f19f4ca358e41901ff3a35872d99bsalomon@google.com        target->resetIndexSource();
9863f30e3a41fc16816105e28e0d4c241eff6d391b4bsalomon@google.com    } else {
9873f30e3a41fc16816105e28e0d4c241eff6d391b4bsalomon@google.com        target->drawNonIndexed(primitiveType, 0, vertexCount);
9883f30e3a41fc16816105e28e0d4c241eff6d391b4bsalomon@google.com    }
9893f30e3a41fc16816105e28e0d4c241eff6d391b4bsalomon@google.com}
9903f30e3a41fc16816105e28e0d4c241eff6d391b4bsalomon@google.com
9913f30e3a41fc16816105e28e0d4c241eff6d391b4bsalomon@google.com///////////////////////////////////////////////////////////////////////////////
9923a51c469906cd04bafd5cabc2bb75edb8e0693febsalomon@google.com
9939f91c15105a642b1e729f8d1ebeac4dc986eb622commit-bot@chromium.orgvoid GrContext::drawRRect(const GrPaint& paint,
9949f91c15105a642b1e729f8d1ebeac4dc986eb622commit-bot@chromium.org                          const SkRRect& rect,
9959f91c15105a642b1e729f8d1ebeac4dc986eb622commit-bot@chromium.org                          const SkStrokeRec& stroke) {
9964d077f56281afad5309f6b9ff951bb9d0b9f6f72commit-bot@chromium.org    if (rect.isEmpty()) {
9974d077f56281afad5309f6b9ff951bb9d0b9f6f72commit-bot@chromium.org       return;
9984d077f56281afad5309f6b9ff951bb9d0b9f6f72commit-bot@chromium.org    }
9999f91c15105a642b1e729f8d1ebeac4dc986eb622commit-bot@chromium.org
1000860912a0affd82bc6b30ad9006658df856ca1d17bsalomon@google.com    AutoRestoreEffects are;
100121c4256a8eccc702d1c4b561da1a3a3e212d3c23commit-bot@chromium.org    AutoCheckFlush acf(this);
100221c4256a8eccc702d1c4b561da1a3a3e212d3c23commit-bot@chromium.org    GrDrawTarget* target = this->prepareToDraw(&paint, BUFFERED_DRAW, &are, &acf);
10039f91c15105a642b1e729f8d1ebeac4dc986eb622commit-bot@chromium.org
1004f19fb364a079dea27c6f99e5bb3d18cc0e86aa54commit-bot@chromium.org    if (!fOvalRenderer->drawSimpleRRect(target, this, paint.isAntiAlias(), rect, stroke)) {
10059f91c15105a642b1e729f8d1ebeac4dc986eb622commit-bot@chromium.org        SkPath path;
10069f91c15105a642b1e729f8d1ebeac4dc986eb622commit-bot@chromium.org        path.addRRect(rect);
1007f19fb364a079dea27c6f99e5bb3d18cc0e86aa54commit-bot@chromium.org        this->internalDrawPath(target, paint.isAntiAlias(), path, stroke);
10089f91c15105a642b1e729f8d1ebeac4dc986eb622commit-bot@chromium.org    }
10099f91c15105a642b1e729f8d1ebeac4dc986eb622commit-bot@chromium.org}
10109f91c15105a642b1e729f8d1ebeac4dc986eb622commit-bot@chromium.org
10119f91c15105a642b1e729f8d1ebeac4dc986eb622commit-bot@chromium.org///////////////////////////////////////////////////////////////////////////////
10129f91c15105a642b1e729f8d1ebeac4dc986eb622commit-bot@chromium.org
1013a5914600241e14e421c8eba91e36bc9a22d5d5b8jvanverth@google.comvoid GrContext::drawOval(const GrPaint& paint,
1014a8cbc57c2d74f8024d149370377bd7dcbd8d204ccommit-bot@chromium.org                         const SkRect& oval,
1015a5914600241e14e421c8eba91e36bc9a22d5d5b8jvanverth@google.com                         const SkStrokeRec& stroke) {
10164d077f56281afad5309f6b9ff951bb9d0b9f6f72commit-bot@chromium.org    if (oval.isEmpty()) {
10174d077f56281afad5309f6b9ff951bb9d0b9f6f72commit-bot@chromium.org       return;
10184d077f56281afad5309f6b9ff951bb9d0b9f6f72commit-bot@chromium.org    }
10193a51c469906cd04bafd5cabc2bb75edb8e0693febsalomon@google.com
1020860912a0affd82bc6b30ad9006658df856ca1d17bsalomon@google.com    AutoRestoreEffects are;
102121c4256a8eccc702d1c4b561da1a3a3e212d3c23commit-bot@chromium.org    AutoCheckFlush acf(this);
102221c4256a8eccc702d1c4b561da1a3a3e212d3c23commit-bot@chromium.org    GrDrawTarget* target = this->prepareToDraw(&paint, BUFFERED_DRAW, &are, &acf);
1023a4129bb45afb50fc8aad9b2d6c9da7b89430941ebsalomon@google.com
1024f19fb364a079dea27c6f99e5bb3d18cc0e86aa54commit-bot@chromium.org    if (!fOvalRenderer->drawOval(target, this, paint.isAntiAlias(), oval, stroke)) {
102551d94f5635c0744ef6aa4514f0055a88753acfeacommit-bot@chromium.org        SkPath path;
102651d94f5635c0744ef6aa4514f0055a88753acfeacommit-bot@chromium.org        path.addOval(oval);
1027f19fb364a079dea27c6f99e5bb3d18cc0e86aa54commit-bot@chromium.org        this->internalDrawPath(target, paint.isAntiAlias(), path, stroke);
1028a5914600241e14e421c8eba91e36bc9a22d5d5b8jvanverth@google.com    }
102980ce7eb86bc75cc887c99b4792c17d564d782cb6bsalomon@google.com}
10303f30e3a41fc16816105e28e0d4c241eff6d391b4bsalomon@google.com
1031b94fd8fd9094c017ee27e38d8bee059b2f4f0eacrobertphillips@google.com// Can 'path' be drawn as a pair of filled nested rectangles?
1032b94fd8fd9094c017ee27e38d8bee059b2f4f0eacrobertphillips@google.comstatic bool is_nested_rects(GrDrawTarget* target,
1033b94fd8fd9094c017ee27e38d8bee059b2f4f0eacrobertphillips@google.com                            const SkPath& path,
1034b94fd8fd9094c017ee27e38d8bee059b2f4f0eacrobertphillips@google.com                            const SkStrokeRec& stroke,
1035b94fd8fd9094c017ee27e38d8bee059b2f4f0eacrobertphillips@google.com                            SkRect rects[2],
1036b94fd8fd9094c017ee27e38d8bee059b2f4f0eacrobertphillips@google.com                            bool* useVertexCoverage) {
1037b94fd8fd9094c017ee27e38d8bee059b2f4f0eacrobertphillips@google.com    SkASSERT(stroke.isFillStyle());
1038b94fd8fd9094c017ee27e38d8bee059b2f4f0eacrobertphillips@google.com
1039b94fd8fd9094c017ee27e38d8bee059b2f4f0eacrobertphillips@google.com    if (path.isInverseFillType()) {
1040b94fd8fd9094c017ee27e38d8bee059b2f4f0eacrobertphillips@google.com        return false;
1041b94fd8fd9094c017ee27e38d8bee059b2f4f0eacrobertphillips@google.com    }
1042b94fd8fd9094c017ee27e38d8bee059b2f4f0eacrobertphillips@google.com
1043b94fd8fd9094c017ee27e38d8bee059b2f4f0eacrobertphillips@google.com    const GrDrawState& drawState = target->getDrawState();
1044b94fd8fd9094c017ee27e38d8bee059b2f4f0eacrobertphillips@google.com
1045b94fd8fd9094c017ee27e38d8bee059b2f4f0eacrobertphillips@google.com    // TODO: this restriction could be lifted if we were willing to apply
1046b94fd8fd9094c017ee27e38d8bee059b2f4f0eacrobertphillips@google.com    // the matrix to all the points individually rather than just to the rect
1047b94fd8fd9094c017ee27e38d8bee059b2f4f0eacrobertphillips@google.com    if (!drawState.getViewMatrix().preservesAxisAlignment()) {
1048b94fd8fd9094c017ee27e38d8bee059b2f4f0eacrobertphillips@google.com        return false;
1049b94fd8fd9094c017ee27e38d8bee059b2f4f0eacrobertphillips@google.com    }
1050b94fd8fd9094c017ee27e38d8bee059b2f4f0eacrobertphillips@google.com
1051b94fd8fd9094c017ee27e38d8bee059b2f4f0eacrobertphillips@google.com    *useVertexCoverage = false;
1052b94fd8fd9094c017ee27e38d8bee059b2f4f0eacrobertphillips@google.com    if (!target->getDrawState().canTweakAlphaForCoverage()) {
1053f19fb364a079dea27c6f99e5bb3d18cc0e86aa54commit-bot@chromium.org        if (target->shouldDisableCoverageAAForBlend()) {
1054b94fd8fd9094c017ee27e38d8bee059b2f4f0eacrobertphillips@google.com            return false;
1055b94fd8fd9094c017ee27e38d8bee059b2f4f0eacrobertphillips@google.com        } else {
1056b94fd8fd9094c017ee27e38d8bee059b2f4f0eacrobertphillips@google.com            *useVertexCoverage = true;
1057b94fd8fd9094c017ee27e38d8bee059b2f4f0eacrobertphillips@google.com        }
1058b94fd8fd9094c017ee27e38d8bee059b2f4f0eacrobertphillips@google.com    }
1059b94fd8fd9094c017ee27e38d8bee059b2f4f0eacrobertphillips@google.com
1060b94fd8fd9094c017ee27e38d8bee059b2f4f0eacrobertphillips@google.com    SkPath::Direction dirs[2];
1061b94fd8fd9094c017ee27e38d8bee059b2f4f0eacrobertphillips@google.com    if (!path.isNestedRects(rects, dirs)) {
1062b94fd8fd9094c017ee27e38d8bee059b2f4f0eacrobertphillips@google.com        return false;
1063b94fd8fd9094c017ee27e38d8bee059b2f4f0eacrobertphillips@google.com    }
1064b94fd8fd9094c017ee27e38d8bee059b2f4f0eacrobertphillips@google.com
10650b92f4e09beacedc4ad101865bed4aabd0f6e88crobertphillips@google.com    if (SkPath::kWinding_FillType == path.getFillType() && dirs[0] == dirs[1]) {
1066b94fd8fd9094c017ee27e38d8bee059b2f4f0eacrobertphillips@google.com        // The two rects need to be wound opposite to each other
10670b92f4e09beacedc4ad101865bed4aabd0f6e88crobertphillips@google.com        return false;
1068b94fd8fd9094c017ee27e38d8bee059b2f4f0eacrobertphillips@google.com    }
1069b94fd8fd9094c017ee27e38d8bee059b2f4f0eacrobertphillips@google.com
10700b92f4e09beacedc4ad101865bed4aabd0f6e88crobertphillips@google.com    // Right now, nested rects where the margin is not the same width
10710b92f4e09beacedc4ad101865bed4aabd0f6e88crobertphillips@google.com    // all around do not render correctly
10720b92f4e09beacedc4ad101865bed4aabd0f6e88crobertphillips@google.com    const SkScalar* outer = rects[0].asScalars();
10730b92f4e09beacedc4ad101865bed4aabd0f6e88crobertphillips@google.com    const SkScalar* inner = rects[1].asScalars();
10740b92f4e09beacedc4ad101865bed4aabd0f6e88crobertphillips@google.com
10750b92f4e09beacedc4ad101865bed4aabd0f6e88crobertphillips@google.com    SkScalar margin = SkScalarAbs(outer[0] - inner[0]);
10760b92f4e09beacedc4ad101865bed4aabd0f6e88crobertphillips@google.com    for (int i = 1; i < 4; ++i) {
10770b92f4e09beacedc4ad101865bed4aabd0f6e88crobertphillips@google.com        SkScalar temp = SkScalarAbs(outer[i] - inner[i]);
10780b92f4e09beacedc4ad101865bed4aabd0f6e88crobertphillips@google.com        if (!SkScalarNearlyEqual(margin, temp)) {
10790b92f4e09beacedc4ad101865bed4aabd0f6e88crobertphillips@google.com            return false;
10800b92f4e09beacedc4ad101865bed4aabd0f6e88crobertphillips@google.com        }
10810b92f4e09beacedc4ad101865bed4aabd0f6e88crobertphillips@google.com    }
10820b92f4e09beacedc4ad101865bed4aabd0f6e88crobertphillips@google.com
10830b92f4e09beacedc4ad101865bed4aabd0f6e88crobertphillips@google.com    return true;
10840b92f4e09beacedc4ad101865bed4aabd0f6e88crobertphillips@google.com}
1085b94fd8fd9094c017ee27e38d8bee059b2f4f0eacrobertphillips@google.com
10865c2ee5c5d8f8593d40a2a9ffd9ca834653ee6af1sugoi@google.comvoid GrContext::drawPath(const GrPaint& paint, const SkPath& path, const SkStrokeRec& stroke) {
10873f30e3a41fc16816105e28e0d4c241eff6d391b4bsalomon@google.com
10883f30e3a41fc16816105e28e0d4c241eff6d391b4bsalomon@google.com    if (path.isEmpty()) {
1089290bf0ae34af76a4350a5df76ce02feb93d68196sugoi@google.com       if (path.isInverseFillType()) {
10903f30e3a41fc16816105e28e0d4c241eff6d391b4bsalomon@google.com           this->drawPaint(paint);
10913f30e3a41fc16816105e28e0d4c241eff6d391b4bsalomon@google.com       }
10923f30e3a41fc16816105e28e0d4c241eff6d391b4bsalomon@google.com       return;
10933f30e3a41fc16816105e28e0d4c241eff6d391b4bsalomon@google.com    }
10943f30e3a41fc16816105e28e0d4c241eff6d391b4bsalomon@google.com
109551d94f5635c0744ef6aa4514f0055a88753acfeacommit-bot@chromium.org    // Note that internalDrawPath may sw-rasterize the path into a scratch texture.
109651d94f5635c0744ef6aa4514f0055a88753acfeacommit-bot@chromium.org    // Scratch textures can be recycled after they are returned to the texture
109751d94f5635c0744ef6aa4514f0055a88753acfeacommit-bot@chromium.org    // cache. This presents a potential hazard for buffered drawing. However,
109851d94f5635c0744ef6aa4514f0055a88753acfeacommit-bot@chromium.org    // the writePixels that uploads to the scratch will perform a flush so we're
109951d94f5635c0744ef6aa4514f0055a88753acfeacommit-bot@chromium.org    // OK.
1100860912a0affd82bc6b30ad9006658df856ca1d17bsalomon@google.com    AutoRestoreEffects are;
110121c4256a8eccc702d1c4b561da1a3a3e212d3c23commit-bot@chromium.org    AutoCheckFlush acf(this);
110221c4256a8eccc702d1c4b561da1a3a3e212d3c23commit-bot@chromium.org    GrDrawTarget* target = this->prepareToDraw(&paint, BUFFERED_DRAW, &are, &acf);
1103f19fb364a079dea27c6f99e5bb3d18cc0e86aa54commit-bot@chromium.org    GrDrawState* drawState = target->drawState();
110451d94f5635c0744ef6aa4514f0055a88753acfeacommit-bot@chromium.org
1105f19fb364a079dea27c6f99e5bb3d18cc0e86aa54commit-bot@chromium.org    bool useCoverageAA = paint.isAntiAlias() && !drawState->getRenderTarget()->isMultisampled();
1106f19fb364a079dea27c6f99e5bb3d18cc0e86aa54commit-bot@chromium.org
1107f19fb364a079dea27c6f99e5bb3d18cc0e86aa54commit-bot@chromium.org    if (useCoverageAA && stroke.getWidth() < 0 && !path.isConvex()) {
1108b94fd8fd9094c017ee27e38d8bee059b2f4f0eacrobertphillips@google.com        // Concave AA paths are expensive - try to avoid them for special cases
1109b94fd8fd9094c017ee27e38d8bee059b2f4f0eacrobertphillips@google.com        bool useVertexCoverage;
1110b94fd8fd9094c017ee27e38d8bee059b2f4f0eacrobertphillips@google.com        SkRect rects[2];
1111b94fd8fd9094c017ee27e38d8bee059b2f4f0eacrobertphillips@google.com
1112b94fd8fd9094c017ee27e38d8bee059b2f4f0eacrobertphillips@google.com        if (is_nested_rects(target, path, stroke, rects, &useVertexCoverage)) {
1113f19fb364a079dea27c6f99e5bb3d18cc0e86aa54commit-bot@chromium.org            SkMatrix origViewMatrix = drawState->getViewMatrix();
1114fbf9f30e11f6dfae9203b152092125fe9b47adb8bsalomon@google.com            GrDrawState::AutoViewMatrixRestore avmr;
1115fbf9f30e11f6dfae9203b152092125fe9b47adb8bsalomon@google.com            if (!avmr.setIdentity(target->drawState())) {
1116b94fd8fd9094c017ee27e38d8bee059b2f4f0eacrobertphillips@google.com                return;
1117b94fd8fd9094c017ee27e38d8bee059b2f4f0eacrobertphillips@google.com            }
1118b94fd8fd9094c017ee27e38d8bee059b2f4f0eacrobertphillips@google.com
1119b94fd8fd9094c017ee27e38d8bee059b2f4f0eacrobertphillips@google.com            fAARectRenderer->fillAANestedRects(this->getGpu(), target,
1120b94fd8fd9094c017ee27e38d8bee059b2f4f0eacrobertphillips@google.com                                               rects,
1121fbf9f30e11f6dfae9203b152092125fe9b47adb8bsalomon@google.com                                               origViewMatrix,
1122b94fd8fd9094c017ee27e38d8bee059b2f4f0eacrobertphillips@google.com                                               useVertexCoverage);
1123b94fd8fd9094c017ee27e38d8bee059b2f4f0eacrobertphillips@google.com            return;
1124b94fd8fd9094c017ee27e38d8bee059b2f4f0eacrobertphillips@google.com        }
1125b94fd8fd9094c017ee27e38d8bee059b2f4f0eacrobertphillips@google.com    }
1126b94fd8fd9094c017ee27e38d8bee059b2f4f0eacrobertphillips@google.com
11273a51c469906cd04bafd5cabc2bb75edb8e0693febsalomon@google.com    SkRect ovalRect;
1128a5914600241e14e421c8eba91e36bc9a22d5d5b8jvanverth@google.com    bool isOval = path.isOval(&ovalRect);
1129a5914600241e14e421c8eba91e36bc9a22d5d5b8jvanverth@google.com
1130bdc4f21162d69b02261815c20fbc2362f4b24829skia.committer@gmail.com    if (!isOval || path.isInverseFillType()
1131f19fb364a079dea27c6f99e5bb3d18cc0e86aa54commit-bot@chromium.org        || !fOvalRenderer->drawOval(target, this, paint.isAntiAlias(), ovalRect, stroke)) {
1132f19fb364a079dea27c6f99e5bb3d18cc0e86aa54commit-bot@chromium.org        this->internalDrawPath(target, paint.isAntiAlias(), path, stroke);
11333a51c469906cd04bafd5cabc2bb75edb8e0693febsalomon@google.com    }
11343a51c469906cd04bafd5cabc2bb75edb8e0693febsalomon@google.com}
11353a51c469906cd04bafd5cabc2bb75edb8e0693febsalomon@google.com
11361ec620110f61e46277065ccf1e0bebb87c96a9ffbsalomon@google.comvoid GrContext::internalDrawPath(GrDrawTarget* target, bool useAA, const SkPath& path,
11371ec620110f61e46277065ccf1e0bebb87c96a9ffbsalomon@google.com                                 const SkStrokeRec& stroke) {
11384d077f56281afad5309f6b9ff951bb9d0b9f6f72commit-bot@chromium.org    SkASSERT(!path.isEmpty());
11393a51c469906cd04bafd5cabc2bb75edb8e0693febsalomon@google.com
11403f30e3a41fc16816105e28e0d4c241eff6d391b4bsalomon@google.com    // An Assumption here is that path renderer would use some form of tweaking
11413f30e3a41fc16816105e28e0d4c241eff6d391b4bsalomon@google.com    // the src color (either the input alpha or in the frag shader) to implement
11423f30e3a41fc16816105e28e0d4c241eff6d391b4bsalomon@google.com    // aa. If we have some future driver-mojo path AA that can do the right
11433f30e3a41fc16816105e28e0d4c241eff6d391b4bsalomon@google.com    // thing WRT to the blend then we'll need some query on the PR.
1144f19fb364a079dea27c6f99e5bb3d18cc0e86aa54commit-bot@chromium.org    bool useCoverageAA = useAA &&
1145f19fb364a079dea27c6f99e5bb3d18cc0e86aa54commit-bot@chromium.org        !target->getDrawState().getRenderTarget()->isMultisampled() &&
1146f19fb364a079dea27c6f99e5bb3d18cc0e86aa54commit-bot@chromium.org        !target->shouldDisableCoverageAAForBlend();
1147f19fb364a079dea27c6f99e5bb3d18cc0e86aa54commit-bot@chromium.org
1148f9ba6e3339b8414de3674c55d86267212b99b07fbsalomon@google.com
1149f19fb364a079dea27c6f99e5bb3d18cc0e86aa54commit-bot@chromium.org    GrPathRendererChain::DrawType type =
1150f19fb364a079dea27c6f99e5bb3d18cc0e86aa54commit-bot@chromium.org        useCoverageAA ? GrPathRendererChain::kColorAntiAlias_DrawType :
1151f19fb364a079dea27c6f99e5bb3d18cc0e86aa54commit-bot@chromium.org                           GrPathRendererChain::kColor_DrawType;
11520afd9ef7f06395f1bbbe9a18d8fcfa181d5f6bb0bsalomon@google.com
11531ed3d2c87e4cae9bb65b859cbecb35bbd24a6440robertphillips@google.com    const SkPath* pathPtr = &path;
11541ed3d2c87e4cae9bb65b859cbecb35bbd24a6440robertphillips@google.com    SkPath tmpPath;
11551ec620110f61e46277065ccf1e0bebb87c96a9ffbsalomon@google.com    SkStrokeRec strokeRec(stroke);
11561ed3d2c87e4cae9bb65b859cbecb35bbd24a6440robertphillips@google.com
11571ed3d2c87e4cae9bb65b859cbecb35bbd24a6440robertphillips@google.com    // Try a 1st time without stroking the path and without allowing the SW renderer
11581ec620110f61e46277065ccf1e0bebb87c96a9ffbsalomon@google.com    GrPathRenderer* pr = this->getPathRenderer(*pathPtr, strokeRec, target, false, type);
11591ed3d2c87e4cae9bb65b859cbecb35bbd24a6440robertphillips@google.com
11601ed3d2c87e4cae9bb65b859cbecb35bbd24a6440robertphillips@google.com    if (NULL == pr) {
1161f19fb364a079dea27c6f99e5bb3d18cc0e86aa54commit-bot@chromium.org        if (!GrPathRenderer::IsStrokeHairlineOrEquivalent(strokeRec, this->getMatrix(), NULL)) {
11621ed3d2c87e4cae9bb65b859cbecb35bbd24a6440robertphillips@google.com            // It didn't work the 1st time, so try again with the stroked path
11631ec620110f61e46277065ccf1e0bebb87c96a9ffbsalomon@google.com            if (strokeRec.applyToPath(&tmpPath, *pathPtr)) {
11641ed3d2c87e4cae9bb65b859cbecb35bbd24a6440robertphillips@google.com                pathPtr = &tmpPath;
11651ec620110f61e46277065ccf1e0bebb87c96a9ffbsalomon@google.com                strokeRec.setFillStyle();
1166f19fb364a079dea27c6f99e5bb3d18cc0e86aa54commit-bot@chromium.org                if (pathPtr->isEmpty()) {
1167f19fb364a079dea27c6f99e5bb3d18cc0e86aa54commit-bot@chromium.org                    return;
1168f19fb364a079dea27c6f99e5bb3d18cc0e86aa54commit-bot@chromium.org                }
11691ed3d2c87e4cae9bb65b859cbecb35bbd24a6440robertphillips@google.com            }
11701ed3d2c87e4cae9bb65b859cbecb35bbd24a6440robertphillips@google.com        }
11714d077f56281afad5309f6b9ff951bb9d0b9f6f72commit-bot@chromium.org
11721ed3d2c87e4cae9bb65b859cbecb35bbd24a6440robertphillips@google.com        // This time, allow SW renderer
11731ec620110f61e46277065ccf1e0bebb87c96a9ffbsalomon@google.com        pr = this->getPathRenderer(*pathPtr, strokeRec, target, true, type);
11741ed3d2c87e4cae9bb65b859cbecb35bbd24a6440robertphillips@google.com    }
11751ed3d2c87e4cae9bb65b859cbecb35bbd24a6440robertphillips@google.com
11763f30e3a41fc16816105e28e0d4c241eff6d391b4bsalomon@google.com    if (NULL == pr) {
11770fde04d1de4773e5168a56dbd455b77e1424434acommit-bot@chromium.org#ifdef SK_DEBUG
11783f30e3a41fc16816105e28e0d4c241eff6d391b4bsalomon@google.com        GrPrintf("Unable to find path renderer compatible with path.\n");
11793f30e3a41fc16816105e28e0d4c241eff6d391b4bsalomon@google.com#endif
11803f30e3a41fc16816105e28e0d4c241eff6d391b4bsalomon@google.com        return;
11813f30e3a41fc16816105e28e0d4c241eff6d391b4bsalomon@google.com    }
11823f30e3a41fc16816105e28e0d4c241eff6d391b4bsalomon@google.com
1183f19fb364a079dea27c6f99e5bb3d18cc0e86aa54commit-bot@chromium.org    pr->drawPath(*pathPtr, strokeRec, target, useCoverageAA);
11843f30e3a41fc16816105e28e0d4c241eff6d391b4bsalomon@google.com}
11853f30e3a41fc16816105e28e0d4c241eff6d391b4bsalomon@google.com
11863f30e3a41fc16816105e28e0d4c241eff6d391b4bsalomon@google.com////////////////////////////////////////////////////////////////////////////////
11873f30e3a41fc16816105e28e0d4c241eff6d391b4bsalomon@google.com
11883f30e3a41fc16816105e28e0d4c241eff6d391b4bsalomon@google.comvoid GrContext::flush(int flagsBitfield) {
11894e5840c041872ee72c11707978edc9e1506b5d6erobertphillips@google.com    if (NULL == fDrawBuffer) {
11904e5840c041872ee72c11707978edc9e1506b5d6erobertphillips@google.com        return;
11914e5840c041872ee72c11707978edc9e1506b5d6erobertphillips@google.com    }
11924e5840c041872ee72c11707978edc9e1506b5d6erobertphillips@google.com
11933f30e3a41fc16816105e28e0d4c241eff6d391b4bsalomon@google.com    if (kDiscard_FlushBit & flagsBitfield) {
11943f30e3a41fc16816105e28e0d4c241eff6d391b4bsalomon@google.com        fDrawBuffer->reset();
11953f30e3a41fc16816105e28e0d4c241eff6d391b4bsalomon@google.com    } else {
11960ad5bd91fd7dc876326ee0832ca8f7947dc1cc24bsalomon@google.com        fDrawBuffer->flush();
11973f30e3a41fc16816105e28e0d4c241eff6d391b4bsalomon@google.com    }
119821c4256a8eccc702d1c4b561da1a3a3e212d3c23commit-bot@chromium.org    fFlushToReduceCacheSize = false;
11993f30e3a41fc16816105e28e0d4c241eff6d391b4bsalomon@google.com}
12003f30e3a41fc16816105e28e0d4c241eff6d391b4bsalomon@google.com
1201281391b6ca1b37738dfbcc934db460f88865d709bsalomon@google.combool GrContext::writeTexturePixels(GrTexture* texture,
12024407645c3f0847754148a2ddc321825a39b8b5bfbsalomon@google.com                                   int left, int top, int width, int height,
12034407645c3f0847754148a2ddc321825a39b8b5bfbsalomon@google.com                                   GrPixelConfig config, const void* buffer, size_t rowBytes,
12044407645c3f0847754148a2ddc321825a39b8b5bfbsalomon@google.com                                   uint32_t flags) {
120577e39423f949e61a899e1bbe64b79b0fa8120d96bsalomon@google.com    SK_TRACE_EVENT0("GrContext::writeTexturePixels");
1206b5ed4edffdba739303dbe834644333b948ecbff9bsalomon@google.com    ASSERT_OWNED_RESOURCE(texture);
1207b5ed4edffdba739303dbe834644333b948ecbff9bsalomon@google.com
1208281391b6ca1b37738dfbcc934db460f88865d709bsalomon@google.com    if ((kUnpremul_PixelOpsFlag & flags) || !fGpu->canWriteTexturePixels(texture, config)) {
1209281391b6ca1b37738dfbcc934db460f88865d709bsalomon@google.com        if (NULL != texture->asRenderTarget()) {
1210281391b6ca1b37738dfbcc934db460f88865d709bsalomon@google.com            return this->writeRenderTargetPixels(texture->asRenderTarget(),
1211281391b6ca1b37738dfbcc934db460f88865d709bsalomon@google.com                                                 left, top, width, height,
1212281391b6ca1b37738dfbcc934db460f88865d709bsalomon@google.com                                                 config, buffer, rowBytes, flags);
1213281391b6ca1b37738dfbcc934db460f88865d709bsalomon@google.com        } else {
1214281391b6ca1b37738dfbcc934db460f88865d709bsalomon@google.com            return false;
1215281391b6ca1b37738dfbcc934db460f88865d709bsalomon@google.com        }
121677e39423f949e61a899e1bbe64b79b0fa8120d96bsalomon@google.com    }
1217281391b6ca1b37738dfbcc934db460f88865d709bsalomon@google.com
12184407645c3f0847754148a2ddc321825a39b8b5bfbsalomon@google.com    if (!(kDontFlush_PixelOpsFlag & flags)) {
12194407645c3f0847754148a2ddc321825a39b8b5bfbsalomon@google.com        this->flush();
12204407645c3f0847754148a2ddc321825a39b8b5bfbsalomon@google.com    }
122177e39423f949e61a899e1bbe64b79b0fa8120d96bsalomon@google.com
1222281391b6ca1b37738dfbcc934db460f88865d709bsalomon@google.com    return fGpu->writeTexturePixels(texture, left, top, width, height,
1223281391b6ca1b37738dfbcc934db460f88865d709bsalomon@google.com                                    config, buffer, rowBytes);
122477e39423f949e61a899e1bbe64b79b0fa8120d96bsalomon@google.com}
122577e39423f949e61a899e1bbe64b79b0fa8120d96bsalomon@google.com
12264407645c3f0847754148a2ddc321825a39b8b5bfbsalomon@google.combool GrContext::readTexturePixels(GrTexture* texture,
12274407645c3f0847754148a2ddc321825a39b8b5bfbsalomon@google.com                                  int left, int top, int width, int height,
12284407645c3f0847754148a2ddc321825a39b8b5bfbsalomon@google.com                                  GrPixelConfig config, void* buffer, size_t rowBytes,
12294407645c3f0847754148a2ddc321825a39b8b5bfbsalomon@google.com                                  uint32_t flags) {
12303f30e3a41fc16816105e28e0d4c241eff6d391b4bsalomon@google.com    SK_TRACE_EVENT0("GrContext::readTexturePixels");
1231b5ed4edffdba739303dbe834644333b948ecbff9bsalomon@google.com    ASSERT_OWNED_RESOURCE(texture);
12323f30e3a41fc16816105e28e0d4c241eff6d391b4bsalomon@google.com
12333f30e3a41fc16816105e28e0d4c241eff6d391b4bsalomon@google.com    GrRenderTarget* target = texture->asRenderTarget();
12343f30e3a41fc16816105e28e0d4c241eff6d391b4bsalomon@google.com    if (NULL != target) {
12354407645c3f0847754148a2ddc321825a39b8b5bfbsalomon@google.com        return this->readRenderTargetPixels(target,
12364407645c3f0847754148a2ddc321825a39b8b5bfbsalomon@google.com                                            left, top, width, height,
12374407645c3f0847754148a2ddc321825a39b8b5bfbsalomon@google.com                                            config, buffer, rowBytes,
12384407645c3f0847754148a2ddc321825a39b8b5bfbsalomon@google.com                                            flags);
12393f30e3a41fc16816105e28e0d4c241eff6d391b4bsalomon@google.com    } else {
1240cc3cec6384303adf017c40ab1bc169e56fd5fd12commit-bot@chromium.org        // TODO: make this more efficient for cases where we're reading the entire
1241cc3cec6384303adf017c40ab1bc169e56fd5fd12commit-bot@chromium.org        //       texture, i.e., use GetTexImage() instead
1242cc3cec6384303adf017c40ab1bc169e56fd5fd12commit-bot@chromium.org
1243cc3cec6384303adf017c40ab1bc169e56fd5fd12commit-bot@chromium.org        // create scratch rendertarget and read from that
1244cc3cec6384303adf017c40ab1bc169e56fd5fd12commit-bot@chromium.org        GrAutoScratchTexture ast;
1245cc3cec6384303adf017c40ab1bc169e56fd5fd12commit-bot@chromium.org        GrTextureDesc desc;
1246cc3cec6384303adf017c40ab1bc169e56fd5fd12commit-bot@chromium.org        desc.fFlags = kRenderTarget_GrTextureFlagBit;
1247cc3cec6384303adf017c40ab1bc169e56fd5fd12commit-bot@chromium.org        desc.fWidth = width;
1248cc3cec6384303adf017c40ab1bc169e56fd5fd12commit-bot@chromium.org        desc.fHeight = height;
1249cc3cec6384303adf017c40ab1bc169e56fd5fd12commit-bot@chromium.org        desc.fConfig = config;
1250cc3cec6384303adf017c40ab1bc169e56fd5fd12commit-bot@chromium.org        desc.fOrigin = kTopLeft_GrSurfaceOrigin;
1251cc3cec6384303adf017c40ab1bc169e56fd5fd12commit-bot@chromium.org        ast.set(this, desc, kExact_ScratchTexMatch);
1252cc3cec6384303adf017c40ab1bc169e56fd5fd12commit-bot@chromium.org        GrTexture* dst = ast.texture();
1253cc3cec6384303adf017c40ab1bc169e56fd5fd12commit-bot@chromium.org        if (NULL != dst && NULL != (target = dst->asRenderTarget())) {
1254cc3cec6384303adf017c40ab1bc169e56fd5fd12commit-bot@chromium.org            this->copyTexture(texture, target, NULL);
1255cc3cec6384303adf017c40ab1bc169e56fd5fd12commit-bot@chromium.org            return this->readRenderTargetPixels(target,
1256cc3cec6384303adf017c40ab1bc169e56fd5fd12commit-bot@chromium.org                                                left, top, width, height,
1257cc3cec6384303adf017c40ab1bc169e56fd5fd12commit-bot@chromium.org                                                config, buffer, rowBytes,
1258cc3cec6384303adf017c40ab1bc169e56fd5fd12commit-bot@chromium.org                                                flags);
1259cc3cec6384303adf017c40ab1bc169e56fd5fd12commit-bot@chromium.org        }
12603b7e9c77d71bd36b87cb847a3df1df05abfcbf26skia.committer@gmail.com
12613f30e3a41fc16816105e28e0d4c241eff6d391b4bsalomon@google.com        return false;
12623f30e3a41fc16816105e28e0d4c241eff6d391b4bsalomon@google.com    }
12633f30e3a41fc16816105e28e0d4c241eff6d391b4bsalomon@google.com}
12643f30e3a41fc16816105e28e0d4c241eff6d391b4bsalomon@google.com
126503f90e2fd488ab168a1bf336fd15fd85c051d7edbsalomon@google.com#include "SkConfig8888.h"
126603f90e2fd488ab168a1bf336fd15fd85c051d7edbsalomon@google.com
126703f90e2fd488ab168a1bf336fd15fd85c051d7edbsalomon@google.comnamespace {
126803f90e2fd488ab168a1bf336fd15fd85c051d7edbsalomon@google.com/**
126903f90e2fd488ab168a1bf336fd15fd85c051d7edbsalomon@google.com * Converts a GrPixelConfig to a SkCanvas::Config8888. Only byte-per-channel
127003f90e2fd488ab168a1bf336fd15fd85c051d7edbsalomon@google.com * formats are representable as Config8888 and so the function returns false
127103f90e2fd488ab168a1bf336fd15fd85c051d7edbsalomon@google.com * if the GrPixelConfig has no equivalent Config8888.
127203f90e2fd488ab168a1bf336fd15fd85c051d7edbsalomon@google.com */
127303f90e2fd488ab168a1bf336fd15fd85c051d7edbsalomon@google.combool grconfig_to_config8888(GrPixelConfig config,
12744407645c3f0847754148a2ddc321825a39b8b5bfbsalomon@google.com                            bool unpremul,
127503f90e2fd488ab168a1bf336fd15fd85c051d7edbsalomon@google.com                            SkCanvas::Config8888* config8888) {
127603f90e2fd488ab168a1bf336fd15fd85c051d7edbsalomon@google.com    switch (config) {
12774407645c3f0847754148a2ddc321825a39b8b5bfbsalomon@google.com        case kRGBA_8888_GrPixelConfig:
12784407645c3f0847754148a2ddc321825a39b8b5bfbsalomon@google.com            if (unpremul) {
12794407645c3f0847754148a2ddc321825a39b8b5bfbsalomon@google.com                *config8888 = SkCanvas::kRGBA_Unpremul_Config8888;
12804407645c3f0847754148a2ddc321825a39b8b5bfbsalomon@google.com            } else {
12814407645c3f0847754148a2ddc321825a39b8b5bfbsalomon@google.com                *config8888 = SkCanvas::kRGBA_Premul_Config8888;
12824407645c3f0847754148a2ddc321825a39b8b5bfbsalomon@google.com            }
128303f90e2fd488ab168a1bf336fd15fd85c051d7edbsalomon@google.com            return true;
12844407645c3f0847754148a2ddc321825a39b8b5bfbsalomon@google.com        case kBGRA_8888_GrPixelConfig:
12854407645c3f0847754148a2ddc321825a39b8b5bfbsalomon@google.com            if (unpremul) {
12864407645c3f0847754148a2ddc321825a39b8b5bfbsalomon@google.com                *config8888 = SkCanvas::kBGRA_Unpremul_Config8888;
12874407645c3f0847754148a2ddc321825a39b8b5bfbsalomon@google.com            } else {
12884407645c3f0847754148a2ddc321825a39b8b5bfbsalomon@google.com                *config8888 = SkCanvas::kBGRA_Premul_Config8888;
12894407645c3f0847754148a2ddc321825a39b8b5bfbsalomon@google.com            }
129003f90e2fd488ab168a1bf336fd15fd85c051d7edbsalomon@google.com            return true;
129103f90e2fd488ab168a1bf336fd15fd85c051d7edbsalomon@google.com        default:
129203f90e2fd488ab168a1bf336fd15fd85c051d7edbsalomon@google.com            return false;
129303f90e2fd488ab168a1bf336fd15fd85c051d7edbsalomon@google.com    }
129403f90e2fd488ab168a1bf336fd15fd85c051d7edbsalomon@google.com}
1295f71764d3272e28817cb5025d2b503aa0170ef9b8bsalomon@google.com
1296f71764d3272e28817cb5025d2b503aa0170ef9b8bsalomon@google.com// It returns a configuration with where the byte position of the R & B components are swapped in
1297f71764d3272e28817cb5025d2b503aa0170ef9b8bsalomon@google.com// relation to the input config. This should only be called with the result of
1298f71764d3272e28817cb5025d2b503aa0170ef9b8bsalomon@google.com// grconfig_to_config8888 as it will fail for other configs.
1299f71764d3272e28817cb5025d2b503aa0170ef9b8bsalomon@google.comSkCanvas::Config8888 swap_config8888_red_and_blue(SkCanvas::Config8888 config8888) {
1300f71764d3272e28817cb5025d2b503aa0170ef9b8bsalomon@google.com    switch (config8888) {
1301f71764d3272e28817cb5025d2b503aa0170ef9b8bsalomon@google.com        case SkCanvas::kBGRA_Premul_Config8888:
1302f71764d3272e28817cb5025d2b503aa0170ef9b8bsalomon@google.com            return SkCanvas::kRGBA_Premul_Config8888;
1303f71764d3272e28817cb5025d2b503aa0170ef9b8bsalomon@google.com        case SkCanvas::kBGRA_Unpremul_Config8888:
1304f71764d3272e28817cb5025d2b503aa0170ef9b8bsalomon@google.com            return SkCanvas::kRGBA_Unpremul_Config8888;
1305f71764d3272e28817cb5025d2b503aa0170ef9b8bsalomon@google.com        case SkCanvas::kRGBA_Premul_Config8888:
1306f71764d3272e28817cb5025d2b503aa0170ef9b8bsalomon@google.com            return SkCanvas::kBGRA_Premul_Config8888;
1307f71764d3272e28817cb5025d2b503aa0170ef9b8bsalomon@google.com        case SkCanvas::kRGBA_Unpremul_Config8888:
1308f71764d3272e28817cb5025d2b503aa0170ef9b8bsalomon@google.com            return SkCanvas::kBGRA_Unpremul_Config8888;
1309f71764d3272e28817cb5025d2b503aa0170ef9b8bsalomon@google.com        default:
1310f71764d3272e28817cb5025d2b503aa0170ef9b8bsalomon@google.com            GrCrash("Unexpected input");
1311f71764d3272e28817cb5025d2b503aa0170ef9b8bsalomon@google.com            return SkCanvas::kBGRA_Unpremul_Config8888;;
1312f71764d3272e28817cb5025d2b503aa0170ef9b8bsalomon@google.com    }
1313f71764d3272e28817cb5025d2b503aa0170ef9b8bsalomon@google.com}
131403f90e2fd488ab168a1bf336fd15fd85c051d7edbsalomon@google.com}
131503f90e2fd488ab168a1bf336fd15fd85c051d7edbsalomon@google.com
13164407645c3f0847754148a2ddc321825a39b8b5bfbsalomon@google.combool GrContext::readRenderTargetPixels(GrRenderTarget* target,
13174407645c3f0847754148a2ddc321825a39b8b5bfbsalomon@google.com                                       int left, int top, int width, int height,
1318281391b6ca1b37738dfbcc934db460f88865d709bsalomon@google.com                                       GrPixelConfig dstConfig, void* buffer, size_t rowBytes,
13194407645c3f0847754148a2ddc321825a39b8b5bfbsalomon@google.com                                       uint32_t flags) {
13203f30e3a41fc16816105e28e0d4c241eff6d391b4bsalomon@google.com    SK_TRACE_EVENT0("GrContext::readRenderTargetPixels");
1321b5ed4edffdba739303dbe834644333b948ecbff9bsalomon@google.com    ASSERT_OWNED_RESOURCE(target);
1322b5ed4edffdba739303dbe834644333b948ecbff9bsalomon@google.com
1323935e9f4fafdfc64130e6be9ea2bb30e3bafd852armistry@google.com    if (NULL == target) {
1324e1884e6f16a6dd9f457970ffab3887e01f268703commit-bot@chromium.org        target = fRenderTarget.get();
132500e32ee9f771bd4d9cd04e4c76e6f5f59b26a4dfbsalomon@google.com        if (NULL == target) {
132600e32ee9f771bd4d9cd04e4c76e6f5f59b26a4dfbsalomon@google.com            return false;
132700e32ee9f771bd4d9cd04e4c76e6f5f59b26a4dfbsalomon@google.com        }
132800e32ee9f771bd4d9cd04e4c76e6f5f59b26a4dfbsalomon@google.com    }
13293f30e3a41fc16816105e28e0d4c241eff6d391b4bsalomon@google.com
133077e39423f949e61a899e1bbe64b79b0fa8120d96bsalomon@google.com    if (!(kDontFlush_PixelOpsFlag & flags)) {
133177e39423f949e61a899e1bbe64b79b0fa8120d96bsalomon@google.com        this->flush();
133277e39423f949e61a899e1bbe64b79b0fa8120d96bsalomon@google.com    }
133300e32ee9f771bd4d9cd04e4c76e6f5f59b26a4dfbsalomon@google.com
1334f71764d3272e28817cb5025d2b503aa0170ef9b8bsalomon@google.com    // Determine which conversions have to be applied: flipY, swapRAnd, and/or unpremul.
133500e32ee9f771bd4d9cd04e4c76e6f5f59b26a4dfbsalomon@google.com
1336f71764d3272e28817cb5025d2b503aa0170ef9b8bsalomon@google.com    // If fGpu->readPixels would incur a y-flip cost then we will read the pixels upside down. We'll
1337f71764d3272e28817cb5025d2b503aa0170ef9b8bsalomon@google.com    // either do the flipY by drawing into a scratch with a matrix or on the cpu after the read.
1338f71764d3272e28817cb5025d2b503aa0170ef9b8bsalomon@google.com    bool flipY = fGpu->readPixelsWillPayForYFlip(target, left, top,
1339281391b6ca1b37738dfbcc934db460f88865d709bsalomon@google.com                                                 width, height, dstConfig,
134000e32ee9f771bd4d9cd04e4c76e6f5f59b26a4dfbsalomon@google.com                                                 rowBytes);
1341281391b6ca1b37738dfbcc934db460f88865d709bsalomon@google.com    // We ignore the preferred config if it is different than our config unless it is an R/B swap.
1342281391b6ca1b37738dfbcc934db460f88865d709bsalomon@google.com    // In that case we'll perform an R and B swap while drawing to a scratch texture of the swapped
1343281391b6ca1b37738dfbcc934db460f88865d709bsalomon@google.com    // config. Then we will call readPixels on the scratch with the swapped config. The swaps during
1344281391b6ca1b37738dfbcc934db460f88865d709bsalomon@google.com    // the draw cancels out the fact that we call readPixels with a config that is R/B swapped from
1345281391b6ca1b37738dfbcc934db460f88865d709bsalomon@google.com    // dstConfig.
1346281391b6ca1b37738dfbcc934db460f88865d709bsalomon@google.com    GrPixelConfig readConfig = dstConfig;
1347281391b6ca1b37738dfbcc934db460f88865d709bsalomon@google.com    bool swapRAndB = false;
134804ac20b5a0e769102205e2110008ae434c114d22commit-bot@chromium.org    if (GrPixelConfigSwapRAndB(dstConfig) ==
134904ac20b5a0e769102205e2110008ae434c114d22commit-bot@chromium.org        fGpu->preferredReadPixelsConfig(dstConfig, target->config())) {
1350281391b6ca1b37738dfbcc934db460f88865d709bsalomon@google.com        readConfig = GrPixelConfigSwapRAndB(readConfig);
1351281391b6ca1b37738dfbcc934db460f88865d709bsalomon@google.com        swapRAndB = true;
1352281391b6ca1b37738dfbcc934db460f88865d709bsalomon@google.com    }
1353f71764d3272e28817cb5025d2b503aa0170ef9b8bsalomon@google.com
13544407645c3f0847754148a2ddc321825a39b8b5bfbsalomon@google.com    bool unpremul = SkToBool(kUnpremul_PixelOpsFlag & flags);
135500e32ee9f771bd4d9cd04e4c76e6f5f59b26a4dfbsalomon@google.com
1356281391b6ca1b37738dfbcc934db460f88865d709bsalomon@google.com    if (unpremul && !GrPixelConfigIs8888(dstConfig)) {
1357f71764d3272e28817cb5025d2b503aa0170ef9b8bsalomon@google.com        // The unpremul flag is only allowed for these two configs.
1358a82039ac3862b7c487426f6adbb6c78d919bca30bsalomon@google.com        return false;
1359a82039ac3862b7c487426f6adbb6c78d919bca30bsalomon@google.com    }
1360f71764d3272e28817cb5025d2b503aa0170ef9b8bsalomon@google.com
1361f71764d3272e28817cb5025d2b503aa0170ef9b8bsalomon@google.com    // If the src is a texture and we would have to do conversions after read pixels, we instead
1362f71764d3272e28817cb5025d2b503aa0170ef9b8bsalomon@google.com    // do the conversions by drawing the src to a scratch texture. If we handle any of the
1363f71764d3272e28817cb5025d2b503aa0170ef9b8bsalomon@google.com    // conversions in the draw we set the corresponding bool to false so that we don't reapply it
1364f71764d3272e28817cb5025d2b503aa0170ef9b8bsalomon@google.com    // on the read back pixels.
1365f71764d3272e28817cb5025d2b503aa0170ef9b8bsalomon@google.com    GrTexture* src = target->asTexture();
1366380636dc314147f30124ce172750c0ebab0a1c60bsalomon@google.com    GrAutoScratchTexture ast;
1367f71764d3272e28817cb5025d2b503aa0170ef9b8bsalomon@google.com    if (NULL != src && (swapRAndB || unpremul || flipY)) {
1368f71764d3272e28817cb5025d2b503aa0170ef9b8bsalomon@google.com        // Make the scratch a render target because we don't have a robust readTexturePixels as of
1369f71764d3272e28817cb5025d2b503aa0170ef9b8bsalomon@google.com        // yet. It calls this function.
1370c937ae9bcbf6bdb6fe7f6b4cdb518a684fb5f1barobertphillips@google.com        GrTextureDesc desc;
1371c937ae9bcbf6bdb6fe7f6b4cdb518a684fb5f1barobertphillips@google.com        desc.fFlags = kRenderTarget_GrTextureFlagBit;
1372c937ae9bcbf6bdb6fe7f6b4cdb518a684fb5f1barobertphillips@google.com        desc.fWidth = width;
1373c937ae9bcbf6bdb6fe7f6b4cdb518a684fb5f1barobertphillips@google.com        desc.fHeight = height;
1374f71764d3272e28817cb5025d2b503aa0170ef9b8bsalomon@google.com        desc.fConfig = readConfig;
1375e86e1ce3df0f3ded2567eabd487d53ad4e6d6692senorblanco@chromium.org        desc.fOrigin = kTopLeft_GrSurfaceOrigin;
1376380636dc314147f30124ce172750c0ebab0a1c60bsalomon@google.com
1377281391b6ca1b37738dfbcc934db460f88865d709bsalomon@google.com        // When a full read back is faster than a partial we could always make the scratch exactly
1378f71764d3272e28817cb5025d2b503aa0170ef9b8bsalomon@google.com        // match the passed rect. However, if we see many different size rectangles we will trash
1379f71764d3272e28817cb5025d2b503aa0170ef9b8bsalomon@google.com        // our texture cache and pay the cost of creating and destroying many textures. So, we only
1380f71764d3272e28817cb5025d2b503aa0170ef9b8bsalomon@google.com        // request an exact match when the caller is reading an entire RT.
13819646b3b9d9c12a545bbee07a9a9e516f09e4aa49bsalomon@google.com        ScratchTexMatch match = kApprox_ScratchTexMatch;
13829646b3b9d9c12a545bbee07a9a9e516f09e4aa49bsalomon@google.com        if (0 == left &&
13839646b3b9d9c12a545bbee07a9a9e516f09e4aa49bsalomon@google.com            0 == top &&
13849646b3b9d9c12a545bbee07a9a9e516f09e4aa49bsalomon@google.com            target->width() == width &&
13859646b3b9d9c12a545bbee07a9a9e516f09e4aa49bsalomon@google.com            target->height() == height &&
13869646b3b9d9c12a545bbee07a9a9e516f09e4aa49bsalomon@google.com            fGpu->fullReadPixelsIsFasterThanPartial()) {
13879646b3b9d9c12a545bbee07a9a9e516f09e4aa49bsalomon@google.com            match = kExact_ScratchTexMatch;
13889646b3b9d9c12a545bbee07a9a9e516f09e4aa49bsalomon@google.com        }
13899646b3b9d9c12a545bbee07a9a9e516f09e4aa49bsalomon@google.com        ast.set(this, desc, match);
139000e32ee9f771bd4d9cd04e4c76e6f5f59b26a4dfbsalomon@google.com        GrTexture* texture = ast.texture();
1391f71764d3272e28817cb5025d2b503aa0170ef9b8bsalomon@google.com        if (texture) {
1392d2a97043a9a9a8a389afc7c551e76586a3cc93afbsalomon@google.com            // compute a matrix to perform the draw
1393a4e2f5beb2d73243c15ab871f013d2ba29e8fea3bsalomon@google.com            SkMatrix textureMatrix;
1394e86e1ce3df0f3ded2567eabd487d53ad4e6d6692senorblanco@chromium.org            textureMatrix.setTranslate(SK_Scalar1 *left, SK_Scalar1 *top);
1395d2a97043a9a9a8a389afc7c551e76586a3cc93afbsalomon@google.com            textureMatrix.postIDiv(src->width(), src->height());
1396d2a97043a9a9a8a389afc7c551e76586a3cc93afbsalomon@google.com
13974783fbd25c350b0ea9fc02264b4b1a291c5988ebbsalomon@google.com            SkAutoTUnref<const GrEffectRef> effect;
1398f71764d3272e28817cb5025d2b503aa0170ef9b8bsalomon@google.com            if (unpremul) {
13994783fbd25c350b0ea9fc02264b4b1a291c5988ebbsalomon@google.com                effect.reset(this->createPMToUPMEffect(src, swapRAndB, textureMatrix));
14004783fbd25c350b0ea9fc02264b4b1a291c5988ebbsalomon@google.com                if (NULL != effect) {
1401281391b6ca1b37738dfbcc934db460f88865d709bsalomon@google.com                    unpremul = false; // we no longer need to do this on CPU after the read back.
1402d2a97043a9a9a8a389afc7c551e76586a3cc93afbsalomon@google.com                }
1403f71764d3272e28817cb5025d2b503aa0170ef9b8bsalomon@google.com            }
1404f71764d3272e28817cb5025d2b503aa0170ef9b8bsalomon@google.com            // If we failed to create a PM->UPM effect and have no other conversions to perform then
1405f71764d3272e28817cb5025d2b503aa0170ef9b8bsalomon@google.com            // there is no longer any point to using the scratch.
14064783fbd25c350b0ea9fc02264b4b1a291c5988ebbsalomon@google.com            if (NULL != effect || flipY || swapRAndB) {
14074783fbd25c350b0ea9fc02264b4b1a291c5988ebbsalomon@google.com                if (!effect) {
14084783fbd25c350b0ea9fc02264b4b1a291c5988ebbsalomon@google.com                    effect.reset(GrConfigConversionEffect::Create(
14094783fbd25c350b0ea9fc02264b4b1a291c5988ebbsalomon@google.com                                                    src,
14104783fbd25c350b0ea9fc02264b4b1a291c5988ebbsalomon@google.com                                                    swapRAndB,
14114783fbd25c350b0ea9fc02264b4b1a291c5988ebbsalomon@google.com                                                    GrConfigConversionEffect::kNone_PMConversion,
14124783fbd25c350b0ea9fc02264b4b1a291c5988ebbsalomon@google.com                                                    textureMatrix));
1413f71764d3272e28817cb5025d2b503aa0170ef9b8bsalomon@google.com                }
1414f71764d3272e28817cb5025d2b503aa0170ef9b8bsalomon@google.com                swapRAndB = false; // we will handle the swap in the draw.
1415f71764d3272e28817cb5025d2b503aa0170ef9b8bsalomon@google.com
1416ccc9cf9a1f76a236d9e30725646933afa0b72e57robertphillips@google.com                // We protect the existing geometry here since it may not be
1417ccc9cf9a1f76a236d9e30725646933afa0b72e57robertphillips@google.com                // clear to the caller that a draw operation (i.e., drawSimpleRect)
1418ccc9cf9a1f76a236d9e30725646933afa0b72e57robertphillips@google.com                // can be invoked in this method
1419ccc9cf9a1f76a236d9e30725646933afa0b72e57robertphillips@google.com                GrDrawTarget::AutoGeometryAndStatePush agasp(fGpu, GrDrawTarget::kReset_ASRInit);
1420f71764d3272e28817cb5025d2b503aa0170ef9b8bsalomon@google.com                GrDrawState* drawState = fGpu->drawState();
1421a91959e0e4997d3a73b38e6d7f0296c566a4b1d0tfarina@chromium.org                SkASSERT(effect);
1422860912a0affd82bc6b30ad9006658df856ca1d17bsalomon@google.com                drawState->addColorEffect(effect);
1423d2a97043a9a9a8a389afc7c551e76586a3cc93afbsalomon@google.com
1424f71764d3272e28817cb5025d2b503aa0170ef9b8bsalomon@google.com                drawState->setRenderTarget(texture->asRenderTarget());
1425a8cbc57c2d74f8024d149370377bd7dcbd8d204ccommit-bot@chromium.org                SkRect rect = SkRect::MakeWH(SkIntToScalar(width), SkIntToScalar(height));
1426f71764d3272e28817cb5025d2b503aa0170ef9b8bsalomon@google.com                fGpu->drawSimpleRect(rect, NULL);
1427f71764d3272e28817cb5025d2b503aa0170ef9b8bsalomon@google.com                // we want to read back from the scratch's origin
1428f71764d3272e28817cb5025d2b503aa0170ef9b8bsalomon@google.com                left = 0;
1429f71764d3272e28817cb5025d2b503aa0170ef9b8bsalomon@google.com                top = 0;
1430f71764d3272e28817cb5025d2b503aa0170ef9b8bsalomon@google.com                target = texture->asRenderTarget();
1431f71764d3272e28817cb5025d2b503aa0170ef9b8bsalomon@google.com            }
143200e32ee9f771bd4d9cd04e4c76e6f5f59b26a4dfbsalomon@google.com        }
1433f71764d3272e28817cb5025d2b503aa0170ef9b8bsalomon@google.com    }
1434f71764d3272e28817cb5025d2b503aa0170ef9b8bsalomon@google.com    if (!fGpu->readPixels(target,
1435f71764d3272e28817cb5025d2b503aa0170ef9b8bsalomon@google.com                          left, top, width, height,
1436e86e1ce3df0f3ded2567eabd487d53ad4e6d6692senorblanco@chromium.org                          readConfig, buffer, rowBytes)) {
1437f71764d3272e28817cb5025d2b503aa0170ef9b8bsalomon@google.com        return false;
1438f71764d3272e28817cb5025d2b503aa0170ef9b8bsalomon@google.com    }
1439d2a97043a9a9a8a389afc7c551e76586a3cc93afbsalomon@google.com    // Perform any conversions we weren't able to perform using a scratch texture.
1440e86e1ce3df0f3ded2567eabd487d53ad4e6d6692senorblanco@chromium.org    if (unpremul || swapRAndB) {
1441fe0f2d69580071c2e42c475b86fb69aa0293b41ebsalomon@google.com        // These are initialized to suppress a warning
1442fe0f2d69580071c2e42c475b86fb69aa0293b41ebsalomon@google.com        SkCanvas::Config8888 srcC8888 = SkCanvas::kNative_Premul_Config8888;
1443fe0f2d69580071c2e42c475b86fb69aa0293b41ebsalomon@google.com        SkCanvas::Config8888 dstC8888 = SkCanvas::kNative_Premul_Config8888;
1444fe0f2d69580071c2e42c475b86fb69aa0293b41ebsalomon@google.com
1445281391b6ca1b37738dfbcc934db460f88865d709bsalomon@google.com        SkDEBUGCODE(bool c8888IsValid =) grconfig_to_config8888(dstConfig, false, &srcC8888);
1446281391b6ca1b37738dfbcc934db460f88865d709bsalomon@google.com        grconfig_to_config8888(dstConfig, unpremul, &dstC8888);
1447fe0f2d69580071c2e42c475b86fb69aa0293b41ebsalomon@google.com
1448f71764d3272e28817cb5025d2b503aa0170ef9b8bsalomon@google.com        if (swapRAndB) {
1449a91959e0e4997d3a73b38e6d7f0296c566a4b1d0tfarina@chromium.org            SkASSERT(c8888IsValid); // we should only do r/b swap on 8888 configs
1450f71764d3272e28817cb5025d2b503aa0170ef9b8bsalomon@google.com            srcC8888 = swap_config8888_red_and_blue(srcC8888);
14514407645c3f0847754148a2ddc321825a39b8b5bfbsalomon@google.com        }
1452a91959e0e4997d3a73b38e6d7f0296c566a4b1d0tfarina@chromium.org        SkASSERT(c8888IsValid);
1453e86e1ce3df0f3ded2567eabd487d53ad4e6d6692senorblanco@chromium.org        uint32_t* b32 = reinterpret_cast<uint32_t*>(buffer);
1454e86e1ce3df0f3ded2567eabd487d53ad4e6d6692senorblanco@chromium.org        SkConvertConfig8888Pixels(b32, rowBytes, dstC8888,
1455e86e1ce3df0f3ded2567eabd487d53ad4e6d6692senorblanco@chromium.org                                  b32, rowBytes, srcC8888,
1456e86e1ce3df0f3ded2567eabd487d53ad4e6d6692senorblanco@chromium.org                                  width, height);
145700e32ee9f771bd4d9cd04e4c76e6f5f59b26a4dfbsalomon@google.com    }
1458f71764d3272e28817cb5025d2b503aa0170ef9b8bsalomon@google.com    return true;
14593f30e3a41fc16816105e28e0d4c241eff6d391b4bsalomon@google.com}
14603f30e3a41fc16816105e28e0d4c241eff6d391b4bsalomon@google.com
1461cbada79e9157c827682b6ea170861d283d2de3a3bsalomon@google.comvoid GrContext::resolveRenderTarget(GrRenderTarget* target) {
1462a91959e0e4997d3a73b38e6d7f0296c566a4b1d0tfarina@chromium.org    SkASSERT(target);
1463cbada79e9157c827682b6ea170861d283d2de3a3bsalomon@google.com    ASSERT_OWNED_RESOURCE(target);
1464cbada79e9157c827682b6ea170861d283d2de3a3bsalomon@google.com    // In the future we may track whether there are any pending draws to this
1465cbada79e9157c827682b6ea170861d283d2de3a3bsalomon@google.com    // target. We don't today so we always perform a flush. We don't promise
1466cbada79e9157c827682b6ea170861d283d2de3a3bsalomon@google.com    // this to our clients, though.
1467cbada79e9157c827682b6ea170861d283d2de3a3bsalomon@google.com    this->flush();
1468cbada79e9157c827682b6ea170861d283d2de3a3bsalomon@google.com    fGpu->resolveRenderTarget(target);
1469cbada79e9157c827682b6ea170861d283d2de3a3bsalomon@google.com}
1470cbada79e9157c827682b6ea170861d283d2de3a3bsalomon@google.com
14716ba1045c1aaf5ffb2a955c4f91f77adce4425548scroggo@google.comvoid GrContext::copyTexture(GrTexture* src, GrRenderTarget* dst, const SkIPoint* topLeft) {
1472425387cbecc5dc8b806ee66732fb4e4d474116e1senorblanco@chromium.org    if (NULL == src || NULL == dst) {
1473425387cbecc5dc8b806ee66732fb4e4d474116e1senorblanco@chromium.org        return;
1474425387cbecc5dc8b806ee66732fb4e4d474116e1senorblanco@chromium.org    }
1475425387cbecc5dc8b806ee66732fb4e4d474116e1senorblanco@chromium.org    ASSERT_OWNED_RESOURCE(src);
1476425387cbecc5dc8b806ee66732fb4e4d474116e1senorblanco@chromium.org
14774857d495bac8680248d0696d3daad8aee79c8b68twiz@google.com    // Writes pending to the source texture are not tracked, so a flush
14784857d495bac8680248d0696d3daad8aee79c8b68twiz@google.com    // is required to ensure that the copy captures the most recent contents
14794783fbd25c350b0ea9fc02264b4b1a291c5988ebbsalomon@google.com    // of the source texture. See similar behavior in
14804857d495bac8680248d0696d3daad8aee79c8b68twiz@google.com    // GrContext::resolveRenderTarget.
14814857d495bac8680248d0696d3daad8aee79c8b68twiz@google.com    this->flush();
14824857d495bac8680248d0696d3daad8aee79c8b68twiz@google.com
1483bfc805bb10f955661ff7641e44c1f6d5be9dd545bsalomon@google.com    GrDrawTarget::AutoStateRestore asr(fGpu, GrDrawTarget::kReset_ASRInit);
1484c08edffbcbe0eed40d8855f8acfe439c237c43bdbsalomon@google.com    GrDrawState* drawState = fGpu->drawState();
1485c08edffbcbe0eed40d8855f8acfe439c237c43bdbsalomon@google.com    drawState->setRenderTarget(dst);
1486a4e2f5beb2d73243c15ab871f013d2ba29e8fea3bsalomon@google.com    SkMatrix sampleM;
1487425387cbecc5dc8b806ee66732fb4e4d474116e1senorblanco@chromium.org    sampleM.setIDiv(src->width(), src->height());
14886ba1045c1aaf5ffb2a955c4f91f77adce4425548scroggo@google.com    SkIRect srcRect = SkIRect::MakeWH(dst->width(), dst->height());
14896ba1045c1aaf5ffb2a955c4f91f77adce4425548scroggo@google.com    if (NULL != topLeft) {
14906ba1045c1aaf5ffb2a955c4f91f77adce4425548scroggo@google.com        srcRect.offset(*topLeft);
14916ba1045c1aaf5ffb2a955c4f91f77adce4425548scroggo@google.com    }
14926ba1045c1aaf5ffb2a955c4f91f77adce4425548scroggo@google.com    SkIRect srcBounds = SkIRect::MakeWH(src->width(), src->height());
14936ba1045c1aaf5ffb2a955c4f91f77adce4425548scroggo@google.com    if (!srcRect.intersect(srcBounds)) {
14946ba1045c1aaf5ffb2a955c4f91f77adce4425548scroggo@google.com        return;
14956ba1045c1aaf5ffb2a955c4f91f77adce4425548scroggo@google.com    }
14966ba1045c1aaf5ffb2a955c4f91f77adce4425548scroggo@google.com    sampleM.preTranslate(SkIntToScalar(srcRect.fLeft), SkIntToScalar(srcRect.fTop));
1497860912a0affd82bc6b30ad9006658df856ca1d17bsalomon@google.com    drawState->addColorTextureEffect(src, sampleM);
14986ba1045c1aaf5ffb2a955c4f91f77adce4425548scroggo@google.com    SkRect dstR = SkRect::MakeWH(SkIntToScalar(srcRect.width()), SkIntToScalar(srcRect.height()));
14996ba1045c1aaf5ffb2a955c4f91f77adce4425548scroggo@google.com    fGpu->drawSimpleRect(dstR, NULL);
1500425387cbecc5dc8b806ee66732fb4e4d474116e1senorblanco@chromium.org}
1501425387cbecc5dc8b806ee66732fb4e4d474116e1senorblanco@chromium.org
1502281391b6ca1b37738dfbcc934db460f88865d709bsalomon@google.combool GrContext::writeRenderTargetPixels(GrRenderTarget* target,
15034407645c3f0847754148a2ddc321825a39b8b5bfbsalomon@google.com                                        int left, int top, int width, int height,
1504281391b6ca1b37738dfbcc934db460f88865d709bsalomon@google.com                                        GrPixelConfig srcConfig,
15054407645c3f0847754148a2ddc321825a39b8b5bfbsalomon@google.com                                        const void* buffer,
15064407645c3f0847754148a2ddc321825a39b8b5bfbsalomon@google.com                                        size_t rowBytes,
15074407645c3f0847754148a2ddc321825a39b8b5bfbsalomon@google.com                                        uint32_t flags) {
150877e39423f949e61a899e1bbe64b79b0fa8120d96bsalomon@google.com    SK_TRACE_EVENT0("GrContext::writeRenderTargetPixels");
1509b5ed4edffdba739303dbe834644333b948ecbff9bsalomon@google.com    ASSERT_OWNED_RESOURCE(target);
151077e39423f949e61a899e1bbe64b79b0fa8120d96bsalomon@google.com
1511935e9f4fafdfc64130e6be9ea2bb30e3bafd852armistry@google.com    if (NULL == target) {
1512e1884e6f16a6dd9f457970ffab3887e01f268703commit-bot@chromium.org        target = fRenderTarget.get();
151377e39423f949e61a899e1bbe64b79b0fa8120d96bsalomon@google.com        if (NULL == target) {
1514281391b6ca1b37738dfbcc934db460f88865d709bsalomon@google.com            return false;
151577e39423f949e61a899e1bbe64b79b0fa8120d96bsalomon@google.com        }
151677e39423f949e61a899e1bbe64b79b0fa8120d96bsalomon@google.com    }
15173f30e3a41fc16816105e28e0d4c241eff6d391b4bsalomon@google.com
1518f71764d3272e28817cb5025d2b503aa0170ef9b8bsalomon@google.com    // TODO: when underlying api has a direct way to do this we should use it (e.g. glDrawPixels on
1519f71764d3272e28817cb5025d2b503aa0170ef9b8bsalomon@google.com    // desktop GL).
1520f71764d3272e28817cb5025d2b503aa0170ef9b8bsalomon@google.com
1521f71764d3272e28817cb5025d2b503aa0170ef9b8bsalomon@google.com    // We will always call some form of writeTexturePixels and we will pass our flags on to it.
1522f71764d3272e28817cb5025d2b503aa0170ef9b8bsalomon@google.com    // Thus, we don't perform a flush here since that call will do it (if the kNoFlush flag isn't
1523f71764d3272e28817cb5025d2b503aa0170ef9b8bsalomon@google.com    // set.)
15243f30e3a41fc16816105e28e0d4c241eff6d391b4bsalomon@google.com
15254407645c3f0847754148a2ddc321825a39b8b5bfbsalomon@google.com    // If the RT is also a texture and we don't have to premultiply then take the texture path.
15264407645c3f0847754148a2ddc321825a39b8b5bfbsalomon@google.com    // We expect to be at least as fast or faster since it doesn't use an intermediate texture as
15274407645c3f0847754148a2ddc321825a39b8b5bfbsalomon@google.com    // we do below.
1528935e9f4fafdfc64130e6be9ea2bb30e3bafd852armistry@google.com
1529a3b4d7b4b4acecdbd4a07d41ce99cea5b07691fbcommit-bot@chromium.org#if !defined(SK_BUILD_FOR_MAC)
1530f71764d3272e28817cb5025d2b503aa0170ef9b8bsalomon@google.com    // At least some drivers on the Mac get confused when glTexImage2D is called on a texture
1531f71764d3272e28817cb5025d2b503aa0170ef9b8bsalomon@google.com    // attached to an FBO. The FBO still sees the old image. TODO: determine what OS versions and/or
1532f71764d3272e28817cb5025d2b503aa0170ef9b8bsalomon@google.com    // HW is affected.
1533281391b6ca1b37738dfbcc934db460f88865d709bsalomon@google.com    if (NULL != target->asTexture() && !(kUnpremul_PixelOpsFlag & flags) &&
1534281391b6ca1b37738dfbcc934db460f88865d709bsalomon@google.com        fGpu->canWriteTexturePixels(target->asTexture(), srcConfig)) {
1535281391b6ca1b37738dfbcc934db460f88865d709bsalomon@google.com        return this->writeTexturePixels(target->asTexture(),
1536281391b6ca1b37738dfbcc934db460f88865d709bsalomon@google.com                                        left, top, width, height,
1537281391b6ca1b37738dfbcc934db460f88865d709bsalomon@google.com                                        srcConfig, buffer, rowBytes, flags);
1538b93d4d5201d643f98709fdaa3efdcb28f475dd6ebsalomon@google.com    }
1539b93d4d5201d643f98709fdaa3efdcb28f475dd6ebsalomon@google.com#endif
1540d2a97043a9a9a8a389afc7c551e76586a3cc93afbsalomon@google.com
1541281391b6ca1b37738dfbcc934db460f88865d709bsalomon@google.com    // We ignore the preferred config unless it is a R/B swap of the src config. In that case
1542281391b6ca1b37738dfbcc934db460f88865d709bsalomon@google.com    // we will upload the original src data to a scratch texture but we will spoof it as the swapped
1543281391b6ca1b37738dfbcc934db460f88865d709bsalomon@google.com    // config. This scratch will then have R and B swapped. We correct for this by swapping again
1544281391b6ca1b37738dfbcc934db460f88865d709bsalomon@google.com    // when drawing the scratch to the dst using a conversion effect.
1545281391b6ca1b37738dfbcc934db460f88865d709bsalomon@google.com    bool swapRAndB = false;
1546281391b6ca1b37738dfbcc934db460f88865d709bsalomon@google.com    GrPixelConfig writeConfig = srcConfig;
154704ac20b5a0e769102205e2110008ae434c114d22commit-bot@chromium.org    if (GrPixelConfigSwapRAndB(srcConfig) ==
154804ac20b5a0e769102205e2110008ae434c114d22commit-bot@chromium.org        fGpu->preferredWritePixelsConfig(srcConfig, target->config())) {
1549281391b6ca1b37738dfbcc934db460f88865d709bsalomon@google.com        writeConfig = GrPixelConfigSwapRAndB(srcConfig);
1550281391b6ca1b37738dfbcc934db460f88865d709bsalomon@google.com        swapRAndB = true;
1551b93d4d5201d643f98709fdaa3efdcb28f475dd6ebsalomon@google.com    }
1552b93d4d5201d643f98709fdaa3efdcb28f475dd6ebsalomon@google.com
1553c937ae9bcbf6bdb6fe7f6b4cdb518a684fb5f1barobertphillips@google.com    GrTextureDesc desc;
1554c937ae9bcbf6bdb6fe7f6b4cdb518a684fb5f1barobertphillips@google.com    desc.fWidth = width;
1555c937ae9bcbf6bdb6fe7f6b4cdb518a684fb5f1barobertphillips@google.com    desc.fHeight = height;
1556281391b6ca1b37738dfbcc934db460f88865d709bsalomon@google.com    desc.fConfig = writeConfig;
15573f30e3a41fc16816105e28e0d4c241eff6d391b4bsalomon@google.com    GrAutoScratchTexture ast(this, desc);
15583f30e3a41fc16816105e28e0d4c241eff6d391b4bsalomon@google.com    GrTexture* texture = ast.texture();
15593f30e3a41fc16816105e28e0d4c241eff6d391b4bsalomon@google.com    if (NULL == texture) {
1560281391b6ca1b37738dfbcc934db460f88865d709bsalomon@google.com        return false;
15613f30e3a41fc16816105e28e0d4c241eff6d391b4bsalomon@google.com    }
1562d2a97043a9a9a8a389afc7c551e76586a3cc93afbsalomon@google.com
15634783fbd25c350b0ea9fc02264b4b1a291c5988ebbsalomon@google.com    SkAutoTUnref<const GrEffectRef> effect;
1564a4e2f5beb2d73243c15ab871f013d2ba29e8fea3bsalomon@google.com    SkMatrix textureMatrix;
1565d2a97043a9a9a8a389afc7c551e76586a3cc93afbsalomon@google.com    textureMatrix.setIDiv(texture->width(), texture->height());
1566d2a97043a9a9a8a389afc7c551e76586a3cc93afbsalomon@google.com
1567f71764d3272e28817cb5025d2b503aa0170ef9b8bsalomon@google.com    // allocate a tmp buffer and sw convert the pixels to premul
1568f71764d3272e28817cb5025d2b503aa0170ef9b8bsalomon@google.com    SkAutoSTMalloc<128 * 128, uint32_t> tmpPixels(0);
1569f71764d3272e28817cb5025d2b503aa0170ef9b8bsalomon@google.com
1570f71764d3272e28817cb5025d2b503aa0170ef9b8bsalomon@google.com    if (kUnpremul_PixelOpsFlag & flags) {
1571281391b6ca1b37738dfbcc934db460f88865d709bsalomon@google.com        if (!GrPixelConfigIs8888(srcConfig)) {
1572281391b6ca1b37738dfbcc934db460f88865d709bsalomon@google.com            return false;
1573f71764d3272e28817cb5025d2b503aa0170ef9b8bsalomon@google.com        }
15744783fbd25c350b0ea9fc02264b4b1a291c5988ebbsalomon@google.com        effect.reset(this->createUPMToPMEffect(texture, swapRAndB, textureMatrix));
1575281391b6ca1b37738dfbcc934db460f88865d709bsalomon@google.com        // handle the unpremul step on the CPU if we couldn't create an effect to do it.
15764783fbd25c350b0ea9fc02264b4b1a291c5988ebbsalomon@google.com        if (NULL == effect) {
1577f71764d3272e28817cb5025d2b503aa0170ef9b8bsalomon@google.com            SkCanvas::Config8888 srcConfig8888, dstConfig8888;
1578cd647ba2f3a71acb66c01e906520a5bec126069ccommit-bot@chromium.org            SkDEBUGCODE(bool success = )
1579281391b6ca1b37738dfbcc934db460f88865d709bsalomon@google.com            grconfig_to_config8888(srcConfig, true, &srcConfig8888);
1580a91959e0e4997d3a73b38e6d7f0296c566a4b1d0tfarina@chromium.org            SkASSERT(success);
1581cd647ba2f3a71acb66c01e906520a5bec126069ccommit-bot@chromium.org            SkDEBUGCODE(success = )
1582281391b6ca1b37738dfbcc934db460f88865d709bsalomon@google.com            grconfig_to_config8888(srcConfig, false, &dstConfig8888);
1583a91959e0e4997d3a73b38e6d7f0296c566a4b1d0tfarina@chromium.org            SkASSERT(success);
1584f71764d3272e28817cb5025d2b503aa0170ef9b8bsalomon@google.com            const uint32_t* src = reinterpret_cast<const uint32_t*>(buffer);
1585f71764d3272e28817cb5025d2b503aa0170ef9b8bsalomon@google.com            tmpPixels.reset(width * height);
1586f71764d3272e28817cb5025d2b503aa0170ef9b8bsalomon@google.com            SkConvertConfig8888Pixels(tmpPixels.get(), 4 * width, dstConfig8888,
1587f71764d3272e28817cb5025d2b503aa0170ef9b8bsalomon@google.com                                      src, rowBytes, srcConfig8888,
1588f71764d3272e28817cb5025d2b503aa0170ef9b8bsalomon@google.com                                      width, height);
1589f71764d3272e28817cb5025d2b503aa0170ef9b8bsalomon@google.com            buffer = tmpPixels.get();
1590f71764d3272e28817cb5025d2b503aa0170ef9b8bsalomon@google.com            rowBytes = 4 * width;
1591f71764d3272e28817cb5025d2b503aa0170ef9b8bsalomon@google.com        }
1592f71764d3272e28817cb5025d2b503aa0170ef9b8bsalomon@google.com    }
15934783fbd25c350b0ea9fc02264b4b1a291c5988ebbsalomon@google.com    if (NULL == effect) {
15944783fbd25c350b0ea9fc02264b4b1a291c5988ebbsalomon@google.com        effect.reset(GrConfigConversionEffect::Create(texture,
15954783fbd25c350b0ea9fc02264b4b1a291c5988ebbsalomon@google.com                                                      swapRAndB,
15964783fbd25c350b0ea9fc02264b4b1a291c5988ebbsalomon@google.com                                                      GrConfigConversionEffect::kNone_PMConversion,
15974783fbd25c350b0ea9fc02264b4b1a291c5988ebbsalomon@google.com                                                      textureMatrix));
1598f71764d3272e28817cb5025d2b503aa0170ef9b8bsalomon@google.com    }
1599f71764d3272e28817cb5025d2b503aa0170ef9b8bsalomon@google.com
1600281391b6ca1b37738dfbcc934db460f88865d709bsalomon@google.com    if (!this->writeTexturePixels(texture,
1601281391b6ca1b37738dfbcc934db460f88865d709bsalomon@google.com                                  0, 0, width, height,
1602281391b6ca1b37738dfbcc934db460f88865d709bsalomon@google.com                                  writeConfig, buffer, rowBytes,
1603281391b6ca1b37738dfbcc934db460f88865d709bsalomon@google.com                                  flags & ~kUnpremul_PixelOpsFlag)) {
1604281391b6ca1b37738dfbcc934db460f88865d709bsalomon@google.com        return false;
1605281391b6ca1b37738dfbcc934db460f88865d709bsalomon@google.com    }
16063f30e3a41fc16816105e28e0d4c241eff6d391b4bsalomon@google.com
1607ccc9cf9a1f76a236d9e30725646933afa0b72e57robertphillips@google.com    // writeRenderTargetPixels can be called in the midst of drawing another
1608f35b0ddb7e95937c441c95d5d36f64a38fa83f7fskia.committer@gmail.com    // object (e.g., when uploading a SW path rendering to the gpu while
1609ccc9cf9a1f76a236d9e30725646933afa0b72e57robertphillips@google.com    // drawing a rect) so preserve the current geometry.
1610fbf9f30e11f6dfae9203b152092125fe9b47adb8bsalomon@google.com    SkMatrix matrix;
1611fbf9f30e11f6dfae9203b152092125fe9b47adb8bsalomon@google.com    matrix.setTranslate(SkIntToScalar(left), SkIntToScalar(top));
1612fbf9f30e11f6dfae9203b152092125fe9b47adb8bsalomon@google.com    GrDrawTarget::AutoGeometryAndStatePush agasp(fGpu, GrDrawTarget::kReset_ASRInit, &matrix);
1613c08edffbcbe0eed40d8855f8acfe439c237c43bdbsalomon@google.com    GrDrawState* drawState = fGpu->drawState();
1614a91959e0e4997d3a73b38e6d7f0296c566a4b1d0tfarina@chromium.org    SkASSERT(effect);
1615860912a0affd82bc6b30ad9006658df856ca1d17bsalomon@google.com    drawState->addColorEffect(effect);
16163f30e3a41fc16816105e28e0d4c241eff6d391b4bsalomon@google.com
1617c08edffbcbe0eed40d8855f8acfe439c237c43bdbsalomon@google.com    drawState->setRenderTarget(target);
16183f30e3a41fc16816105e28e0d4c241eff6d391b4bsalomon@google.com
1619a8cbc57c2d74f8024d149370377bd7dcbd8d204ccommit-bot@chromium.org    fGpu->drawSimpleRect(SkRect::MakeWH(SkIntToScalar(width), SkIntToScalar(height)), NULL);
1620281391b6ca1b37738dfbcc934db460f88865d709bsalomon@google.com    return true;
16213f30e3a41fc16816105e28e0d4c241eff6d391b4bsalomon@google.com}
16223f30e3a41fc16816105e28e0d4c241eff6d391b4bsalomon@google.com////////////////////////////////////////////////////////////////////////////////
16233f30e3a41fc16816105e28e0d4c241eff6d391b4bsalomon@google.com
1624860912a0affd82bc6b30ad9006658df856ca1d17bsalomon@google.comGrDrawTarget* GrContext::prepareToDraw(const GrPaint* paint,
1625860912a0affd82bc6b30ad9006658df856ca1d17bsalomon@google.com                                       BufferedDraw buffered,
162621c4256a8eccc702d1c4b561da1a3a3e212d3c23commit-bot@chromium.org                                       AutoRestoreEffects* are,
162721c4256a8eccc702d1c4b561da1a3a3e212d3c23commit-bot@chromium.org                                       AutoCheckFlush* acf) {
1628860912a0affd82bc6b30ad9006658df856ca1d17bsalomon@google.com    // All users of this draw state should be freeing up all effects when they're done.
1629860912a0affd82bc6b30ad9006658df856ca1d17bsalomon@google.com    // Otherwise effects that own resources may keep those resources alive indefinitely.
1630a91959e0e4997d3a73b38e6d7f0296c566a4b1d0tfarina@chromium.org    SkASSERT(0 == fDrawState->numColorStages() && 0 == fDrawState->numCoverageStages());
1631860912a0affd82bc6b30ad9006658df856ca1d17bsalomon@google.com
163273631cc5a64283b9ed285b40739abe9b9a039b2absalomon@google.com    if (kNo_BufferedDraw == buffered && kYes_BufferedDraw == fLastDrawWasBuffered) {
1633be6b6c5266305f895cd216e616a823afe7fe621brobertphillips@google.com        fDrawBuffer->flush();
163473631cc5a64283b9ed285b40739abe9b9a039b2absalomon@google.com        fLastDrawWasBuffered = kNo_BufferedDraw;
16353f30e3a41fc16816105e28e0d4c241eff6d391b4bsalomon@google.com    }
1636e1884e6f16a6dd9f457970ffab3887e01f268703commit-bot@chromium.org    ASSERT_OWNED_RESOURCE(fRenderTarget.get());
16373bf3da2c23cf17d4711ec6ccb6e9965ae74e7b1dbsalomon@google.com    if (NULL != paint) {
1638a91959e0e4997d3a73b38e6d7f0296c566a4b1d0tfarina@chromium.org        SkASSERT(NULL != are);
163921c4256a8eccc702d1c4b561da1a3a3e212d3c23commit-bot@chromium.org        SkASSERT(NULL != acf);
1640860912a0affd82bc6b30ad9006658df856ca1d17bsalomon@google.com        are->set(fDrawState);
1641e1884e6f16a6dd9f457970ffab3887e01f268703commit-bot@chromium.org        fDrawState->setFromPaint(*paint, fViewMatrix, fRenderTarget.get());
164230b87f78d62a193a4b6eaf0d90461bd1d8935d59bsalomon@google.com#if GR_DEBUG_PARTIAL_COVERAGE_CHECK
164330b87f78d62a193a4b6eaf0d90461bd1d8935d59bsalomon@google.com        if ((paint->hasMask() || 0xff != paint->fCoverage) &&
164430b87f78d62a193a4b6eaf0d90461bd1d8935d59bsalomon@google.com            !fGpu->canApplyCoverage()) {
164530b87f78d62a193a4b6eaf0d90461bd1d8935d59bsalomon@google.com            GrPrintf("Partial pixel coverage will be incorrectly blended.\n");
164630b87f78d62a193a4b6eaf0d90461bd1d8935d59bsalomon@google.com        }
164730b87f78d62a193a4b6eaf0d90461bd1d8935d59bsalomon@google.com#endif
1648e1884e6f16a6dd9f457970ffab3887e01f268703commit-bot@chromium.org    } else {
1649fbf9f30e11f6dfae9203b152092125fe9b47adb8bsalomon@google.com        fDrawState->reset(fViewMatrix);
1650e1884e6f16a6dd9f457970ffab3887e01f268703commit-bot@chromium.org        fDrawState->setRenderTarget(fRenderTarget.get());
16513bf3da2c23cf17d4711ec6ccb6e9965ae74e7b1dbsalomon@google.com    }
1652e1884e6f16a6dd9f457970ffab3887e01f268703commit-bot@chromium.org    GrDrawTarget* target;
165373631cc5a64283b9ed285b40739abe9b9a039b2absalomon@google.com    if (kYes_BufferedDraw == buffered) {
165473631cc5a64283b9ed285b40739abe9b9a039b2absalomon@google.com        fLastDrawWasBuffered = kYes_BufferedDraw;
1655e1884e6f16a6dd9f457970ffab3887e01f268703commit-bot@chromium.org        target = fDrawBuffer;
165673631cc5a64283b9ed285b40739abe9b9a039b2absalomon@google.com    } else {
1657a91959e0e4997d3a73b38e6d7f0296c566a4b1d0tfarina@chromium.org        SkASSERT(kNo_BufferedDraw == buffered);
1658e1884e6f16a6dd9f457970ffab3887e01f268703commit-bot@chromium.org        fLastDrawWasBuffered = kNo_BufferedDraw;
1659e1884e6f16a6dd9f457970ffab3887e01f268703commit-bot@chromium.org        target = fGpu;
16603f30e3a41fc16816105e28e0d4c241eff6d391b4bsalomon@google.com    }
1661e1884e6f16a6dd9f457970ffab3887e01f268703commit-bot@chromium.org    fDrawState->setState(GrDrawState::kClip_StateBit, NULL != fClip &&
1662e1884e6f16a6dd9f457970ffab3887e01f268703commit-bot@chromium.org                                                     !fClip->fClipStack->isWideOpen());
1663e1884e6f16a6dd9f457970ffab3887e01f268703commit-bot@chromium.org    target->setClip(fClip);
1664a91959e0e4997d3a73b38e6d7f0296c566a4b1d0tfarina@chromium.org    SkASSERT(fDrawState == target->drawState());
1665e1884e6f16a6dd9f457970ffab3887e01f268703commit-bot@chromium.org    return target;
16663f30e3a41fc16816105e28e0d4c241eff6d391b4bsalomon@google.com}
16673f30e3a41fc16816105e28e0d4c241eff6d391b4bsalomon@google.com
1668a1a88ae20406b1cc7eae3d64bc1788d92eaf3816robertphillips@google.com/*
1669a1a88ae20406b1cc7eae3d64bc1788d92eaf3816robertphillips@google.com * This method finds a path renderer that can draw the specified path on
1670a1a88ae20406b1cc7eae3d64bc1788d92eaf3816robertphillips@google.com * the provided target.
1671935e9f4fafdfc64130e6be9ea2bb30e3bafd852armistry@google.com * Due to its expense, the software path renderer has split out so it can
1672a1a88ae20406b1cc7eae3d64bc1788d92eaf3816robertphillips@google.com * can be individually allowed/disallowed via the "allowSW" boolean.
1673a1a88ae20406b1cc7eae3d64bc1788d92eaf3816robertphillips@google.com */
167405069ac4dedd2f4b6c10238dbd31400c0fe3a879bsalomon@google.comGrPathRenderer* GrContext::getPathRenderer(const SkPath& path,
16755c2ee5c5d8f8593d40a2a9ffd9ca834653ee6af1sugoi@google.com                                           const SkStrokeRec& stroke,
1676111fa9c0003b99e052d665af57b51ff973dcb416bsalomon@google.com                                           const GrDrawTarget* target,
16770afd9ef7f06395f1bbbe9a18d8fcfa181d5f6bb0bsalomon@google.com                                           bool allowSW,
16780afd9ef7f06395f1bbbe9a18d8fcfa181d5f6bb0bsalomon@google.com                                           GrPathRendererChain::DrawType drawType,
16790afd9ef7f06395f1bbbe9a18d8fcfa181d5f6bb0bsalomon@google.com                                           GrPathRendererChain::StencilSupport* stencilSupport) {
16800afd9ef7f06395f1bbbe9a18d8fcfa181d5f6bb0bsalomon@google.com
16813f30e3a41fc16816105e28e0d4c241eff6d391b4bsalomon@google.com    if (NULL == fPathRendererChain) {
16820afd9ef7f06395f1bbbe9a18d8fcfa181d5f6bb0bsalomon@google.com        fPathRendererChain = SkNEW_ARGS(GrPathRendererChain, (this));
16833f30e3a41fc16816105e28e0d4c241eff6d391b4bsalomon@google.com    }
1684a1a88ae20406b1cc7eae3d64bc1788d92eaf3816robertphillips@google.com
1685290bf0ae34af76a4350a5df76ce02feb93d68196sugoi@google.com    GrPathRenderer* pr = fPathRendererChain->getPathRenderer(path,
1686290bf0ae34af76a4350a5df76ce02feb93d68196sugoi@google.com                                                             stroke,
1687a1a88ae20406b1cc7eae3d64bc1788d92eaf3816robertphillips@google.com                                                             target,
16880afd9ef7f06395f1bbbe9a18d8fcfa181d5f6bb0bsalomon@google.com                                                             drawType,
16890afd9ef7f06395f1bbbe9a18d8fcfa181d5f6bb0bsalomon@google.com                                                             stencilSupport);
1690a1a88ae20406b1cc7eae3d64bc1788d92eaf3816robertphillips@google.com
1691a1a88ae20406b1cc7eae3d64bc1788d92eaf3816robertphillips@google.com    if (NULL == pr && allowSW) {
1692a1a88ae20406b1cc7eae3d64bc1788d92eaf3816robertphillips@google.com        if (NULL == fSoftwarePathRenderer) {
16933697dec537a5d9941c5662d1b6c948c921edb5d4tomhudson@google.com            fSoftwarePathRenderer = SkNEW_ARGS(GrSoftwarePathRenderer, (this));
1694a1a88ae20406b1cc7eae3d64bc1788d92eaf3816robertphillips@google.com        }
1695a1a88ae20406b1cc7eae3d64bc1788d92eaf3816robertphillips@google.com        pr = fSoftwarePathRenderer;
1696a1a88ae20406b1cc7eae3d64bc1788d92eaf3816robertphillips@google.com    }
1697a1a88ae20406b1cc7eae3d64bc1788d92eaf3816robertphillips@google.com
1698a1a88ae20406b1cc7eae3d64bc1788d92eaf3816robertphillips@google.com    return pr;
16993f30e3a41fc16816105e28e0d4c241eff6d391b4bsalomon@google.com}
17003f30e3a41fc16816105e28e0d4c241eff6d391b4bsalomon@google.com
17013f30e3a41fc16816105e28e0d4c241eff6d391b4bsalomon@google.com////////////////////////////////////////////////////////////////////////////////
17026012533a061b85ff4f42e4ba808624071dcfe01bcommit-bot@chromium.orgbool GrContext::isConfigRenderable(GrPixelConfig config, bool withMSAA) const {
17036012533a061b85ff4f42e4ba808624071dcfe01bcommit-bot@chromium.org    return fGpu->caps()->isConfigRenderable(config, withMSAA);
1704e1f4ecccd0cd95301aab293853959a84860d1c56robertphillips@google.com}
1705e1f4ecccd0cd95301aab293853959a84860d1c56robertphillips@google.com
17063f30e3a41fc16816105e28e0d4c241eff6d391b4bsalomon@google.comvoid GrContext::setupDrawBuffer() {
1707a91959e0e4997d3a73b38e6d7f0296c566a4b1d0tfarina@chromium.org    SkASSERT(NULL == fDrawBuffer);
1708a91959e0e4997d3a73b38e6d7f0296c566a4b1d0tfarina@chromium.org    SkASSERT(NULL == fDrawBufferVBAllocPool);
1709a91959e0e4997d3a73b38e6d7f0296c566a4b1d0tfarina@chromium.org    SkASSERT(NULL == fDrawBufferIBAllocPool);
17103f30e3a41fc16816105e28e0d4c241eff6d391b4bsalomon@google.com
17113f30e3a41fc16816105e28e0d4c241eff6d391b4bsalomon@google.com    fDrawBufferVBAllocPool =
17123697dec537a5d9941c5662d1b6c948c921edb5d4tomhudson@google.com        SkNEW_ARGS(GrVertexBufferAllocPool, (fGpu, false,
17133f30e3a41fc16816105e28e0d4c241eff6d391b4bsalomon@google.com                                    DRAW_BUFFER_VBPOOL_BUFFER_SIZE,
17143697dec537a5d9941c5662d1b6c948c921edb5d4tomhudson@google.com                                    DRAW_BUFFER_VBPOOL_PREALLOC_BUFFERS));
17153f30e3a41fc16816105e28e0d4c241eff6d391b4bsalomon@google.com    fDrawBufferIBAllocPool =
17163697dec537a5d9941c5662d1b6c948c921edb5d4tomhudson@google.com        SkNEW_ARGS(GrIndexBufferAllocPool, (fGpu, false,
17173f30e3a41fc16816105e28e0d4c241eff6d391b4bsalomon@google.com                                   DRAW_BUFFER_IBPOOL_BUFFER_SIZE,
17183697dec537a5d9941c5662d1b6c948c921edb5d4tomhudson@google.com                                   DRAW_BUFFER_IBPOOL_PREALLOC_BUFFERS));
17193f30e3a41fc16816105e28e0d4c241eff6d391b4bsalomon@google.com
17203697dec537a5d9941c5662d1b6c948c921edb5d4tomhudson@google.com    fDrawBuffer = SkNEW_ARGS(GrInOrderDrawBuffer, (fGpu,
17210ad5bd91fd7dc876326ee0832ca8f7947dc1cc24bsalomon@google.com                                                   fDrawBufferVBAllocPool,
17220ad5bd91fd7dc876326ee0832ca8f7947dc1cc24bsalomon@google.com                                                   fDrawBufferIBAllocPool));
1723ec04ec0e334f46f82393827204a431667b8a0368bsalomon@google.com
17240ad5bd91fd7dc876326ee0832ca8f7947dc1cc24bsalomon@google.com    fDrawBuffer->setDrawState(fDrawState);
17253f30e3a41fc16816105e28e0d4c241eff6d391b4bsalomon@google.com}
17263f30e3a41fc16816105e28e0d4c241eff6d391b4bsalomon@google.com
1727c9f13ee9268ca0bc11d617b69a03e65582eb8210bsalomon@google.comGrDrawTarget* GrContext::getTextTarget() {
172821c4256a8eccc702d1c4b561da1a3a3e212d3c23commit-bot@chromium.org    return this->prepareToDraw(NULL, BUFFERED_DRAW, NULL, NULL);
17293f30e3a41fc16816105e28e0d4c241eff6d391b4bsalomon@google.com}
17303f30e3a41fc16816105e28e0d4c241eff6d391b4bsalomon@google.com
17313f30e3a41fc16816105e28e0d4c241eff6d391b4bsalomon@google.comconst GrIndexBuffer* GrContext::getQuadIndexBuffer() const {
17323f30e3a41fc16816105e28e0d4c241eff6d391b4bsalomon@google.com    return fGpu->getQuadIndexBuffer();
17333f30e3a41fc16816105e28e0d4c241eff6d391b4bsalomon@google.com}
17343f30e3a41fc16816105e28e0d4c241eff6d391b4bsalomon@google.com
1735f71764d3272e28817cb5025d2b503aa0170ef9b8bsalomon@google.comnamespace {
1736f71764d3272e28817cb5025d2b503aa0170ef9b8bsalomon@google.comvoid test_pm_conversions(GrContext* ctx, int* pmToUPMValue, int* upmToPMValue) {
1737f71764d3272e28817cb5025d2b503aa0170ef9b8bsalomon@google.com    GrConfigConversionEffect::PMConversion pmToUPM;
1738f71764d3272e28817cb5025d2b503aa0170ef9b8bsalomon@google.com    GrConfigConversionEffect::PMConversion upmToPM;
1739f71764d3272e28817cb5025d2b503aa0170ef9b8bsalomon@google.com    GrConfigConversionEffect::TestForPreservingPMConversions(ctx, &pmToUPM, &upmToPM);
1740f71764d3272e28817cb5025d2b503aa0170ef9b8bsalomon@google.com    *pmToUPMValue = pmToUPM;
1741f71764d3272e28817cb5025d2b503aa0170ef9b8bsalomon@google.com    *upmToPMValue = upmToPM;
1742f71764d3272e28817cb5025d2b503aa0170ef9b8bsalomon@google.com}
1743f71764d3272e28817cb5025d2b503aa0170ef9b8bsalomon@google.com}
1744f71764d3272e28817cb5025d2b503aa0170ef9b8bsalomon@google.com
17454783fbd25c350b0ea9fc02264b4b1a291c5988ebbsalomon@google.comconst GrEffectRef* GrContext::createPMToUPMEffect(GrTexture* texture,
17464783fbd25c350b0ea9fc02264b4b1a291c5988ebbsalomon@google.com                                                  bool swapRAndB,
17474783fbd25c350b0ea9fc02264b4b1a291c5988ebbsalomon@google.com                                                  const SkMatrix& matrix) {
1748f71764d3272e28817cb5025d2b503aa0170ef9b8bsalomon@google.com    if (!fDidTestPMConversions) {
1749f71764d3272e28817cb5025d2b503aa0170ef9b8bsalomon@google.com        test_pm_conversions(this, &fPMToUPMConversion, &fUPMToPMConversion);
1750c18a64e62fa6d9519f435315d682c3f2c4210820bsalomon@google.com        fDidTestPMConversions = true;
1751f71764d3272e28817cb5025d2b503aa0170ef9b8bsalomon@google.com    }
1752f71764d3272e28817cb5025d2b503aa0170ef9b8bsalomon@google.com    GrConfigConversionEffect::PMConversion pmToUPM =
1753f71764d3272e28817cb5025d2b503aa0170ef9b8bsalomon@google.com        static_cast<GrConfigConversionEffect::PMConversion>(fPMToUPMConversion);
1754f71764d3272e28817cb5025d2b503aa0170ef9b8bsalomon@google.com    if (GrConfigConversionEffect::kNone_PMConversion != pmToUPM) {
17554783fbd25c350b0ea9fc02264b4b1a291c5988ebbsalomon@google.com        return GrConfigConversionEffect::Create(texture, swapRAndB, pmToUPM, matrix);
1756f71764d3272e28817cb5025d2b503aa0170ef9b8bsalomon@google.com    } else {
17574783fbd25c350b0ea9fc02264b4b1a291c5988ebbsalomon@google.com        return NULL;
1758f71764d3272e28817cb5025d2b503aa0170ef9b8bsalomon@google.com    }
1759f71764d3272e28817cb5025d2b503aa0170ef9b8bsalomon@google.com}
1760f71764d3272e28817cb5025d2b503aa0170ef9b8bsalomon@google.com
17614783fbd25c350b0ea9fc02264b4b1a291c5988ebbsalomon@google.comconst GrEffectRef* GrContext::createUPMToPMEffect(GrTexture* texture,
17624783fbd25c350b0ea9fc02264b4b1a291c5988ebbsalomon@google.com                                                  bool swapRAndB,
17634783fbd25c350b0ea9fc02264b4b1a291c5988ebbsalomon@google.com                                                  const SkMatrix& matrix) {
1764f71764d3272e28817cb5025d2b503aa0170ef9b8bsalomon@google.com    if (!fDidTestPMConversions) {
1765f71764d3272e28817cb5025d2b503aa0170ef9b8bsalomon@google.com        test_pm_conversions(this, &fPMToUPMConversion, &fUPMToPMConversion);
1766c18a64e62fa6d9519f435315d682c3f2c4210820bsalomon@google.com        fDidTestPMConversions = true;
1767f71764d3272e28817cb5025d2b503aa0170ef9b8bsalomon@google.com    }
1768f71764d3272e28817cb5025d2b503aa0170ef9b8bsalomon@google.com    GrConfigConversionEffect::PMConversion upmToPM =
1769f71764d3272e28817cb5025d2b503aa0170ef9b8bsalomon@google.com        static_cast<GrConfigConversionEffect::PMConversion>(fUPMToPMConversion);
1770f71764d3272e28817cb5025d2b503aa0170ef9b8bsalomon@google.com    if (GrConfigConversionEffect::kNone_PMConversion != upmToPM) {
17714783fbd25c350b0ea9fc02264b4b1a291c5988ebbsalomon@google.com        return GrConfigConversionEffect::Create(texture, swapRAndB, upmToPM, matrix);
1772f71764d3272e28817cb5025d2b503aa0170ef9b8bsalomon@google.com    } else {
17734783fbd25c350b0ea9fc02264b4b1a291c5988ebbsalomon@google.com        return NULL;
1774f71764d3272e28817cb5025d2b503aa0170ef9b8bsalomon@google.com    }
1775f71764d3272e28817cb5025d2b503aa0170ef9b8bsalomon@google.com}
1776f71764d3272e28817cb5025d2b503aa0170ef9b8bsalomon@google.com
177709af991708bb73d5e1c8bff9c1e7f8423bde09ddcommit-bot@chromium.orgGrPath* GrContext::createPath(const SkPath& inPath, const SkStrokeRec& stroke) {
177809af991708bb73d5e1c8bff9c1e7f8423bde09ddcommit-bot@chromium.org    SkASSERT(fGpu->caps()->pathRenderingSupport());
177909af991708bb73d5e1c8bff9c1e7f8423bde09ddcommit-bot@chromium.org
178009af991708bb73d5e1c8bff9c1e7f8423bde09ddcommit-bot@chromium.org    // TODO: now we add to fTextureCache. This should change to fResourceCache.
178109af991708bb73d5e1c8bff9c1e7f8423bde09ddcommit-bot@chromium.org    GrResourceKey resourceKey = GrPath::ComputeKey(inPath, stroke);
178209af991708bb73d5e1c8bff9c1e7f8423bde09ddcommit-bot@chromium.org    GrPath* path = static_cast<GrPath*>(fTextureCache->find(resourceKey));
178309af991708bb73d5e1c8bff9c1e7f8423bde09ddcommit-bot@chromium.org    if (NULL != path && path->isEqualTo(inPath, stroke)) {
178409af991708bb73d5e1c8bff9c1e7f8423bde09ddcommit-bot@chromium.org        path->ref();
178509af991708bb73d5e1c8bff9c1e7f8423bde09ddcommit-bot@chromium.org    } else {
178609af991708bb73d5e1c8bff9c1e7f8423bde09ddcommit-bot@chromium.org        path = fGpu->createPath(inPath, stroke);
178709af991708bb73d5e1c8bff9c1e7f8423bde09ddcommit-bot@chromium.org        fTextureCache->purgeAsNeeded(1, path->sizeInBytes());
178809af991708bb73d5e1c8bff9c1e7f8423bde09ddcommit-bot@chromium.org        fTextureCache->addResource(resourceKey, path);
178909af991708bb73d5e1c8bff9c1e7f8423bde09ddcommit-bot@chromium.org    }
179009af991708bb73d5e1c8bff9c1e7f8423bde09ddcommit-bot@chromium.org    return path;
179109af991708bb73d5e1c8bff9c1e7f8423bde09ddcommit-bot@chromium.org}
179209af991708bb73d5e1c8bff9c1e7f8423bde09ddcommit-bot@chromium.org
179300e32ee9f771bd4d9cd04e4c76e6f5f59b26a4dfbsalomon@google.com///////////////////////////////////////////////////////////////////////////////
17943592f532d77bedf33bdc7486c155acfb41c774e5robertphillips@google.com#if GR_CACHE_STATS
17953e52c155a99bba22fb3641e6181e65623cabd43drobertphillips@google.comvoid GrContext::printCacheStats() const {
17963e52c155a99bba22fb3641e6181e65623cabd43drobertphillips@google.com    fTextureCache->printStats();
17973e52c155a99bba22fb3641e6181e65623cabd43drobertphillips@google.com}
17983e52c155a99bba22fb3641e6181e65623cabd43drobertphillips@google.com#endif
1799