GrContext.cpp revision e79f320ed6c5ec9f6164ba84be1ff586532e6517
127847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com
2ec3ed6a5ebf6f2c406d7bcf94b6bc34fcaeb976eepoger@google.com/*
3ec3ed6a5ebf6f2c406d7bcf94b6bc34fcaeb976eepoger@google.com * Copyright 2011 Google Inc.
4ec3ed6a5ebf6f2c406d7bcf94b6bc34fcaeb976eepoger@google.com *
5ec3ed6a5ebf6f2c406d7bcf94b6bc34fcaeb976eepoger@google.com * Use of this source code is governed by a BSD-style license that can be
6ec3ed6a5ebf6f2c406d7bcf94b6bc34fcaeb976eepoger@google.com * found in the LICENSE file.
727847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com */
827847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com
9ec3ed6a5ebf6f2c406d7bcf94b6bc34fcaeb976eepoger@google.com
101fadb20c50c2302565f73ae12057a6f5d22192c7bsalomon@google.com#include "GrContext.h"
111fadb20c50c2302565f73ae12057a6f5d22192c7bsalomon@google.com
12aa72eab5d82d4c2aa9f6f41755a001282443b042tomhudson@google.com#include "effects/GrSingleTextureEffect.h"
13a04e8e842450e606dd938ddae17857849bd504d4bsalomon@google.com#include "effects/GrConfigConversionEffect.h"
14b505a128efae9debcaa9642bade90bab5525d477bsalomon@google.com
15bfe2b9d3a290d0153b82617cd6b65a4814fe89e3jvanverth@google.com#include "GrAARectRenderer.h"
16278cbb452a260de1550769b168df448e0911cf3ctomhudson@google.com#include "GrBufferAllocPool.h"
1705ef510389950e1ae8dcba40e41e001db771b12dbsalomon@google.com#include "GrGpu.h"
18c26d94fd7dc0b00cd6d0e42d28285f4a38aff021bsalomon@google.com#include "GrDrawTargetCaps.h"
1927847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com#include "GrIndexBuffer.h"
2027847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com#include "GrInOrderDrawBuffer.h"
2181312830ef73420efdc4821feb7c2d6fd9152af8commit-bot@chromium.org#include "GrOvalRenderer.h"
2227847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com#include "GrPathRenderer.h"
23d22b6e4351e552a8379d7781096d9e79feeae263tomhudson@google.com#include "GrPathUtils.h"
2450398bf7f1953e640e5529616e710cf540799731bsalomon@google.com#include "GrResourceCache.h"
2572176b2d38db005863a54e3dd6657bbabd068bb6robertphillips@google.com#include "GrSoftwarePathRenderer.h"
26558a75bcb323c03dd7482555c7214062a363276fbsalomon@google.com#include "GrStencilBuffer.h"
27278cbb452a260de1550769b168df448e0911cf3ctomhudson@google.com#include "GrTextStrike.h"
2882b0ec6ea408d866e02805fbe0519d00d2e87627bsalomon@google.com#include "SkRTConf.h"
2919dd017a6256be636ccb550752bb563c4e7caeb5commit-bot@chromium.org#include "SkRRect.h"
305f74cf8c49701f514b69dc6f1a8b5c0ffd78af0asugoi@google.com#include "SkStrokeRec.h"
318c2fe99ed2c210317786683e8c1f1e86cff0be49bsalomon@google.com#include "SkTLazy.h"
32c0af3173314e227611d8c5541ef2deee0052d412bsalomon@google.com#include "SkTLS.h"
330c8d93a94099dee2dff8da6000ded9ad59676488tomhudson@google.com#include "SkTrace.h"
3427847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com
3582b0ec6ea408d866e02805fbe0519d00d2e87627bsalomon@google.com// It can be useful to set this to false to test whether a bug is caused by using the
361d4edd38f6b62d1cc54cb7bc6f3c6ce10ccb1471bsalomon@google.com// InOrderDrawBuffer, to compare performance of using/not using InOrderDrawBuffer, or to make
3782b0ec6ea408d866e02805fbe0519d00d2e87627bsalomon@google.com// debugging simpler.
38e932c98069fd6831a03ff63d331271ef0e9703d9bsalomon@google.comSK_CONF_DECLARE(bool, c_Defer, "gpu.deferContext", true,
3965eb4d5a210884cc92c43a8582cbd1ccbddcab57jvanverth@google.com                "Defers rendering in GrContext via GrInOrderDrawBuffer.");
4082b0ec6ea408d866e02805fbe0519d00d2e87627bsalomon@google.com
4182b0ec6ea408d866e02805fbe0519d00d2e87627bsalomon@google.com#define BUFFERED_DRAW (c_Defer ? kYes_BufferedDraw : kNo_BufferedDraw)
4227847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com
43515dcd36032997ce335daa0163c6d67e851bcad1commit-bot@chromium.org#ifdef SK_DEBUG
444b2d3f30d047435263642ef8ed170a37ca642c1breed@google.com    // change this to a 1 to see notifications when partial coverage fails
454b2d3f30d047435263642ef8ed170a37ca642c1breed@google.com    #define GR_DEBUG_PARTIAL_COVERAGE_CHECK 0
464b2d3f30d047435263642ef8ed170a37ca642c1breed@google.com#else
474b2d3f30d047435263642ef8ed170a37ca642c1breed@google.com    #define GR_DEBUG_PARTIAL_COVERAGE_CHECK 0
484b2d3f30d047435263642ef8ed170a37ca642c1breed@google.com#endif
494b2d3f30d047435263642ef8ed170a37ca642c1breed@google.com
504e5559af8947ae7dc3df531b6d7a73323db20c3frobertphillips@google.comstatic const size_t MAX_RESOURCE_CACHE_COUNT = GR_DEFAULT_RESOURCE_CACHE_COUNT_LIMIT;
514e5559af8947ae7dc3df531b6d7a73323db20c3frobertphillips@google.comstatic const size_t MAX_RESOURCE_CACHE_BYTES = GR_DEFAULT_RESOURCE_CACHE_MB_LIMIT * 1024 * 1024;
5227847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com
5360361493548d5259d0a8afae84274c2a3c31dcacbsalomon@google.comstatic const size_t DRAW_BUFFER_VBPOOL_BUFFER_SIZE = 1 << 15;
5427847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.comstatic const int DRAW_BUFFER_VBPOOL_PREALLOC_BUFFERS = 4;
5527847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com
561d4edd38f6b62d1cc54cb7bc6f3c6ce10ccb1471bsalomon@google.comstatic const size_t DRAW_BUFFER_IBPOOL_BUFFER_SIZE = 1 << 11;
571d4edd38f6b62d1cc54cb7bc6f3c6ce10ccb1471bsalomon@google.comstatic const int DRAW_BUFFER_IBPOOL_PREALLOC_BUFFERS = 4;
5827847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com
59f6de475e5cbd143f348ff7738919e397b7fe7f57tfarina@chromium.org#define ASSERT_OWNED_RESOURCE(R) SkASSERT(!(R) || (R)->getContext() == this)
60bc4b654af85fa67bdd9cc1b88747b8c394a00e27bsalomon@google.com
61eb6879f50a5564eeb981ec5616b55bf685eb76fcbsalomon@google.com// Glorified typedef to avoid including GrDrawState.h in GrContext.h
62eb6879f50a5564eeb981ec5616b55bf685eb76fcbsalomon@google.comclass GrContext::AutoRestoreEffects : public GrDrawState::AutoRestoreEffects {};
63eb6879f50a5564eeb981ec5616b55bf685eb76fcbsalomon@google.com
645dbb149fda134941e5d168790127caf294d322e2commit-bot@chromium.orgclass GrContext::AutoCheckFlush {
655dbb149fda134941e5d168790127caf294d322e2commit-bot@chromium.orgpublic:
665dbb149fda134941e5d168790127caf294d322e2commit-bot@chromium.org    AutoCheckFlush(GrContext* context) : fContext(context) { SkASSERT(NULL != context); }
675dbb149fda134941e5d168790127caf294d322e2commit-bot@chromium.org
685dbb149fda134941e5d168790127caf294d322e2commit-bot@chromium.org    ~AutoCheckFlush() {
695dbb149fda134941e5d168790127caf294d322e2commit-bot@chromium.org        if (fContext->fFlushToReduceCacheSize) {
705dbb149fda134941e5d168790127caf294d322e2commit-bot@chromium.org            fContext->flush();
715dbb149fda134941e5d168790127caf294d322e2commit-bot@chromium.org        }
725dbb149fda134941e5d168790127caf294d322e2commit-bot@chromium.org    }
735dbb149fda134941e5d168790127caf294d322e2commit-bot@chromium.org
745dbb149fda134941e5d168790127caf294d322e2commit-bot@chromium.orgprivate:
755dbb149fda134941e5d168790127caf294d322e2commit-bot@chromium.org    GrContext* fContext;
765dbb149fda134941e5d168790127caf294d322e2commit-bot@chromium.org};
775dbb149fda134941e5d168790127caf294d322e2commit-bot@chromium.org
786e4e65066a7c0dbc9bfbfe4b8f5d49c3d8a79b59bsalomon@google.comGrContext* GrContext::Create(GrBackend backend, GrBackendContext backendContext) {
796e4e65066a7c0dbc9bfbfe4b8f5d49c3d8a79b59bsalomon@google.com    GrContext* context = SkNEW(GrContext);
806e4e65066a7c0dbc9bfbfe4b8f5d49c3d8a79b59bsalomon@google.com    if (context->init(backend, backendContext)) {
816e4e65066a7c0dbc9bfbfe4b8f5d49c3d8a79b59bsalomon@google.com        return context;
826e4e65066a7c0dbc9bfbfe4b8f5d49c3d8a79b59bsalomon@google.com    } else {
836e4e65066a7c0dbc9bfbfe4b8f5d49c3d8a79b59bsalomon@google.com        context->unref();
846e4e65066a7c0dbc9bfbfe4b8f5d49c3d8a79b59bsalomon@google.com        return NULL;
8527847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com    }
8627847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com}
8727847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com
886e4e65066a7c0dbc9bfbfe4b8f5d49c3d8a79b59bsalomon@google.comGrContext::GrContext() {
896e4e65066a7c0dbc9bfbfe4b8f5d49c3d8a79b59bsalomon@google.com    fDrawState = NULL;
906e4e65066a7c0dbc9bfbfe4b8f5d49c3d8a79b59bsalomon@google.com    fGpu = NULL;
91bb6a3178c3e79c8549b332e4ce84c64b59964f1ecommit-bot@chromium.org    fClip = NULL;
926e4e65066a7c0dbc9bfbfe4b8f5d49c3d8a79b59bsalomon@google.com    fPathRendererChain = NULL;
936e4e65066a7c0dbc9bfbfe4b8f5d49c3d8a79b59bsalomon@google.com    fSoftwarePathRenderer = NULL;
946e4e65066a7c0dbc9bfbfe4b8f5d49c3d8a79b59bsalomon@google.com    fTextureCache = NULL;
956e4e65066a7c0dbc9bfbfe4b8f5d49c3d8a79b59bsalomon@google.com    fFontCache = NULL;
966e4e65066a7c0dbc9bfbfe4b8f5d49c3d8a79b59bsalomon@google.com    fDrawBuffer = NULL;
976e4e65066a7c0dbc9bfbfe4b8f5d49c3d8a79b59bsalomon@google.com    fDrawBufferVBAllocPool = NULL;
986e4e65066a7c0dbc9bfbfe4b8f5d49c3d8a79b59bsalomon@google.com    fDrawBufferIBAllocPool = NULL;
995dbb149fda134941e5d168790127caf294d322e2commit-bot@chromium.org    fFlushToReduceCacheSize = false;
1006e4e65066a7c0dbc9bfbfe4b8f5d49c3d8a79b59bsalomon@google.com    fAARectRenderer = NULL;
10181312830ef73420efdc4821feb7c2d6fd9152af8commit-bot@chromium.org    fOvalRenderer = NULL;
102bb6a3178c3e79c8549b332e4ce84c64b59964f1ecommit-bot@chromium.org    fViewMatrix.reset();
10344a91dcf2542c2aa93f159ebbb5bf813ae7362c0robertphillips@google.com    fMaxTextureSizeOverride = 1 << 20;
1046e4e65066a7c0dbc9bfbfe4b8f5d49c3d8a79b59bsalomon@google.com}
1056e4e65066a7c0dbc9bfbfe4b8f5d49c3d8a79b59bsalomon@google.com
1066e4e65066a7c0dbc9bfbfe4b8f5d49c3d8a79b59bsalomon@google.combool GrContext::init(GrBackend backend, GrBackendContext backendContext) {
107f6de475e5cbd143f348ff7738919e397b7fe7f57tfarina@chromium.org    SkASSERT(NULL == fGpu);
1086e4e65066a7c0dbc9bfbfe4b8f5d49c3d8a79b59bsalomon@google.com
1096e4e65066a7c0dbc9bfbfe4b8f5d49c3d8a79b59bsalomon@google.com    fGpu = GrGpu::Create(backend, backendContext, this);
1106e4e65066a7c0dbc9bfbfe4b8f5d49c3d8a79b59bsalomon@google.com    if (NULL == fGpu) {
1116e4e65066a7c0dbc9bfbfe4b8f5d49c3d8a79b59bsalomon@google.com        return false;
1126e4e65066a7c0dbc9bfbfe4b8f5d49c3d8a79b59bsalomon@google.com    }
1136e4e65066a7c0dbc9bfbfe4b8f5d49c3d8a79b59bsalomon@google.com
1146e4e65066a7c0dbc9bfbfe4b8f5d49c3d8a79b59bsalomon@google.com    fDrawState = SkNEW(GrDrawState);
1156e4e65066a7c0dbc9bfbfe4b8f5d49c3d8a79b59bsalomon@google.com    fGpu->setDrawState(fDrawState);
1166e4e65066a7c0dbc9bfbfe4b8f5d49c3d8a79b59bsalomon@google.com
1176e4e65066a7c0dbc9bfbfe4b8f5d49c3d8a79b59bsalomon@google.com    fTextureCache = SkNEW_ARGS(GrResourceCache,
1184e5559af8947ae7dc3df531b6d7a73323db20c3frobertphillips@google.com                               (MAX_RESOURCE_CACHE_COUNT,
1194e5559af8947ae7dc3df531b6d7a73323db20c3frobertphillips@google.com                                MAX_RESOURCE_CACHE_BYTES));
1201836d337a85b82689287231091823f404d8cab43commit-bot@chromium.org    fTextureCache->setOverbudgetCallback(OverbudgetCB, this);
1211836d337a85b82689287231091823f404d8cab43commit-bot@chromium.org
1226e4e65066a7c0dbc9bfbfe4b8f5d49c3d8a79b59bsalomon@google.com    fFontCache = SkNEW_ARGS(GrFontCache, (fGpu));
1236e4e65066a7c0dbc9bfbfe4b8f5d49c3d8a79b59bsalomon@google.com
1246e4e65066a7c0dbc9bfbfe4b8f5d49c3d8a79b59bsalomon@google.com    fLastDrawWasBuffered = kNo_BufferedDraw;
1256e4e65066a7c0dbc9bfbfe4b8f5d49c3d8a79b59bsalomon@google.com
1266e4e65066a7c0dbc9bfbfe4b8f5d49c3d8a79b59bsalomon@google.com    fAARectRenderer = SkNEW(GrAARectRenderer);
12781312830ef73420efdc4821feb7c2d6fd9152af8commit-bot@chromium.org    fOvalRenderer = SkNEW(GrOvalRenderer);
1286e4e65066a7c0dbc9bfbfe4b8f5d49c3d8a79b59bsalomon@google.com
1296e4e65066a7c0dbc9bfbfe4b8f5d49c3d8a79b59bsalomon@google.com    fDidTestPMConversions = false;
1306e4e65066a7c0dbc9bfbfe4b8f5d49c3d8a79b59bsalomon@google.com
1316e4e65066a7c0dbc9bfbfe4b8f5d49c3d8a79b59bsalomon@google.com    this->setupDrawBuffer();
1326e4e65066a7c0dbc9bfbfe4b8f5d49c3d8a79b59bsalomon@google.com
1336e4e65066a7c0dbc9bfbfe4b8f5d49c3d8a79b59bsalomon@google.com    return true;
134c0af3173314e227611d8c5541ef2deee0052d412bsalomon@google.com}
135c0af3173314e227611d8c5541ef2deee0052d412bsalomon@google.com
13627847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.comGrContext::~GrContext() {
137733c062c09bfe3ec4a32658510136fc5850a6e2cbsalomon@google.com    if (NULL == fGpu) {
138733c062c09bfe3ec4a32658510136fc5850a6e2cbsalomon@google.com        return;
139733c062c09bfe3ec4a32658510136fc5850a6e2cbsalomon@google.com    }
140733c062c09bfe3ec4a32658510136fc5850a6e2cbsalomon@google.com
1418fe72477f204b1a45393e6a64caa84fd287b805bbsalomon@google.com    this->flush();
1425acc0e36d987dff3172fd45a14b66c52a51d49e4robertphillips@google.com
143950b1b079a782e208c2f38cf222184fa1ca1006drobertphillips@google.com    for (int i = 0; i < fCleanUpData.count(); ++i) {
144950b1b079a782e208c2f38cf222184fa1ca1006drobertphillips@google.com        (*fCleanUpData[i].fFunc)(this, fCleanUpData[i].fInfo);
145950b1b079a782e208c2f38cf222184fa1ca1006drobertphillips@google.com    }
146950b1b079a782e208c2f38cf222184fa1ca1006drobertphillips@google.com
1475acc0e36d987dff3172fd45a14b66c52a51d49e4robertphillips@google.com    // Since the gpu can hold scratch textures, give it a chance to let go
1485acc0e36d987dff3172fd45a14b66c52a51d49e4robertphillips@google.com    // of them before freeing the texture cache
1495acc0e36d987dff3172fd45a14b66c52a51d49e4robertphillips@google.com    fGpu->purgeResources();
1505acc0e36d987dff3172fd45a14b66c52a51d49e4robertphillips@google.com
15127847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com    delete fTextureCache;
152eb9b3e164e55b8d15e1c25bfb1332917453cbc3arobertphillips@google.com    fTextureCache = NULL;
15327847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com    delete fFontCache;
15427847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com    delete fDrawBuffer;
15527847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com    delete fDrawBufferVBAllocPool;
156de6ac2dec54a34545dae1986cd743d24c8d655e8bsalomon@google.com    delete fDrawBufferIBAllocPool;
1573008519e9f977cd60194841d558a4f45c28e9833bsalomon@google.com
158f6747b0b90b3a270ec7b7bdfdc211cf5c19f28c2robertphillips@google.com    fAARectRenderer->unref();
15981312830ef73420efdc4821feb7c2d6fd9152af8commit-bot@chromium.org    fOvalRenderer->unref();
160f6747b0b90b3a270ec7b7bdfdc211cf5c19f28c2robertphillips@google.com
161205d46067ace24bd4b111cf44efc96caff6c4d30bsalomon@google.com    fGpu->unref();
162a4de8c257ea0be8ff7081f645249b6afe5c48e7ecommit-bot@chromium.org    SkSafeUnref(fPathRendererChain);
163a4de8c257ea0be8ff7081f645249b6afe5c48e7ecommit-bot@chromium.org    SkSafeUnref(fSoftwarePathRenderer);
16410e04bf1c5025389d999f22467405782e9f9ffccbsalomon@google.com    fDrawState->unref();
16527847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com}
16627847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com
1678fe72477f204b1a45393e6a64caa84fd287b805bbsalomon@google.comvoid GrContext::contextLost() {
1686e4e65066a7c0dbc9bfbfe4b8f5d49c3d8a79b59bsalomon@google.com    this->contextDestroyed();
16953a5584bb0094e19c39a66cec7f346aad04ecac4junov@google.com    this->setupDrawBuffer();
17053a5584bb0094e19c39a66cec7f346aad04ecac4junov@google.com}
17153a5584bb0094e19c39a66cec7f346aad04ecac4junov@google.com
17253a5584bb0094e19c39a66cec7f346aad04ecac4junov@google.comvoid GrContext::contextDestroyed() {
173205d46067ace24bd4b111cf44efc96caff6c4d30bsalomon@google.com    // abandon first to so destructors
174205d46067ace24bd4b111cf44efc96caff6c4d30bsalomon@google.com    // don't try to free the resources in the API.
175205d46067ace24bd4b111cf44efc96caff6c4d30bsalomon@google.com    fGpu->abandonResources();
176205d46067ace24bd4b111cf44efc96caff6c4d30bsalomon@google.com
1773008519e9f977cd60194841d558a4f45c28e9833bsalomon@google.com    // a path renderer may be holding onto resources that
1783008519e9f977cd60194841d558a4f45c28e9833bsalomon@google.com    // are now unusable
179a4de8c257ea0be8ff7081f645249b6afe5c48e7ecommit-bot@chromium.org    SkSafeSetNull(fPathRendererChain);
180a4de8c257ea0be8ff7081f645249b6afe5c48e7ecommit-bot@chromium.org    SkSafeSetNull(fSoftwarePathRenderer);
1813008519e9f977cd60194841d558a4f45c28e9833bsalomon@google.com
1828fe72477f204b1a45393e6a64caa84fd287b805bbsalomon@google.com    delete fDrawBuffer;
1838fe72477f204b1a45393e6a64caa84fd287b805bbsalomon@google.com    fDrawBuffer = NULL;
184205d46067ace24bd4b111cf44efc96caff6c4d30bsalomon@google.com
1858fe72477f204b1a45393e6a64caa84fd287b805bbsalomon@google.com    delete fDrawBufferVBAllocPool;
1868fe72477f204b1a45393e6a64caa84fd287b805bbsalomon@google.com    fDrawBufferVBAllocPool = NULL;
187205d46067ace24bd4b111cf44efc96caff6c4d30bsalomon@google.com
1888fe72477f204b1a45393e6a64caa84fd287b805bbsalomon@google.com    delete fDrawBufferIBAllocPool;
1898fe72477f204b1a45393e6a64caa84fd287b805bbsalomon@google.com    fDrawBufferIBAllocPool = NULL;
1908fe72477f204b1a45393e6a64caa84fd287b805bbsalomon@google.com
191f6747b0b90b3a270ec7b7bdfdc211cf5c19f28c2robertphillips@google.com    fAARectRenderer->reset();
192ef284a84f503adfd08ee52b5aee142c548698ea4commit-bot@chromium.org    fOvalRenderer->reset();
193205d46067ace24bd4b111cf44efc96caff6c4d30bsalomon@google.com
194a292112154f803feb9f5cc002bbfab559f7cb633bsalomon@google.com    fTextureCache->purgeAllUnlocked();
1955c8ee2539b9316b22416a991a1f560ef5cec7957commit-bot@chromium.org
1968fe72477f204b1a45393e6a64caa84fd287b805bbsalomon@google.com    fFontCache->freeAll();
1978fe72477f204b1a45393e6a64caa84fd287b805bbsalomon@google.com    fGpu->markContextDirty();
1988fe72477f204b1a45393e6a64caa84fd287b805bbsalomon@google.com}
1998fe72477f204b1a45393e6a64caa84fd287b805bbsalomon@google.com
2000a208a117b2d7f2c2231aa357f1db4864dbdcba3bsalomon@google.comvoid GrContext::resetContext(uint32_t state) {
2010a208a117b2d7f2c2231aa357f1db4864dbdcba3bsalomon@google.com    fGpu->markContextDirty(state);
2028fe72477f204b1a45393e6a64caa84fd287b805bbsalomon@google.com}
2038fe72477f204b1a45393e6a64caa84fd287b805bbsalomon@google.com
2048fe72477f204b1a45393e6a64caa84fd287b805bbsalomon@google.comvoid GrContext::freeGpuResources() {
2058fe72477f204b1a45393e6a64caa84fd287b805bbsalomon@google.com    this->flush();
206fbfcd5602128ec010c82cb733c9cdc0a3254f9f3rmistry@google.com
207ff17584e1c15f68ccc296be517e8a6776a9ddabdrobertphillips@google.com    fGpu->purgeResources();
208ff17584e1c15f68ccc296be517e8a6776a9ddabdrobertphillips@google.com
209f6747b0b90b3a270ec7b7bdfdc211cf5c19f28c2robertphillips@google.com    fAARectRenderer->reset();
210ef284a84f503adfd08ee52b5aee142c548698ea4commit-bot@chromium.org    fOvalRenderer->reset();
211f6747b0b90b3a270ec7b7bdfdc211cf5c19f28c2robertphillips@google.com
212a292112154f803feb9f5cc002bbfab559f7cb633bsalomon@google.com    fTextureCache->purgeAllUnlocked();
2138fe72477f204b1a45393e6a64caa84fd287b805bbsalomon@google.com    fFontCache->freeAll();
2143008519e9f977cd60194841d558a4f45c28e9833bsalomon@google.com    // a path renderer may be holding onto resources
215a4de8c257ea0be8ff7081f645249b6afe5c48e7ecommit-bot@chromium.org    SkSafeSetNull(fPathRendererChain);
216a4de8c257ea0be8ff7081f645249b6afe5c48e7ecommit-bot@chromium.org    SkSafeSetNull(fSoftwarePathRenderer);
21727847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com}
21827847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com
21905e70247c31ae927074ef27ea9893634a8dda543twiz@google.comsize_t GrContext::getGpuTextureCacheBytes() const {
22005e70247c31ae927074ef27ea9893634a8dda543twiz@google.com  return fTextureCache->getCachedResourceBytes();
22105e70247c31ae927074ef27ea9893634a8dda543twiz@google.com}
22205e70247c31ae927074ef27ea9893634a8dda543twiz@google.com
223fea37b5e532dfe776269253afb9951e763c3b205bsalomon@google.com////////////////////////////////////////////////////////////////////////////////
224fea37b5e532dfe776269253afb9951e763c3b205bsalomon@google.com
22595ed55adc6b8f0cee063c2cf2e14782773b0087fbsalomon@google.comGrTexture* GrContext::findAndRefTexture(const GrTextureDesc& desc,
22695ed55adc6b8f0cee063c2cf2e14782773b0087fbsalomon@google.com                                        const GrCacheID& cacheID,
22795ed55adc6b8f0cee063c2cf2e14782773b0087fbsalomon@google.com                                        const GrTextureParams* params) {
2280797c2cceadd7dfc2e7f9efa30b611d18efcdcddbsalomon@google.com    GrResourceKey resourceKey = GrTexture::ComputeKey(fGpu, params, desc, cacheID);
2299fbcad0f00d7098574cf3394a812c9d845c9cc5brobertphillips@google.com    GrResource* resource = fTextureCache->find(resourceKey);
23095ed55adc6b8f0cee063c2cf2e14782773b0087fbsalomon@google.com    SkSafeRef(resource);
2311f47f4f7325971dd53991e2bb02da94fa7c6d962robertphillips@google.com    return static_cast<GrTexture*>(resource);
232558a75bcb323c03dd7482555c7214062a363276fbsalomon@google.com}
233558a75bcb323c03dd7482555c7214062a363276fbsalomon@google.com
23475b3c9633cb9a594dab0ccf51dab1e694c149a18robertphillips@google.combool GrContext::isTextureInCache(const GrTextureDesc& desc,
2350797c2cceadd7dfc2e7f9efa30b611d18efcdcddbsalomon@google.com                                 const GrCacheID& cacheID,
236b8670998a59d305cd22a3c0cbdc6e075b0a37a6ebsalomon@google.com                                 const GrTextureParams* params) const {
2370797c2cceadd7dfc2e7f9efa30b611d18efcdcddbsalomon@google.com    GrResourceKey resourceKey = GrTexture::ComputeKey(fGpu, params, desc, cacheID);
238fb30951cd9346a7a2d36e7d5f81f9e7ee792b669bsalomon@google.com    return fTextureCache->hasKey(resourceKey);
239fb30951cd9346a7a2d36e7d5f81f9e7ee792b669bsalomon@google.com}
240fb30951cd9346a7a2d36e7d5f81f9e7ee792b669bsalomon@google.com
2419fbcad0f00d7098574cf3394a812c9d845c9cc5brobertphillips@google.comvoid GrContext::addStencilBuffer(GrStencilBuffer* sb) {
242bc4b654af85fa67bdd9cc1b88747b8c394a00e27bsalomon@google.com    ASSERT_OWNED_RESOURCE(sb);
24346a8600405e678718271f62c5994119b8d3241e9robertphillips@google.com
24446a8600405e678718271f62c5994119b8d3241e9robertphillips@google.com    GrResourceKey resourceKey = GrStencilBuffer::ComputeKey(sb->width(),
24546a8600405e678718271f62c5994119b8d3241e9robertphillips@google.com                                                            sb->height(),
24646a8600405e678718271f62c5994119b8d3241e9robertphillips@google.com                                                            sb->numSamples());
247209a1143a1a26935578d45c7f86dc6f9aa2eb1a6robertphillips@google.com    fTextureCache->addResource(resourceKey, sb);
248558a75bcb323c03dd7482555c7214062a363276fbsalomon@google.com}
249558a75bcb323c03dd7482555c7214062a363276fbsalomon@google.com
2509fbcad0f00d7098574cf3394a812c9d845c9cc5brobertphillips@google.comGrStencilBuffer* GrContext::findStencilBuffer(int width, int height,
251558a75bcb323c03dd7482555c7214062a363276fbsalomon@google.com                                              int sampleCnt) {
25246a8600405e678718271f62c5994119b8d3241e9robertphillips@google.com    GrResourceKey resourceKey = GrStencilBuffer::ComputeKey(width,
25346a8600405e678718271f62c5994119b8d3241e9robertphillips@google.com                                                            height,
25446a8600405e678718271f62c5994119b8d3241e9robertphillips@google.com                                                            sampleCnt);
2559fbcad0f00d7098574cf3394a812c9d845c9cc5brobertphillips@google.com    GrResource* resource = fTextureCache->find(resourceKey);
2561f47f4f7325971dd53991e2bb02da94fa7c6d962robertphillips@google.com    return static_cast<GrStencilBuffer*>(resource);
257558a75bcb323c03dd7482555c7214062a363276fbsalomon@google.com}
258558a75bcb323c03dd7482555c7214062a363276fbsalomon@google.com
25927847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.comstatic void stretchImage(void* dst,
26027847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com                         int dstW,
26127847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com                         int dstH,
26227847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com                         void* src,
26327847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com                         int srcW,
26427847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com                         int srcH,
2658b169311b59ab84e8ca6f3630a1e960cc1be751erobertphillips@google.com                         size_t bpp) {
26627847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com    GrFixed dx = (srcW << 16) / dstW;
26727847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com    GrFixed dy = (srcH << 16) / dstH;
26827847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com
26927847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com    GrFixed y = dy >> 1;
27027847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com
2718b169311b59ab84e8ca6f3630a1e960cc1be751erobertphillips@google.com    size_t dstXLimit = dstW*bpp;
27227847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com    for (int j = 0; j < dstH; ++j) {
27327847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com        GrFixed x = dx >> 1;
27427847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com        void* srcRow = (uint8_t*)src + (y>>16)*srcW*bpp;
27527847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com        void* dstRow = (uint8_t*)dst + j*dstW*bpp;
2768b169311b59ab84e8ca6f3630a1e960cc1be751erobertphillips@google.com        for (size_t i = 0; i < dstXLimit; i += bpp) {
27727847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com            memcpy((uint8_t*) dstRow + i,
27827847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com                   (uint8_t*) srcRow + (x>>16)*bpp,
27927847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com                   bpp);
28027847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com            x += dx;
28127847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com        }
28227847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com        y += dy;
28327847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com    }
28427847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com}
28527847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com
286429033038271147ed66b4bc2675ac98a5ccfa75crobertphillips@google.comnamespace {
287429033038271147ed66b4bc2675ac98a5ccfa75crobertphillips@google.com
288429033038271147ed66b4bc2675ac98a5ccfa75crobertphillips@google.com// position + local coordinate
289429033038271147ed66b4bc2675ac98a5ccfa75crobertphillips@google.comextern const GrVertexAttrib gVertexAttribs[] = {
290429033038271147ed66b4bc2675ac98a5ccfa75crobertphillips@google.com    {kVec2f_GrVertexAttribType, 0,               kPosition_GrVertexAttribBinding},
291429033038271147ed66b4bc2675ac98a5ccfa75crobertphillips@google.com    {kVec2f_GrVertexAttribType, sizeof(GrPoint), kLocalCoord_GrVertexAttribBinding}
292429033038271147ed66b4bc2675ac98a5ccfa75crobertphillips@google.com};
293429033038271147ed66b4bc2675ac98a5ccfa75crobertphillips@google.com
294429033038271147ed66b4bc2675ac98a5ccfa75crobertphillips@google.com};
295429033038271147ed66b4bc2675ac98a5ccfa75crobertphillips@google.com
296fbfcd5602128ec010c82cb733c9cdc0a3254f9f3rmistry@google.com// The desired texture is NPOT and tiled but that isn't supported by
2973319f33470abc50a6f3da3a565d917050f9b2f53robertphillips@google.com// the current hardware. Resize the texture to be a POT
2983319f33470abc50a6f3da3a565d917050f9b2f53robertphillips@google.comGrTexture* GrContext::createResizedTexture(const GrTextureDesc& desc,
2990797c2cceadd7dfc2e7f9efa30b611d18efcdcddbsalomon@google.com                                           const GrCacheID& cacheID,
3003319f33470abc50a6f3da3a565d917050f9b2f53robertphillips@google.com                                           void* srcData,
3013319f33470abc50a6f3da3a565d917050f9b2f53robertphillips@google.com                                           size_t rowBytes,
302b86add1ad37776818e1f730359ec587c9fdbff5fhumper@google.com                                           bool filter) {
30395ed55adc6b8f0cee063c2cf2e14782773b0087fbsalomon@google.com    SkAutoTUnref<GrTexture> clampedTexture(this->findAndRefTexture(desc, cacheID, NULL));
3041f47f4f7325971dd53991e2bb02da94fa7c6d962robertphillips@google.com    if (NULL == clampedTexture) {
30595ed55adc6b8f0cee063c2cf2e14782773b0087fbsalomon@google.com        clampedTexture.reset(this->createTexture(NULL, desc, cacheID, srcData, rowBytes));
3069fbcad0f00d7098574cf3394a812c9d845c9cc5brobertphillips@google.com
3071f47f4f7325971dd53991e2bb02da94fa7c6d962robertphillips@google.com        if (NULL == clampedTexture) {
3083319f33470abc50a6f3da3a565d917050f9b2f53robertphillips@google.com            return NULL;
3093319f33470abc50a6f3da3a565d917050f9b2f53robertphillips@google.com        }
3103319f33470abc50a6f3da3a565d917050f9b2f53robertphillips@google.com    }
3110d25eefd7a25afe859cb2d4cf733a3cf07f12139robertphillips@google.com
3123319f33470abc50a6f3da3a565d917050f9b2f53robertphillips@google.com    GrTextureDesc rtDesc = desc;
3133319f33470abc50a6f3da3a565d917050f9b2f53robertphillips@google.com    rtDesc.fFlags =  rtDesc.fFlags |
3143319f33470abc50a6f3da3a565d917050f9b2f53robertphillips@google.com                     kRenderTarget_GrTextureFlagBit |
3153319f33470abc50a6f3da3a565d917050f9b2f53robertphillips@google.com                     kNoStencil_GrTextureFlagBit;
3165898dce287b0d1ec535a9cfc1c5870a9cdcf5d1bcommit-bot@chromium.org    rtDesc.fWidth  = GrNextPow2(desc.fWidth);
3175898dce287b0d1ec535a9cfc1c5870a9cdcf5d1bcommit-bot@chromium.org    rtDesc.fHeight = GrNextPow2(desc.fHeight);
3183319f33470abc50a6f3da3a565d917050f9b2f53robertphillips@google.com
3193319f33470abc50a6f3da3a565d917050f9b2f53robertphillips@google.com    GrTexture* texture = fGpu->createTexture(rtDesc, NULL, 0);
3203319f33470abc50a6f3da3a565d917050f9b2f53robertphillips@google.com
3213319f33470abc50a6f3da3a565d917050f9b2f53robertphillips@google.com    if (NULL != texture) {
3223319f33470abc50a6f3da3a565d917050f9b2f53robertphillips@google.com        GrDrawTarget::AutoStateRestore asr(fGpu, GrDrawTarget::kReset_ASRInit);
3233319f33470abc50a6f3da3a565d917050f9b2f53robertphillips@google.com        GrDrawState* drawState = fGpu->drawState();
3243319f33470abc50a6f3da3a565d917050f9b2f53robertphillips@google.com        drawState->setRenderTarget(texture->asRenderTarget());
3253319f33470abc50a6f3da3a565d917050f9b2f53robertphillips@google.com
3263319f33470abc50a6f3da3a565d917050f9b2f53robertphillips@google.com        // if filtering is not desired then we want to ensure all
3273319f33470abc50a6f3da3a565d917050f9b2f53robertphillips@google.com        // texels in the resampled image are copies of texels from
3283319f33470abc50a6f3da3a565d917050f9b2f53robertphillips@google.com        // the original.
329b86add1ad37776818e1f730359ec587c9fdbff5fhumper@google.com        GrTextureParams params(SkShader::kClamp_TileMode, filter ? GrTextureParams::kBilerp_FilterMode :
330b86add1ad37776818e1f730359ec587c9fdbff5fhumper@google.com                                                                   GrTextureParams::kNone_FilterMode);
331eb6879f50a5564eeb981ec5616b55bf685eb76fcbsalomon@google.com        drawState->addColorTextureEffect(clampedTexture, SkMatrix::I(), params);
3323319f33470abc50a6f3da3a565d917050f9b2f53robertphillips@google.com
333429033038271147ed66b4bc2675ac98a5ccfa75crobertphillips@google.com        drawState->setVertexAttribs<gVertexAttribs>(SK_ARRAY_COUNT(gVertexAttribs));
334054ae99d93711c26e40682a0e3a03a47ea605c53jvanverth@google.com
335b75b0a0b8492e14c7728e0a0881f87dc64ce60f9jvanverth@google.com        GrDrawTarget::AutoReleaseGeometry arg(fGpu, 4, 0);
3363319f33470abc50a6f3da3a565d917050f9b2f53robertphillips@google.com
3373319f33470abc50a6f3da3a565d917050f9b2f53robertphillips@google.com        if (arg.succeeded()) {
3383319f33470abc50a6f3da3a565d917050f9b2f53robertphillips@google.com            GrPoint* verts = (GrPoint*) arg.vertices();
33995ed55adc6b8f0cee063c2cf2e14782773b0087fbsalomon@google.com            verts[0].setIRectFan(0, 0, texture->width(), texture->height(), 2 * sizeof(GrPoint));
34095ed55adc6b8f0cee063c2cf2e14782773b0087fbsalomon@google.com            verts[1].setIRectFan(0, 0, 1, 1, 2 * sizeof(GrPoint));
34195ed55adc6b8f0cee063c2cf2e14782773b0087fbsalomon@google.com            fGpu->drawNonIndexed(kTriangleFan_GrPrimitiveType, 0, 4);
3423319f33470abc50a6f3da3a565d917050f9b2f53robertphillips@google.com        }
3433319f33470abc50a6f3da3a565d917050f9b2f53robertphillips@google.com    } else {
3443319f33470abc50a6f3da3a565d917050f9b2f53robertphillips@google.com        // TODO: Our CPU stretch doesn't filter. But we create separate
34508283afc265f1153834256fc1012519813ba6b73bsalomon@google.com        // stretched textures when the texture params is either filtered or
3463319f33470abc50a6f3da3a565d917050f9b2f53robertphillips@google.com        // not. Either implement filtered stretch blit on CPU or just create
3473319f33470abc50a6f3da3a565d917050f9b2f53robertphillips@google.com        // one when FBO case fails.
3483319f33470abc50a6f3da3a565d917050f9b2f53robertphillips@google.com
3493319f33470abc50a6f3da3a565d917050f9b2f53robertphillips@google.com        rtDesc.fFlags = kNone_GrTextureFlags;
3503319f33470abc50a6f3da3a565d917050f9b2f53robertphillips@google.com        // no longer need to clamp at min RT size.
3513319f33470abc50a6f3da3a565d917050f9b2f53robertphillips@google.com        rtDesc.fWidth  = GrNextPow2(desc.fWidth);
3523319f33470abc50a6f3da3a565d917050f9b2f53robertphillips@google.com        rtDesc.fHeight = GrNextPow2(desc.fHeight);
3538b169311b59ab84e8ca6f3630a1e960cc1be751erobertphillips@google.com        size_t bpp = GrBytesPerPixel(desc.fConfig);
35408283afc265f1153834256fc1012519813ba6b73bsalomon@google.com        SkAutoSMalloc<128*128*4> stretchedPixels(bpp * rtDesc.fWidth * rtDesc.fHeight);
3553319f33470abc50a6f3da3a565d917050f9b2f53robertphillips@google.com        stretchImage(stretchedPixels.get(), rtDesc.fWidth, rtDesc.fHeight,
35608283afc265f1153834256fc1012519813ba6b73bsalomon@google.com                     srcData, desc.fWidth, desc.fHeight, bpp);
3573319f33470abc50a6f3da3a565d917050f9b2f53robertphillips@google.com
3583319f33470abc50a6f3da3a565d917050f9b2f53robertphillips@google.com        size_t stretchedRowBytes = rtDesc.fWidth * bpp;
3593319f33470abc50a6f3da3a565d917050f9b2f53robertphillips@google.com
36065eb4d5a210884cc92c43a8582cbd1ccbddcab57jvanverth@google.com        SkDEBUGCODE(GrTexture* texture = )fGpu->createTexture(rtDesc, stretchedPixels.get(),
36165eb4d5a210884cc92c43a8582cbd1ccbddcab57jvanverth@google.com                                                              stretchedRowBytes);
362f6de475e5cbd143f348ff7738919e397b7fe7f57tfarina@chromium.org        SkASSERT(NULL != texture);
3633319f33470abc50a6f3da3a565d917050f9b2f53robertphillips@google.com    }
3643319f33470abc50a6f3da3a565d917050f9b2f53robertphillips@google.com
3653319f33470abc50a6f3da3a565d917050f9b2f53robertphillips@google.com    return texture;
3663319f33470abc50a6f3da3a565d917050f9b2f53robertphillips@google.com}
3673319f33470abc50a6f3da3a565d917050f9b2f53robertphillips@google.com
36895ed55adc6b8f0cee063c2cf2e14782773b0087fbsalomon@google.comGrTexture* GrContext::createTexture(const GrTextureParams* params,
36995ed55adc6b8f0cee063c2cf2e14782773b0087fbsalomon@google.com                                    const GrTextureDesc& desc,
37095ed55adc6b8f0cee063c2cf2e14782773b0087fbsalomon@google.com                                    const GrCacheID& cacheID,
37195ed55adc6b8f0cee063c2cf2e14782773b0087fbsalomon@google.com                                    void* srcData,
37250a3043194cf278a74ff51c33c6cdb52cbe1f8f9commit-bot@chromium.org                                    size_t rowBytes,
37350a3043194cf278a74ff51c33c6cdb52cbe1f8f9commit-bot@chromium.org                                    GrResourceKey* cacheKey) {
3740797c2cceadd7dfc2e7f9efa30b611d18efcdcddbsalomon@google.com    SK_TRACE_EVENT0("GrContext::createTexture");
37527847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com
3760797c2cceadd7dfc2e7f9efa30b611d18efcdcddbsalomon@google.com    GrResourceKey resourceKey = GrTexture::ComputeKey(fGpu, params, desc, cacheID);
377a1e5795279bd085496fa04c59e588f440bf30457robertphillips@google.com
37895ed55adc6b8f0cee063c2cf2e14782773b0087fbsalomon@google.com    GrTexture* texture;
379a1e5795279bd085496fa04c59e588f440bf30457robertphillips@google.com    if (GrTexture::NeedsResizing(resourceKey)) {
38095ed55adc6b8f0cee063c2cf2e14782773b0087fbsalomon@google.com        texture = this->createResizedTexture(desc, cacheID,
38195ed55adc6b8f0cee063c2cf2e14782773b0087fbsalomon@google.com                                             srcData, rowBytes,
382b86add1ad37776818e1f730359ec587c9fdbff5fhumper@google.com                                             GrTexture::NeedsBilerp(resourceKey));
38327847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com    } else {
38495ed55adc6b8f0cee063c2cf2e14782773b0087fbsalomon@google.com        texture= fGpu->createTexture(desc, srcData, rowBytes);
3853319f33470abc50a6f3da3a565d917050f9b2f53robertphillips@google.com    }
3863319f33470abc50a6f3da3a565d917050f9b2f53robertphillips@google.com
3873319f33470abc50a6f3da3a565d917050f9b2f53robertphillips@google.com    if (NULL != texture) {
3881622a6d950a4a1deb13048210bdb78d952375f05robertphillips@google.com        // Adding a resource could put us overbudget. Try to free up the
3891622a6d950a4a1deb13048210bdb78d952375f05robertphillips@google.com        // necessary space before adding it.
3901622a6d950a4a1deb13048210bdb78d952375f05robertphillips@google.com        fTextureCache->purgeAsNeeded(1, texture->sizeInBytes());
391209a1143a1a26935578d45c7f86dc6f9aa2eb1a6robertphillips@google.com        fTextureCache->addResource(resourceKey, texture);
39250a3043194cf278a74ff51c33c6cdb52cbe1f8f9commit-bot@chromium.org
39350a3043194cf278a74ff51c33c6cdb52cbe1f8f9commit-bot@chromium.org        if (NULL != cacheKey) {
39450a3043194cf278a74ff51c33c6cdb52cbe1f8f9commit-bot@chromium.org            *cacheKey = resourceKey;
39550a3043194cf278a74ff51c33c6cdb52cbe1f8f9commit-bot@chromium.org        }
39627847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com    }
3973319f33470abc50a6f3da3a565d917050f9b2f53robertphillips@google.com
3981f47f4f7325971dd53991e2bb02da94fa7c6d962robertphillips@google.com    return texture;
39927847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com}
40027847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com
4011f3c73825b8a1752abc6b74fbce978a430de6473skia.committer@gmail.comstatic GrTexture* create_scratch_texture(GrGpu* gpu,
4021f3c73825b8a1752abc6b74fbce978a430de6473skia.committer@gmail.com                                         GrResourceCache* textureCache,
403e4eaea2d126d58d8ce4034a1ce921404e83fe3f4robertphillips@google.com                                         const GrTextureDesc& desc) {
404e4eaea2d126d58d8ce4034a1ce921404e83fe3f4robertphillips@google.com    GrTexture* texture = gpu->createTexture(desc, NULL, 0);
405e4eaea2d126d58d8ce4034a1ce921404e83fe3f4robertphillips@google.com    if (NULL != texture) {
406e4eaea2d126d58d8ce4034a1ce921404e83fe3f4robertphillips@google.com        GrResourceKey key = GrTexture::ComputeScratchKey(texture->desc());
407e4eaea2d126d58d8ce4034a1ce921404e83fe3f4robertphillips@google.com        // Adding a resource could put us overbudget. Try to free up the
408e4eaea2d126d58d8ce4034a1ce921404e83fe3f4robertphillips@google.com        // necessary space before adding it.
409e4eaea2d126d58d8ce4034a1ce921404e83fe3f4robertphillips@google.com        textureCache->purgeAsNeeded(1, texture->sizeInBytes());
410e4eaea2d126d58d8ce4034a1ce921404e83fe3f4robertphillips@google.com        // Make the resource exclusive so future 'find' calls don't return it
411e4eaea2d126d58d8ce4034a1ce921404e83fe3f4robertphillips@google.com        textureCache->addResource(key, texture, GrResourceCache::kHide_OwnershipFlag);
412e4eaea2d126d58d8ce4034a1ce921404e83fe3f4robertphillips@google.com    }
413e4eaea2d126d58d8ce4034a1ce921404e83fe3f4robertphillips@google.com    return texture;
414e4eaea2d126d58d8ce4034a1ce921404e83fe3f4robertphillips@google.com}
415e4eaea2d126d58d8ce4034a1ce921404e83fe3f4robertphillips@google.com
41695ed55adc6b8f0cee063c2cf2e14782773b0087fbsalomon@google.comGrTexture* GrContext::lockAndRefScratchTexture(const GrTextureDesc& inDesc, ScratchTexMatch match) {
41775b3c9633cb9a594dab0ccf51dab1e694c149a18robertphillips@google.com
418f6de475e5cbd143f348ff7738919e397b7fe7f57tfarina@chromium.org    SkASSERT((inDesc.fFlags & kRenderTarget_GrTextureFlagBit) ||
419e4eaea2d126d58d8ce4034a1ce921404e83fe3f4robertphillips@google.com             !(inDesc.fFlags & kNoStencil_GrTextureFlagBit));
420e4eaea2d126d58d8ce4034a1ce921404e83fe3f4robertphillips@google.com
421e4eaea2d126d58d8ce4034a1ce921404e83fe3f4robertphillips@google.com    // Renderable A8 targets are not universally supported (e.g., not on ANGLE)
4228aaac8da36bb88ab13c62e84ee6ac9ebc5cb8466bsalomon@google.com    SkASSERT(this->isConfigRenderable(kAlpha_8_GrPixelConfig, inDesc.fSampleCnt > 0) ||
423e4eaea2d126d58d8ce4034a1ce921404e83fe3f4robertphillips@google.com             !(inDesc.fFlags & kRenderTarget_GrTextureFlagBit) ||
424e4eaea2d126d58d8ce4034a1ce921404e83fe3f4robertphillips@google.com             (inDesc.fConfig != kAlpha_8_GrPixelConfig));
425e4eaea2d126d58d8ce4034a1ce921404e83fe3f4robertphillips@google.com
4262d2e5c4e2425a1cb64d31d7d10832f4a3a9137a4robertphillips@google.com    if (!fGpu->caps()->reuseScratchTextures() &&
4272d2e5c4e2425a1cb64d31d7d10832f4a3a9137a4robertphillips@google.com        !(inDesc.fFlags & kRenderTarget_GrTextureFlagBit)) {
4282d2e5c4e2425a1cb64d31d7d10832f4a3a9137a4robertphillips@google.com        // If we're never recycling this texture we can always make it the right size
429e4eaea2d126d58d8ce4034a1ce921404e83fe3f4robertphillips@google.com        return create_scratch_texture(fGpu, fTextureCache, inDesc);
430e4eaea2d126d58d8ce4034a1ce921404e83fe3f4robertphillips@google.com    }
431e4eaea2d126d58d8ce4034a1ce921404e83fe3f4robertphillips@google.com
432e4eaea2d126d58d8ce4034a1ce921404e83fe3f4robertphillips@google.com    GrTextureDesc desc = inDesc;
4332afb8ec738fc50ea6e4500545c3cacbf346ed187rileya@google.com
4340797c2cceadd7dfc2e7f9efa30b611d18efcdcddbsalomon@google.com    if (kApprox_ScratchTexMatch == match) {
43550398bf7f1953e640e5529616e710cf540799731bsalomon@google.com        // bin by pow2 with a reasonable min
43640db6dc98d13e4632cdeaab1577a5e09fd2ad18fbsalomon@google.com        static const int MIN_SIZE = 16;
43750398bf7f1953e640e5529616e710cf540799731bsalomon@google.com        desc.fWidth  = GrMax(MIN_SIZE, GrNextPow2(desc.fWidth));
43850398bf7f1953e640e5529616e710cf540799731bsalomon@google.com        desc.fHeight = GrMax(MIN_SIZE, GrNextPow2(desc.fHeight));
43950398bf7f1953e640e5529616e710cf540799731bsalomon@google.com    }
440b5b3168a645802f66233234a06dd5a3764f18018bsalomon@google.com
4411f47f4f7325971dd53991e2bb02da94fa7c6d962robertphillips@google.com    GrResource* resource = NULL;
442b5b3168a645802f66233234a06dd5a3764f18018bsalomon@google.com    int origWidth = desc.fWidth;
443b5b3168a645802f66233234a06dd5a3764f18018bsalomon@google.com    int origHeight = desc.fHeight;
444b5b3168a645802f66233234a06dd5a3764f18018bsalomon@google.com
445b5b3168a645802f66233234a06dd5a3764f18018bsalomon@google.com    do {
4460797c2cceadd7dfc2e7f9efa30b611d18efcdcddbsalomon@google.com        GrResourceKey key = GrTexture::ComputeScratchKey(desc);
447209a1143a1a26935578d45c7f86dc6f9aa2eb1a6robertphillips@google.com        // Ensure we have exclusive access to the texture so future 'find' calls don't return it
448209a1143a1a26935578d45c7f86dc6f9aa2eb1a6robertphillips@google.com        resource = fTextureCache->find(key, GrResourceCache::kHide_OwnershipFlag);
44995ed55adc6b8f0cee063c2cf2e14782773b0087fbsalomon@google.com        if (NULL != resource) {
45095ed55adc6b8f0cee063c2cf2e14782773b0087fbsalomon@google.com            resource->ref();
45195ed55adc6b8f0cee063c2cf2e14782773b0087fbsalomon@google.com            break;
45295ed55adc6b8f0cee063c2cf2e14782773b0087fbsalomon@google.com        }
45395ed55adc6b8f0cee063c2cf2e14782773b0087fbsalomon@google.com        if (kExact_ScratchTexMatch == match) {
454b5b3168a645802f66233234a06dd5a3764f18018bsalomon@google.com            break;
455b5b3168a645802f66233234a06dd5a3764f18018bsalomon@google.com        }
45640db6dc98d13e4632cdeaab1577a5e09fd2ad18fbsalomon@google.com        // We had a cache miss and we are in approx mode, relax the fit of the flags.
45795ed55adc6b8f0cee063c2cf2e14782773b0087fbsalomon@google.com
458fbfcd5602128ec010c82cb733c9cdc0a3254f9f3rmistry@google.com        // We no longer try to reuse textures that were previously used as render targets in
4592afb8ec738fc50ea6e4500545c3cacbf346ed187rileya@google.com        // situations where no RT is needed; doing otherwise can confuse the video driver and
4602afb8ec738fc50ea6e4500545c3cacbf346ed187rileya@google.com        // cause significant performance problems in some cases.
4612afb8ec738fc50ea6e4500545c3cacbf346ed187rileya@google.com        if (desc.fFlags & kNoStencil_GrTextureFlagBit) {
462b5b3168a645802f66233234a06dd5a3764f18018bsalomon@google.com            desc.fFlags = desc.fFlags & ~kNoStencil_GrTextureFlagBit;
463b5b3168a645802f66233234a06dd5a3764f18018bsalomon@google.com        } else {
464b5b3168a645802f66233234a06dd5a3764f18018bsalomon@google.com            break;
465b5b3168a645802f66233234a06dd5a3764f18018bsalomon@google.com        }
466fbfcd5602128ec010c82cb733c9cdc0a3254f9f3rmistry@google.com
467b5b3168a645802f66233234a06dd5a3764f18018bsalomon@google.com    } while (true);
468b5b3168a645802f66233234a06dd5a3764f18018bsalomon@google.com
4691f47f4f7325971dd53991e2bb02da94fa7c6d962robertphillips@google.com    if (NULL == resource) {
470b5b3168a645802f66233234a06dd5a3764f18018bsalomon@google.com        desc.fFlags = inDesc.fFlags;
471b5b3168a645802f66233234a06dd5a3764f18018bsalomon@google.com        desc.fWidth = origWidth;
472b5b3168a645802f66233234a06dd5a3764f18018bsalomon@google.com        desc.fHeight = origHeight;
473e4eaea2d126d58d8ce4034a1ce921404e83fe3f4robertphillips@google.com        resource = create_scratch_texture(fGpu, fTextureCache, desc);
474b5b3168a645802f66233234a06dd5a3764f18018bsalomon@google.com    }
475b5b3168a645802f66233234a06dd5a3764f18018bsalomon@google.com
4761f47f4f7325971dd53991e2bb02da94fa7c6d962robertphillips@google.com    return static_cast<GrTexture*>(resource);
477b5b3168a645802f66233234a06dd5a3764f18018bsalomon@google.com}
478b5b3168a645802f66233234a06dd5a3764f18018bsalomon@google.com
47915c0fea699b25343fe6f49668a5632866e1a0306robertphillips@google.comvoid GrContext::addExistingTextureToCache(GrTexture* texture) {
48015c0fea699b25343fe6f49668a5632866e1a0306robertphillips@google.com
48115c0fea699b25343fe6f49668a5632866e1a0306robertphillips@google.com    if (NULL == texture) {
48215c0fea699b25343fe6f49668a5632866e1a0306robertphillips@google.com        return;
48315c0fea699b25343fe6f49668a5632866e1a0306robertphillips@google.com    }
48415c0fea699b25343fe6f49668a5632866e1a0306robertphillips@google.com
485521eaf8cc73cebebeaf54338c51c22922ac70951robertphillips@google.com    // This texture should already have a cache entry since it was once
486521eaf8cc73cebebeaf54338c51c22922ac70951robertphillips@google.com    // attached
487f6de475e5cbd143f348ff7738919e397b7fe7f57tfarina@chromium.org    SkASSERT(NULL != texture->getCacheEntry());
488521eaf8cc73cebebeaf54338c51c22922ac70951robertphillips@google.com
489521eaf8cc73cebebeaf54338c51c22922ac70951robertphillips@google.com    // Conceptually, the cache entry is going to assume responsibility
4909ef0426e7c126f6ad6ba833d4543b92a197c95afrobertphillips@google.com    // for the creation ref. Assert refcnt == 1.
491f6de475e5cbd143f348ff7738919e397b7fe7f57tfarina@chromium.org    SkASSERT(texture->unique());
492521eaf8cc73cebebeaf54338c51c22922ac70951robertphillips@google.com
4932d2e5c4e2425a1cb64d31d7d10832f4a3a9137a4robertphillips@google.com    if (fGpu->caps()->reuseScratchTextures() || NULL != texture->asRenderTarget()) {
4949ef0426e7c126f6ad6ba833d4543b92a197c95afrobertphillips@google.com        // Since this texture came from an AutoScratchTexture it should
4959ef0426e7c126f6ad6ba833d4543b92a197c95afrobertphillips@google.com        // still be in the exclusive pile. Recycle it.
4969ef0426e7c126f6ad6ba833d4543b92a197c95afrobertphillips@google.com        fTextureCache->makeNonExclusive(texture->getCacheEntry());
497e4eaea2d126d58d8ce4034a1ce921404e83fe3f4robertphillips@google.com        this->purgeCache();
4989ef0426e7c126f6ad6ba833d4543b92a197c95afrobertphillips@google.com    } else if (texture->getDeferredRefCount() <= 0) {
499e4eaea2d126d58d8ce4034a1ce921404e83fe3f4robertphillips@google.com        // When we aren't reusing textures we know this scratch texture
500e4eaea2d126d58d8ce4034a1ce921404e83fe3f4robertphillips@google.com        // will never be reused and would be just wasting time in the cache
5019ef0426e7c126f6ad6ba833d4543b92a197c95afrobertphillips@google.com        fTextureCache->makeNonExclusive(texture->getCacheEntry());
502e4eaea2d126d58d8ce4034a1ce921404e83fe3f4robertphillips@google.com        fTextureCache->deleteResource(texture->getCacheEntry());
5039ef0426e7c126f6ad6ba833d4543b92a197c95afrobertphillips@google.com    } else {
5049ef0426e7c126f6ad6ba833d4543b92a197c95afrobertphillips@google.com        // In this case (fDeferredRefCount > 0) but the cache is the only
5059ef0426e7c126f6ad6ba833d4543b92a197c95afrobertphillips@google.com        // one holding a real ref. Mark the object so when the deferred
5069ef0426e7c126f6ad6ba833d4543b92a197c95afrobertphillips@google.com        // ref count goes to 0 the texture will be deleted (remember
5079ef0426e7c126f6ad6ba833d4543b92a197c95afrobertphillips@google.com        // in this code path scratch textures aren't getting reused).
5089ef0426e7c126f6ad6ba833d4543b92a197c95afrobertphillips@google.com        texture->setNeedsDeferredUnref();
509e4eaea2d126d58d8ce4034a1ce921404e83fe3f4robertphillips@google.com    }
51015c0fea699b25343fe6f49668a5632866e1a0306robertphillips@google.com}
51115c0fea699b25343fe6f49668a5632866e1a0306robertphillips@google.com
512a9b0623eac4a473517c15418dbdc1e331ee752d2robertphillips@google.com
5139fbcad0f00d7098574cf3394a812c9d845c9cc5brobertphillips@google.comvoid GrContext::unlockScratchTexture(GrTexture* texture) {
5141f47f4f7325971dd53991e2bb02da94fa7c6d962robertphillips@google.com    ASSERT_OWNED_RESOURCE(texture);
515f6de475e5cbd143f348ff7738919e397b7fe7f57tfarina@chromium.org    SkASSERT(NULL != texture->getCacheEntry());
5161f47f4f7325971dd53991e2bb02da94fa7c6d962robertphillips@google.com
51750398bf7f1953e640e5529616e710cf540799731bsalomon@google.com    // If this is a scratch texture we detached it from the cache
51850398bf7f1953e640e5529616e710cf540799731bsalomon@google.com    // while it was locked (to avoid two callers simultaneously getting
51950398bf7f1953e640e5529616e710cf540799731bsalomon@google.com    // the same texture).
5200797c2cceadd7dfc2e7f9efa30b611d18efcdcddbsalomon@google.com    if (texture->getCacheEntry()->key().isScratch()) {
5212d2e5c4e2425a1cb64d31d7d10832f4a3a9137a4robertphillips@google.com        if (fGpu->caps()->reuseScratchTextures() || NULL != texture->asRenderTarget()) {
5229ef0426e7c126f6ad6ba833d4543b92a197c95afrobertphillips@google.com            fTextureCache->makeNonExclusive(texture->getCacheEntry());
5239ef0426e7c126f6ad6ba833d4543b92a197c95afrobertphillips@google.com            this->purgeCache();
5249ef0426e7c126f6ad6ba833d4543b92a197c95afrobertphillips@google.com        } else if (texture->unique() && texture->getDeferredRefCount() <= 0) {
525b77f0f4ae560e97cc4cd2758752d955549017c3cskia.committer@gmail.com            // Only the cache now knows about this texture. Since we're never
526b77f0f4ae560e97cc4cd2758752d955549017c3cskia.committer@gmail.com            // reusing scratch textures (in this code path) it would just be
5279ef0426e7c126f6ad6ba833d4543b92a197c95afrobertphillips@google.com            // wasting time sitting in the cache.
5289ef0426e7c126f6ad6ba833d4543b92a197c95afrobertphillips@google.com            fTextureCache->makeNonExclusive(texture->getCacheEntry());
5299ef0426e7c126f6ad6ba833d4543b92a197c95afrobertphillips@google.com            fTextureCache->deleteResource(texture->getCacheEntry());
5309ef0426e7c126f6ad6ba833d4543b92a197c95afrobertphillips@google.com        } else {
5319ef0426e7c126f6ad6ba833d4543b92a197c95afrobertphillips@google.com            // In this case (fRefCnt > 1 || defRefCnt > 0) but we don't really
532b77f0f4ae560e97cc4cd2758752d955549017c3cskia.committer@gmail.com            // want to readd it to the cache (since it will never be reused).
5339ef0426e7c126f6ad6ba833d4543b92a197c95afrobertphillips@google.com            // Instead, give up the cache's ref and leave the decision up to
5349ef0426e7c126f6ad6ba833d4543b92a197c95afrobertphillips@google.com            // addExistingTextureToCache once its ref count reaches 0. For
5359ef0426e7c126f6ad6ba833d4543b92a197c95afrobertphillips@google.com            // this to work we need to leave it in the exclusive list.
5369ef0426e7c126f6ad6ba833d4543b92a197c95afrobertphillips@google.com            texture->setFlag((GrTextureFlags) GrTexture::kReturnToCache_FlagBit);
5379ef0426e7c126f6ad6ba833d4543b92a197c95afrobertphillips@google.com            // Give up the cache's ref to the texture
5389ef0426e7c126f6ad6ba833d4543b92a197c95afrobertphillips@google.com            texture->unref();
5399ef0426e7c126f6ad6ba833d4543b92a197c95afrobertphillips@google.com        }
540fea37b5e532dfe776269253afb9951e763c3b205bsalomon@google.com    }
54150a035ddbb068446645b0978f4c092dec87a1a02robertphillips@google.com}
54250a035ddbb068446645b0978f4c092dec87a1a02robertphillips@google.com
54350a035ddbb068446645b0978f4c092dec87a1a02robertphillips@google.comvoid GrContext::purgeCache() {
544eb9b3e164e55b8d15e1c25bfb1332917453cbc3arobertphillips@google.com    if (NULL != fTextureCache) {
545eb9b3e164e55b8d15e1c25bfb1332917453cbc3arobertphillips@google.com        fTextureCache->purgeAsNeeded();
546eb9b3e164e55b8d15e1c25bfb1332917453cbc3arobertphillips@google.com    }
54715c0fea699b25343fe6f49668a5632866e1a0306robertphillips@google.com}
54815c0fea699b25343fe6f49668a5632866e1a0306robertphillips@google.com
549cae27fed5e45e8899e56ece22b27e8958ffc0162commit-bot@chromium.orgbool GrContext::OverbudgetCB(void* data) {
550f6de475e5cbd143f348ff7738919e397b7fe7f57tfarina@chromium.org    SkASSERT(NULL != data);
551cae27fed5e45e8899e56ece22b27e8958ffc0162commit-bot@chromium.org
552cae27fed5e45e8899e56ece22b27e8958ffc0162commit-bot@chromium.org    GrContext* context = reinterpret_cast<GrContext*>(data);
553cae27fed5e45e8899e56ece22b27e8958ffc0162commit-bot@chromium.org
554cae27fed5e45e8899e56ece22b27e8958ffc0162commit-bot@chromium.org    // Flush the InOrderDrawBuffer to possibly free up some textures
5555dbb149fda134941e5d168790127caf294d322e2commit-bot@chromium.org    context->fFlushToReduceCacheSize = true;
556cae27fed5e45e8899e56ece22b27e8958ffc0162commit-bot@chromium.org
557cae27fed5e45e8899e56ece22b27e8958ffc0162commit-bot@chromium.org    return true;
558cae27fed5e45e8899e56ece22b27e8958ffc0162commit-bot@chromium.org}
559cae27fed5e45e8899e56ece22b27e8958ffc0162commit-bot@chromium.org
560cae27fed5e45e8899e56ece22b27e8958ffc0162commit-bot@chromium.org
56175b3c9633cb9a594dab0ccf51dab1e694c149a18robertphillips@google.comGrTexture* GrContext::createUncachedTexture(const GrTextureDesc& descIn,
56227847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com                                            void* srcData,
56327847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com                                            size_t rowBytes) {
56475b3c9633cb9a594dab0ccf51dab1e694c149a18robertphillips@google.com    GrTextureDesc descCopy = descIn;
56575b3c9633cb9a594dab0ccf51dab1e694c149a18robertphillips@google.com    return fGpu->createTexture(descCopy, srcData, rowBytes);
56627847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com}
56727847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com
56807fc0d178e20f74a88dd78384f817b53204e625fbsalomon@google.comvoid GrContext::getTextureCacheLimits(int* maxTextures,
56907fc0d178e20f74a88dd78384f817b53204e625fbsalomon@google.com                                      size_t* maxTextureBytes) const {
57007fc0d178e20f74a88dd78384f817b53204e625fbsalomon@google.com    fTextureCache->getLimits(maxTextures, maxTextureBytes);
57127847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com}
57227847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com
57307fc0d178e20f74a88dd78384f817b53204e625fbsalomon@google.comvoid GrContext::setTextureCacheLimits(int maxTextures, size_t maxTextureBytes) {
57407fc0d178e20f74a88dd78384f817b53204e625fbsalomon@google.com    fTextureCache->setLimits(maxTextures, maxTextureBytes);
57527847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com}
57627847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com
577919583674bd5daeb60327c0bc1ce8aaa80d54e13bsalomon@google.comint GrContext::getMaxTextureSize() const {
57844a91dcf2542c2aa93f159ebbb5bf813ae7362c0robertphillips@google.com    return GrMin(fGpu->caps()->maxTextureSize(), fMaxTextureSizeOverride);
579919583674bd5daeb60327c0bc1ce8aaa80d54e13bsalomon@google.com}
580919583674bd5daeb60327c0bc1ce8aaa80d54e13bsalomon@google.com
581919583674bd5daeb60327c0bc1ce8aaa80d54e13bsalomon@google.comint GrContext::getMaxRenderTargetSize() const {
582bcce8926524827775539874346dd424a9510dbc9bsalomon@google.com    return fGpu->caps()->maxRenderTargetSize();
58327847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com}
58427847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com
5858a70eef71cf369803e97ffea786f43f944de758ebsalomon@google.comint GrContext::getMaxSampleCount() const {
586bcce8926524827775539874346dd424a9510dbc9bsalomon@google.com    return fGpu->caps()->maxSampleCount();
5878a70eef71cf369803e97ffea786f43f944de758ebsalomon@google.com}
5888a70eef71cf369803e97ffea786f43f944de758ebsalomon@google.com
58927847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com///////////////////////////////////////////////////////////////////////////////
59027847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com
59116e3ddea6a80972aced04b21b1d66377fa95e7c7bsalomon@google.comGrTexture* GrContext::wrapBackendTexture(const GrBackendTextureDesc& desc) {
59216e3ddea6a80972aced04b21b1d66377fa95e7c7bsalomon@google.com    return fGpu->wrapBackendTexture(desc);
593e269f210bdae0288643afaf8a579b22d3f6d5bebbsalomon@google.com}
594e269f210bdae0288643afaf8a579b22d3f6d5bebbsalomon@google.com
59516e3ddea6a80972aced04b21b1d66377fa95e7c7bsalomon@google.comGrRenderTarget* GrContext::wrapBackendRenderTarget(const GrBackendRenderTargetDesc& desc) {
59616e3ddea6a80972aced04b21b1d66377fa95e7c7bsalomon@google.com    return fGpu->wrapBackendRenderTarget(desc);
597e269f210bdae0288643afaf8a579b22d3f6d5bebbsalomon@google.com}
598e269f210bdae0288643afaf8a579b22d3f6d5bebbsalomon@google.com
5995877ffd5ea71a3ea70096d5c11c843798defa690bsalomon@google.com///////////////////////////////////////////////////////////////////////////////
6005877ffd5ea71a3ea70096d5c11c843798defa690bsalomon@google.com
601b8670998a59d305cd22a3c0cbdc6e075b0a37a6ebsalomon@google.combool GrContext::supportsIndex8PixelConfig(const GrTextureParams* params,
6021f221a70214fa1ab87b8a32dd66facf485f318eebsalomon@google.com                                          int width, int height) const {
603c26d94fd7dc0b00cd6d0e42d28285f4a38aff021bsalomon@google.com    const GrDrawTargetCaps* caps = fGpu->caps();
604bcce8926524827775539874346dd424a9510dbc9bsalomon@google.com    if (!caps->eightBitPaletteSupport()) {
60527847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com        return false;
60627847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com    }
60727847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com
60827847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com    bool isPow2 = GrIsPow2(width) && GrIsPow2(height);
60927847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com
61027847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com    if (!isPow2) {
611b8670998a59d305cd22a3c0cbdc6e075b0a37a6ebsalomon@google.com        bool tiled = NULL != params && params->isTiled();
612bcce8926524827775539874346dd424a9510dbc9bsalomon@google.com        if (tiled && !caps->npotTextureTileSupport()) {
61327847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com            return false;
61427847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com        }
61527847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com    }
61627847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com    return true;
61727847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com}
61827847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com
61927847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com
62027847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com////////////////////////////////////////////////////////////////////////////////
62127847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com
622fd03d4a829efe2d77a712fd991927c55f59a2ffecommit-bot@chromium.orgvoid GrContext::clear(const SkIRect* rect,
62307ea2db0260d8e6cd2bf605571b68b1c574b5a77bsalomon@google.com                      const GrColor color,
62456ce48ade325f6f49acb0da31d6252806e4ed7efrobertphillips@google.com                      bool canIgnoreRect,
625c82a8b7aa4ec19fba508c394920a9e88d3e5bd12robertphillips@google.com                      GrRenderTarget* target) {
626eb6879f50a5564eeb981ec5616b55bf685eb76fcbsalomon@google.com    AutoRestoreEffects are;
6275dbb149fda134941e5d168790127caf294d322e2commit-bot@chromium.org    AutoCheckFlush acf(this);
62818bb41e9563748fbde07c1540da9314cbb7d1dc8skia.committer@gmail.com    this->prepareToDraw(NULL, BUFFERED_DRAW, &are, &acf)->clear(rect, color,
62956ce48ade325f6f49acb0da31d6252806e4ed7efrobertphillips@google.com                                                                canIgnoreRect, target);
63027847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com}
63127847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com
6325dc26b97366934ba0f896cea02a3fec027d5d5c1bsalomon@google.comvoid GrContext::drawPaint(const GrPaint& origPaint) {
63327847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com    // set rect to be big enough to fill the space, but not super-huge, so we
63427847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com    // don't overflow fixed-point implementations
635fd03d4a829efe2d77a712fd991927c55f59a2ffecommit-bot@chromium.org    SkRect r;
636d302f1401b3c9aea094804bad4e76de98782cfe8bsalomon@google.com    r.setLTRB(0, 0,
63781712883419f76e25d2ffec38a9438284a45a48dbsalomon@google.com              SkIntToScalar(getRenderTarget()->width()),
63881712883419f76e25d2ffec38a9438284a45a48dbsalomon@google.com              SkIntToScalar(getRenderTarget()->height()));
639b9086a026844e4cfd08b219e49ce3f12294cba98bsalomon@google.com    SkMatrix inverse;
6405dc26b97366934ba0f896cea02a3fec027d5d5c1bsalomon@google.com    SkTCopyOnFirstWrite<GrPaint> paint(origPaint);
641fea85ac3e31842f80493e2df8a93a28f21cd815frobertphillips@google.com    AutoMatrix am;
6428f9cbd62ec108d410b91155dcf6a4789c641246fbsalomon@google.com
6434f83be8f865921b60e3326b3fed6d5bc8281b541bsalomon@google.com    // We attempt to map r by the inverse matrix and draw that. mapRect will
6444f83be8f865921b60e3326b3fed6d5bc8281b541bsalomon@google.com    // map the four corners and bound them with a new rect. This will not
6454f83be8f865921b60e3326b3fed6d5bc8281b541bsalomon@google.com    // produce a correct result for some perspective matrices.
6468c2fe99ed2c210317786683e8c1f1e86cff0be49bsalomon@google.com    if (!this->getMatrix().hasPerspective()) {
647bb6a3178c3e79c8549b332e4ce84c64b59964f1ecommit-bot@chromium.org        if (!fViewMatrix.invert(&inverse)) {
648e3d3216fe17b6afb2e613271b5246a2766e12df6bsalomon@google.com            GrPrintf("Could not invert matrix\n");
6498c2fe99ed2c210317786683e8c1f1e86cff0be49bsalomon@google.com            return;
6508c2fe99ed2c210317786683e8c1f1e86cff0be49bsalomon@google.com        }
65127847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com        inverse.mapRect(&r);
65227847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com    } else {
6533cbaa2d4da8bc39a99bf3afaaab43cc6dc481723bsalomon@google.com        if (!am.setIdentity(this, paint.writable())) {
6543cbaa2d4da8bc39a99bf3afaaab43cc6dc481723bsalomon@google.com            GrPrintf("Could not invert matrix\n");
6553cbaa2d4da8bc39a99bf3afaaab43cc6dc481723bsalomon@google.com            return;
6568c2fe99ed2c210317786683e8c1f1e86cff0be49bsalomon@google.com        }
65727847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com    }
6584f83be8f865921b60e3326b3fed6d5bc8281b541bsalomon@google.com    // by definition this fills the entire clip, no need for AA
6595dc26b97366934ba0f896cea02a3fec027d5d5c1bsalomon@google.com    if (paint->isAntiAlias()) {
6605dc26b97366934ba0f896cea02a3fec027d5d5c1bsalomon@google.com        paint.writable()->setAntiAlias(false);
6614f83be8f865921b60e3326b3fed6d5bc8281b541bsalomon@google.com    }
6625dc26b97366934ba0f896cea02a3fec027d5d5c1bsalomon@google.com    this->drawRect(*paint, r);
66327847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com}
66427847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com
66503e3e89641c93df603dfb705d518848dfe81427ecommit-bot@chromium.org#ifdef SK_DEVELOPER
66603e3e89641c93df603dfb705d518848dfe81427ecommit-bot@chromium.orgvoid GrContext::dumpFontCache() const {
66703e3e89641c93df603dfb705d518848dfe81427ecommit-bot@chromium.org    fFontCache->dump();
66803e3e89641c93df603dfb705d518848dfe81427ecommit-bot@chromium.org}
66903e3e89641c93df603dfb705d518848dfe81427ecommit-bot@chromium.org#endif
67003e3e89641c93df603dfb705d518848dfe81427ecommit-bot@chromium.org
671205d46067ace24bd4b111cf44efc96caff6c4d30bsalomon@google.com////////////////////////////////////////////////////////////////////////////////
672205d46067ace24bd4b111cf44efc96caff6c4d30bsalomon@google.com
67327847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com/*  create a triangle strip that strokes the specified triangle. There are 8
67427847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com unique vertices, but we repreat the last 2 to close up. Alternatively we
67527847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com could use an indices array, and then only send 8 verts, but not sure that
67627847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com would be faster.
67727847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com */
678fd03d4a829efe2d77a712fd991927c55f59a2ffecommit-bot@chromium.orgstatic void setStrokeRectStrip(GrPoint verts[10], SkRect rect,
67981712883419f76e25d2ffec38a9438284a45a48dbsalomon@google.com                               SkScalar width) {
68081712883419f76e25d2ffec38a9438284a45a48dbsalomon@google.com    const SkScalar rad = SkScalarHalf(width);
681205d46067ace24bd4b111cf44efc96caff6c4d30bsalomon@google.com    rect.sort();
68227847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com
68327847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com    verts[0].set(rect.fLeft + rad, rect.fTop + rad);
68427847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com    verts[1].set(rect.fLeft - rad, rect.fTop - rad);
68527847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com    verts[2].set(rect.fRight - rad, rect.fTop + rad);
68627847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com    verts[3].set(rect.fRight + rad, rect.fTop - rad);
68727847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com    verts[4].set(rect.fRight - rad, rect.fBottom - rad);
68827847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com    verts[5].set(rect.fRight + rad, rect.fBottom + rad);
68927847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com    verts[6].set(rect.fLeft + rad, rect.fBottom - rad);
69027847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com    verts[7].set(rect.fLeft - rad, rect.fBottom + rad);
69127847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com    verts[8] = verts[0];
69227847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com    verts[9] = verts[1];
69327847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com}
69427847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com
695fd03d4a829efe2d77a712fd991927c55f59a2ffecommit-bot@chromium.orgstatic bool isIRect(const SkRect& r) {
696eafdf126d44abadf01e7d2910739e228f557df51skia.committer@gmail.com    return SkScalarIsInt(r.fLeft)  && SkScalarIsInt(r.fTop) &&
697eafdf126d44abadf01e7d2910739e228f557df51skia.committer@gmail.com           SkScalarIsInt(r.fRight) && SkScalarIsInt(r.fBottom);
698afd1cba5237eba5394ee011106eede9f6c8074c8robertphillips@google.com}
699afd1cba5237eba5394ee011106eede9f6c8074c8robertphillips@google.com
700205d46067ace24bd4b111cf44efc96caff6c4d30bsalomon@google.comstatic bool apply_aa_to_rect(GrDrawTarget* target,
701fd03d4a829efe2d77a712fd991927c55f59a2ffecommit-bot@chromium.org                             const SkRect& rect,
702df3695e5c72b3b4401e71ff259827d87bfe8a06frobertphillips@google.com                             SkScalar strokeWidth,
70324ab3b0ce50b3428f063849b6160e468f047487ccommit-bot@chromium.org                             const SkMatrix& combinedMatrix,
70424ab3b0ce50b3428f063849b6160e468f047487ccommit-bot@chromium.org                             SkRect* devBoundRect,
705a31082685544d0ae4c0b203d7f5ff960640ed8dfbsalomon@google.com                             bool* useVertexCoverage) {
7062eba795bcda66813fdc7a7c4388a99ae9cb2c864bsalomon@google.com    // we use a simple coverage ramp to do aa on axis-aligned rects
707fbfcd5602128ec010c82cb733c9cdc0a3254f9f3rmistry@google.com    // we check if the rect will be axis-aligned, and the rect won't land on
7082eba795bcda66813fdc7a7c4388a99ae9cb2c864bsalomon@google.com    // integer coords.
709d46e2423a71d38b8a057cec2356741e35b03334dbsalomon@google.com
710a31082685544d0ae4c0b203d7f5ff960640ed8dfbsalomon@google.com    // we are keeping around the "tweak the alpha" trick because
711a31082685544d0ae4c0b203d7f5ff960640ed8dfbsalomon@google.com    // it is our only hope for the fixed-pipe implementation.
712a31082685544d0ae4c0b203d7f5ff960640ed8dfbsalomon@google.com    // In a shader implementation we can give a separate coverage input
713289533ada623f2238a83771eec977f204f75994fbsalomon@google.com    // TODO: remove this ugliness when we drop the fixed-pipe impl
714a31082685544d0ae4c0b203d7f5ff960640ed8dfbsalomon@google.com    *useVertexCoverage = false;
7152b446734cfa8201e5478648988de86b646cb9544bsalomon@google.com    if (!target->getDrawState().canTweakAlphaForCoverage()) {
716e0a868c84ebc34c5a16b5faa1546016abb9ca0accommit-bot@chromium.org        if (target->shouldDisableCoverageAAForBlend()) {
717515dcd36032997ce335daa0163c6d67e851bcad1commit-bot@chromium.org#ifdef SK_DEBUG
7182eba795bcda66813fdc7a7c4388a99ae9cb2c864bsalomon@google.com            //GrPrintf("Turning off AA to correctly apply blend.\n");
7191983f39f1bf6295c96c0f1f7ead9f568923390bcbsalomon@google.com#endif
720a31082685544d0ae4c0b203d7f5ff960640ed8dfbsalomon@google.com            return false;
7212eba795bcda66813fdc7a7c4388a99ae9cb2c864bsalomon@google.com        } else {
7222eba795bcda66813fdc7a7c4388a99ae9cb2c864bsalomon@google.com            *useVertexCoverage = true;
723a31082685544d0ae4c0b203d7f5ff960640ed8dfbsalomon@google.com        }
724205d46067ace24bd4b111cf44efc96caff6c4d30bsalomon@google.com    }
7258f9cbd62ec108d410b91155dcf6a4789c641246fbsalomon@google.com    const GrDrawState& drawState = target->getDrawState();
7268f9cbd62ec108d410b91155dcf6a4789c641246fbsalomon@google.com    if (drawState.getRenderTarget()->isMultisampled()) {
727205d46067ace24bd4b111cf44efc96caff6c4d30bsalomon@google.com        return false;
728205d46067ace24bd4b111cf44efc96caff6c4d30bsalomon@google.com    }
729205d46067ace24bd4b111cf44efc96caff6c4d30bsalomon@google.com
730df3695e5c72b3b4401e71ff259827d87bfe8a06frobertphillips@google.com    if (0 == strokeWidth && target->willUseHWAALines()) {
731205d46067ace24bd4b111cf44efc96caff6c4d30bsalomon@google.com        return false;
732205d46067ace24bd4b111cf44efc96caff6c4d30bsalomon@google.com    }
733205d46067ace24bd4b111cf44efc96caff6c4d30bsalomon@google.com
7344b140b5fbedcb75d0b9587fa9d232ce54d9c7eb5robertphillips@google.com#if defined(SHADER_AA_FILL_RECT) || !defined(IGNORE_ROT_AA_RECT_OPT)
735df3695e5c72b3b4401e71ff259827d87bfe8a06frobertphillips@google.com    if (strokeWidth >= 0) {
736df3695e5c72b3b4401e71ff259827d87bfe8a06frobertphillips@google.com#endif
73724ab3b0ce50b3428f063849b6160e468f047487ccommit-bot@chromium.org        if (!combinedMatrix.preservesAxisAlignment()) {
738df3695e5c72b3b4401e71ff259827d87bfe8a06frobertphillips@google.com            return false;
739df3695e5c72b3b4401e71ff259827d87bfe8a06frobertphillips@google.com        }
740205d46067ace24bd4b111cf44efc96caff6c4d30bsalomon@google.com
7414b140b5fbedcb75d0b9587fa9d232ce54d9c7eb5robertphillips@google.com#if defined(SHADER_AA_FILL_RECT) || !defined(IGNORE_ROT_AA_RECT_OPT)
742df3695e5c72b3b4401e71ff259827d87bfe8a06frobertphillips@google.com    } else {
74324ab3b0ce50b3428f063849b6160e468f047487ccommit-bot@chromium.org        if (!combinedMatrix.preservesRightAngles()) {
744df3695e5c72b3b4401e71ff259827d87bfe8a06frobertphillips@google.com            return false;
745df3695e5c72b3b4401e71ff259827d87bfe8a06frobertphillips@google.com        }
746205d46067ace24bd4b111cf44efc96caff6c4d30bsalomon@google.com    }
747df3695e5c72b3b4401e71ff259827d87bfe8a06frobertphillips@google.com#endif
748205d46067ace24bd4b111cf44efc96caff6c4d30bsalomon@google.com
74924ab3b0ce50b3428f063849b6160e468f047487ccommit-bot@chromium.org    combinedMatrix.mapRect(devBoundRect, rect);
75028ac96e40d705f7fb08a61ac027e15de8d91823crobertphillips@google.com
751afd1cba5237eba5394ee011106eede9f6c8074c8robertphillips@google.com    if (strokeWidth < 0) {
75224ab3b0ce50b3428f063849b6160e468f047487ccommit-bot@chromium.org        return !isIRect(*devBoundRect);
753afd1cba5237eba5394ee011106eede9f6c8074c8robertphillips@google.com    } else {
754afd1cba5237eba5394ee011106eede9f6c8074c8robertphillips@google.com        return true;
755afd1cba5237eba5394ee011106eede9f6c8074c8robertphillips@google.com    }
756205d46067ace24bd4b111cf44efc96caff6c4d30bsalomon@google.com}
757205d46067ace24bd4b111cf44efc96caff6c4d30bsalomon@google.com
75824ab3b0ce50b3428f063849b6160e468f047487ccommit-bot@chromium.orgstatic inline bool rect_contains_inclusive(const SkRect& rect, const SkPoint& point) {
75924ab3b0ce50b3428f063849b6160e468f047487ccommit-bot@chromium.org    return point.fX >= rect.fLeft && point.fX <= rect.fRight &&
76024ab3b0ce50b3428f063849b6160e468f047487ccommit-bot@chromium.org           point.fY >= rect.fTop && point.fY <= rect.fBottom;
76124ab3b0ce50b3428f063849b6160e468f047487ccommit-bot@chromium.org}
76224ab3b0ce50b3428f063849b6160e468f047487ccommit-bot@chromium.org
76327847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.comvoid GrContext::drawRect(const GrPaint& paint,
764fd03d4a829efe2d77a712fd991927c55f59a2ffecommit-bot@chromium.org                         const SkRect& rect,
7656006d0f8c4f19d19a12de20826f731f52ac822a7commit-bot@chromium.org                         const SkStrokeRec* stroke,
766b9086a026844e4cfd08b219e49ce3f12294cba98bsalomon@google.com                         const SkMatrix* matrix) {
767278cbb452a260de1550769b168df448e0911cf3ctomhudson@google.com    SK_TRACE_EVENT0("GrContext::drawRect");
76827847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com
769eb6879f50a5564eeb981ec5616b55bf685eb76fcbsalomon@google.com    AutoRestoreEffects are;
7705dbb149fda134941e5d168790127caf294d322e2commit-bot@chromium.org    AutoCheckFlush acf(this);
7715dbb149fda134941e5d168790127caf294d322e2commit-bot@chromium.org    GrDrawTarget* target = this->prepareToDraw(&paint, BUFFERED_DRAW, &are, &acf);
77227847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com
7736006d0f8c4f19d19a12de20826f731f52ac822a7commit-bot@chromium.org    SkScalar width = stroke == NULL ? -1 : stroke->getWidth();
77424ab3b0ce50b3428f063849b6160e468f047487ccommit-bot@chromium.org    SkMatrix combinedMatrix = target->drawState()->getViewMatrix();
77524ab3b0ce50b3428f063849b6160e468f047487ccommit-bot@chromium.org    if (NULL != matrix) {
77624ab3b0ce50b3428f063849b6160e468f047487ccommit-bot@chromium.org        combinedMatrix.preConcat(*matrix);
77724ab3b0ce50b3428f063849b6160e468f047487ccommit-bot@chromium.org    }
77824ab3b0ce50b3428f063849b6160e468f047487ccommit-bot@chromium.org
77924ab3b0ce50b3428f063849b6160e468f047487ccommit-bot@chromium.org    // Check if this is a full RT draw and can be replaced with a clear. We don't bother checking
78024ab3b0ce50b3428f063849b6160e468f047487ccommit-bot@chromium.org    // cases where the RT is fully inside a stroke.
78124ab3b0ce50b3428f063849b6160e468f047487ccommit-bot@chromium.org    if (width < 0) {
78224ab3b0ce50b3428f063849b6160e468f047487ccommit-bot@chromium.org        SkRect rtRect;
78324ab3b0ce50b3428f063849b6160e468f047487ccommit-bot@chromium.org        target->getDrawState().getRenderTarget()->getBoundsRect(&rtRect);
78424ab3b0ce50b3428f063849b6160e468f047487ccommit-bot@chromium.org        SkRect clipSpaceRTRect = rtRect;
78524ab3b0ce50b3428f063849b6160e468f047487ccommit-bot@chromium.org        bool checkClip = false;
78624ab3b0ce50b3428f063849b6160e468f047487ccommit-bot@chromium.org        if (NULL != this->getClip()) {
78724ab3b0ce50b3428f063849b6160e468f047487ccommit-bot@chromium.org            checkClip = true;
78824ab3b0ce50b3428f063849b6160e468f047487ccommit-bot@chromium.org            clipSpaceRTRect.offset(SkIntToScalar(this->getClip()->fOrigin.fX),
78924ab3b0ce50b3428f063849b6160e468f047487ccommit-bot@chromium.org                                   SkIntToScalar(this->getClip()->fOrigin.fY));
79024ab3b0ce50b3428f063849b6160e468f047487ccommit-bot@chromium.org        }
79124ab3b0ce50b3428f063849b6160e468f047487ccommit-bot@chromium.org        // Does the clip contain the entire RT?
79224ab3b0ce50b3428f063849b6160e468f047487ccommit-bot@chromium.org        if (!checkClip || target->getClip()->fClipStack->quickContains(clipSpaceRTRect)) {
79324ab3b0ce50b3428f063849b6160e468f047487ccommit-bot@chromium.org            SkMatrix invM;
79424ab3b0ce50b3428f063849b6160e468f047487ccommit-bot@chromium.org            if (!combinedMatrix.invert(&invM)) {
79524ab3b0ce50b3428f063849b6160e468f047487ccommit-bot@chromium.org                return;
79624ab3b0ce50b3428f063849b6160e468f047487ccommit-bot@chromium.org            }
79724ab3b0ce50b3428f063849b6160e468f047487ccommit-bot@chromium.org            // Does the rect bound the RT?
79824ab3b0ce50b3428f063849b6160e468f047487ccommit-bot@chromium.org            SkPoint srcSpaceRTQuad[4];
79924ab3b0ce50b3428f063849b6160e468f047487ccommit-bot@chromium.org            invM.mapRectToQuad(srcSpaceRTQuad, rtRect);
80024ab3b0ce50b3428f063849b6160e468f047487ccommit-bot@chromium.org            if (rect_contains_inclusive(rect, srcSpaceRTQuad[0]) &&
80124ab3b0ce50b3428f063849b6160e468f047487ccommit-bot@chromium.org                rect_contains_inclusive(rect, srcSpaceRTQuad[1]) &&
80224ab3b0ce50b3428f063849b6160e468f047487ccommit-bot@chromium.org                rect_contains_inclusive(rect, srcSpaceRTQuad[2]) &&
80324ab3b0ce50b3428f063849b6160e468f047487ccommit-bot@chromium.org                rect_contains_inclusive(rect, srcSpaceRTQuad[3])) {
80424ab3b0ce50b3428f063849b6160e468f047487ccommit-bot@chromium.org                // Will it blend?
80524ab3b0ce50b3428f063849b6160e468f047487ccommit-bot@chromium.org                GrColor clearColor;
80624ab3b0ce50b3428f063849b6160e468f047487ccommit-bot@chromium.org                if (paint.isOpaqueAndConstantColor(&clearColor)) {
80756ce48ade325f6f49acb0da31d6252806e4ed7efrobertphillips@google.com                    target->clear(NULL, clearColor, true);
80824ab3b0ce50b3428f063849b6160e468f047487ccommit-bot@chromium.org                    return;
80924ab3b0ce50b3428f063849b6160e468f047487ccommit-bot@chromium.org                }
81024ab3b0ce50b3428f063849b6160e468f047487ccommit-bot@chromium.org            }
81124ab3b0ce50b3428f063849b6160e468f047487ccommit-bot@chromium.org        }
81224ab3b0ce50b3428f063849b6160e468f047487ccommit-bot@chromium.org    }
81324ab3b0ce50b3428f063849b6160e468f047487ccommit-bot@chromium.org
81424ab3b0ce50b3428f063849b6160e468f047487ccommit-bot@chromium.org    SkRect devBoundRect;
815a31082685544d0ae4c0b203d7f5ff960640ed8dfbsalomon@google.com    bool useVertexCoverage;
816c7448cef098b835d6f9adf8a365fde9de076f178bsalomon@google.com    bool needAA = paint.isAntiAlias() &&
817bb6a3178c3e79c8549b332e4ce84c64b59964f1ecommit-bot@chromium.org                  !target->getDrawState().getRenderTarget()->isMultisampled();
81824ab3b0ce50b3428f063849b6160e468f047487ccommit-bot@chromium.org    bool doAA = needAA && apply_aa_to_rect(target, rect, width, combinedMatrix, &devBoundRect,
819289533ada623f2238a83771eec977f204f75994fbsalomon@google.com                                           &useVertexCoverage);
820205d46067ace24bd4b111cf44efc96caff6c4d30bsalomon@google.com    if (doAA) {
821137f1347abaf0bb6a945e91c2f6cb49f0ee69bc3bsalomon@google.com        GrDrawState::AutoViewMatrixRestore avmr;
822137f1347abaf0bb6a945e91c2f6cb49f0ee69bc3bsalomon@google.com        if (!avmr.setIdentity(target->drawState())) {
823e3d3216fe17b6afb2e613271b5246a2766e12df6bsalomon@google.com            return;
824e3d3216fe17b6afb2e613271b5246a2766e12df6bsalomon@google.com        }
825205d46067ace24bd4b111cf44efc96caff6c4d30bsalomon@google.com        if (width >= 0) {
8266006d0f8c4f19d19a12de20826f731f52ac822a7commit-bot@chromium.org            fAARectRenderer->strokeAARect(this->getGpu(), target, rect,
8276006d0f8c4f19d19a12de20826f731f52ac822a7commit-bot@chromium.org                                          combinedMatrix, devBoundRect,
8286006d0f8c4f19d19a12de20826f731f52ac822a7commit-bot@chromium.org                                          stroke, useVertexCoverage);
829205d46067ace24bd4b111cf44efc96caff6c4d30bsalomon@google.com        } else {
830df3695e5c72b3b4401e71ff259827d87bfe8a06frobertphillips@google.com            // filled AA rect
831fbfcd5602128ec010c82cb733c9cdc0a3254f9f3rmistry@google.com            fAARectRenderer->fillAARect(this->getGpu(), target,
83224ab3b0ce50b3428f063849b6160e468f047487ccommit-bot@chromium.org                                        rect, combinedMatrix, devBoundRect,
833b19cb7f36785f3ad3b1512c342fc662ab79e3fcarobertphillips@google.com                                        useVertexCoverage);
834205d46067ace24bd4b111cf44efc96caff6c4d30bsalomon@google.com        }
835205d46067ace24bd4b111cf44efc96caff6c4d30bsalomon@google.com        return;
836205d46067ace24bd4b111cf44efc96caff6c4d30bsalomon@google.com    }
837205d46067ace24bd4b111cf44efc96caff6c4d30bsalomon@google.com
83827847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com    if (width >= 0) {
83927847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com        // TODO: consider making static vertex buffers for these cases.
8406438695222333981fafee9c8c09f3bf51dce3816bsalomon@google.com        // Hairline could be done by just adding closing vertex to
8416438695222333981fafee9c8c09f3bf51dce3816bsalomon@google.com        // unitSquareVertexBuffer()
84226c2d0a69e66f1656d2dc23953a6f153e5d5009fbsalomon@google.com
84327847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com        static const int worstCaseVertCount = 10;
8449b855c7c95ce9fff7a447e4a6bdf8a469c1f3097jvanverth@google.com        target->drawState()->setDefaultVertexAttribs();
845b75b0a0b8492e14c7728e0a0881f87dc64ce60f9jvanverth@google.com        GrDrawTarget::AutoReleaseGeometry geo(target, worstCaseVertCount, 0);
84627847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com
84727847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com        if (!geo.succeeded()) {
8486513cd06ae34f5d777b3aaea0b4533014d0a10f2bsalomon@google.com            GrPrintf("Failed to get space for vertices!\n");
84927847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com            return;
85027847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com        }
85127847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com
85227847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com        GrPrimitiveType primType;
85327847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com        int vertCount;
85427847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com        GrPoint* vertex = geo.positions();
85527847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com
85627847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com        if (width > 0) {
85727847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com            vertCount = 10;
85847059542e7aa153926377456a6c611e55c8e428cbsalomon@google.com            primType = kTriangleStrip_GrPrimitiveType;
85927847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com            setStrokeRectStrip(vertex, rect, width);
86027847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com        } else {
86127847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com            // hairline
86227847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com            vertCount = 5;
86347059542e7aa153926377456a6c611e55c8e428cbsalomon@google.com            primType = kLineStrip_GrPrimitiveType;
86427847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com            vertex[0].set(rect.fLeft, rect.fTop);
86527847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com            vertex[1].set(rect.fRight, rect.fTop);
86627847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com            vertex[2].set(rect.fRight, rect.fBottom);
86727847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com            vertex[3].set(rect.fLeft, rect.fBottom);
86827847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com            vertex[4].set(rect.fLeft, rect.fTop);
86927847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com        }
87027847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com
8718f9cbd62ec108d410b91155dcf6a4789c641246fbsalomon@google.com        GrDrawState::AutoViewMatrixRestore avmr;
87227847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com        if (NULL != matrix) {
8738f9cbd62ec108d410b91155dcf6a4789c641246fbsalomon@google.com            GrDrawState* drawState = target->drawState();
8742fdcdeb86788206c23410109b3e2b7976747fd11bsalomon@google.com            avmr.set(drawState, *matrix);
87527847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com        }
87627847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com
87727847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com        target->drawNonIndexed(primType, 0, vertCount);
87827847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com    } else {
879df3695e5c72b3b4401e71ff259827d87bfe8a06frobertphillips@google.com        // filled BW rect
880235ef3d0e253200af43bb69139df09744f5ddbefrobertphillips@google.com        target->drawSimpleRect(rect, matrix);
88127847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com    }
88227847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com}
88327847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com
88427847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.comvoid GrContext::drawRectToRect(const GrPaint& paint,
885fd03d4a829efe2d77a712fd991927c55f59a2ffecommit-bot@chromium.org                               const SkRect& dstRect,
886fd03d4a829efe2d77a712fd991927c55f59a2ffecommit-bot@chromium.org                               const SkRect& localRect,
887b9086a026844e4cfd08b219e49ce3f12294cba98bsalomon@google.com                               const SkMatrix* dstMatrix,
888c78188896e28a4ae49e406a7422b345ae177dafebsalomon@google.com                               const SkMatrix* localMatrix) {
889278cbb452a260de1550769b168df448e0911cf3ctomhudson@google.com    SK_TRACE_EVENT0("GrContext::drawRectToRect");
890eb6879f50a5564eeb981ec5616b55bf685eb76fcbsalomon@google.com    AutoRestoreEffects are;
8915dbb149fda134941e5d168790127caf294d322e2commit-bot@chromium.org    AutoCheckFlush acf(this);
8925dbb149fda134941e5d168790127caf294d322e2commit-bot@chromium.org    GrDrawTarget* target = this->prepareToDraw(&paint, BUFFERED_DRAW, &are, &acf);
8936438695222333981fafee9c8c09f3bf51dce3816bsalomon@google.com
894c78188896e28a4ae49e406a7422b345ae177dafebsalomon@google.com    target->drawRect(dstRect, dstMatrix, &localRect, localMatrix);
89527847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com}
89627847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com
897429033038271147ed66b4bc2675ac98a5ccfa75crobertphillips@google.comnamespace {
898429033038271147ed66b4bc2675ac98a5ccfa75crobertphillips@google.com
899429033038271147ed66b4bc2675ac98a5ccfa75crobertphillips@google.comextern const GrVertexAttrib gPosUVColorAttribs[] = {
900429033038271147ed66b4bc2675ac98a5ccfa75crobertphillips@google.com    {kVec2f_GrVertexAttribType,  0, kPosition_GrVertexAttribBinding },
901429033038271147ed66b4bc2675ac98a5ccfa75crobertphillips@google.com    {kVec2f_GrVertexAttribType,  sizeof(GrPoint), kLocalCoord_GrVertexAttribBinding },
902c9f3b38f67893b22c3e02a6a934bc676e36c5cfcrmistry@google.com    {kVec4ub_GrVertexAttribType, 2*sizeof(GrPoint), kColor_GrVertexAttribBinding}
903429033038271147ed66b4bc2675ac98a5ccfa75crobertphillips@google.com};
904429033038271147ed66b4bc2675ac98a5ccfa75crobertphillips@google.com
905429033038271147ed66b4bc2675ac98a5ccfa75crobertphillips@google.comextern const GrVertexAttrib gPosColorAttribs[] = {
906429033038271147ed66b4bc2675ac98a5ccfa75crobertphillips@google.com    {kVec2f_GrVertexAttribType,  0, kPosition_GrVertexAttribBinding},
907429033038271147ed66b4bc2675ac98a5ccfa75crobertphillips@google.com    {kVec4ub_GrVertexAttribType, sizeof(GrPoint), kColor_GrVertexAttribBinding},
908429033038271147ed66b4bc2675ac98a5ccfa75crobertphillips@google.com};
909429033038271147ed66b4bc2675ac98a5ccfa75crobertphillips@google.com
910429033038271147ed66b4bc2675ac98a5ccfa75crobertphillips@google.comstatic void set_vertex_attributes(GrDrawState* drawState,
911429033038271147ed66b4bc2675ac98a5ccfa75crobertphillips@google.com                                  const GrPoint* texCoords,
912429033038271147ed66b4bc2675ac98a5ccfa75crobertphillips@google.com                                  const GrColor* colors,
913429033038271147ed66b4bc2675ac98a5ccfa75crobertphillips@google.com                                  int* colorOffset,
914429033038271147ed66b4bc2675ac98a5ccfa75crobertphillips@google.com                                  int* texOffset) {
915429033038271147ed66b4bc2675ac98a5ccfa75crobertphillips@google.com    *texOffset = -1;
916429033038271147ed66b4bc2675ac98a5ccfa75crobertphillips@google.com    *colorOffset = -1;
917429033038271147ed66b4bc2675ac98a5ccfa75crobertphillips@google.com
918429033038271147ed66b4bc2675ac98a5ccfa75crobertphillips@google.com    if (NULL != texCoords && NULL != colors) {
919429033038271147ed66b4bc2675ac98a5ccfa75crobertphillips@google.com        *texOffset = sizeof(GrPoint);
920429033038271147ed66b4bc2675ac98a5ccfa75crobertphillips@google.com        *colorOffset = 2*sizeof(GrPoint);
921429033038271147ed66b4bc2675ac98a5ccfa75crobertphillips@google.com        drawState->setVertexAttribs<gPosUVColorAttribs>(3);
922429033038271147ed66b4bc2675ac98a5ccfa75crobertphillips@google.com    } else if (NULL != texCoords) {
923429033038271147ed66b4bc2675ac98a5ccfa75crobertphillips@google.com        *texOffset = sizeof(GrPoint);
924429033038271147ed66b4bc2675ac98a5ccfa75crobertphillips@google.com        drawState->setVertexAttribs<gPosUVColorAttribs>(2);
925429033038271147ed66b4bc2675ac98a5ccfa75crobertphillips@google.com    } else if (NULL != colors) {
926429033038271147ed66b4bc2675ac98a5ccfa75crobertphillips@google.com        *colorOffset = sizeof(GrPoint);
927429033038271147ed66b4bc2675ac98a5ccfa75crobertphillips@google.com        drawState->setVertexAttribs<gPosColorAttribs>(2);
928429033038271147ed66b4bc2675ac98a5ccfa75crobertphillips@google.com    } else {
929429033038271147ed66b4bc2675ac98a5ccfa75crobertphillips@google.com        drawState->setVertexAttribs<gPosColorAttribs>(1);
930429033038271147ed66b4bc2675ac98a5ccfa75crobertphillips@google.com    }
931429033038271147ed66b4bc2675ac98a5ccfa75crobertphillips@google.com}
932429033038271147ed66b4bc2675ac98a5ccfa75crobertphillips@google.com
933429033038271147ed66b4bc2675ac98a5ccfa75crobertphillips@google.com};
934429033038271147ed66b4bc2675ac98a5ccfa75crobertphillips@google.com
93527847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.comvoid GrContext::drawVertices(const GrPaint& paint,
93627847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com                             GrPrimitiveType primitiveType,
93727847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com                             int vertexCount,
93827847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com                             const GrPoint positions[],
93927847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com                             const GrPoint texCoords[],
94027847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com                             const GrColor colors[],
94127847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com                             const uint16_t indices[],
94227847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com                             int indexCount) {
943278cbb452a260de1550769b168df448e0911cf3ctomhudson@google.com    SK_TRACE_EVENT0("GrContext::drawVertices");
94427847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com
945eb6879f50a5564eeb981ec5616b55bf685eb76fcbsalomon@google.com    AutoRestoreEffects are;
9465dbb149fda134941e5d168790127caf294d322e2commit-bot@chromium.org    AutoCheckFlush acf(this);
9475a56793b2a19eaf90b67d6f24441cc475d74ef17commit-bot@chromium.org    GrDrawTarget::AutoReleaseGeometry geo; // must be inside AutoCheckFlush scope
9485a56793b2a19eaf90b67d6f24441cc475d74ef17commit-bot@chromium.org
9495dbb149fda134941e5d168790127caf294d322e2commit-bot@chromium.org    GrDrawTarget* target = this->prepareToDraw(&paint, BUFFERED_DRAW, &are, &acf);
95027847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com
9519b855c7c95ce9fff7a447e4a6bdf8a469c1f3097jvanverth@google.com    GrDrawState* drawState = target->drawState();
9529b855c7c95ce9fff7a447e4a6bdf8a469c1f3097jvanverth@google.com
9539b855c7c95ce9fff7a447e4a6bdf8a469c1f3097jvanverth@google.com    int colorOffset = -1, texOffset = -1;
954429033038271147ed66b4bc2675ac98a5ccfa75crobertphillips@google.com    set_vertex_attributes(drawState, texCoords, colors, &colorOffset, &texOffset);
9559b855c7c95ce9fff7a447e4a6bdf8a469c1f3097jvanverth@google.com
9569b855c7c95ce9fff7a447e4a6bdf8a469c1f3097jvanverth@google.com    size_t vertexSize = drawState->getVertexSize();
95727847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com    if (sizeof(GrPoint) != vertexSize) {
958b75b0a0b8492e14c7728e0a0881f87dc64ce60f9jvanverth@google.com        if (!geo.set(target, vertexCount, 0)) {
9596513cd06ae34f5d777b3aaea0b4533014d0a10f2bsalomon@google.com            GrPrintf("Failed to get space for vertices!\n");
96027847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com            return;
96127847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com        }
96227847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com        void* curVertex = geo.vertices();
96327847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com
96427847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com        for (int i = 0; i < vertexCount; ++i) {
96527847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com            *((GrPoint*)curVertex) = positions[i];
96627847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com
9679b855c7c95ce9fff7a447e4a6bdf8a469c1f3097jvanverth@google.com            if (texOffset >= 0) {
9683976825a21532e254311b90b4a9046e25717e335jvanverth@google.com                *(GrPoint*)((intptr_t)curVertex + texOffset) = texCoords[i];
96927847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com            }
9709b855c7c95ce9fff7a447e4a6bdf8a469c1f3097jvanverth@google.com            if (colorOffset >= 0) {
97127847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com                *(GrColor*)((intptr_t)curVertex + colorOffset) = colors[i];
97227847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com            }
97326c2d0a69e66f1656d2dc23953a6f153e5d5009fbsalomon@google.com            curVertex = (void*)((intptr_t)curVertex + vertexSize);
97427847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com        }
97527847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com    } else {
976b75b0a0b8492e14c7728e0a0881f87dc64ce60f9jvanverth@google.com        target->setVertexSourceToArray(positions, vertexCount);
97727847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com    }
97827847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com
979fbfcd5602128ec010c82cb733c9cdc0a3254f9f3rmistry@google.com    // we don't currently apply offscreen AA to this path. Need improved
980919583674bd5daeb60327c0bc1ce8aaa80d54e13bsalomon@google.com    // management of GrDrawTarget's geometry to avoid copying points per-tile.
981a47a48dca5045d71cbc5de343404045209a13e15bsalomon@google.com
9828295dc1474db279df08d816b2115e807c681fad5bsalomon@google.com    if (NULL != indices) {
983919583674bd5daeb60327c0bc1ce8aaa80d54e13bsalomon@google.com        target->setIndexSourceToArray(indices, indexCount);
9848295dc1474db279df08d816b2115e807c681fad5bsalomon@google.com        target->drawIndexed(primitiveType, 0, 0, vertexCount, indexCount);
9850406b9e1faee06c6ecb2732a1bcf3b0e53104e07bsalomon@google.com        target->resetIndexSource();
98627847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com    } else {
9878295dc1474db279df08d816b2115e807c681fad5bsalomon@google.com        target->drawNonIndexed(primitiveType, 0, vertexCount);
9888295dc1474db279df08d816b2115e807c681fad5bsalomon@google.com    }
98927847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com}
99027847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com
99106afe7b5a1ef03bfc6494c51ab2a1f7a386de5c2bsalomon@google.com///////////////////////////////////////////////////////////////////////////////
99293c9660cd158c5d0cab0ba4223e4257f699d5bb8bsalomon@google.com
993f2bfd54de32ffbcf90ddcd0e249aaebb1559d9c2commit-bot@chromium.orgvoid GrContext::drawRRect(const GrPaint& paint,
994f2bfd54de32ffbcf90ddcd0e249aaebb1559d9c2commit-bot@chromium.org                          const SkRRect& rect,
995f2bfd54de32ffbcf90ddcd0e249aaebb1559d9c2commit-bot@chromium.org                          const SkStrokeRec& stroke) {
99619dd017a6256be636ccb550752bb563c4e7caeb5commit-bot@chromium.org    if (rect.isEmpty()) {
99719dd017a6256be636ccb550752bb563c4e7caeb5commit-bot@chromium.org       return;
99819dd017a6256be636ccb550752bb563c4e7caeb5commit-bot@chromium.org    }
999f2bfd54de32ffbcf90ddcd0e249aaebb1559d9c2commit-bot@chromium.org
1000eb6879f50a5564eeb981ec5616b55bf685eb76fcbsalomon@google.com    AutoRestoreEffects are;
10015dbb149fda134941e5d168790127caf294d322e2commit-bot@chromium.org    AutoCheckFlush acf(this);
10025dbb149fda134941e5d168790127caf294d322e2commit-bot@chromium.org    GrDrawTarget* target = this->prepareToDraw(&paint, BUFFERED_DRAW, &are, &acf);
1003f2bfd54de32ffbcf90ddcd0e249aaebb1559d9c2commit-bot@chromium.org
1004e0a868c84ebc34c5a16b5faa1546016abb9ca0accommit-bot@chromium.org    if (!fOvalRenderer->drawSimpleRRect(target, this, paint.isAntiAlias(), rect, stroke)) {
1005f2bfd54de32ffbcf90ddcd0e249aaebb1559d9c2commit-bot@chromium.org        SkPath path;
1006f2bfd54de32ffbcf90ddcd0e249aaebb1559d9c2commit-bot@chromium.org        path.addRRect(rect);
1007e0a868c84ebc34c5a16b5faa1546016abb9ca0accommit-bot@chromium.org        this->internalDrawPath(target, paint.isAntiAlias(), path, stroke);
1008f2bfd54de32ffbcf90ddcd0e249aaebb1559d9c2commit-bot@chromium.org    }
1009f2bfd54de32ffbcf90ddcd0e249aaebb1559d9c2commit-bot@chromium.org}
1010f2bfd54de32ffbcf90ddcd0e249aaebb1559d9c2commit-bot@chromium.org
1011f2bfd54de32ffbcf90ddcd0e249aaebb1559d9c2commit-bot@chromium.org///////////////////////////////////////////////////////////////////////////////
1012f2bfd54de32ffbcf90ddcd0e249aaebb1559d9c2commit-bot@chromium.org
101346d3d39e65e0b3ea2ad7c91c176ccafb4df0fa24jvanverth@google.comvoid GrContext::drawOval(const GrPaint& paint,
1014fd03d4a829efe2d77a712fd991927c55f59a2ffecommit-bot@chromium.org                         const SkRect& oval,
101546d3d39e65e0b3ea2ad7c91c176ccafb4df0fa24jvanverth@google.com                         const SkStrokeRec& stroke) {
101619dd017a6256be636ccb550752bb563c4e7caeb5commit-bot@chromium.org    if (oval.isEmpty()) {
101719dd017a6256be636ccb550752bb563c4e7caeb5commit-bot@chromium.org       return;
101819dd017a6256be636ccb550752bb563c4e7caeb5commit-bot@chromium.org    }
101993c9660cd158c5d0cab0ba4223e4257f699d5bb8bsalomon@google.com
1020eb6879f50a5564eeb981ec5616b55bf685eb76fcbsalomon@google.com    AutoRestoreEffects are;
10215dbb149fda134941e5d168790127caf294d322e2commit-bot@chromium.org    AutoCheckFlush acf(this);
10225dbb149fda134941e5d168790127caf294d322e2commit-bot@chromium.org    GrDrawTarget* target = this->prepareToDraw(&paint, BUFFERED_DRAW, &are, &acf);
10230982d35187da7e1ed6c0eba5951bbdadca8b33e7bsalomon@google.com
1024e0a868c84ebc34c5a16b5faa1546016abb9ca0accommit-bot@chromium.org    if (!fOvalRenderer->drawOval(target, this, paint.isAntiAlias(), oval, stroke)) {
102581312830ef73420efdc4821feb7c2d6fd9152af8commit-bot@chromium.org        SkPath path;
102681312830ef73420efdc4821feb7c2d6fd9152af8commit-bot@chromium.org        path.addOval(oval);
1027e0a868c84ebc34c5a16b5faa1546016abb9ca0accommit-bot@chromium.org        this->internalDrawPath(target, paint.isAntiAlias(), path, stroke);
102846d3d39e65e0b3ea2ad7c91c176ccafb4df0fa24jvanverth@google.com    }
1029150d28465d340e3c6da6a3e1fd5adfdb128e61d0bsalomon@google.com}
103027847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com
103183d1a68141830cbfa0d5fca6f9c9bccf9c978ad2robertphillips@google.com// Can 'path' be drawn as a pair of filled nested rectangles?
103283d1a68141830cbfa0d5fca6f9c9bccf9c978ad2robertphillips@google.comstatic bool is_nested_rects(GrDrawTarget* target,
103383d1a68141830cbfa0d5fca6f9c9bccf9c978ad2robertphillips@google.com                            const SkPath& path,
103483d1a68141830cbfa0d5fca6f9c9bccf9c978ad2robertphillips@google.com                            const SkStrokeRec& stroke,
103583d1a68141830cbfa0d5fca6f9c9bccf9c978ad2robertphillips@google.com                            SkRect rects[2],
103683d1a68141830cbfa0d5fca6f9c9bccf9c978ad2robertphillips@google.com                            bool* useVertexCoverage) {
103783d1a68141830cbfa0d5fca6f9c9bccf9c978ad2robertphillips@google.com    SkASSERT(stroke.isFillStyle());
103883d1a68141830cbfa0d5fca6f9c9bccf9c978ad2robertphillips@google.com
103983d1a68141830cbfa0d5fca6f9c9bccf9c978ad2robertphillips@google.com    if (path.isInverseFillType()) {
104083d1a68141830cbfa0d5fca6f9c9bccf9c978ad2robertphillips@google.com        return false;
104183d1a68141830cbfa0d5fca6f9c9bccf9c978ad2robertphillips@google.com    }
104283d1a68141830cbfa0d5fca6f9c9bccf9c978ad2robertphillips@google.com
104383d1a68141830cbfa0d5fca6f9c9bccf9c978ad2robertphillips@google.com    const GrDrawState& drawState = target->getDrawState();
104483d1a68141830cbfa0d5fca6f9c9bccf9c978ad2robertphillips@google.com
104583d1a68141830cbfa0d5fca6f9c9bccf9c978ad2robertphillips@google.com    // TODO: this restriction could be lifted if we were willing to apply
104683d1a68141830cbfa0d5fca6f9c9bccf9c978ad2robertphillips@google.com    // the matrix to all the points individually rather than just to the rect
104783d1a68141830cbfa0d5fca6f9c9bccf9c978ad2robertphillips@google.com    if (!drawState.getViewMatrix().preservesAxisAlignment()) {
104883d1a68141830cbfa0d5fca6f9c9bccf9c978ad2robertphillips@google.com        return false;
104983d1a68141830cbfa0d5fca6f9c9bccf9c978ad2robertphillips@google.com    }
105083d1a68141830cbfa0d5fca6f9c9bccf9c978ad2robertphillips@google.com
105183d1a68141830cbfa0d5fca6f9c9bccf9c978ad2robertphillips@google.com    *useVertexCoverage = false;
105283d1a68141830cbfa0d5fca6f9c9bccf9c978ad2robertphillips@google.com    if (!target->getDrawState().canTweakAlphaForCoverage()) {
1053e0a868c84ebc34c5a16b5faa1546016abb9ca0accommit-bot@chromium.org        if (target->shouldDisableCoverageAAForBlend()) {
105483d1a68141830cbfa0d5fca6f9c9bccf9c978ad2robertphillips@google.com            return false;
105583d1a68141830cbfa0d5fca6f9c9bccf9c978ad2robertphillips@google.com        } else {
105683d1a68141830cbfa0d5fca6f9c9bccf9c978ad2robertphillips@google.com            *useVertexCoverage = true;
105783d1a68141830cbfa0d5fca6f9c9bccf9c978ad2robertphillips@google.com        }
105883d1a68141830cbfa0d5fca6f9c9bccf9c978ad2robertphillips@google.com    }
105983d1a68141830cbfa0d5fca6f9c9bccf9c978ad2robertphillips@google.com
106083d1a68141830cbfa0d5fca6f9c9bccf9c978ad2robertphillips@google.com    SkPath::Direction dirs[2];
106183d1a68141830cbfa0d5fca6f9c9bccf9c978ad2robertphillips@google.com    if (!path.isNestedRects(rects, dirs)) {
106283d1a68141830cbfa0d5fca6f9c9bccf9c978ad2robertphillips@google.com        return false;
106383d1a68141830cbfa0d5fca6f9c9bccf9c978ad2robertphillips@google.com    }
106483d1a68141830cbfa0d5fca6f9c9bccf9c978ad2robertphillips@google.com
10658d3c640b5aa96d6316a3e52975602b35e1a66ac7robertphillips@google.com    if (SkPath::kWinding_FillType == path.getFillType() && dirs[0] == dirs[1]) {
106683d1a68141830cbfa0d5fca6f9c9bccf9c978ad2robertphillips@google.com        // The two rects need to be wound opposite to each other
10678d3c640b5aa96d6316a3e52975602b35e1a66ac7robertphillips@google.com        return false;
106883d1a68141830cbfa0d5fca6f9c9bccf9c978ad2robertphillips@google.com    }
106983d1a68141830cbfa0d5fca6f9c9bccf9c978ad2robertphillips@google.com
10708d3c640b5aa96d6316a3e52975602b35e1a66ac7robertphillips@google.com    // Right now, nested rects where the margin is not the same width
10718d3c640b5aa96d6316a3e52975602b35e1a66ac7robertphillips@google.com    // all around do not render correctly
10728d3c640b5aa96d6316a3e52975602b35e1a66ac7robertphillips@google.com    const SkScalar* outer = rects[0].asScalars();
10738d3c640b5aa96d6316a3e52975602b35e1a66ac7robertphillips@google.com    const SkScalar* inner = rects[1].asScalars();
10748d3c640b5aa96d6316a3e52975602b35e1a66ac7robertphillips@google.com
10758d3c640b5aa96d6316a3e52975602b35e1a66ac7robertphillips@google.com    SkScalar margin = SkScalarAbs(outer[0] - inner[0]);
10768d3c640b5aa96d6316a3e52975602b35e1a66ac7robertphillips@google.com    for (int i = 1; i < 4; ++i) {
10778d3c640b5aa96d6316a3e52975602b35e1a66ac7robertphillips@google.com        SkScalar temp = SkScalarAbs(outer[i] - inner[i]);
10788d3c640b5aa96d6316a3e52975602b35e1a66ac7robertphillips@google.com        if (!SkScalarNearlyEqual(margin, temp)) {
10798d3c640b5aa96d6316a3e52975602b35e1a66ac7robertphillips@google.com            return false;
10808d3c640b5aa96d6316a3e52975602b35e1a66ac7robertphillips@google.com        }
10818d3c640b5aa96d6316a3e52975602b35e1a66ac7robertphillips@google.com    }
10828d3c640b5aa96d6316a3e52975602b35e1a66ac7robertphillips@google.com
10838d3c640b5aa96d6316a3e52975602b35e1a66ac7robertphillips@google.com    return true;
10848d3c640b5aa96d6316a3e52975602b35e1a66ac7robertphillips@google.com}
108583d1a68141830cbfa0d5fca6f9c9bccf9c978ad2robertphillips@google.com
10865f74cf8c49701f514b69dc6f1a8b5c0ffd78af0asugoi@google.comvoid GrContext::drawPath(const GrPaint& paint, const SkPath& path, const SkStrokeRec& stroke) {
108727847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com
1088fa6ac938e64fe11b442d05fe8a90ddac2d1951f9bsalomon@google.com    if (path.isEmpty()) {
108912b4e27ae1a29460e91a59f38122483e1faec697sugoi@google.com       if (path.isInverseFillType()) {
1090fa6ac938e64fe11b442d05fe8a90ddac2d1951f9bsalomon@google.com           this->drawPaint(paint);
1091fa6ac938e64fe11b442d05fe8a90ddac2d1951f9bsalomon@google.com       }
1092fa6ac938e64fe11b442d05fe8a90ddac2d1951f9bsalomon@google.com       return;
1093fa6ac938e64fe11b442d05fe8a90ddac2d1951f9bsalomon@google.com    }
1094fa6ac938e64fe11b442d05fe8a90ddac2d1951f9bsalomon@google.com
109581312830ef73420efdc4821feb7c2d6fd9152af8commit-bot@chromium.org    // Note that internalDrawPath may sw-rasterize the path into a scratch texture.
109681312830ef73420efdc4821feb7c2d6fd9152af8commit-bot@chromium.org    // Scratch textures can be recycled after they are returned to the texture
109781312830ef73420efdc4821feb7c2d6fd9152af8commit-bot@chromium.org    // cache. This presents a potential hazard for buffered drawing. However,
109881312830ef73420efdc4821feb7c2d6fd9152af8commit-bot@chromium.org    // the writePixels that uploads to the scratch will perform a flush so we're
109981312830ef73420efdc4821feb7c2d6fd9152af8commit-bot@chromium.org    // OK.
1100eb6879f50a5564eeb981ec5616b55bf685eb76fcbsalomon@google.com    AutoRestoreEffects are;
11015dbb149fda134941e5d168790127caf294d322e2commit-bot@chromium.org    AutoCheckFlush acf(this);
11025dbb149fda134941e5d168790127caf294d322e2commit-bot@chromium.org    GrDrawTarget* target = this->prepareToDraw(&paint, BUFFERED_DRAW, &are, &acf);
1103e0a868c84ebc34c5a16b5faa1546016abb9ca0accommit-bot@chromium.org    GrDrawState* drawState = target->drawState();
110481312830ef73420efdc4821feb7c2d6fd9152af8commit-bot@chromium.org
1105e0a868c84ebc34c5a16b5faa1546016abb9ca0accommit-bot@chromium.org    bool useCoverageAA = paint.isAntiAlias() && !drawState->getRenderTarget()->isMultisampled();
1106e0a868c84ebc34c5a16b5faa1546016abb9ca0accommit-bot@chromium.org
1107e0a868c84ebc34c5a16b5faa1546016abb9ca0accommit-bot@chromium.org    if (useCoverageAA && stroke.getWidth() < 0 && !path.isConvex()) {
110883d1a68141830cbfa0d5fca6f9c9bccf9c978ad2robertphillips@google.com        // Concave AA paths are expensive - try to avoid them for special cases
110983d1a68141830cbfa0d5fca6f9c9bccf9c978ad2robertphillips@google.com        bool useVertexCoverage;
111083d1a68141830cbfa0d5fca6f9c9bccf9c978ad2robertphillips@google.com        SkRect rects[2];
111183d1a68141830cbfa0d5fca6f9c9bccf9c978ad2robertphillips@google.com
111283d1a68141830cbfa0d5fca6f9c9bccf9c978ad2robertphillips@google.com        if (is_nested_rects(target, path, stroke, rects, &useVertexCoverage)) {
1113e0a868c84ebc34c5a16b5faa1546016abb9ca0accommit-bot@chromium.org            SkMatrix origViewMatrix = drawState->getViewMatrix();
1114137f1347abaf0bb6a945e91c2f6cb49f0ee69bc3bsalomon@google.com            GrDrawState::AutoViewMatrixRestore avmr;
1115137f1347abaf0bb6a945e91c2f6cb49f0ee69bc3bsalomon@google.com            if (!avmr.setIdentity(target->drawState())) {
111683d1a68141830cbfa0d5fca6f9c9bccf9c978ad2robertphillips@google.com                return;
111783d1a68141830cbfa0d5fca6f9c9bccf9c978ad2robertphillips@google.com            }
111883d1a68141830cbfa0d5fca6f9c9bccf9c978ad2robertphillips@google.com
111983d1a68141830cbfa0d5fca6f9c9bccf9c978ad2robertphillips@google.com            fAARectRenderer->fillAANestedRects(this->getGpu(), target,
112083d1a68141830cbfa0d5fca6f9c9bccf9c978ad2robertphillips@google.com                                               rects,
1121137f1347abaf0bb6a945e91c2f6cb49f0ee69bc3bsalomon@google.com                                               origViewMatrix,
112283d1a68141830cbfa0d5fca6f9c9bccf9c978ad2robertphillips@google.com                                               useVertexCoverage);
112383d1a68141830cbfa0d5fca6f9c9bccf9c978ad2robertphillips@google.com            return;
112483d1a68141830cbfa0d5fca6f9c9bccf9c978ad2robertphillips@google.com        }
112583d1a68141830cbfa0d5fca6f9c9bccf9c978ad2robertphillips@google.com    }
112683d1a68141830cbfa0d5fca6f9c9bccf9c978ad2robertphillips@google.com
112793c9660cd158c5d0cab0ba4223e4257f699d5bb8bsalomon@google.com    SkRect ovalRect;
112846d3d39e65e0b3ea2ad7c91c176ccafb4df0fa24jvanverth@google.com    bool isOval = path.isOval(&ovalRect);
112946d3d39e65e0b3ea2ad7c91c176ccafb4df0fa24jvanverth@google.com
11307e32851d5473d14db5c396f5877e3dfcb7b19f6dskia.committer@gmail.com    if (!isOval || path.isInverseFillType()
1131e0a868c84ebc34c5a16b5faa1546016abb9ca0accommit-bot@chromium.org        || !fOvalRenderer->drawOval(target, this, paint.isAntiAlias(), ovalRect, stroke)) {
1132e0a868c84ebc34c5a16b5faa1546016abb9ca0accommit-bot@chromium.org        this->internalDrawPath(target, paint.isAntiAlias(), path, stroke);
113393c9660cd158c5d0cab0ba4223e4257f699d5bb8bsalomon@google.com    }
113493c9660cd158c5d0cab0ba4223e4257f699d5bb8bsalomon@google.com}
113593c9660cd158c5d0cab0ba4223e4257f699d5bb8bsalomon@google.com
11361b20a10f0205da2d53e0837e4ddc6b2bd3b8a462bsalomon@google.comvoid GrContext::internalDrawPath(GrDrawTarget* target, bool useAA, const SkPath& path,
1137f0c41e24d5322022c7678b60837274c1340fc109commit-bot@chromium.org                                 const SkStrokeRec& origStroke) {
113819dd017a6256be636ccb550752bb563c4e7caeb5commit-bot@chromium.org    SkASSERT(!path.isEmpty());
113993c9660cd158c5d0cab0ba4223e4257f699d5bb8bsalomon@google.com
1140d46e2423a71d38b8a057cec2356741e35b03334dbsalomon@google.com    // An Assumption here is that path renderer would use some form of tweaking
1141d46e2423a71d38b8a057cec2356741e35b03334dbsalomon@google.com    // the src color (either the input alpha or in the frag shader) to implement
1142d46e2423a71d38b8a057cec2356741e35b03334dbsalomon@google.com    // aa. If we have some future driver-mojo path AA that can do the right
1143d46e2423a71d38b8a057cec2356741e35b03334dbsalomon@google.com    // thing WRT to the blend then we'll need some query on the PR.
1144e0a868c84ebc34c5a16b5faa1546016abb9ca0accommit-bot@chromium.org    bool useCoverageAA = useAA &&
1145e0a868c84ebc34c5a16b5faa1546016abb9ca0accommit-bot@chromium.org        !target->getDrawState().getRenderTarget()->isMultisampled() &&
1146e0a868c84ebc34c5a16b5faa1546016abb9ca0accommit-bot@chromium.org        !target->shouldDisableCoverageAAForBlend();
1147e0a868c84ebc34c5a16b5faa1546016abb9ca0accommit-bot@chromium.org
1148289533ada623f2238a83771eec977f204f75994fbsalomon@google.com
1149e0a868c84ebc34c5a16b5faa1546016abb9ca0accommit-bot@chromium.org    GrPathRendererChain::DrawType type =
1150e0a868c84ebc34c5a16b5faa1546016abb9ca0accommit-bot@chromium.org        useCoverageAA ? GrPathRendererChain::kColorAntiAlias_DrawType :
1151e79f320ed6c5ec9f6164ba84be1ff586532e6517robertphillips@google.com                           GrPathRendererChain::kColor_DrawType;
115245a15f551b5b3c6c747d8eaf6466b7d3b76a8faebsalomon@google.com
1153eb928ea49a1c8a72ba3e01f64452b20713232059robertphillips@google.com    const SkPath* pathPtr = &path;
1154f0c41e24d5322022c7678b60837274c1340fc109commit-bot@chromium.org    SkTLazy<SkPath> tmpPath;
1155f0c41e24d5322022c7678b60837274c1340fc109commit-bot@chromium.org    SkTCopyOnFirstWrite<SkStrokeRec> stroke(origStroke);
1156eb928ea49a1c8a72ba3e01f64452b20713232059robertphillips@google.com
1157eb928ea49a1c8a72ba3e01f64452b20713232059robertphillips@google.com    // Try a 1st time without stroking the path and without allowing the SW renderer
1158e79f320ed6c5ec9f6164ba84be1ff586532e6517robertphillips@google.com    GrPathRenderer* pr = this->getPathRenderer(*pathPtr, *stroke, target, false, type);
1159eb928ea49a1c8a72ba3e01f64452b20713232059robertphillips@google.com
1160e79f320ed6c5ec9f6164ba84be1ff586532e6517robertphillips@google.com    if (NULL == pr) {
1161f0c41e24d5322022c7678b60837274c1340fc109commit-bot@chromium.org        if (!GrPathRenderer::IsStrokeHairlineOrEquivalent(*stroke, this->getMatrix(), NULL)) {
1162eb928ea49a1c8a72ba3e01f64452b20713232059robertphillips@google.com            // It didn't work the 1st time, so try again with the stroked path
1163f0c41e24d5322022c7678b60837274c1340fc109commit-bot@chromium.org            if (stroke->applyToPath(tmpPath.init(), *pathPtr)) {
1164f0c41e24d5322022c7678b60837274c1340fc109commit-bot@chromium.org                pathPtr = tmpPath.get();
1165f0c41e24d5322022c7678b60837274c1340fc109commit-bot@chromium.org                stroke.writable()->setFillStyle();
1166e0a868c84ebc34c5a16b5faa1546016abb9ca0accommit-bot@chromium.org                if (pathPtr->isEmpty()) {
1167e0a868c84ebc34c5a16b5faa1546016abb9ca0accommit-bot@chromium.org                    return;
1168e0a868c84ebc34c5a16b5faa1546016abb9ca0accommit-bot@chromium.org                }
1169eb928ea49a1c8a72ba3e01f64452b20713232059robertphillips@google.com            }
1170eb928ea49a1c8a72ba3e01f64452b20713232059robertphillips@google.com        }
117119dd017a6256be636ccb550752bb563c4e7caeb5commit-bot@chromium.org
1172eb928ea49a1c8a72ba3e01f64452b20713232059robertphillips@google.com        // This time, allow SW renderer
1173e79f320ed6c5ec9f6164ba84be1ff586532e6517robertphillips@google.com        pr = this->getPathRenderer(*pathPtr, *stroke, target, true, type);
1174eb928ea49a1c8a72ba3e01f64452b20713232059robertphillips@google.com    }
1175eb928ea49a1c8a72ba3e01f64452b20713232059robertphillips@google.com
1176e79f320ed6c5ec9f6164ba84be1ff586532e6517robertphillips@google.com    if (NULL == pr) {
1177515dcd36032997ce335daa0163c6d67e851bcad1commit-bot@chromium.org#ifdef SK_DEBUG
11783008519e9f977cd60194841d558a4f45c28e9833bsalomon@google.com        GrPrintf("Unable to find path renderer compatible with path.\n");
11791983f39f1bf6295c96c0f1f7ead9f568923390bcbsalomon@google.com#endif
11803008519e9f977cd60194841d558a4f45c28e9833bsalomon@google.com        return;
11813008519e9f977cd60194841d558a4f45c28e9833bsalomon@google.com    }
11823008519e9f977cd60194841d558a4f45c28e9833bsalomon@google.com
1183e79f320ed6c5ec9f6164ba84be1ff586532e6517robertphillips@google.com    pr->drawPath(*pathPtr, *stroke, target, useCoverageAA);
118427847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com}
11858295dc1474db279df08d816b2115e807c681fad5bsalomon@google.com
118627847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com////////////////////////////////////////////////////////////////////////////////
118727847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com
1188a7f84e150cb9e821267a8ca9e59c1ae9a3cfa300bsalomon@google.comvoid GrContext::flush(int flagsBitfield) {
1189e7db8d6c0291371ae2766fd0b6fc0918a0ed1c03robertphillips@google.com    if (NULL == fDrawBuffer) {
1190e7db8d6c0291371ae2766fd0b6fc0918a0ed1c03robertphillips@google.com        return;
1191e7db8d6c0291371ae2766fd0b6fc0918a0ed1c03robertphillips@google.com    }
1192e7db8d6c0291371ae2766fd0b6fc0918a0ed1c03robertphillips@google.com
1193a7f84e150cb9e821267a8ca9e59c1ae9a3cfa300bsalomon@google.com    if (kDiscard_FlushBit & flagsBitfield) {
1194a7f84e150cb9e821267a8ca9e59c1ae9a3cfa300bsalomon@google.com        fDrawBuffer->reset();
1195a7f84e150cb9e821267a8ca9e59c1ae9a3cfa300bsalomon@google.com    } else {
11966e4e65066a7c0dbc9bfbfe4b8f5d49c3d8a79b59bsalomon@google.com        fDrawBuffer->flush();
119753a5584bb0094e19c39a66cec7f346aad04ecac4junov@google.com    }
11985dbb149fda134941e5d168790127caf294d322e2commit-bot@chromium.org    fFlushToReduceCacheSize = false;
119927847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com}
120027847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com
12019c68058b679aee81e6e0158e7fcbfb5d8479c91absalomon@google.combool GrContext::writeTexturePixels(GrTexture* texture,
12020342a85091fd430c90a142d155dc9642aa729d9ebsalomon@google.com                                   int left, int top, int width, int height,
12030342a85091fd430c90a142d155dc9642aa729d9ebsalomon@google.com                                   GrPixelConfig config, const void* buffer, size_t rowBytes,
12040342a85091fd430c90a142d155dc9642aa729d9ebsalomon@google.com                                   uint32_t flags) {
12056f3795105b2b458079e53a721c1735c9518f6bb5bsalomon@google.com    SK_TRACE_EVENT0("GrContext::writeTexturePixels");
1206bc4b654af85fa67bdd9cc1b88747b8c394a00e27bsalomon@google.com    ASSERT_OWNED_RESOURCE(texture);
1207bc4b654af85fa67bdd9cc1b88747b8c394a00e27bsalomon@google.com
12089c68058b679aee81e6e0158e7fcbfb5d8479c91absalomon@google.com    if ((kUnpremul_PixelOpsFlag & flags) || !fGpu->canWriteTexturePixels(texture, config)) {
12099c68058b679aee81e6e0158e7fcbfb5d8479c91absalomon@google.com        if (NULL != texture->asRenderTarget()) {
12109c68058b679aee81e6e0158e7fcbfb5d8479c91absalomon@google.com            return this->writeRenderTargetPixels(texture->asRenderTarget(),
12119c68058b679aee81e6e0158e7fcbfb5d8479c91absalomon@google.com                                                 left, top, width, height,
12129c68058b679aee81e6e0158e7fcbfb5d8479c91absalomon@google.com                                                 config, buffer, rowBytes, flags);
12139c68058b679aee81e6e0158e7fcbfb5d8479c91absalomon@google.com        } else {
12149c68058b679aee81e6e0158e7fcbfb5d8479c91absalomon@google.com            return false;
12159c68058b679aee81e6e0158e7fcbfb5d8479c91absalomon@google.com        }
12166f3795105b2b458079e53a721c1735c9518f6bb5bsalomon@google.com    }
12179c68058b679aee81e6e0158e7fcbfb5d8479c91absalomon@google.com
12180342a85091fd430c90a142d155dc9642aa729d9ebsalomon@google.com    if (!(kDontFlush_PixelOpsFlag & flags)) {
12190342a85091fd430c90a142d155dc9642aa729d9ebsalomon@google.com        this->flush();
12200342a85091fd430c90a142d155dc9642aa729d9ebsalomon@google.com    }
12216f3795105b2b458079e53a721c1735c9518f6bb5bsalomon@google.com
12229c68058b679aee81e6e0158e7fcbfb5d8479c91absalomon@google.com    return fGpu->writeTexturePixels(texture, left, top, width, height,
12239c68058b679aee81e6e0158e7fcbfb5d8479c91absalomon@google.com                                    config, buffer, rowBytes);
12246f3795105b2b458079e53a721c1735c9518f6bb5bsalomon@google.com}
12256f3795105b2b458079e53a721c1735c9518f6bb5bsalomon@google.com
12260342a85091fd430c90a142d155dc9642aa729d9ebsalomon@google.combool GrContext::readTexturePixels(GrTexture* texture,
12270342a85091fd430c90a142d155dc9642aa729d9ebsalomon@google.com                                  int left, int top, int width, int height,
12280342a85091fd430c90a142d155dc9642aa729d9ebsalomon@google.com                                  GrPixelConfig config, void* buffer, size_t rowBytes,
12290342a85091fd430c90a142d155dc9642aa729d9ebsalomon@google.com                                  uint32_t flags) {
1230278cbb452a260de1550769b168df448e0911cf3ctomhudson@google.com    SK_TRACE_EVENT0("GrContext::readTexturePixels");
1231bc4b654af85fa67bdd9cc1b88747b8c394a00e27bsalomon@google.com    ASSERT_OWNED_RESOURCE(texture);
1232669fdc4ed8ed461a141cb97d0afdd9ef72a82be1bsalomon@google.com
1233669fdc4ed8ed461a141cb97d0afdd9ef72a82be1bsalomon@google.com    GrRenderTarget* target = texture->asRenderTarget();
1234669fdc4ed8ed461a141cb97d0afdd9ef72a82be1bsalomon@google.com    if (NULL != target) {
12350342a85091fd430c90a142d155dc9642aa729d9ebsalomon@google.com        return this->readRenderTargetPixels(target,
12360342a85091fd430c90a142d155dc9642aa729d9ebsalomon@google.com                                            left, top, width, height,
12370342a85091fd430c90a142d155dc9642aa729d9ebsalomon@google.com                                            config, buffer, rowBytes,
12380342a85091fd430c90a142d155dc9642aa729d9ebsalomon@google.com                                            flags);
1239669fdc4ed8ed461a141cb97d0afdd9ef72a82be1bsalomon@google.com    } else {
12403f80dd5f01a194d4fd9ce502734bc9f56bf3fb9fcommit-bot@chromium.org        // TODO: make this more efficient for cases where we're reading the entire
12413f80dd5f01a194d4fd9ce502734bc9f56bf3fb9fcommit-bot@chromium.org        //       texture, i.e., use GetTexImage() instead
12423f80dd5f01a194d4fd9ce502734bc9f56bf3fb9fcommit-bot@chromium.org
12433f80dd5f01a194d4fd9ce502734bc9f56bf3fb9fcommit-bot@chromium.org        // create scratch rendertarget and read from that
12443f80dd5f01a194d4fd9ce502734bc9f56bf3fb9fcommit-bot@chromium.org        GrAutoScratchTexture ast;
12453f80dd5f01a194d4fd9ce502734bc9f56bf3fb9fcommit-bot@chromium.org        GrTextureDesc desc;
12463f80dd5f01a194d4fd9ce502734bc9f56bf3fb9fcommit-bot@chromium.org        desc.fFlags = kRenderTarget_GrTextureFlagBit;
12473f80dd5f01a194d4fd9ce502734bc9f56bf3fb9fcommit-bot@chromium.org        desc.fWidth = width;
12483f80dd5f01a194d4fd9ce502734bc9f56bf3fb9fcommit-bot@chromium.org        desc.fHeight = height;
12493f80dd5f01a194d4fd9ce502734bc9f56bf3fb9fcommit-bot@chromium.org        desc.fConfig = config;
12503f80dd5f01a194d4fd9ce502734bc9f56bf3fb9fcommit-bot@chromium.org        desc.fOrigin = kTopLeft_GrSurfaceOrigin;
12513f80dd5f01a194d4fd9ce502734bc9f56bf3fb9fcommit-bot@chromium.org        ast.set(this, desc, kExact_ScratchTexMatch);
12523f80dd5f01a194d4fd9ce502734bc9f56bf3fb9fcommit-bot@chromium.org        GrTexture* dst = ast.texture();
12533f80dd5f01a194d4fd9ce502734bc9f56bf3fb9fcommit-bot@chromium.org        if (NULL != dst && NULL != (target = dst->asRenderTarget())) {
12543f80dd5f01a194d4fd9ce502734bc9f56bf3fb9fcommit-bot@chromium.org            this->copyTexture(texture, target, NULL);
12553f80dd5f01a194d4fd9ce502734bc9f56bf3fb9fcommit-bot@chromium.org            return this->readRenderTargetPixels(target,
12563f80dd5f01a194d4fd9ce502734bc9f56bf3fb9fcommit-bot@chromium.org                                                left, top, width, height,
12573f80dd5f01a194d4fd9ce502734bc9f56bf3fb9fcommit-bot@chromium.org                                                config, buffer, rowBytes,
12583f80dd5f01a194d4fd9ce502734bc9f56bf3fb9fcommit-bot@chromium.org                                                flags);
12593f80dd5f01a194d4fd9ce502734bc9f56bf3fb9fcommit-bot@chromium.org        }
1260583b18a20959c9ac360316a366f4ddd9598bdf52skia.committer@gmail.com
1261669fdc4ed8ed461a141cb97d0afdd9ef72a82be1bsalomon@google.com        return false;
1262669fdc4ed8ed461a141cb97d0afdd9ef72a82be1bsalomon@google.com    }
1263669fdc4ed8ed461a141cb97d0afdd9ef72a82be1bsalomon@google.com}
1264669fdc4ed8ed461a141cb97d0afdd9ef72a82be1bsalomon@google.com
1265a91e923874ca0565b4f4816b5697dfdcd337b889bsalomon@google.com#include "SkConfig8888.h"
1266a91e923874ca0565b4f4816b5697dfdcd337b889bsalomon@google.com
1267a91e923874ca0565b4f4816b5697dfdcd337b889bsalomon@google.comnamespace {
1268a91e923874ca0565b4f4816b5697dfdcd337b889bsalomon@google.com/**
1269a91e923874ca0565b4f4816b5697dfdcd337b889bsalomon@google.com * Converts a GrPixelConfig to a SkCanvas::Config8888. Only byte-per-channel
1270a91e923874ca0565b4f4816b5697dfdcd337b889bsalomon@google.com * formats are representable as Config8888 and so the function returns false
1271a91e923874ca0565b4f4816b5697dfdcd337b889bsalomon@google.com * if the GrPixelConfig has no equivalent Config8888.
1272a91e923874ca0565b4f4816b5697dfdcd337b889bsalomon@google.com */
1273a91e923874ca0565b4f4816b5697dfdcd337b889bsalomon@google.combool grconfig_to_config8888(GrPixelConfig config,
12740342a85091fd430c90a142d155dc9642aa729d9ebsalomon@google.com                            bool unpremul,
1275a91e923874ca0565b4f4816b5697dfdcd337b889bsalomon@google.com                            SkCanvas::Config8888* config8888) {
1276a91e923874ca0565b4f4816b5697dfdcd337b889bsalomon@google.com    switch (config) {
12770342a85091fd430c90a142d155dc9642aa729d9ebsalomon@google.com        case kRGBA_8888_GrPixelConfig:
12780342a85091fd430c90a142d155dc9642aa729d9ebsalomon@google.com            if (unpremul) {
12790342a85091fd430c90a142d155dc9642aa729d9ebsalomon@google.com                *config8888 = SkCanvas::kRGBA_Unpremul_Config8888;
12800342a85091fd430c90a142d155dc9642aa729d9ebsalomon@google.com            } else {
12810342a85091fd430c90a142d155dc9642aa729d9ebsalomon@google.com                *config8888 = SkCanvas::kRGBA_Premul_Config8888;
12820342a85091fd430c90a142d155dc9642aa729d9ebsalomon@google.com            }
1283a91e923874ca0565b4f4816b5697dfdcd337b889bsalomon@google.com            return true;
12840342a85091fd430c90a142d155dc9642aa729d9ebsalomon@google.com        case kBGRA_8888_GrPixelConfig:
12850342a85091fd430c90a142d155dc9642aa729d9ebsalomon@google.com            if (unpremul) {
12860342a85091fd430c90a142d155dc9642aa729d9ebsalomon@google.com                *config8888 = SkCanvas::kBGRA_Unpremul_Config8888;
12870342a85091fd430c90a142d155dc9642aa729d9ebsalomon@google.com            } else {
12880342a85091fd430c90a142d155dc9642aa729d9ebsalomon@google.com                *config8888 = SkCanvas::kBGRA_Premul_Config8888;
12890342a85091fd430c90a142d155dc9642aa729d9ebsalomon@google.com            }
1290a91e923874ca0565b4f4816b5697dfdcd337b889bsalomon@google.com            return true;
1291a91e923874ca0565b4f4816b5697dfdcd337b889bsalomon@google.com        default:
1292a91e923874ca0565b4f4816b5697dfdcd337b889bsalomon@google.com            return false;
1293a91e923874ca0565b4f4816b5697dfdcd337b889bsalomon@google.com    }
1294a91e923874ca0565b4f4816b5697dfdcd337b889bsalomon@google.com}
1295a04e8e842450e606dd938ddae17857849bd504d4bsalomon@google.com
1296a04e8e842450e606dd938ddae17857849bd504d4bsalomon@google.com// It returns a configuration with where the byte position of the R & B components are swapped in
1297a04e8e842450e606dd938ddae17857849bd504d4bsalomon@google.com// relation to the input config. This should only be called with the result of
1298a04e8e842450e606dd938ddae17857849bd504d4bsalomon@google.com// grconfig_to_config8888 as it will fail for other configs.
1299a04e8e842450e606dd938ddae17857849bd504d4bsalomon@google.comSkCanvas::Config8888 swap_config8888_red_and_blue(SkCanvas::Config8888 config8888) {
1300a04e8e842450e606dd938ddae17857849bd504d4bsalomon@google.com    switch (config8888) {
1301a04e8e842450e606dd938ddae17857849bd504d4bsalomon@google.com        case SkCanvas::kBGRA_Premul_Config8888:
1302a04e8e842450e606dd938ddae17857849bd504d4bsalomon@google.com            return SkCanvas::kRGBA_Premul_Config8888;
1303a04e8e842450e606dd938ddae17857849bd504d4bsalomon@google.com        case SkCanvas::kBGRA_Unpremul_Config8888:
1304a04e8e842450e606dd938ddae17857849bd504d4bsalomon@google.com            return SkCanvas::kRGBA_Unpremul_Config8888;
1305a04e8e842450e606dd938ddae17857849bd504d4bsalomon@google.com        case SkCanvas::kRGBA_Premul_Config8888:
1306a04e8e842450e606dd938ddae17857849bd504d4bsalomon@google.com            return SkCanvas::kBGRA_Premul_Config8888;
1307a04e8e842450e606dd938ddae17857849bd504d4bsalomon@google.com        case SkCanvas::kRGBA_Unpremul_Config8888:
1308a04e8e842450e606dd938ddae17857849bd504d4bsalomon@google.com            return SkCanvas::kBGRA_Unpremul_Config8888;
1309a04e8e842450e606dd938ddae17857849bd504d4bsalomon@google.com        default:
1310a04e8e842450e606dd938ddae17857849bd504d4bsalomon@google.com            GrCrash("Unexpected input");
1311a04e8e842450e606dd938ddae17857849bd504d4bsalomon@google.com            return SkCanvas::kBGRA_Unpremul_Config8888;;
1312a04e8e842450e606dd938ddae17857849bd504d4bsalomon@google.com    }
1313a04e8e842450e606dd938ddae17857849bd504d4bsalomon@google.com}
1314a91e923874ca0565b4f4816b5697dfdcd337b889bsalomon@google.com}
1315a91e923874ca0565b4f4816b5697dfdcd337b889bsalomon@google.com
13160342a85091fd430c90a142d155dc9642aa729d9ebsalomon@google.combool GrContext::readRenderTargetPixels(GrRenderTarget* target,
13170342a85091fd430c90a142d155dc9642aa729d9ebsalomon@google.com                                       int left, int top, int width, int height,
13189c68058b679aee81e6e0158e7fcbfb5d8479c91absalomon@google.com                                       GrPixelConfig dstConfig, void* buffer, size_t rowBytes,
13190342a85091fd430c90a142d155dc9642aa729d9ebsalomon@google.com                                       uint32_t flags) {
1320278cbb452a260de1550769b168df448e0911cf3ctomhudson@google.com    SK_TRACE_EVENT0("GrContext::readRenderTargetPixels");
1321bc4b654af85fa67bdd9cc1b88747b8c394a00e27bsalomon@google.com    ASSERT_OWNED_RESOURCE(target);
1322bc4b654af85fa67bdd9cc1b88747b8c394a00e27bsalomon@google.com
1323fbfcd5602128ec010c82cb733c9cdc0a3254f9f3rmistry@google.com    if (NULL == target) {
1324bb6a3178c3e79c8549b332e4ce84c64b59964f1ecommit-bot@chromium.org        target = fRenderTarget.get();
1325c43649962221c348d656d425a3fa9b29c78231d4bsalomon@google.com        if (NULL == target) {
1326c43649962221c348d656d425a3fa9b29c78231d4bsalomon@google.com            return false;
1327c43649962221c348d656d425a3fa9b29c78231d4bsalomon@google.com        }
1328c43649962221c348d656d425a3fa9b29c78231d4bsalomon@google.com    }
1329669fdc4ed8ed461a141cb97d0afdd9ef72a82be1bsalomon@google.com
13306f3795105b2b458079e53a721c1735c9518f6bb5bsalomon@google.com    if (!(kDontFlush_PixelOpsFlag & flags)) {
13316f3795105b2b458079e53a721c1735c9518f6bb5bsalomon@google.com        this->flush();
13326f3795105b2b458079e53a721c1735c9518f6bb5bsalomon@google.com    }
1333c43649962221c348d656d425a3fa9b29c78231d4bsalomon@google.com
1334a04e8e842450e606dd938ddae17857849bd504d4bsalomon@google.com    // Determine which conversions have to be applied: flipY, swapRAnd, and/or unpremul.
1335c43649962221c348d656d425a3fa9b29c78231d4bsalomon@google.com
1336a04e8e842450e606dd938ddae17857849bd504d4bsalomon@google.com    // If fGpu->readPixels would incur a y-flip cost then we will read the pixels upside down. We'll
1337a04e8e842450e606dd938ddae17857849bd504d4bsalomon@google.com    // either do the flipY by drawing into a scratch with a matrix or on the cpu after the read.
1338a04e8e842450e606dd938ddae17857849bd504d4bsalomon@google.com    bool flipY = fGpu->readPixelsWillPayForYFlip(target, left, top,
13399c68058b679aee81e6e0158e7fcbfb5d8479c91absalomon@google.com                                                 width, height, dstConfig,
1340c43649962221c348d656d425a3fa9b29c78231d4bsalomon@google.com                                                 rowBytes);
13419c68058b679aee81e6e0158e7fcbfb5d8479c91absalomon@google.com    // We ignore the preferred config if it is different than our config unless it is an R/B swap.
13429c68058b679aee81e6e0158e7fcbfb5d8479c91absalomon@google.com    // In that case we'll perform an R and B swap while drawing to a scratch texture of the swapped
13439c68058b679aee81e6e0158e7fcbfb5d8479c91absalomon@google.com    // config. Then we will call readPixels on the scratch with the swapped config. The swaps during
13449c68058b679aee81e6e0158e7fcbfb5d8479c91absalomon@google.com    // the draw cancels out the fact that we call readPixels with a config that is R/B swapped from
13459c68058b679aee81e6e0158e7fcbfb5d8479c91absalomon@google.com    // dstConfig.
13469c68058b679aee81e6e0158e7fcbfb5d8479c91absalomon@google.com    GrPixelConfig readConfig = dstConfig;
13479c68058b679aee81e6e0158e7fcbfb5d8479c91absalomon@google.com    bool swapRAndB = false;
13485d1d79a1f9d351e6f2390d844e6a7361d7d607cacommit-bot@chromium.org    if (GrPixelConfigSwapRAndB(dstConfig) ==
13495d1d79a1f9d351e6f2390d844e6a7361d7d607cacommit-bot@chromium.org        fGpu->preferredReadPixelsConfig(dstConfig, target->config())) {
13509c68058b679aee81e6e0158e7fcbfb5d8479c91absalomon@google.com        readConfig = GrPixelConfigSwapRAndB(readConfig);
13519c68058b679aee81e6e0158e7fcbfb5d8479c91absalomon@google.com        swapRAndB = true;
13529c68058b679aee81e6e0158e7fcbfb5d8479c91absalomon@google.com    }
1353a04e8e842450e606dd938ddae17857849bd504d4bsalomon@google.com
13540342a85091fd430c90a142d155dc9642aa729d9ebsalomon@google.com    bool unpremul = SkToBool(kUnpremul_PixelOpsFlag & flags);
1355c43649962221c348d656d425a3fa9b29c78231d4bsalomon@google.com
13569c68058b679aee81e6e0158e7fcbfb5d8479c91absalomon@google.com    if (unpremul && !GrPixelConfigIs8888(dstConfig)) {
1357a04e8e842450e606dd938ddae17857849bd504d4bsalomon@google.com        // The unpremul flag is only allowed for these two configs.
13580a97be216df494291fe929b79d438809af7e9c83bsalomon@google.com        return false;
13590a97be216df494291fe929b79d438809af7e9c83bsalomon@google.com    }
1360a04e8e842450e606dd938ddae17857849bd504d4bsalomon@google.com
1361a04e8e842450e606dd938ddae17857849bd504d4bsalomon@google.com    // If the src is a texture and we would have to do conversions after read pixels, we instead
1362a04e8e842450e606dd938ddae17857849bd504d4bsalomon@google.com    // do the conversions by drawing the src to a scratch texture. If we handle any of the
1363a04e8e842450e606dd938ddae17857849bd504d4bsalomon@google.com    // conversions in the draw we set the corresponding bool to false so that we don't reapply it
1364a04e8e842450e606dd938ddae17857849bd504d4bsalomon@google.com    // on the read back pixels.
1365a04e8e842450e606dd938ddae17857849bd504d4bsalomon@google.com    GrTexture* src = target->asTexture();
1366c4ff22a2965616629765b8ffe0e58f6d05f92fa3bsalomon@google.com    GrAutoScratchTexture ast;
1367a04e8e842450e606dd938ddae17857849bd504d4bsalomon@google.com    if (NULL != src && (swapRAndB || unpremul || flipY)) {
1368a04e8e842450e606dd938ddae17857849bd504d4bsalomon@google.com        // Make the scratch a render target because we don't have a robust readTexturePixels as of
1369a04e8e842450e606dd938ddae17857849bd504d4bsalomon@google.com        // yet. It calls this function.
137075b3c9633cb9a594dab0ccf51dab1e694c149a18robertphillips@google.com        GrTextureDesc desc;
137175b3c9633cb9a594dab0ccf51dab1e694c149a18robertphillips@google.com        desc.fFlags = kRenderTarget_GrTextureFlagBit;
137275b3c9633cb9a594dab0ccf51dab1e694c149a18robertphillips@google.com        desc.fWidth = width;
137375b3c9633cb9a594dab0ccf51dab1e694c149a18robertphillips@google.com        desc.fHeight = height;
1374a04e8e842450e606dd938ddae17857849bd504d4bsalomon@google.com        desc.fConfig = readConfig;
13753cb406bb88f5aa09cf9f5a9554b4b1314cf1a2eesenorblanco@chromium.org        desc.fOrigin = kTopLeft_GrSurfaceOrigin;
1376c4ff22a2965616629765b8ffe0e58f6d05f92fa3bsalomon@google.com
13779c68058b679aee81e6e0158e7fcbfb5d8479c91absalomon@google.com        // When a full read back is faster than a partial we could always make the scratch exactly
1378a04e8e842450e606dd938ddae17857849bd504d4bsalomon@google.com        // match the passed rect. However, if we see many different size rectangles we will trash
1379a04e8e842450e606dd938ddae17857849bd504d4bsalomon@google.com        // our texture cache and pay the cost of creating and destroying many textures. So, we only
1380a04e8e842450e606dd938ddae17857849bd504d4bsalomon@google.com        // request an exact match when the caller is reading an entire RT.
138156d11e097b1975371d0e0b1452ac0c4d5fc46930bsalomon@google.com        ScratchTexMatch match = kApprox_ScratchTexMatch;
138256d11e097b1975371d0e0b1452ac0c4d5fc46930bsalomon@google.com        if (0 == left &&
138356d11e097b1975371d0e0b1452ac0c4d5fc46930bsalomon@google.com            0 == top &&
138456d11e097b1975371d0e0b1452ac0c4d5fc46930bsalomon@google.com            target->width() == width &&
138556d11e097b1975371d0e0b1452ac0c4d5fc46930bsalomon@google.com            target->height() == height &&
138656d11e097b1975371d0e0b1452ac0c4d5fc46930bsalomon@google.com            fGpu->fullReadPixelsIsFasterThanPartial()) {
138756d11e097b1975371d0e0b1452ac0c4d5fc46930bsalomon@google.com            match = kExact_ScratchTexMatch;
138856d11e097b1975371d0e0b1452ac0c4d5fc46930bsalomon@google.com        }
138956d11e097b1975371d0e0b1452ac0c4d5fc46930bsalomon@google.com        ast.set(this, desc, match);
1390c43649962221c348d656d425a3fa9b29c78231d4bsalomon@google.com        GrTexture* texture = ast.texture();
1391a04e8e842450e606dd938ddae17857849bd504d4bsalomon@google.com        if (texture) {
1392d8b5faca043100d7a1e4594b4d10e462532af390bsalomon@google.com            // compute a matrix to perform the draw
1393b9086a026844e4cfd08b219e49ce3f12294cba98bsalomon@google.com            SkMatrix textureMatrix;
13943cb406bb88f5aa09cf9f5a9554b4b1314cf1a2eesenorblanco@chromium.org            textureMatrix.setTranslate(SK_Scalar1 *left, SK_Scalar1 *top);
1395d8b5faca043100d7a1e4594b4d10e462532af390bsalomon@google.com            textureMatrix.postIDiv(src->width(), src->height());
1396d8b5faca043100d7a1e4594b4d10e462532af390bsalomon@google.com
1397adc6536fe5baff2216fb76ecda6cc81c61109d5cbsalomon@google.com            SkAutoTUnref<const GrEffectRef> effect;
1398a04e8e842450e606dd938ddae17857849bd504d4bsalomon@google.com            if (unpremul) {
1399adc6536fe5baff2216fb76ecda6cc81c61109d5cbsalomon@google.com                effect.reset(this->createPMToUPMEffect(src, swapRAndB, textureMatrix));
1400adc6536fe5baff2216fb76ecda6cc81c61109d5cbsalomon@google.com                if (NULL != effect) {
14019c68058b679aee81e6e0158e7fcbfb5d8479c91absalomon@google.com                    unpremul = false; // we no longer need to do this on CPU after the read back.
1402d8b5faca043100d7a1e4594b4d10e462532af390bsalomon@google.com                }
1403a04e8e842450e606dd938ddae17857849bd504d4bsalomon@google.com            }
1404a04e8e842450e606dd938ddae17857849bd504d4bsalomon@google.com            // If we failed to create a PM->UPM effect and have no other conversions to perform then
1405a04e8e842450e606dd938ddae17857849bd504d4bsalomon@google.com            // there is no longer any point to using the scratch.
1406adc6536fe5baff2216fb76ecda6cc81c61109d5cbsalomon@google.com            if (NULL != effect || flipY || swapRAndB) {
1407adc6536fe5baff2216fb76ecda6cc81c61109d5cbsalomon@google.com                if (!effect) {
1408adc6536fe5baff2216fb76ecda6cc81c61109d5cbsalomon@google.com                    effect.reset(GrConfigConversionEffect::Create(
1409adc6536fe5baff2216fb76ecda6cc81c61109d5cbsalomon@google.com                                                    src,
1410adc6536fe5baff2216fb76ecda6cc81c61109d5cbsalomon@google.com                                                    swapRAndB,
1411adc6536fe5baff2216fb76ecda6cc81c61109d5cbsalomon@google.com                                                    GrConfigConversionEffect::kNone_PMConversion,
1412adc6536fe5baff2216fb76ecda6cc81c61109d5cbsalomon@google.com                                                    textureMatrix));
1413a04e8e842450e606dd938ddae17857849bd504d4bsalomon@google.com                }
1414a04e8e842450e606dd938ddae17857849bd504d4bsalomon@google.com                swapRAndB = false; // we will handle the swap in the draw.
1415a04e8e842450e606dd938ddae17857849bd504d4bsalomon@google.com
141613f181f28f4336adcc93b7297b6d16503f4c323crobertphillips@google.com                // We protect the existing geometry here since it may not be
141713f181f28f4336adcc93b7297b6d16503f4c323crobertphillips@google.com                // clear to the caller that a draw operation (i.e., drawSimpleRect)
141813f181f28f4336adcc93b7297b6d16503f4c323crobertphillips@google.com                // can be invoked in this method
141913f181f28f4336adcc93b7297b6d16503f4c323crobertphillips@google.com                GrDrawTarget::AutoGeometryAndStatePush agasp(fGpu, GrDrawTarget::kReset_ASRInit);
1420a04e8e842450e606dd938ddae17857849bd504d4bsalomon@google.com                GrDrawState* drawState = fGpu->drawState();
1421f6de475e5cbd143f348ff7738919e397b7fe7f57tfarina@chromium.org                SkASSERT(effect);
1422eb6879f50a5564eeb981ec5616b55bf685eb76fcbsalomon@google.com                drawState->addColorEffect(effect);
1423d8b5faca043100d7a1e4594b4d10e462532af390bsalomon@google.com
1424a04e8e842450e606dd938ddae17857849bd504d4bsalomon@google.com                drawState->setRenderTarget(texture->asRenderTarget());
1425fd03d4a829efe2d77a712fd991927c55f59a2ffecommit-bot@chromium.org                SkRect rect = SkRect::MakeWH(SkIntToScalar(width), SkIntToScalar(height));
1426a04e8e842450e606dd938ddae17857849bd504d4bsalomon@google.com                fGpu->drawSimpleRect(rect, NULL);
1427a04e8e842450e606dd938ddae17857849bd504d4bsalomon@google.com                // we want to read back from the scratch's origin
1428a04e8e842450e606dd938ddae17857849bd504d4bsalomon@google.com                left = 0;
1429a04e8e842450e606dd938ddae17857849bd504d4bsalomon@google.com                top = 0;
1430a04e8e842450e606dd938ddae17857849bd504d4bsalomon@google.com                target = texture->asRenderTarget();
1431a04e8e842450e606dd938ddae17857849bd504d4bsalomon@google.com            }
1432c43649962221c348d656d425a3fa9b29c78231d4bsalomon@google.com        }
1433a04e8e842450e606dd938ddae17857849bd504d4bsalomon@google.com    }
1434a04e8e842450e606dd938ddae17857849bd504d4bsalomon@google.com    if (!fGpu->readPixels(target,
1435a04e8e842450e606dd938ddae17857849bd504d4bsalomon@google.com                          left, top, width, height,
14363cb406bb88f5aa09cf9f5a9554b4b1314cf1a2eesenorblanco@chromium.org                          readConfig, buffer, rowBytes)) {
1437a04e8e842450e606dd938ddae17857849bd504d4bsalomon@google.com        return false;
1438a04e8e842450e606dd938ddae17857849bd504d4bsalomon@google.com    }
1439d8b5faca043100d7a1e4594b4d10e462532af390bsalomon@google.com    // Perform any conversions we weren't able to perform using a scratch texture.
14403cb406bb88f5aa09cf9f5a9554b4b1314cf1a2eesenorblanco@chromium.org    if (unpremul || swapRAndB) {
1441ccaa002dd81a6a8bd5acb7a2fa69a2437873c1fdbsalomon@google.com        // These are initialized to suppress a warning
1442ccaa002dd81a6a8bd5acb7a2fa69a2437873c1fdbsalomon@google.com        SkCanvas::Config8888 srcC8888 = SkCanvas::kNative_Premul_Config8888;
1443ccaa002dd81a6a8bd5acb7a2fa69a2437873c1fdbsalomon@google.com        SkCanvas::Config8888 dstC8888 = SkCanvas::kNative_Premul_Config8888;
1444ccaa002dd81a6a8bd5acb7a2fa69a2437873c1fdbsalomon@google.com
14459c68058b679aee81e6e0158e7fcbfb5d8479c91absalomon@google.com        SkDEBUGCODE(bool c8888IsValid =) grconfig_to_config8888(dstConfig, false, &srcC8888);
14469c68058b679aee81e6e0158e7fcbfb5d8479c91absalomon@google.com        grconfig_to_config8888(dstConfig, unpremul, &dstC8888);
1447ccaa002dd81a6a8bd5acb7a2fa69a2437873c1fdbsalomon@google.com
1448a04e8e842450e606dd938ddae17857849bd504d4bsalomon@google.com        if (swapRAndB) {
1449f6de475e5cbd143f348ff7738919e397b7fe7f57tfarina@chromium.org            SkASSERT(c8888IsValid); // we should only do r/b swap on 8888 configs
1450a04e8e842450e606dd938ddae17857849bd504d4bsalomon@google.com            srcC8888 = swap_config8888_red_and_blue(srcC8888);
14510342a85091fd430c90a142d155dc9642aa729d9ebsalomon@google.com        }
1452f6de475e5cbd143f348ff7738919e397b7fe7f57tfarina@chromium.org        SkASSERT(c8888IsValid);
14533cb406bb88f5aa09cf9f5a9554b4b1314cf1a2eesenorblanco@chromium.org        uint32_t* b32 = reinterpret_cast<uint32_t*>(buffer);
14543cb406bb88f5aa09cf9f5a9554b4b1314cf1a2eesenorblanco@chromium.org        SkConvertConfig8888Pixels(b32, rowBytes, dstC8888,
14553cb406bb88f5aa09cf9f5a9554b4b1314cf1a2eesenorblanco@chromium.org                                  b32, rowBytes, srcC8888,
14563cb406bb88f5aa09cf9f5a9554b4b1314cf1a2eesenorblanco@chromium.org                                  width, height);
1457c43649962221c348d656d425a3fa9b29c78231d4bsalomon@google.com    }
1458a04e8e842450e606dd938ddae17857849bd504d4bsalomon@google.com    return true;
145927847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com}
146027847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com
146175f9f25d8bf2adc0494f9afbbd5965809ee13acabsalomon@google.comvoid GrContext::resolveRenderTarget(GrRenderTarget* target) {
1462f6de475e5cbd143f348ff7738919e397b7fe7f57tfarina@chromium.org    SkASSERT(target);
146375f9f25d8bf2adc0494f9afbbd5965809ee13acabsalomon@google.com    ASSERT_OWNED_RESOURCE(target);
146475f9f25d8bf2adc0494f9afbbd5965809ee13acabsalomon@google.com    // In the future we may track whether there are any pending draws to this
146575f9f25d8bf2adc0494f9afbbd5965809ee13acabsalomon@google.com    // target. We don't today so we always perform a flush. We don't promise
146675f9f25d8bf2adc0494f9afbbd5965809ee13acabsalomon@google.com    // this to our clients, though.
146775f9f25d8bf2adc0494f9afbbd5965809ee13acabsalomon@google.com    this->flush();
146875f9f25d8bf2adc0494f9afbbd5965809ee13acabsalomon@google.com    fGpu->resolveRenderTarget(target);
146975f9f25d8bf2adc0494f9afbbd5965809ee13acabsalomon@google.com}
147075f9f25d8bf2adc0494f9afbbd5965809ee13acabsalomon@google.com
1471a2a31928470dfb642880f6ab2e4d34b1c7f5d476scroggo@google.comvoid GrContext::copyTexture(GrTexture* src, GrRenderTarget* dst, const SkIPoint* topLeft) {
1472ef843cdcd1be858fe55cc99ff134ffbd080c9a51senorblanco@chromium.org    if (NULL == src || NULL == dst) {
1473ef843cdcd1be858fe55cc99ff134ffbd080c9a51senorblanco@chromium.org        return;
1474ef843cdcd1be858fe55cc99ff134ffbd080c9a51senorblanco@chromium.org    }
1475ef843cdcd1be858fe55cc99ff134ffbd080c9a51senorblanco@chromium.org    ASSERT_OWNED_RESOURCE(src);
1476ef843cdcd1be858fe55cc99ff134ffbd080c9a51senorblanco@chromium.org
14771ac87ff5aaff284b337652cf3ac0b41bd56fb781twiz@google.com    // Writes pending to the source texture are not tracked, so a flush
14781ac87ff5aaff284b337652cf3ac0b41bd56fb781twiz@google.com    // is required to ensure that the copy captures the most recent contents
1479adc6536fe5baff2216fb76ecda6cc81c61109d5cbsalomon@google.com    // of the source texture. See similar behavior in
14801ac87ff5aaff284b337652cf3ac0b41bd56fb781twiz@google.com    // GrContext::resolveRenderTarget.
14811ac87ff5aaff284b337652cf3ac0b41bd56fb781twiz@google.com    this->flush();
14821ac87ff5aaff284b337652cf3ac0b41bd56fb781twiz@google.com
1483873ea0c93f202600ec2591bc1e2e5d7a1e05f59dbsalomon@google.com    GrDrawTarget::AutoStateRestore asr(fGpu, GrDrawTarget::kReset_ASRInit);
14848f9cbd62ec108d410b91155dcf6a4789c641246fbsalomon@google.com    GrDrawState* drawState = fGpu->drawState();
14858f9cbd62ec108d410b91155dcf6a4789c641246fbsalomon@google.com    drawState->setRenderTarget(dst);
1486b9086a026844e4cfd08b219e49ce3f12294cba98bsalomon@google.com    SkMatrix sampleM;
1487ef843cdcd1be858fe55cc99ff134ffbd080c9a51senorblanco@chromium.org    sampleM.setIDiv(src->width(), src->height());
1488a2a31928470dfb642880f6ab2e4d34b1c7f5d476scroggo@google.com    SkIRect srcRect = SkIRect::MakeWH(dst->width(), dst->height());
1489a2a31928470dfb642880f6ab2e4d34b1c7f5d476scroggo@google.com    if (NULL != topLeft) {
1490a2a31928470dfb642880f6ab2e4d34b1c7f5d476scroggo@google.com        srcRect.offset(*topLeft);
1491a2a31928470dfb642880f6ab2e4d34b1c7f5d476scroggo@google.com    }
1492a2a31928470dfb642880f6ab2e4d34b1c7f5d476scroggo@google.com    SkIRect srcBounds = SkIRect::MakeWH(src->width(), src->height());
1493a2a31928470dfb642880f6ab2e4d34b1c7f5d476scroggo@google.com    if (!srcRect.intersect(srcBounds)) {
1494a2a31928470dfb642880f6ab2e4d34b1c7f5d476scroggo@google.com        return;
1495a2a31928470dfb642880f6ab2e4d34b1c7f5d476scroggo@google.com    }
1496a2a31928470dfb642880f6ab2e4d34b1c7f5d476scroggo@google.com    sampleM.preTranslate(SkIntToScalar(srcRect.fLeft), SkIntToScalar(srcRect.fTop));
1497eb6879f50a5564eeb981ec5616b55bf685eb76fcbsalomon@google.com    drawState->addColorTextureEffect(src, sampleM);
1498a2a31928470dfb642880f6ab2e4d34b1c7f5d476scroggo@google.com    SkRect dstR = SkRect::MakeWH(SkIntToScalar(srcRect.width()), SkIntToScalar(srcRect.height()));
1499a2a31928470dfb642880f6ab2e4d34b1c7f5d476scroggo@google.com    fGpu->drawSimpleRect(dstR, NULL);
1500ef843cdcd1be858fe55cc99ff134ffbd080c9a51senorblanco@chromium.org}
1501ef843cdcd1be858fe55cc99ff134ffbd080c9a51senorblanco@chromium.org
15029c68058b679aee81e6e0158e7fcbfb5d8479c91absalomon@google.combool GrContext::writeRenderTargetPixels(GrRenderTarget* target,
15030342a85091fd430c90a142d155dc9642aa729d9ebsalomon@google.com                                        int left, int top, int width, int height,
15049c68058b679aee81e6e0158e7fcbfb5d8479c91absalomon@google.com                                        GrPixelConfig srcConfig,
15050342a85091fd430c90a142d155dc9642aa729d9ebsalomon@google.com                                        const void* buffer,
15060342a85091fd430c90a142d155dc9642aa729d9ebsalomon@google.com                                        size_t rowBytes,
15070342a85091fd430c90a142d155dc9642aa729d9ebsalomon@google.com                                        uint32_t flags) {
15086f3795105b2b458079e53a721c1735c9518f6bb5bsalomon@google.com    SK_TRACE_EVENT0("GrContext::writeRenderTargetPixels");
1509bc4b654af85fa67bdd9cc1b88747b8c394a00e27bsalomon@google.com    ASSERT_OWNED_RESOURCE(target);
15106f3795105b2b458079e53a721c1735c9518f6bb5bsalomon@google.com
1511fbfcd5602128ec010c82cb733c9cdc0a3254f9f3rmistry@google.com    if (NULL == target) {
1512bb6a3178c3e79c8549b332e4ce84c64b59964f1ecommit-bot@chromium.org        target = fRenderTarget.get();
15136f3795105b2b458079e53a721c1735c9518f6bb5bsalomon@google.com        if (NULL == target) {
15149c68058b679aee81e6e0158e7fcbfb5d8479c91absalomon@google.com            return false;
15156f3795105b2b458079e53a721c1735c9518f6bb5bsalomon@google.com        }
15166f3795105b2b458079e53a721c1735c9518f6bb5bsalomon@google.com    }
151727847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com
1518a04e8e842450e606dd938ddae17857849bd504d4bsalomon@google.com    // TODO: when underlying api has a direct way to do this we should use it (e.g. glDrawPixels on
1519a04e8e842450e606dd938ddae17857849bd504d4bsalomon@google.com    // desktop GL).
1520a04e8e842450e606dd938ddae17857849bd504d4bsalomon@google.com
1521a04e8e842450e606dd938ddae17857849bd504d4bsalomon@google.com    // We will always call some form of writeTexturePixels and we will pass our flags on to it.
1522a04e8e842450e606dd938ddae17857849bd504d4bsalomon@google.com    // Thus, we don't perform a flush here since that call will do it (if the kNoFlush flag isn't
1523a04e8e842450e606dd938ddae17857849bd504d4bsalomon@google.com    // set.)
152427847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com
15250342a85091fd430c90a142d155dc9642aa729d9ebsalomon@google.com    // If the RT is also a texture and we don't have to premultiply then take the texture path.
15260342a85091fd430c90a142d155dc9642aa729d9ebsalomon@google.com    // We expect to be at least as fast or faster since it doesn't use an intermediate texture as
15270342a85091fd430c90a142d155dc9642aa729d9ebsalomon@google.com    // we do below.
1528fbfcd5602128ec010c82cb733c9cdc0a3254f9f3rmistry@google.com
15294382330a15e13b9ef54010606eb758c0c66e1868commit-bot@chromium.org#if !defined(SK_BUILD_FOR_MAC)
1530a04e8e842450e606dd938ddae17857849bd504d4bsalomon@google.com    // At least some drivers on the Mac get confused when glTexImage2D is called on a texture
1531a04e8e842450e606dd938ddae17857849bd504d4bsalomon@google.com    // attached to an FBO. The FBO still sees the old image. TODO: determine what OS versions and/or
1532a04e8e842450e606dd938ddae17857849bd504d4bsalomon@google.com    // HW is affected.
15339c68058b679aee81e6e0158e7fcbfb5d8479c91absalomon@google.com    if (NULL != target->asTexture() && !(kUnpremul_PixelOpsFlag & flags) &&
15349c68058b679aee81e6e0158e7fcbfb5d8479c91absalomon@google.com        fGpu->canWriteTexturePixels(target->asTexture(), srcConfig)) {
15359c68058b679aee81e6e0158e7fcbfb5d8479c91absalomon@google.com        return this->writeTexturePixels(target->asTexture(),
15369c68058b679aee81e6e0158e7fcbfb5d8479c91absalomon@google.com                                        left, top, width, height,
15379c68058b679aee81e6e0158e7fcbfb5d8479c91absalomon@google.com                                        srcConfig, buffer, rowBytes, flags);
1538a85449dac125b8985010df7c057e9e6201d55112bsalomon@google.com    }
1539a85449dac125b8985010df7c057e9e6201d55112bsalomon@google.com#endif
1540d8b5faca043100d7a1e4594b4d10e462532af390bsalomon@google.com
15419c68058b679aee81e6e0158e7fcbfb5d8479c91absalomon@google.com    // We ignore the preferred config unless it is a R/B swap of the src config. In that case
15429c68058b679aee81e6e0158e7fcbfb5d8479c91absalomon@google.com    // we will upload the original src data to a scratch texture but we will spoof it as the swapped
15439c68058b679aee81e6e0158e7fcbfb5d8479c91absalomon@google.com    // config. This scratch will then have R and B swapped. We correct for this by swapping again
15449c68058b679aee81e6e0158e7fcbfb5d8479c91absalomon@google.com    // when drawing the scratch to the dst using a conversion effect.
15459c68058b679aee81e6e0158e7fcbfb5d8479c91absalomon@google.com    bool swapRAndB = false;
15469c68058b679aee81e6e0158e7fcbfb5d8479c91absalomon@google.com    GrPixelConfig writeConfig = srcConfig;
15475d1d79a1f9d351e6f2390d844e6a7361d7d607cacommit-bot@chromium.org    if (GrPixelConfigSwapRAndB(srcConfig) ==
15485d1d79a1f9d351e6f2390d844e6a7361d7d607cacommit-bot@chromium.org        fGpu->preferredWritePixelsConfig(srcConfig, target->config())) {
15499c68058b679aee81e6e0158e7fcbfb5d8479c91absalomon@google.com        writeConfig = GrPixelConfigSwapRAndB(srcConfig);
15509c68058b679aee81e6e0158e7fcbfb5d8479c91absalomon@google.com        swapRAndB = true;
1551a85449dac125b8985010df7c057e9e6201d55112bsalomon@google.com    }
1552a85449dac125b8985010df7c057e9e6201d55112bsalomon@google.com
155375b3c9633cb9a594dab0ccf51dab1e694c149a18robertphillips@google.com    GrTextureDesc desc;
155475b3c9633cb9a594dab0ccf51dab1e694c149a18robertphillips@google.com    desc.fWidth = width;
155575b3c9633cb9a594dab0ccf51dab1e694c149a18robertphillips@google.com    desc.fHeight = height;
15569c68058b679aee81e6e0158e7fcbfb5d8479c91absalomon@google.com    desc.fConfig = writeConfig;
155750398bf7f1953e640e5529616e710cf540799731bsalomon@google.com    GrAutoScratchTexture ast(this, desc);
155850398bf7f1953e640e5529616e710cf540799731bsalomon@google.com    GrTexture* texture = ast.texture();
155927847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com    if (NULL == texture) {
15609c68058b679aee81e6e0158e7fcbfb5d8479c91absalomon@google.com        return false;
156127847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com    }
1562d8b5faca043100d7a1e4594b4d10e462532af390bsalomon@google.com
1563adc6536fe5baff2216fb76ecda6cc81c61109d5cbsalomon@google.com    SkAutoTUnref<const GrEffectRef> effect;
1564b9086a026844e4cfd08b219e49ce3f12294cba98bsalomon@google.com    SkMatrix textureMatrix;
1565d8b5faca043100d7a1e4594b4d10e462532af390bsalomon@google.com    textureMatrix.setIDiv(texture->width(), texture->height());
1566d8b5faca043100d7a1e4594b4d10e462532af390bsalomon@google.com
1567a04e8e842450e606dd938ddae17857849bd504d4bsalomon@google.com    // allocate a tmp buffer and sw convert the pixels to premul
1568a04e8e842450e606dd938ddae17857849bd504d4bsalomon@google.com    SkAutoSTMalloc<128 * 128, uint32_t> tmpPixels(0);
1569a04e8e842450e606dd938ddae17857849bd504d4bsalomon@google.com
1570a04e8e842450e606dd938ddae17857849bd504d4bsalomon@google.com    if (kUnpremul_PixelOpsFlag & flags) {
15719c68058b679aee81e6e0158e7fcbfb5d8479c91absalomon@google.com        if (!GrPixelConfigIs8888(srcConfig)) {
15729c68058b679aee81e6e0158e7fcbfb5d8479c91absalomon@google.com            return false;
1573a04e8e842450e606dd938ddae17857849bd504d4bsalomon@google.com        }
1574adc6536fe5baff2216fb76ecda6cc81c61109d5cbsalomon@google.com        effect.reset(this->createUPMToPMEffect(texture, swapRAndB, textureMatrix));
15759c68058b679aee81e6e0158e7fcbfb5d8479c91absalomon@google.com        // handle the unpremul step on the CPU if we couldn't create an effect to do it.
1576adc6536fe5baff2216fb76ecda6cc81c61109d5cbsalomon@google.com        if (NULL == effect) {
1577a04e8e842450e606dd938ddae17857849bd504d4bsalomon@google.com            SkCanvas::Config8888 srcConfig8888, dstConfig8888;
15781acc3d7cc28c5631b5300578ab13439bdefd4e33commit-bot@chromium.org            SkDEBUGCODE(bool success = )
15799c68058b679aee81e6e0158e7fcbfb5d8479c91absalomon@google.com            grconfig_to_config8888(srcConfig, true, &srcConfig8888);
1580f6de475e5cbd143f348ff7738919e397b7fe7f57tfarina@chromium.org            SkASSERT(success);
15811acc3d7cc28c5631b5300578ab13439bdefd4e33commit-bot@chromium.org            SkDEBUGCODE(success = )
15829c68058b679aee81e6e0158e7fcbfb5d8479c91absalomon@google.com            grconfig_to_config8888(srcConfig, false, &dstConfig8888);
1583f6de475e5cbd143f348ff7738919e397b7fe7f57tfarina@chromium.org            SkASSERT(success);
1584a04e8e842450e606dd938ddae17857849bd504d4bsalomon@google.com            const uint32_t* src = reinterpret_cast<const uint32_t*>(buffer);
1585a04e8e842450e606dd938ddae17857849bd504d4bsalomon@google.com            tmpPixels.reset(width * height);
1586a04e8e842450e606dd938ddae17857849bd504d4bsalomon@google.com            SkConvertConfig8888Pixels(tmpPixels.get(), 4 * width, dstConfig8888,
1587a04e8e842450e606dd938ddae17857849bd504d4bsalomon@google.com                                      src, rowBytes, srcConfig8888,
1588a04e8e842450e606dd938ddae17857849bd504d4bsalomon@google.com                                      width, height);
1589a04e8e842450e606dd938ddae17857849bd504d4bsalomon@google.com            buffer = tmpPixels.get();
1590a04e8e842450e606dd938ddae17857849bd504d4bsalomon@google.com            rowBytes = 4 * width;
1591a04e8e842450e606dd938ddae17857849bd504d4bsalomon@google.com        }
1592a04e8e842450e606dd938ddae17857849bd504d4bsalomon@google.com    }
1593adc6536fe5baff2216fb76ecda6cc81c61109d5cbsalomon@google.com    if (NULL == effect) {
1594adc6536fe5baff2216fb76ecda6cc81c61109d5cbsalomon@google.com        effect.reset(GrConfigConversionEffect::Create(texture,
1595adc6536fe5baff2216fb76ecda6cc81c61109d5cbsalomon@google.com                                                      swapRAndB,
1596adc6536fe5baff2216fb76ecda6cc81c61109d5cbsalomon@google.com                                                      GrConfigConversionEffect::kNone_PMConversion,
1597adc6536fe5baff2216fb76ecda6cc81c61109d5cbsalomon@google.com                                                      textureMatrix));
1598a04e8e842450e606dd938ddae17857849bd504d4bsalomon@google.com    }
1599a04e8e842450e606dd938ddae17857849bd504d4bsalomon@google.com
16009c68058b679aee81e6e0158e7fcbfb5d8479c91absalomon@google.com    if (!this->writeTexturePixels(texture,
16019c68058b679aee81e6e0158e7fcbfb5d8479c91absalomon@google.com                                  0, 0, width, height,
16029c68058b679aee81e6e0158e7fcbfb5d8479c91absalomon@google.com                                  writeConfig, buffer, rowBytes,
16039c68058b679aee81e6e0158e7fcbfb5d8479c91absalomon@google.com                                  flags & ~kUnpremul_PixelOpsFlag)) {
16049c68058b679aee81e6e0158e7fcbfb5d8479c91absalomon@google.com        return false;
16059c68058b679aee81e6e0158e7fcbfb5d8479c91absalomon@google.com    }
160627847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com
160713f181f28f4336adcc93b7297b6d16503f4c323crobertphillips@google.com    // writeRenderTargetPixels can be called in the midst of drawing another
16080c23faf222c24529781139495a5f4f4ab61f7cb2skia.committer@gmail.com    // object (e.g., when uploading a SW path rendering to the gpu while
160913f181f28f4336adcc93b7297b6d16503f4c323crobertphillips@google.com    // drawing a rect) so preserve the current geometry.
1610137f1347abaf0bb6a945e91c2f6cb49f0ee69bc3bsalomon@google.com    SkMatrix matrix;
1611137f1347abaf0bb6a945e91c2f6cb49f0ee69bc3bsalomon@google.com    matrix.setTranslate(SkIntToScalar(left), SkIntToScalar(top));
1612137f1347abaf0bb6a945e91c2f6cb49f0ee69bc3bsalomon@google.com    GrDrawTarget::AutoGeometryAndStatePush agasp(fGpu, GrDrawTarget::kReset_ASRInit, &matrix);
16138f9cbd62ec108d410b91155dcf6a4789c641246fbsalomon@google.com    GrDrawState* drawState = fGpu->drawState();
1614f6de475e5cbd143f348ff7738919e397b7fe7f57tfarina@chromium.org    SkASSERT(effect);
1615eb6879f50a5564eeb981ec5616b55bf685eb76fcbsalomon@google.com    drawState->addColorEffect(effect);
161627847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com
16178f9cbd62ec108d410b91155dcf6a4789c641246fbsalomon@google.com    drawState->setRenderTarget(target);
161827847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com
1619fd03d4a829efe2d77a712fd991927c55f59a2ffecommit-bot@chromium.org    fGpu->drawSimpleRect(SkRect::MakeWH(SkIntToScalar(width), SkIntToScalar(height)), NULL);
16209c68058b679aee81e6e0158e7fcbfb5d8479c91absalomon@google.com    return true;
162127847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com}
162227847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com////////////////////////////////////////////////////////////////////////////////
162327847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com
1624eb6879f50a5564eeb981ec5616b55bf685eb76fcbsalomon@google.comGrDrawTarget* GrContext::prepareToDraw(const GrPaint* paint,
1625eb6879f50a5564eeb981ec5616b55bf685eb76fcbsalomon@google.com                                       BufferedDraw buffered,
16265dbb149fda134941e5d168790127caf294d322e2commit-bot@chromium.org                                       AutoRestoreEffects* are,
16275dbb149fda134941e5d168790127caf294d322e2commit-bot@chromium.org                                       AutoCheckFlush* acf) {
1628eb6879f50a5564eeb981ec5616b55bf685eb76fcbsalomon@google.com    // All users of this draw state should be freeing up all effects when they're done.
1629eb6879f50a5564eeb981ec5616b55bf685eb76fcbsalomon@google.com    // Otherwise effects that own resources may keep those resources alive indefinitely.
1630f6de475e5cbd143f348ff7738919e397b7fe7f57tfarina@chromium.org    SkASSERT(0 == fDrawState->numColorStages() && 0 == fDrawState->numCoverageStages());
1631eb6879f50a5564eeb981ec5616b55bf685eb76fcbsalomon@google.com
16321d4edd38f6b62d1cc54cb7bc6f3c6ce10ccb1471bsalomon@google.com    if (kNo_BufferedDraw == buffered && kYes_BufferedDraw == fLastDrawWasBuffered) {
16331267fbd95290f58443652ca8d947bde50b212618robertphillips@google.com        fDrawBuffer->flush();
16341d4edd38f6b62d1cc54cb7bc6f3c6ce10ccb1471bsalomon@google.com        fLastDrawWasBuffered = kNo_BufferedDraw;
163527847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com    }
1636bb6a3178c3e79c8549b332e4ce84c64b59964f1ecommit-bot@chromium.org    ASSERT_OWNED_RESOURCE(fRenderTarget.get());
163707ea2db0260d8e6cd2bf605571b68b1c574b5a77bsalomon@google.com    if (NULL != paint) {
1638f6de475e5cbd143f348ff7738919e397b7fe7f57tfarina@chromium.org        SkASSERT(NULL != are);
16395dbb149fda134941e5d168790127caf294d322e2commit-bot@chromium.org        SkASSERT(NULL != acf);
1640eb6879f50a5564eeb981ec5616b55bf685eb76fcbsalomon@google.com        are->set(fDrawState);
1641bb6a3178c3e79c8549b332e4ce84c64b59964f1ecommit-bot@chromium.org        fDrawState->setFromPaint(*paint, fViewMatrix, fRenderTarget.get());
1642af84e748cedbf43e2d0e8d2eac9b7800c8d8ca19bsalomon@google.com#if GR_DEBUG_PARTIAL_COVERAGE_CHECK
1643af84e748cedbf43e2d0e8d2eac9b7800c8d8ca19bsalomon@google.com        if ((paint->hasMask() || 0xff != paint->fCoverage) &&
1644af84e748cedbf43e2d0e8d2eac9b7800c8d8ca19bsalomon@google.com            !fGpu->canApplyCoverage()) {
1645af84e748cedbf43e2d0e8d2eac9b7800c8d8ca19bsalomon@google.com            GrPrintf("Partial pixel coverage will be incorrectly blended.\n");
1646af84e748cedbf43e2d0e8d2eac9b7800c8d8ca19bsalomon@google.com        }
1647af84e748cedbf43e2d0e8d2eac9b7800c8d8ca19bsalomon@google.com#endif
1648bb6a3178c3e79c8549b332e4ce84c64b59964f1ecommit-bot@chromium.org    } else {
1649137f1347abaf0bb6a945e91c2f6cb49f0ee69bc3bsalomon@google.com        fDrawState->reset(fViewMatrix);
1650bb6a3178c3e79c8549b332e4ce84c64b59964f1ecommit-bot@chromium.org        fDrawState->setRenderTarget(fRenderTarget.get());
165107ea2db0260d8e6cd2bf605571b68b1c574b5a77bsalomon@google.com    }
1652bb6a3178c3e79c8549b332e4ce84c64b59964f1ecommit-bot@chromium.org    GrDrawTarget* target;
16531d4edd38f6b62d1cc54cb7bc6f3c6ce10ccb1471bsalomon@google.com    if (kYes_BufferedDraw == buffered) {
16541d4edd38f6b62d1cc54cb7bc6f3c6ce10ccb1471bsalomon@google.com        fLastDrawWasBuffered = kYes_BufferedDraw;
1655bb6a3178c3e79c8549b332e4ce84c64b59964f1ecommit-bot@chromium.org        target = fDrawBuffer;
16561d4edd38f6b62d1cc54cb7bc6f3c6ce10ccb1471bsalomon@google.com    } else {
1657f6de475e5cbd143f348ff7738919e397b7fe7f57tfarina@chromium.org        SkASSERT(kNo_BufferedDraw == buffered);
1658bb6a3178c3e79c8549b332e4ce84c64b59964f1ecommit-bot@chromium.org        fLastDrawWasBuffered = kNo_BufferedDraw;
1659bb6a3178c3e79c8549b332e4ce84c64b59964f1ecommit-bot@chromium.org        target = fGpu;
166027847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com    }
1661bb6a3178c3e79c8549b332e4ce84c64b59964f1ecommit-bot@chromium.org    fDrawState->setState(GrDrawState::kClip_StateBit, NULL != fClip &&
1662bb6a3178c3e79c8549b332e4ce84c64b59964f1ecommit-bot@chromium.org                                                     !fClip->fClipStack->isWideOpen());
1663bb6a3178c3e79c8549b332e4ce84c64b59964f1ecommit-bot@chromium.org    target->setClip(fClip);
1664f6de475e5cbd143f348ff7738919e397b7fe7f57tfarina@chromium.org    SkASSERT(fDrawState == target->drawState());
1665bb6a3178c3e79c8549b332e4ce84c64b59964f1ecommit-bot@chromium.org    return target;
166627847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com}
166727847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com
166872176b2d38db005863a54e3dd6657bbabd068bb6robertphillips@google.com/*
166972176b2d38db005863a54e3dd6657bbabd068bb6robertphillips@google.com * This method finds a path renderer that can draw the specified path on
167072176b2d38db005863a54e3dd6657bbabd068bb6robertphillips@google.com * the provided target.
1671fbfcd5602128ec010c82cb733c9cdc0a3254f9f3rmistry@google.com * Due to its expense, the software path renderer has split out so it can
167272176b2d38db005863a54e3dd6657bbabd068bb6robertphillips@google.com * can be individually allowed/disallowed via the "allowSW" boolean.
167372176b2d38db005863a54e3dd6657bbabd068bb6robertphillips@google.com */
16748d033a1b125886c62906d975b5cc28a382064526bsalomon@google.comGrPathRenderer* GrContext::getPathRenderer(const SkPath& path,
16755f74cf8c49701f514b69dc6f1a8b5c0ffd78af0asugoi@google.com                                           const SkStrokeRec& stroke,
1676c2099d2707abcc94e139627399aed4b8894b69bbbsalomon@google.com                                           const GrDrawTarget* target,
167745a15f551b5b3c6c747d8eaf6466b7d3b76a8faebsalomon@google.com                                           bool allowSW,
167845a15f551b5b3c6c747d8eaf6466b7d3b76a8faebsalomon@google.com                                           GrPathRendererChain::DrawType drawType,
167945a15f551b5b3c6c747d8eaf6466b7d3b76a8faebsalomon@google.com                                           GrPathRendererChain::StencilSupport* stencilSupport) {
168045a15f551b5b3c6c747d8eaf6466b7d3b76a8faebsalomon@google.com
16813008519e9f977cd60194841d558a4f45c28e9833bsalomon@google.com    if (NULL == fPathRendererChain) {
168245a15f551b5b3c6c747d8eaf6466b7d3b76a8faebsalomon@google.com        fPathRendererChain = SkNEW_ARGS(GrPathRendererChain, (this));
16833008519e9f977cd60194841d558a4f45c28e9833bsalomon@google.com    }
168472176b2d38db005863a54e3dd6657bbabd068bb6robertphillips@google.com
168512b4e27ae1a29460e91a59f38122483e1faec697sugoi@google.com    GrPathRenderer* pr = fPathRendererChain->getPathRenderer(path,
168612b4e27ae1a29460e91a59f38122483e1faec697sugoi@google.com                                                             stroke,
168772176b2d38db005863a54e3dd6657bbabd068bb6robertphillips@google.com                                                             target,
168845a15f551b5b3c6c747d8eaf6466b7d3b76a8faebsalomon@google.com                                                             drawType,
168945a15f551b5b3c6c747d8eaf6466b7d3b76a8faebsalomon@google.com                                                             stencilSupport);
169072176b2d38db005863a54e3dd6657bbabd068bb6robertphillips@google.com
169172176b2d38db005863a54e3dd6657bbabd068bb6robertphillips@google.com    if (NULL == pr && allowSW) {
169272176b2d38db005863a54e3dd6657bbabd068bb6robertphillips@google.com        if (NULL == fSoftwarePathRenderer) {
1693c377baf406996aed18d82d328029c82dbc3b8ddatomhudson@google.com            fSoftwarePathRenderer = SkNEW_ARGS(GrSoftwarePathRenderer, (this));
169472176b2d38db005863a54e3dd6657bbabd068bb6robertphillips@google.com        }
169572176b2d38db005863a54e3dd6657bbabd068bb6robertphillips@google.com        pr = fSoftwarePathRenderer;
169672176b2d38db005863a54e3dd6657bbabd068bb6robertphillips@google.com    }
169772176b2d38db005863a54e3dd6657bbabd068bb6robertphillips@google.com
169872176b2d38db005863a54e3dd6657bbabd068bb6robertphillips@google.com    return pr;
16993008519e9f977cd60194841d558a4f45c28e9833bsalomon@google.com}
17003008519e9f977cd60194841d558a4f45c28e9833bsalomon@google.com
170127847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com////////////////////////////////////////////////////////////////////////////////
17026b7938f9cb250086a7c6325cf31576f894ca4a1bcommit-bot@chromium.orgbool GrContext::isConfigRenderable(GrPixelConfig config, bool withMSAA) const {
17036b7938f9cb250086a7c6325cf31576f894ca4a1bcommit-bot@chromium.org    return fGpu->caps()->isConfigRenderable(config, withMSAA);
170499a5ac0b67a14048a1db3f429878775854d29397robertphillips@google.com}
170599a5ac0b67a14048a1db3f429878775854d29397robertphillips@google.com
17068fe72477f204b1a45393e6a64caa84fd287b805bbsalomon@google.comvoid GrContext::setupDrawBuffer() {
1707f6de475e5cbd143f348ff7738919e397b7fe7f57tfarina@chromium.org    SkASSERT(NULL == fDrawBuffer);
1708f6de475e5cbd143f348ff7738919e397b7fe7f57tfarina@chromium.org    SkASSERT(NULL == fDrawBufferVBAllocPool);
1709f6de475e5cbd143f348ff7738919e397b7fe7f57tfarina@chromium.org    SkASSERT(NULL == fDrawBufferIBAllocPool);
17108fe72477f204b1a45393e6a64caa84fd287b805bbsalomon@google.com
1711de6ac2dec54a34545dae1986cd743d24c8d655e8bsalomon@google.com    fDrawBufferVBAllocPool =
1712c377baf406996aed18d82d328029c82dbc3b8ddatomhudson@google.com        SkNEW_ARGS(GrVertexBufferAllocPool, (fGpu, false,
171327847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com                                    DRAW_BUFFER_VBPOOL_BUFFER_SIZE,
1714c377baf406996aed18d82d328029c82dbc3b8ddatomhudson@google.com                                    DRAW_BUFFER_VBPOOL_PREALLOC_BUFFERS));
1715de6ac2dec54a34545dae1986cd743d24c8d655e8bsalomon@google.com    fDrawBufferIBAllocPool =
1716c377baf406996aed18d82d328029c82dbc3b8ddatomhudson@google.com        SkNEW_ARGS(GrIndexBufferAllocPool, (fGpu, false,
1717de6ac2dec54a34545dae1986cd743d24c8d655e8bsalomon@google.com                                   DRAW_BUFFER_IBPOOL_BUFFER_SIZE,
1718c377baf406996aed18d82d328029c82dbc3b8ddatomhudson@google.com                                   DRAW_BUFFER_IBPOOL_PREALLOC_BUFFERS));
171927847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com
1720c377baf406996aed18d82d328029c82dbc3b8ddatomhudson@google.com    fDrawBuffer = SkNEW_ARGS(GrInOrderDrawBuffer, (fGpu,
17216e4e65066a7c0dbc9bfbfe4b8f5d49c3d8a79b59bsalomon@google.com                                                   fDrawBufferVBAllocPool,
17226e4e65066a7c0dbc9bfbfe4b8f5d49c3d8a79b59bsalomon@google.com                                                   fDrawBufferIBAllocPool));
17233c4d032aeb2831a64fd6eff570667d590e3ed209bsalomon@google.com
17246e4e65066a7c0dbc9bfbfe4b8f5d49c3d8a79b59bsalomon@google.com    fDrawBuffer->setDrawState(fDrawState);
172527847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com}
172627847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com
172721c10c5ff50cb8f2fd995fc9396d435d3396258bbsalomon@google.comGrDrawTarget* GrContext::getTextTarget() {
17285dbb149fda134941e5d168790127caf294d322e2commit-bot@chromium.org    return this->prepareToDraw(NULL, BUFFERED_DRAW, NULL, NULL);
172927847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com}
173027847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com
173127847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.comconst GrIndexBuffer* GrContext::getQuadIndexBuffer() const {
173227847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com    return fGpu->getQuadIndexBuffer();
173327847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com}
1734dfe75bcf98b0c04535efbf7fe36492a7fb53c90dbsalomon@google.com
1735a04e8e842450e606dd938ddae17857849bd504d4bsalomon@google.comnamespace {
1736a04e8e842450e606dd938ddae17857849bd504d4bsalomon@google.comvoid test_pm_conversions(GrContext* ctx, int* pmToUPMValue, int* upmToPMValue) {
1737a04e8e842450e606dd938ddae17857849bd504d4bsalomon@google.com    GrConfigConversionEffect::PMConversion pmToUPM;
1738a04e8e842450e606dd938ddae17857849bd504d4bsalomon@google.com    GrConfigConversionEffect::PMConversion upmToPM;
1739a04e8e842450e606dd938ddae17857849bd504d4bsalomon@google.com    GrConfigConversionEffect::TestForPreservingPMConversions(ctx, &pmToUPM, &upmToPM);
1740a04e8e842450e606dd938ddae17857849bd504d4bsalomon@google.com    *pmToUPMValue = pmToUPM;
1741a04e8e842450e606dd938ddae17857849bd504d4bsalomon@google.com    *upmToPMValue = upmToPM;
1742a04e8e842450e606dd938ddae17857849bd504d4bsalomon@google.com}
1743a04e8e842450e606dd938ddae17857849bd504d4bsalomon@google.com}
1744a04e8e842450e606dd938ddae17857849bd504d4bsalomon@google.com
1745adc6536fe5baff2216fb76ecda6cc81c61109d5cbsalomon@google.comconst GrEffectRef* GrContext::createPMToUPMEffect(GrTexture* texture,
1746adc6536fe5baff2216fb76ecda6cc81c61109d5cbsalomon@google.com                                                  bool swapRAndB,
1747adc6536fe5baff2216fb76ecda6cc81c61109d5cbsalomon@google.com                                                  const SkMatrix& matrix) {
1748a04e8e842450e606dd938ddae17857849bd504d4bsalomon@google.com    if (!fDidTestPMConversions) {
1749a04e8e842450e606dd938ddae17857849bd504d4bsalomon@google.com        test_pm_conversions(this, &fPMToUPMConversion, &fUPMToPMConversion);
1750d0f3f6825bd5c232da52f4dc1af69b76403b797fbsalomon@google.com        fDidTestPMConversions = true;
1751a04e8e842450e606dd938ddae17857849bd504d4bsalomon@google.com    }
1752a04e8e842450e606dd938ddae17857849bd504d4bsalomon@google.com    GrConfigConversionEffect::PMConversion pmToUPM =
1753a04e8e842450e606dd938ddae17857849bd504d4bsalomon@google.com        static_cast<GrConfigConversionEffect::PMConversion>(fPMToUPMConversion);
1754a04e8e842450e606dd938ddae17857849bd504d4bsalomon@google.com    if (GrConfigConversionEffect::kNone_PMConversion != pmToUPM) {
1755adc6536fe5baff2216fb76ecda6cc81c61109d5cbsalomon@google.com        return GrConfigConversionEffect::Create(texture, swapRAndB, pmToUPM, matrix);
1756a04e8e842450e606dd938ddae17857849bd504d4bsalomon@google.com    } else {
1757adc6536fe5baff2216fb76ecda6cc81c61109d5cbsalomon@google.com        return NULL;
1758a04e8e842450e606dd938ddae17857849bd504d4bsalomon@google.com    }
1759a04e8e842450e606dd938ddae17857849bd504d4bsalomon@google.com}
1760a04e8e842450e606dd938ddae17857849bd504d4bsalomon@google.com
1761adc6536fe5baff2216fb76ecda6cc81c61109d5cbsalomon@google.comconst GrEffectRef* GrContext::createUPMToPMEffect(GrTexture* texture,
1762adc6536fe5baff2216fb76ecda6cc81c61109d5cbsalomon@google.com                                                  bool swapRAndB,
1763adc6536fe5baff2216fb76ecda6cc81c61109d5cbsalomon@google.com                                                  const SkMatrix& matrix) {
1764a04e8e842450e606dd938ddae17857849bd504d4bsalomon@google.com    if (!fDidTestPMConversions) {
1765a04e8e842450e606dd938ddae17857849bd504d4bsalomon@google.com        test_pm_conversions(this, &fPMToUPMConversion, &fUPMToPMConversion);
1766d0f3f6825bd5c232da52f4dc1af69b76403b797fbsalomon@google.com        fDidTestPMConversions = true;
1767a04e8e842450e606dd938ddae17857849bd504d4bsalomon@google.com    }
1768a04e8e842450e606dd938ddae17857849bd504d4bsalomon@google.com    GrConfigConversionEffect::PMConversion upmToPM =
1769a04e8e842450e606dd938ddae17857849bd504d4bsalomon@google.com        static_cast<GrConfigConversionEffect::PMConversion>(fUPMToPMConversion);
1770a04e8e842450e606dd938ddae17857849bd504d4bsalomon@google.com    if (GrConfigConversionEffect::kNone_PMConversion != upmToPM) {
1771adc6536fe5baff2216fb76ecda6cc81c61109d5cbsalomon@google.com        return GrConfigConversionEffect::Create(texture, swapRAndB, upmToPM, matrix);
1772a04e8e842450e606dd938ddae17857849bd504d4bsalomon@google.com    } else {
1773adc6536fe5baff2216fb76ecda6cc81c61109d5cbsalomon@google.com        return NULL;
1774a04e8e842450e606dd938ddae17857849bd504d4bsalomon@google.com    }
1775a04e8e842450e606dd938ddae17857849bd504d4bsalomon@google.com}
1776a04e8e842450e606dd938ddae17857849bd504d4bsalomon@google.com
17775c8ee2539b9316b22416a991a1f560ef5cec7957commit-bot@chromium.orgGrPath* GrContext::createPath(const SkPath& inPath, const SkStrokeRec& stroke) {
17785c8ee2539b9316b22416a991a1f560ef5cec7957commit-bot@chromium.org    SkASSERT(fGpu->caps()->pathRenderingSupport());
17795c8ee2539b9316b22416a991a1f560ef5cec7957commit-bot@chromium.org
17805c8ee2539b9316b22416a991a1f560ef5cec7957commit-bot@chromium.org    // TODO: now we add to fTextureCache. This should change to fResourceCache.
17815c8ee2539b9316b22416a991a1f560ef5cec7957commit-bot@chromium.org    GrResourceKey resourceKey = GrPath::ComputeKey(inPath, stroke);
17825c8ee2539b9316b22416a991a1f560ef5cec7957commit-bot@chromium.org    GrPath* path = static_cast<GrPath*>(fTextureCache->find(resourceKey));
17835c8ee2539b9316b22416a991a1f560ef5cec7957commit-bot@chromium.org    if (NULL != path && path->isEqualTo(inPath, stroke)) {
17845c8ee2539b9316b22416a991a1f560ef5cec7957commit-bot@chromium.org        path->ref();
17855c8ee2539b9316b22416a991a1f560ef5cec7957commit-bot@chromium.org    } else {
17865c8ee2539b9316b22416a991a1f560ef5cec7957commit-bot@chromium.org        path = fGpu->createPath(inPath, stroke);
17875c8ee2539b9316b22416a991a1f560ef5cec7957commit-bot@chromium.org        fTextureCache->purgeAsNeeded(1, path->sizeInBytes());
17885c8ee2539b9316b22416a991a1f560ef5cec7957commit-bot@chromium.org        fTextureCache->addResource(resourceKey, path);
17895c8ee2539b9316b22416a991a1f560ef5cec7957commit-bot@chromium.org    }
17905c8ee2539b9316b22416a991a1f560ef5cec7957commit-bot@chromium.org    return path;
17915c8ee2539b9316b22416a991a1f560ef5cec7957commit-bot@chromium.org}
17925c8ee2539b9316b22416a991a1f560ef5cec7957commit-bot@chromium.org
1793c43649962221c348d656d425a3fa9b29c78231d4bsalomon@google.com///////////////////////////////////////////////////////////////////////////////
17945955202c805c7ef1448103cbf666972ea9d1ded1robertphillips@google.com#if GR_CACHE_STATS
17955f9f2f574fe9b195f5f3e40edeb2e28b673511fdrobertphillips@google.comvoid GrContext::printCacheStats() const {
17965f9f2f574fe9b195f5f3e40edeb2e28b673511fdrobertphillips@google.com    fTextureCache->printStats();
17975f9f2f574fe9b195f5f3e40edeb2e28b673511fdrobertphillips@google.com}
17985f9f2f574fe9b195f5f3e40edeb2e28b673511fdrobertphillips@google.com#endif
1799