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
12a04e8e842450e606dd938ddae17857849bd504d4bsalomon@google.com#include "effects/GrConfigConversionEffect.h"
13e61c411c1258a323a010558c08de3d9f8d170dcaegdaniel#include "effects/GrDashingEffect.h"
14e61c411c1258a323a010558c08de3d9f8d170dcaegdaniel#include "effects/GrSingleTextureEffect.h"
15b505a128efae9debcaa9642bade90bab5525d477bsalomon@google.com
16bfe2b9d3a290d0153b82617cd6b65a4814fe89e3jvanverth@google.com#include "GrAARectRenderer.h"
17278cbb452a260de1550769b168df448e0911cf3ctomhudson@google.com#include "GrBufferAllocPool.h"
18dcb8ef9e866b2674e8f9a70b761fcc4fec87dbbecommit-bot@chromium.org#include "GrGpu.h"
194784182993a336b673619f3eb13ce2539aa890dacommit-bot@chromium.org#include "GrDrawTargetCaps.h"
20dcb8ef9e866b2674e8f9a70b761fcc4fec87dbbecommit-bot@chromium.org#include "GrIndexBuffer.h"
214784182993a336b673619f3eb13ce2539aa890dacommit-bot@chromium.org#include "GrInOrderDrawBuffer.h"
22e930a075625d3d90c023c2570a6a4cae1a4b484frobertphillips@google.com#include "GrLayerCache.h"
2381312830ef73420efdc4821feb7c2d6fd9152af8commit-bot@chromium.org#include "GrOvalRenderer.h"
2427847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com#include "GrPathRenderer.h"
25d22b6e4351e552a8379d7781096d9e79feeae263tomhudson@google.com#include "GrPathUtils.h"
2650398bf7f1953e640e5529616e710cf540799731bsalomon@google.com#include "GrResourceCache.h"
2772176b2d38db005863a54e3dd6657bbabd068bb6robertphillips@google.com#include "GrSoftwarePathRenderer.h"
28558a75bcb323c03dd7482555c7214062a363276fbsalomon@google.com#include "GrStencilBuffer.h"
29d58a0ba9cff9fcefe5047e88ccb4a6e76c591c40egdaniel#include "GrStrokeInfo.h"
30278cbb452a260de1550769b168df448e0911cf3ctomhudson@google.com#include "GrTextStrike.h"
31bbcb38df4f7477aa0a38da00a0757586a0125954egdaniel#include "GrTraceMarker.h"
322a05de0c049a8648942a55016126a1f92e1c14d6commit-bot@chromium.org#include "GrTracing.h"
33d58a0ba9cff9fcefe5047e88ccb4a6e76c591c40egdaniel#include "SkDashPathPriv.h"
347111d463cee893a479280c7af41757e709e33ef5reed@google.com#include "SkGr.h"
35dcb8ef9e866b2674e8f9a70b761fcc4fec87dbbecommit-bot@chromium.org#include "SkRTConf.h"
364784182993a336b673619f3eb13ce2539aa890dacommit-bot@chromium.org#include "SkRRect.h"
375f74cf8c49701f514b69dc6f1a8b5c0ffd78af0asugoi@google.com#include "SkStrokeRec.h"
38dcb8ef9e866b2674e8f9a70b761fcc4fec87dbbecommit-bot@chromium.org#include "SkTLazy.h"
394784182993a336b673619f3eb13ce2539aa890dacommit-bot@chromium.org#include "SkTLS.h"
40933e65d914eb86b1fbbf8ea9cf1da58ac7c42500commit-bot@chromium.org#include "SkTraceEvent.h"
4127847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com
4282b0ec6ea408d866e02805fbe0519d00d2e87627bsalomon@google.com// It can be useful to set this to false to test whether a bug is caused by using the
431d4edd38f6b62d1cc54cb7bc6f3c6ce10ccb1471bsalomon@google.com// InOrderDrawBuffer, to compare performance of using/not using InOrderDrawBuffer, or to make
4482b0ec6ea408d866e02805fbe0519d00d2e87627bsalomon@google.com// debugging simpler.
45e932c98069fd6831a03ff63d331271ef0e9703d9bsalomon@google.comSK_CONF_DECLARE(bool, c_Defer, "gpu.deferContext", true,
4665eb4d5a210884cc92c43a8582cbd1ccbddcab57jvanverth@google.com                "Defers rendering in GrContext via GrInOrderDrawBuffer.");
4782b0ec6ea408d866e02805fbe0519d00d2e87627bsalomon@google.com
4882b0ec6ea408d866e02805fbe0519d00d2e87627bsalomon@google.com#define BUFFERED_DRAW (c_Defer ? kYes_BufferedDraw : kNo_BufferedDraw)
4927847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com
50515dcd36032997ce335daa0163c6d67e851bcad1commit-bot@chromium.org#ifdef SK_DEBUG
514b2d3f30d047435263642ef8ed170a37ca642c1breed@google.com    // change this to a 1 to see notifications when partial coverage fails
524b2d3f30d047435263642ef8ed170a37ca642c1breed@google.com    #define GR_DEBUG_PARTIAL_COVERAGE_CHECK 0
534b2d3f30d047435263642ef8ed170a37ca642c1breed@google.com#else
544b2d3f30d047435263642ef8ed170a37ca642c1breed@google.com    #define GR_DEBUG_PARTIAL_COVERAGE_CHECK 0
554b2d3f30d047435263642ef8ed170a37ca642c1breed@google.com#endif
564b2d3f30d047435263642ef8ed170a37ca642c1breed@google.com
574e5559af8947ae7dc3df531b6d7a73323db20c3frobertphillips@google.comstatic const size_t MAX_RESOURCE_CACHE_COUNT = GR_DEFAULT_RESOURCE_CACHE_COUNT_LIMIT;
584e5559af8947ae7dc3df531b6d7a73323db20c3frobertphillips@google.comstatic const size_t MAX_RESOURCE_CACHE_BYTES = GR_DEFAULT_RESOURCE_CACHE_MB_LIMIT * 1024 * 1024;
5927847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com
6060361493548d5259d0a8afae84274c2a3c31dcacbsalomon@google.comstatic const size_t DRAW_BUFFER_VBPOOL_BUFFER_SIZE = 1 << 15;
6127847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.comstatic const int DRAW_BUFFER_VBPOOL_PREALLOC_BUFFERS = 4;
6227847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com
631d4edd38f6b62d1cc54cb7bc6f3c6ce10ccb1471bsalomon@google.comstatic const size_t DRAW_BUFFER_IBPOOL_BUFFER_SIZE = 1 << 11;
641d4edd38f6b62d1cc54cb7bc6f3c6ce10ccb1471bsalomon@google.comstatic const int DRAW_BUFFER_IBPOOL_PREALLOC_BUFFERS = 4;
6527847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com
66f6de475e5cbd143f348ff7738919e397b7fe7f57tfarina@chromium.org#define ASSERT_OWNED_RESOURCE(R) SkASSERT(!(R) || (R)->getContext() == this)
67bc4b654af85fa67bdd9cc1b88747b8c394a00e27bsalomon@google.com
68eb6879f50a5564eeb981ec5616b55bf685eb76fcbsalomon@google.com// Glorified typedef to avoid including GrDrawState.h in GrContext.h
69eb6879f50a5564eeb981ec5616b55bf685eb76fcbsalomon@google.comclass GrContext::AutoRestoreEffects : public GrDrawState::AutoRestoreEffects {};
70eb6879f50a5564eeb981ec5616b55bf685eb76fcbsalomon@google.com
715dbb149fda134941e5d168790127caf294d322e2commit-bot@chromium.orgclass GrContext::AutoCheckFlush {
725dbb149fda134941e5d168790127caf294d322e2commit-bot@chromium.orgpublic:
735dbb149fda134941e5d168790127caf294d322e2commit-bot@chromium.org    AutoCheckFlush(GrContext* context) : fContext(context) { SkASSERT(NULL != context); }
745dbb149fda134941e5d168790127caf294d322e2commit-bot@chromium.org
755dbb149fda134941e5d168790127caf294d322e2commit-bot@chromium.org    ~AutoCheckFlush() {
765dbb149fda134941e5d168790127caf294d322e2commit-bot@chromium.org        if (fContext->fFlushToReduceCacheSize) {
775dbb149fda134941e5d168790127caf294d322e2commit-bot@chromium.org            fContext->flush();
785dbb149fda134941e5d168790127caf294d322e2commit-bot@chromium.org        }
795dbb149fda134941e5d168790127caf294d322e2commit-bot@chromium.org    }
805dbb149fda134941e5d168790127caf294d322e2commit-bot@chromium.org
815dbb149fda134941e5d168790127caf294d322e2commit-bot@chromium.orgprivate:
825dbb149fda134941e5d168790127caf294d322e2commit-bot@chromium.org    GrContext* fContext;
835dbb149fda134941e5d168790127caf294d322e2commit-bot@chromium.org};
845dbb149fda134941e5d168790127caf294d322e2commit-bot@chromium.org
856e4e65066a7c0dbc9bfbfe4b8f5d49c3d8a79b59bsalomon@google.comGrContext* GrContext::Create(GrBackend backend, GrBackendContext backendContext) {
866e4e65066a7c0dbc9bfbfe4b8f5d49c3d8a79b59bsalomon@google.com    GrContext* context = SkNEW(GrContext);
876e4e65066a7c0dbc9bfbfe4b8f5d49c3d8a79b59bsalomon@google.com    if (context->init(backend, backendContext)) {
886e4e65066a7c0dbc9bfbfe4b8f5d49c3d8a79b59bsalomon@google.com        return context;
896e4e65066a7c0dbc9bfbfe4b8f5d49c3d8a79b59bsalomon@google.com    } else {
906e4e65066a7c0dbc9bfbfe4b8f5d49c3d8a79b59bsalomon@google.com        context->unref();
916e4e65066a7c0dbc9bfbfe4b8f5d49c3d8a79b59bsalomon@google.com        return NULL;
9227847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com    }
9327847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com}
9427847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com
956e4e65066a7c0dbc9bfbfe4b8f5d49c3d8a79b59bsalomon@google.comGrContext::GrContext() {
966e4e65066a7c0dbc9bfbfe4b8f5d49c3d8a79b59bsalomon@google.com    fDrawState = NULL;
976e4e65066a7c0dbc9bfbfe4b8f5d49c3d8a79b59bsalomon@google.com    fGpu = NULL;
98bb6a3178c3e79c8549b332e4ce84c64b59964f1ecommit-bot@chromium.org    fClip = NULL;
996e4e65066a7c0dbc9bfbfe4b8f5d49c3d8a79b59bsalomon@google.com    fPathRendererChain = NULL;
1006e4e65066a7c0dbc9bfbfe4b8f5d49c3d8a79b59bsalomon@google.com    fSoftwarePathRenderer = NULL;
10195c2003740c4cd01fd1b02ed93b9de7227b1d0f5commit-bot@chromium.org    fResourceCache = NULL;
1026e4e65066a7c0dbc9bfbfe4b8f5d49c3d8a79b59bsalomon@google.com    fFontCache = NULL;
1036e4e65066a7c0dbc9bfbfe4b8f5d49c3d8a79b59bsalomon@google.com    fDrawBuffer = NULL;
1046e4e65066a7c0dbc9bfbfe4b8f5d49c3d8a79b59bsalomon@google.com    fDrawBufferVBAllocPool = NULL;
1056e4e65066a7c0dbc9bfbfe4b8f5d49c3d8a79b59bsalomon@google.com    fDrawBufferIBAllocPool = NULL;
1065dbb149fda134941e5d168790127caf294d322e2commit-bot@chromium.org    fFlushToReduceCacheSize = false;
1076e4e65066a7c0dbc9bfbfe4b8f5d49c3d8a79b59bsalomon@google.com    fAARectRenderer = NULL;
10881312830ef73420efdc4821feb7c2d6fd9152af8commit-bot@chromium.org    fOvalRenderer = NULL;
109bb6a3178c3e79c8549b332e4ce84c64b59964f1ecommit-bot@chromium.org    fViewMatrix.reset();
11044a91dcf2542c2aa93f159ebbb5bf813ae7362c0robertphillips@google.com    fMaxTextureSizeOverride = 1 << 20;
1112a05de0c049a8648942a55016126a1f92e1c14d6commit-bot@chromium.org    fGpuTracingEnabled = false;
1126e4e65066a7c0dbc9bfbfe4b8f5d49c3d8a79b59bsalomon@google.com}
1136e4e65066a7c0dbc9bfbfe4b8f5d49c3d8a79b59bsalomon@google.com
1146e4e65066a7c0dbc9bfbfe4b8f5d49c3d8a79b59bsalomon@google.combool GrContext::init(GrBackend backend, GrBackendContext backendContext) {
115f6de475e5cbd143f348ff7738919e397b7fe7f57tfarina@chromium.org    SkASSERT(NULL == fGpu);
1166e4e65066a7c0dbc9bfbfe4b8f5d49c3d8a79b59bsalomon@google.com
1176e4e65066a7c0dbc9bfbfe4b8f5d49c3d8a79b59bsalomon@google.com    fGpu = GrGpu::Create(backend, backendContext, this);
1186e4e65066a7c0dbc9bfbfe4b8f5d49c3d8a79b59bsalomon@google.com    if (NULL == fGpu) {
1196e4e65066a7c0dbc9bfbfe4b8f5d49c3d8a79b59bsalomon@google.com        return false;
1206e4e65066a7c0dbc9bfbfe4b8f5d49c3d8a79b59bsalomon@google.com    }
1216e4e65066a7c0dbc9bfbfe4b8f5d49c3d8a79b59bsalomon@google.com
1226e4e65066a7c0dbc9bfbfe4b8f5d49c3d8a79b59bsalomon@google.com    fDrawState = SkNEW(GrDrawState);
1236e4e65066a7c0dbc9bfbfe4b8f5d49c3d8a79b59bsalomon@google.com    fGpu->setDrawState(fDrawState);
1246e4e65066a7c0dbc9bfbfe4b8f5d49c3d8a79b59bsalomon@google.com
12595c2003740c4cd01fd1b02ed93b9de7227b1d0f5commit-bot@chromium.org    fResourceCache = SkNEW_ARGS(GrResourceCache, (MAX_RESOURCE_CACHE_COUNT,
12695c2003740c4cd01fd1b02ed93b9de7227b1d0f5commit-bot@chromium.org                                                  MAX_RESOURCE_CACHE_BYTES));
12795c2003740c4cd01fd1b02ed93b9de7227b1d0f5commit-bot@chromium.org    fResourceCache->setOverbudgetCallback(OverbudgetCB, this);
1281836d337a85b82689287231091823f404d8cab43commit-bot@chromium.org
1296e4e65066a7c0dbc9bfbfe4b8f5d49c3d8a79b59bsalomon@google.com    fFontCache = SkNEW_ARGS(GrFontCache, (fGpu));
1306e4e65066a7c0dbc9bfbfe4b8f5d49c3d8a79b59bsalomon@google.com
131e930a075625d3d90c023c2570a6a4cae1a4b484frobertphillips@google.com    fLayerCache.reset(SkNEW_ARGS(GrLayerCache, (fGpu)));
132e930a075625d3d90c023c2570a6a4cae1a4b484frobertphillips@google.com
1336e4e65066a7c0dbc9bfbfe4b8f5d49c3d8a79b59bsalomon@google.com    fLastDrawWasBuffered = kNo_BufferedDraw;
1346e4e65066a7c0dbc9bfbfe4b8f5d49c3d8a79b59bsalomon@google.com
1356e4e65066a7c0dbc9bfbfe4b8f5d49c3d8a79b59bsalomon@google.com    fAARectRenderer = SkNEW(GrAARectRenderer);
13681312830ef73420efdc4821feb7c2d6fd9152af8commit-bot@chromium.org    fOvalRenderer = SkNEW(GrOvalRenderer);
1376e4e65066a7c0dbc9bfbfe4b8f5d49c3d8a79b59bsalomon@google.com
1386e4e65066a7c0dbc9bfbfe4b8f5d49c3d8a79b59bsalomon@google.com    fDidTestPMConversions = false;
1396e4e65066a7c0dbc9bfbfe4b8f5d49c3d8a79b59bsalomon@google.com
1406e4e65066a7c0dbc9bfbfe4b8f5d49c3d8a79b59bsalomon@google.com    this->setupDrawBuffer();
1416e4e65066a7c0dbc9bfbfe4b8f5d49c3d8a79b59bsalomon@google.com
1426e4e65066a7c0dbc9bfbfe4b8f5d49c3d8a79b59bsalomon@google.com    return true;
143c0af3173314e227611d8c5541ef2deee0052d412bsalomon@google.com}
144c0af3173314e227611d8c5541ef2deee0052d412bsalomon@google.com
14527847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.comGrContext::~GrContext() {
146733c062c09bfe3ec4a32658510136fc5850a6e2cbsalomon@google.com    if (NULL == fGpu) {
147733c062c09bfe3ec4a32658510136fc5850a6e2cbsalomon@google.com        return;
148733c062c09bfe3ec4a32658510136fc5850a6e2cbsalomon@google.com    }
149733c062c09bfe3ec4a32658510136fc5850a6e2cbsalomon@google.com
1508fe72477f204b1a45393e6a64caa84fd287b805bbsalomon@google.com    this->flush();
1515acc0e36d987dff3172fd45a14b66c52a51d49e4robertphillips@google.com
152950b1b079a782e208c2f38cf222184fa1ca1006drobertphillips@google.com    for (int i = 0; i < fCleanUpData.count(); ++i) {
153950b1b079a782e208c2f38cf222184fa1ca1006drobertphillips@google.com        (*fCleanUpData[i].fFunc)(this, fCleanUpData[i].fInfo);
154950b1b079a782e208c2f38cf222184fa1ca1006drobertphillips@google.com    }
155950b1b079a782e208c2f38cf222184fa1ca1006drobertphillips@google.com
1565acc0e36d987dff3172fd45a14b66c52a51d49e4robertphillips@google.com    // Since the gpu can hold scratch textures, give it a chance to let go
1575acc0e36d987dff3172fd45a14b66c52a51d49e4robertphillips@google.com    // of them before freeing the texture cache
1585acc0e36d987dff3172fd45a14b66c52a51d49e4robertphillips@google.com    fGpu->purgeResources();
1595acc0e36d987dff3172fd45a14b66c52a51d49e4robertphillips@google.com
16095c2003740c4cd01fd1b02ed93b9de7227b1d0f5commit-bot@chromium.org    delete fResourceCache;
16195c2003740c4cd01fd1b02ed93b9de7227b1d0f5commit-bot@chromium.org    fResourceCache = NULL;
16227847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com    delete fFontCache;
16327847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com    delete fDrawBuffer;
16427847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com    delete fDrawBufferVBAllocPool;
165de6ac2dec54a34545dae1986cd743d24c8d655e8bsalomon@google.com    delete fDrawBufferIBAllocPool;
1663008519e9f977cd60194841d558a4f45c28e9833bsalomon@google.com
167f6747b0b90b3a270ec7b7bdfdc211cf5c19f28c2robertphillips@google.com    fAARectRenderer->unref();
16881312830ef73420efdc4821feb7c2d6fd9152af8commit-bot@chromium.org    fOvalRenderer->unref();
169f6747b0b90b3a270ec7b7bdfdc211cf5c19f28c2robertphillips@google.com
170205d46067ace24bd4b111cf44efc96caff6c4d30bsalomon@google.com    fGpu->unref();
171a4de8c257ea0be8ff7081f645249b6afe5c48e7ecommit-bot@chromium.org    SkSafeUnref(fPathRendererChain);
172a4de8c257ea0be8ff7081f645249b6afe5c48e7ecommit-bot@chromium.org    SkSafeUnref(fSoftwarePathRenderer);
17310e04bf1c5025389d999f22467405782e9f9ffccbsalomon@google.com    fDrawState->unref();
17427847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com}
17527847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com
1768fe72477f204b1a45393e6a64caa84fd287b805bbsalomon@google.comvoid GrContext::contextLost() {
1776e4e65066a7c0dbc9bfbfe4b8f5d49c3d8a79b59bsalomon@google.com    this->contextDestroyed();
17853a5584bb0094e19c39a66cec7f346aad04ecac4junov@google.com    this->setupDrawBuffer();
17953a5584bb0094e19c39a66cec7f346aad04ecac4junov@google.com}
18053a5584bb0094e19c39a66cec7f346aad04ecac4junov@google.com
18153a5584bb0094e19c39a66cec7f346aad04ecac4junov@google.comvoid GrContext::contextDestroyed() {
182205d46067ace24bd4b111cf44efc96caff6c4d30bsalomon@google.com    // abandon first to so destructors
183205d46067ace24bd4b111cf44efc96caff6c4d30bsalomon@google.com    // don't try to free the resources in the API.
184205d46067ace24bd4b111cf44efc96caff6c4d30bsalomon@google.com    fGpu->abandonResources();
185205d46067ace24bd4b111cf44efc96caff6c4d30bsalomon@google.com
1863008519e9f977cd60194841d558a4f45c28e9833bsalomon@google.com    // a path renderer may be holding onto resources that
1873008519e9f977cd60194841d558a4f45c28e9833bsalomon@google.com    // are now unusable
188a4de8c257ea0be8ff7081f645249b6afe5c48e7ecommit-bot@chromium.org    SkSafeSetNull(fPathRendererChain);
189a4de8c257ea0be8ff7081f645249b6afe5c48e7ecommit-bot@chromium.org    SkSafeSetNull(fSoftwarePathRenderer);
1903008519e9f977cd60194841d558a4f45c28e9833bsalomon@google.com
1918fe72477f204b1a45393e6a64caa84fd287b805bbsalomon@google.com    delete fDrawBuffer;
1928fe72477f204b1a45393e6a64caa84fd287b805bbsalomon@google.com    fDrawBuffer = NULL;
193205d46067ace24bd4b111cf44efc96caff6c4d30bsalomon@google.com
1948fe72477f204b1a45393e6a64caa84fd287b805bbsalomon@google.com    delete fDrawBufferVBAllocPool;
1958fe72477f204b1a45393e6a64caa84fd287b805bbsalomon@google.com    fDrawBufferVBAllocPool = NULL;
196205d46067ace24bd4b111cf44efc96caff6c4d30bsalomon@google.com
1978fe72477f204b1a45393e6a64caa84fd287b805bbsalomon@google.com    delete fDrawBufferIBAllocPool;
1988fe72477f204b1a45393e6a64caa84fd287b805bbsalomon@google.com    fDrawBufferIBAllocPool = NULL;
1998fe72477f204b1a45393e6a64caa84fd287b805bbsalomon@google.com
200f6747b0b90b3a270ec7b7bdfdc211cf5c19f28c2robertphillips@google.com    fAARectRenderer->reset();
201ef284a84f503adfd08ee52b5aee142c548698ea4commit-bot@chromium.org    fOvalRenderer->reset();
202205d46067ace24bd4b111cf44efc96caff6c4d30bsalomon@google.com
20395c2003740c4cd01fd1b02ed93b9de7227b1d0f5commit-bot@chromium.org    fResourceCache->purgeAllUnlocked();
2045c8ee2539b9316b22416a991a1f560ef5cec7957commit-bot@chromium.org
2058fe72477f204b1a45393e6a64caa84fd287b805bbsalomon@google.com    fFontCache->freeAll();
206e930a075625d3d90c023c2570a6a4cae1a4b484frobertphillips@google.com    fLayerCache->freeAll();
2078fe72477f204b1a45393e6a64caa84fd287b805bbsalomon@google.com    fGpu->markContextDirty();
2088fe72477f204b1a45393e6a64caa84fd287b805bbsalomon@google.com}
2098fe72477f204b1a45393e6a64caa84fd287b805bbsalomon@google.com
2100a208a117b2d7f2c2231aa357f1db4864dbdcba3bsalomon@google.comvoid GrContext::resetContext(uint32_t state) {
2110a208a117b2d7f2c2231aa357f1db4864dbdcba3bsalomon@google.com    fGpu->markContextDirty(state);
2128fe72477f204b1a45393e6a64caa84fd287b805bbsalomon@google.com}
2138fe72477f204b1a45393e6a64caa84fd287b805bbsalomon@google.com
2148fe72477f204b1a45393e6a64caa84fd287b805bbsalomon@google.comvoid GrContext::freeGpuResources() {
2158fe72477f204b1a45393e6a64caa84fd287b805bbsalomon@google.com    this->flush();
216fbfcd5602128ec010c82cb733c9cdc0a3254f9f3rmistry@google.com
217ff17584e1c15f68ccc296be517e8a6776a9ddabdrobertphillips@google.com    fGpu->purgeResources();
218ff17584e1c15f68ccc296be517e8a6776a9ddabdrobertphillips@google.com
219f6747b0b90b3a270ec7b7bdfdc211cf5c19f28c2robertphillips@google.com    fAARectRenderer->reset();
220ef284a84f503adfd08ee52b5aee142c548698ea4commit-bot@chromium.org    fOvalRenderer->reset();
221f6747b0b90b3a270ec7b7bdfdc211cf5c19f28c2robertphillips@google.com
22295c2003740c4cd01fd1b02ed93b9de7227b1d0f5commit-bot@chromium.org    fResourceCache->purgeAllUnlocked();
2238fe72477f204b1a45393e6a64caa84fd287b805bbsalomon@google.com    fFontCache->freeAll();
224e930a075625d3d90c023c2570a6a4cae1a4b484frobertphillips@google.com    fLayerCache->freeAll();
2253008519e9f977cd60194841d558a4f45c28e9833bsalomon@google.com    // a path renderer may be holding onto resources
226a4de8c257ea0be8ff7081f645249b6afe5c48e7ecommit-bot@chromium.org    SkSafeSetNull(fPathRendererChain);
227a4de8c257ea0be8ff7081f645249b6afe5c48e7ecommit-bot@chromium.org    SkSafeSetNull(fSoftwarePathRenderer);
22827847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com}
22927847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com
23095c2003740c4cd01fd1b02ed93b9de7227b1d0f5commit-bot@chromium.orgvoid GrContext::getResourceCacheUsage(int* resourceCount, size_t* resourceBytes) const {
23195c2003740c4cd01fd1b02ed93b9de7227b1d0f5commit-bot@chromium.org  if (NULL != resourceCount) {
23295c2003740c4cd01fd1b02ed93b9de7227b1d0f5commit-bot@chromium.org    *resourceCount = fResourceCache->getCachedResourceCount();
23395c2003740c4cd01fd1b02ed93b9de7227b1d0f5commit-bot@chromium.org  }
23495c2003740c4cd01fd1b02ed93b9de7227b1d0f5commit-bot@chromium.org  if (NULL != resourceBytes) {
23595c2003740c4cd01fd1b02ed93b9de7227b1d0f5commit-bot@chromium.org    *resourceBytes = fResourceCache->getCachedResourceBytes();
23695c2003740c4cd01fd1b02ed93b9de7227b1d0f5commit-bot@chromium.org  }
237d8a57af725e8fa8905207df3cf7465be50598752commit-bot@chromium.org}
238d8a57af725e8fa8905207df3cf7465be50598752commit-bot@chromium.org
239fea37b5e532dfe776269253afb9951e763c3b205bsalomon@google.com////////////////////////////////////////////////////////////////////////////////
240fea37b5e532dfe776269253afb9951e763c3b205bsalomon@google.com
24195ed55adc6b8f0cee063c2cf2e14782773b0087fbsalomon@google.comGrTexture* GrContext::findAndRefTexture(const GrTextureDesc& desc,
24295ed55adc6b8f0cee063c2cf2e14782773b0087fbsalomon@google.com                                        const GrCacheID& cacheID,
24395ed55adc6b8f0cee063c2cf2e14782773b0087fbsalomon@google.com                                        const GrTextureParams* params) {
244e49157f0838c615b10da0ef2b297c742da662e34commit-bot@chromium.org    GrResourceKey resourceKey = GrTextureImpl::ComputeKey(fGpu, params, desc, cacheID);
24595c2003740c4cd01fd1b02ed93b9de7227b1d0f5commit-bot@chromium.org    GrCacheable* resource = fResourceCache->find(resourceKey);
24695ed55adc6b8f0cee063c2cf2e14782773b0087fbsalomon@google.com    SkSafeRef(resource);
2471f47f4f7325971dd53991e2bb02da94fa7c6d962robertphillips@google.com    return static_cast<GrTexture*>(resource);
248558a75bcb323c03dd7482555c7214062a363276fbsalomon@google.com}
249558a75bcb323c03dd7482555c7214062a363276fbsalomon@google.com
25075b3c9633cb9a594dab0ccf51dab1e694c149a18robertphillips@google.combool GrContext::isTextureInCache(const GrTextureDesc& desc,
2510797c2cceadd7dfc2e7f9efa30b611d18efcdcddbsalomon@google.com                                 const GrCacheID& cacheID,
252b8670998a59d305cd22a3c0cbdc6e075b0a37a6ebsalomon@google.com                                 const GrTextureParams* params) const {
253e49157f0838c615b10da0ef2b297c742da662e34commit-bot@chromium.org    GrResourceKey resourceKey = GrTextureImpl::ComputeKey(fGpu, params, desc, cacheID);
25495c2003740c4cd01fd1b02ed93b9de7227b1d0f5commit-bot@chromium.org    return fResourceCache->hasKey(resourceKey);
255fb30951cd9346a7a2d36e7d5f81f9e7ee792b669bsalomon@google.com}
256fb30951cd9346a7a2d36e7d5f81f9e7ee792b669bsalomon@google.com
2579fbcad0f00d7098574cf3394a812c9d845c9cc5brobertphillips@google.comvoid GrContext::addStencilBuffer(GrStencilBuffer* sb) {
258bc4b654af85fa67bdd9cc1b88747b8c394a00e27bsalomon@google.com    ASSERT_OWNED_RESOURCE(sb);
25946a8600405e678718271f62c5994119b8d3241e9robertphillips@google.com
26046a8600405e678718271f62c5994119b8d3241e9robertphillips@google.com    GrResourceKey resourceKey = GrStencilBuffer::ComputeKey(sb->width(),
26146a8600405e678718271f62c5994119b8d3241e9robertphillips@google.com                                                            sb->height(),
26246a8600405e678718271f62c5994119b8d3241e9robertphillips@google.com                                                            sb->numSamples());
26395c2003740c4cd01fd1b02ed93b9de7227b1d0f5commit-bot@chromium.org    fResourceCache->addResource(resourceKey, sb);
264558a75bcb323c03dd7482555c7214062a363276fbsalomon@google.com}
265558a75bcb323c03dd7482555c7214062a363276fbsalomon@google.com
2669fbcad0f00d7098574cf3394a812c9d845c9cc5brobertphillips@google.comGrStencilBuffer* GrContext::findStencilBuffer(int width, int height,
267558a75bcb323c03dd7482555c7214062a363276fbsalomon@google.com                                              int sampleCnt) {
26846a8600405e678718271f62c5994119b8d3241e9robertphillips@google.com    GrResourceKey resourceKey = GrStencilBuffer::ComputeKey(width,
26946a8600405e678718271f62c5994119b8d3241e9robertphillips@google.com                                                            height,
27046a8600405e678718271f62c5994119b8d3241e9robertphillips@google.com                                                            sampleCnt);
27195c2003740c4cd01fd1b02ed93b9de7227b1d0f5commit-bot@chromium.org    GrCacheable* resource = fResourceCache->find(resourceKey);
2721f47f4f7325971dd53991e2bb02da94fa7c6d962robertphillips@google.com    return static_cast<GrStencilBuffer*>(resource);
273558a75bcb323c03dd7482555c7214062a363276fbsalomon@google.com}
274558a75bcb323c03dd7482555c7214062a363276fbsalomon@google.com
275b0ce4b6fc8da4c3aa491fc43512e9187df1dfdaecommit-bot@chromium.orgstatic void stretch_image(void* dst,
276b0ce4b6fc8da4c3aa491fc43512e9187df1dfdaecommit-bot@chromium.org                          int dstW,
277b0ce4b6fc8da4c3aa491fc43512e9187df1dfdaecommit-bot@chromium.org                          int dstH,
278f9bd04faffb936602f7f957413a8cd5b7fc44addcommit-bot@chromium.org                          const void* src,
279b0ce4b6fc8da4c3aa491fc43512e9187df1dfdaecommit-bot@chromium.org                          int srcW,
280b0ce4b6fc8da4c3aa491fc43512e9187df1dfdaecommit-bot@chromium.org                          int srcH,
281b0ce4b6fc8da4c3aa491fc43512e9187df1dfdaecommit-bot@chromium.org                          size_t bpp) {
282972f9cd7a063d0544f8c919fd12b9a3adbd12b24commit-bot@chromium.org    SkFixed dx = (srcW << 16) / dstW;
283972f9cd7a063d0544f8c919fd12b9a3adbd12b24commit-bot@chromium.org    SkFixed dy = (srcH << 16) / dstH;
28427847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com
285972f9cd7a063d0544f8c919fd12b9a3adbd12b24commit-bot@chromium.org    SkFixed y = dy >> 1;
28627847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com
2878b169311b59ab84e8ca6f3630a1e960cc1be751erobertphillips@google.com    size_t dstXLimit = dstW*bpp;
28827847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com    for (int j = 0; j < dstH; ++j) {
289972f9cd7a063d0544f8c919fd12b9a3adbd12b24commit-bot@chromium.org        SkFixed x = dx >> 1;
290f9bd04faffb936602f7f957413a8cd5b7fc44addcommit-bot@chromium.org        const uint8_t* srcRow = reinterpret_cast<const uint8_t *>(src) + (y>>16)*srcW*bpp;
291f9bd04faffb936602f7f957413a8cd5b7fc44addcommit-bot@chromium.org        uint8_t* dstRow = reinterpret_cast<uint8_t *>(dst) + j*dstW*bpp;
2928b169311b59ab84e8ca6f3630a1e960cc1be751erobertphillips@google.com        for (size_t i = 0; i < dstXLimit; i += bpp) {
293f9bd04faffb936602f7f957413a8cd5b7fc44addcommit-bot@chromium.org            memcpy(dstRow + i, srcRow + (x>>16)*bpp, bpp);
29427847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com            x += dx;
29527847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com        }
29627847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com        y += dy;
29727847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com    }
29827847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com}
29927847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com
300429033038271147ed66b4bc2675ac98a5ccfa75crobertphillips@google.comnamespace {
301429033038271147ed66b4bc2675ac98a5ccfa75crobertphillips@google.com
302429033038271147ed66b4bc2675ac98a5ccfa75crobertphillips@google.com// position + local coordinate
303429033038271147ed66b4bc2675ac98a5ccfa75crobertphillips@google.comextern const GrVertexAttrib gVertexAttribs[] = {
304429033038271147ed66b4bc2675ac98a5ccfa75crobertphillips@google.com    {kVec2f_GrVertexAttribType, 0,               kPosition_GrVertexAttribBinding},
305972f9cd7a063d0544f8c919fd12b9a3adbd12b24commit-bot@chromium.org    {kVec2f_GrVertexAttribType, sizeof(SkPoint), kLocalCoord_GrVertexAttribBinding}
306429033038271147ed66b4bc2675ac98a5ccfa75crobertphillips@google.com};
307429033038271147ed66b4bc2675ac98a5ccfa75crobertphillips@google.com
308429033038271147ed66b4bc2675ac98a5ccfa75crobertphillips@google.com};
309429033038271147ed66b4bc2675ac98a5ccfa75crobertphillips@google.com
310fbfcd5602128ec010c82cb733c9cdc0a3254f9f3rmistry@google.com// The desired texture is NPOT and tiled but that isn't supported by
3113319f33470abc50a6f3da3a565d917050f9b2f53robertphillips@google.com// the current hardware. Resize the texture to be a POT
3123319f33470abc50a6f3da3a565d917050f9b2f53robertphillips@google.comGrTexture* GrContext::createResizedTexture(const GrTextureDesc& desc,
3130797c2cceadd7dfc2e7f9efa30b611d18efcdcddbsalomon@google.com                                           const GrCacheID& cacheID,
314f9bd04faffb936602f7f957413a8cd5b7fc44addcommit-bot@chromium.org                                           const void* srcData,
3153319f33470abc50a6f3da3a565d917050f9b2f53robertphillips@google.com                                           size_t rowBytes,
316b86add1ad37776818e1f730359ec587c9fdbff5fhumper@google.com                                           bool filter) {
31795ed55adc6b8f0cee063c2cf2e14782773b0087fbsalomon@google.com    SkAutoTUnref<GrTexture> clampedTexture(this->findAndRefTexture(desc, cacheID, NULL));
3181f47f4f7325971dd53991e2bb02da94fa7c6d962robertphillips@google.com    if (NULL == clampedTexture) {
31995ed55adc6b8f0cee063c2cf2e14782773b0087fbsalomon@google.com        clampedTexture.reset(this->createTexture(NULL, desc, cacheID, srcData, rowBytes));
3209fbcad0f00d7098574cf3394a812c9d845c9cc5brobertphillips@google.com
3211f47f4f7325971dd53991e2bb02da94fa7c6d962robertphillips@google.com        if (NULL == clampedTexture) {
3223319f33470abc50a6f3da3a565d917050f9b2f53robertphillips@google.com            return NULL;
3233319f33470abc50a6f3da3a565d917050f9b2f53robertphillips@google.com        }
3243319f33470abc50a6f3da3a565d917050f9b2f53robertphillips@google.com    }
3250d25eefd7a25afe859cb2d4cf733a3cf07f12139robertphillips@google.com
3263319f33470abc50a6f3da3a565d917050f9b2f53robertphillips@google.com    GrTextureDesc rtDesc = desc;
3273319f33470abc50a6f3da3a565d917050f9b2f53robertphillips@google.com    rtDesc.fFlags =  rtDesc.fFlags |
3283319f33470abc50a6f3da3a565d917050f9b2f53robertphillips@google.com                     kRenderTarget_GrTextureFlagBit |
3293319f33470abc50a6f3da3a565d917050f9b2f53robertphillips@google.com                     kNoStencil_GrTextureFlagBit;
3305898dce287b0d1ec535a9cfc1c5870a9cdcf5d1bcommit-bot@chromium.org    rtDesc.fWidth  = GrNextPow2(desc.fWidth);
3315898dce287b0d1ec535a9cfc1c5870a9cdcf5d1bcommit-bot@chromium.org    rtDesc.fHeight = GrNextPow2(desc.fHeight);
3323319f33470abc50a6f3da3a565d917050f9b2f53robertphillips@google.com
3333319f33470abc50a6f3da3a565d917050f9b2f53robertphillips@google.com    GrTexture* texture = fGpu->createTexture(rtDesc, NULL, 0);
3343319f33470abc50a6f3da3a565d917050f9b2f53robertphillips@google.com
3353319f33470abc50a6f3da3a565d917050f9b2f53robertphillips@google.com    if (NULL != texture) {
3363319f33470abc50a6f3da3a565d917050f9b2f53robertphillips@google.com        GrDrawTarget::AutoStateRestore asr(fGpu, GrDrawTarget::kReset_ASRInit);
3373319f33470abc50a6f3da3a565d917050f9b2f53robertphillips@google.com        GrDrawState* drawState = fGpu->drawState();
3383319f33470abc50a6f3da3a565d917050f9b2f53robertphillips@google.com        drawState->setRenderTarget(texture->asRenderTarget());
3393319f33470abc50a6f3da3a565d917050f9b2f53robertphillips@google.com
3403319f33470abc50a6f3da3a565d917050f9b2f53robertphillips@google.com        // if filtering is not desired then we want to ensure all
3413319f33470abc50a6f3da3a565d917050f9b2f53robertphillips@google.com        // texels in the resampled image are copies of texels from
3423319f33470abc50a6f3da3a565d917050f9b2f53robertphillips@google.com        // the original.
343b86add1ad37776818e1f730359ec587c9fdbff5fhumper@google.com        GrTextureParams params(SkShader::kClamp_TileMode, filter ? GrTextureParams::kBilerp_FilterMode :
344b86add1ad37776818e1f730359ec587c9fdbff5fhumper@google.com                                                                   GrTextureParams::kNone_FilterMode);
345eb6879f50a5564eeb981ec5616b55bf685eb76fcbsalomon@google.com        drawState->addColorTextureEffect(clampedTexture, SkMatrix::I(), params);
3463319f33470abc50a6f3da3a565d917050f9b2f53robertphillips@google.com
347429033038271147ed66b4bc2675ac98a5ccfa75crobertphillips@google.com        drawState->setVertexAttribs<gVertexAttribs>(SK_ARRAY_COUNT(gVertexAttribs));
348054ae99d93711c26e40682a0e3a03a47ea605c53jvanverth@google.com
349b75b0a0b8492e14c7728e0a0881f87dc64ce60f9jvanverth@google.com        GrDrawTarget::AutoReleaseGeometry arg(fGpu, 4, 0);
3503319f33470abc50a6f3da3a565d917050f9b2f53robertphillips@google.com
3513319f33470abc50a6f3da3a565d917050f9b2f53robertphillips@google.com        if (arg.succeeded()) {
352972f9cd7a063d0544f8c919fd12b9a3adbd12b24commit-bot@chromium.org            SkPoint* verts = (SkPoint*) arg.vertices();
353972f9cd7a063d0544f8c919fd12b9a3adbd12b24commit-bot@chromium.org            verts[0].setIRectFan(0, 0, texture->width(), texture->height(), 2 * sizeof(SkPoint));
354972f9cd7a063d0544f8c919fd12b9a3adbd12b24commit-bot@chromium.org            verts[1].setIRectFan(0, 0, 1, 1, 2 * sizeof(SkPoint));
35595ed55adc6b8f0cee063c2cf2e14782773b0087fbsalomon@google.com            fGpu->drawNonIndexed(kTriangleFan_GrPrimitiveType, 0, 4);
3563319f33470abc50a6f3da3a565d917050f9b2f53robertphillips@google.com        }
3573319f33470abc50a6f3da3a565d917050f9b2f53robertphillips@google.com    } else {
3583319f33470abc50a6f3da3a565d917050f9b2f53robertphillips@google.com        // TODO: Our CPU stretch doesn't filter. But we create separate
35908283afc265f1153834256fc1012519813ba6b73bsalomon@google.com        // stretched textures when the texture params is either filtered or
3603319f33470abc50a6f3da3a565d917050f9b2f53robertphillips@google.com        // not. Either implement filtered stretch blit on CPU or just create
3613319f33470abc50a6f3da3a565d917050f9b2f53robertphillips@google.com        // one when FBO case fails.
3623319f33470abc50a6f3da3a565d917050f9b2f53robertphillips@google.com
3633319f33470abc50a6f3da3a565d917050f9b2f53robertphillips@google.com        rtDesc.fFlags = kNone_GrTextureFlags;
3643319f33470abc50a6f3da3a565d917050f9b2f53robertphillips@google.com        // no longer need to clamp at min RT size.
3653319f33470abc50a6f3da3a565d917050f9b2f53robertphillips@google.com        rtDesc.fWidth  = GrNextPow2(desc.fWidth);
3663319f33470abc50a6f3da3a565d917050f9b2f53robertphillips@google.com        rtDesc.fHeight = GrNextPow2(desc.fHeight);
3676e7ddaae0a077a777b8b8872ec27f8faab275536commit-bot@chromium.org
3686e7ddaae0a077a777b8b8872ec27f8faab275536commit-bot@chromium.org        // We shouldn't be resizing a compressed texture.
3696e7ddaae0a077a777b8b8872ec27f8faab275536commit-bot@chromium.org        SkASSERT(!GrPixelConfigIsCompressed(desc.fConfig));
3706e7ddaae0a077a777b8b8872ec27f8faab275536commit-bot@chromium.org
3718b169311b59ab84e8ca6f3630a1e960cc1be751erobertphillips@google.com        size_t bpp = GrBytesPerPixel(desc.fConfig);
37208283afc265f1153834256fc1012519813ba6b73bsalomon@google.com        SkAutoSMalloc<128*128*4> stretchedPixels(bpp * rtDesc.fWidth * rtDesc.fHeight);
373b0ce4b6fc8da4c3aa491fc43512e9187df1dfdaecommit-bot@chromium.org        stretch_image(stretchedPixels.get(), rtDesc.fWidth, rtDesc.fHeight,
374b0ce4b6fc8da4c3aa491fc43512e9187df1dfdaecommit-bot@chromium.org                      srcData, desc.fWidth, desc.fHeight, bpp);
3753319f33470abc50a6f3da3a565d917050f9b2f53robertphillips@google.com
3763319f33470abc50a6f3da3a565d917050f9b2f53robertphillips@google.com        size_t stretchedRowBytes = rtDesc.fWidth * bpp;
3773319f33470abc50a6f3da3a565d917050f9b2f53robertphillips@google.com
378b0ce4b6fc8da4c3aa491fc43512e9187df1dfdaecommit-bot@chromium.org        texture = fGpu->createTexture(rtDesc, stretchedPixels.get(), stretchedRowBytes);
379f6de475e5cbd143f348ff7738919e397b7fe7f57tfarina@chromium.org        SkASSERT(NULL != texture);
3803319f33470abc50a6f3da3a565d917050f9b2f53robertphillips@google.com    }
3813319f33470abc50a6f3da3a565d917050f9b2f53robertphillips@google.com
3823319f33470abc50a6f3da3a565d917050f9b2f53robertphillips@google.com    return texture;
3833319f33470abc50a6f3da3a565d917050f9b2f53robertphillips@google.com}
3843319f33470abc50a6f3da3a565d917050f9b2f53robertphillips@google.com
38595ed55adc6b8f0cee063c2cf2e14782773b0087fbsalomon@google.comGrTexture* GrContext::createTexture(const GrTextureParams* params,
38695ed55adc6b8f0cee063c2cf2e14782773b0087fbsalomon@google.com                                    const GrTextureDesc& desc,
38795ed55adc6b8f0cee063c2cf2e14782773b0087fbsalomon@google.com                                    const GrCacheID& cacheID,
388f9bd04faffb936602f7f957413a8cd5b7fc44addcommit-bot@chromium.org                                    const void* srcData,
38950a3043194cf278a74ff51c33c6cdb52cbe1f8f9commit-bot@chromium.org                                    size_t rowBytes,
39050a3043194cf278a74ff51c33c6cdb52cbe1f8f9commit-bot@chromium.org                                    GrResourceKey* cacheKey) {
391e49157f0838c615b10da0ef2b297c742da662e34commit-bot@chromium.org    GrResourceKey resourceKey = GrTextureImpl::ComputeKey(fGpu, params, desc, cacheID);
392a1e5795279bd085496fa04c59e588f440bf30457robertphillips@google.com
39395ed55adc6b8f0cee063c2cf2e14782773b0087fbsalomon@google.com    GrTexture* texture;
394e49157f0838c615b10da0ef2b297c742da662e34commit-bot@chromium.org    if (GrTextureImpl::NeedsResizing(resourceKey)) {
3959c0e629c64c0fa93ac9bf5c2eaa1821370a6fbe5krajcevski        // We do not know how to resize compressed textures.
3969c0e629c64c0fa93ac9bf5c2eaa1821370a6fbe5krajcevski        SkASSERT(!GrPixelConfigIsCompressed(desc.fConfig));
3979c0e629c64c0fa93ac9bf5c2eaa1821370a6fbe5krajcevski
39895ed55adc6b8f0cee063c2cf2e14782773b0087fbsalomon@google.com        texture = this->createResizedTexture(desc, cacheID,
39995ed55adc6b8f0cee063c2cf2e14782773b0087fbsalomon@google.com                                             srcData, rowBytes,
400e49157f0838c615b10da0ef2b297c742da662e34commit-bot@chromium.org                                             GrTextureImpl::NeedsBilerp(resourceKey));
40127847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com    } else {
4029c0e629c64c0fa93ac9bf5c2eaa1821370a6fbe5krajcevski        texture = fGpu->createTexture(desc, srcData, rowBytes);
4033319f33470abc50a6f3da3a565d917050f9b2f53robertphillips@google.com    }
4043319f33470abc50a6f3da3a565d917050f9b2f53robertphillips@google.com
4053319f33470abc50a6f3da3a565d917050f9b2f53robertphillips@google.com    if (NULL != texture) {
4061622a6d950a4a1deb13048210bdb78d952375f05robertphillips@google.com        // Adding a resource could put us overbudget. Try to free up the
4071622a6d950a4a1deb13048210bdb78d952375f05robertphillips@google.com        // necessary space before adding it.
40895c2003740c4cd01fd1b02ed93b9de7227b1d0f5commit-bot@chromium.org        fResourceCache->purgeAsNeeded(1, texture->gpuMemorySize());
40995c2003740c4cd01fd1b02ed93b9de7227b1d0f5commit-bot@chromium.org        fResourceCache->addResource(resourceKey, texture);
41050a3043194cf278a74ff51c33c6cdb52cbe1f8f9commit-bot@chromium.org
41150a3043194cf278a74ff51c33c6cdb52cbe1f8f9commit-bot@chromium.org        if (NULL != cacheKey) {
41250a3043194cf278a74ff51c33c6cdb52cbe1f8f9commit-bot@chromium.org            *cacheKey = resourceKey;
41350a3043194cf278a74ff51c33c6cdb52cbe1f8f9commit-bot@chromium.org        }
41427847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com    }
4153319f33470abc50a6f3da3a565d917050f9b2f53robertphillips@google.com
4161f47f4f7325971dd53991e2bb02da94fa7c6d962robertphillips@google.com    return texture;
41727847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com}
41827847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com
4191f3c73825b8a1752abc6b74fbce978a430de6473skia.committer@gmail.comstatic GrTexture* create_scratch_texture(GrGpu* gpu,
42095c2003740c4cd01fd1b02ed93b9de7227b1d0f5commit-bot@chromium.org                                         GrResourceCache* resourceCache,
421e4eaea2d126d58d8ce4034a1ce921404e83fe3f4robertphillips@google.com                                         const GrTextureDesc& desc) {
422e4eaea2d126d58d8ce4034a1ce921404e83fe3f4robertphillips@google.com    GrTexture* texture = gpu->createTexture(desc, NULL, 0);
423e4eaea2d126d58d8ce4034a1ce921404e83fe3f4robertphillips@google.com    if (NULL != texture) {
424e49157f0838c615b10da0ef2b297c742da662e34commit-bot@chromium.org        GrResourceKey key = GrTextureImpl::ComputeScratchKey(texture->desc());
425e4eaea2d126d58d8ce4034a1ce921404e83fe3f4robertphillips@google.com        // Adding a resource could put us overbudget. Try to free up the
426e4eaea2d126d58d8ce4034a1ce921404e83fe3f4robertphillips@google.com        // necessary space before adding it.
42795c2003740c4cd01fd1b02ed93b9de7227b1d0f5commit-bot@chromium.org        resourceCache->purgeAsNeeded(1, texture->gpuMemorySize());
428e4eaea2d126d58d8ce4034a1ce921404e83fe3f4robertphillips@google.com        // Make the resource exclusive so future 'find' calls don't return it
42995c2003740c4cd01fd1b02ed93b9de7227b1d0f5commit-bot@chromium.org        resourceCache->addResource(key, texture, GrResourceCache::kHide_OwnershipFlag);
430e4eaea2d126d58d8ce4034a1ce921404e83fe3f4robertphillips@google.com    }
431e4eaea2d126d58d8ce4034a1ce921404e83fe3f4robertphillips@google.com    return texture;
432e4eaea2d126d58d8ce4034a1ce921404e83fe3f4robertphillips@google.com}
433e4eaea2d126d58d8ce4034a1ce921404e83fe3f4robertphillips@google.com
43495ed55adc6b8f0cee063c2cf2e14782773b0087fbsalomon@google.comGrTexture* GrContext::lockAndRefScratchTexture(const GrTextureDesc& inDesc, ScratchTexMatch match) {
43575b3c9633cb9a594dab0ccf51dab1e694c149a18robertphillips@google.com
436f6de475e5cbd143f348ff7738919e397b7fe7f57tfarina@chromium.org    SkASSERT((inDesc.fFlags & kRenderTarget_GrTextureFlagBit) ||
437e4eaea2d126d58d8ce4034a1ce921404e83fe3f4robertphillips@google.com             !(inDesc.fFlags & kNoStencil_GrTextureFlagBit));
438e4eaea2d126d58d8ce4034a1ce921404e83fe3f4robertphillips@google.com
439e4eaea2d126d58d8ce4034a1ce921404e83fe3f4robertphillips@google.com    // Renderable A8 targets are not universally supported (e.g., not on ANGLE)
4408aaac8da36bb88ab13c62e84ee6ac9ebc5cb8466bsalomon@google.com    SkASSERT(this->isConfigRenderable(kAlpha_8_GrPixelConfig, inDesc.fSampleCnt > 0) ||
441e4eaea2d126d58d8ce4034a1ce921404e83fe3f4robertphillips@google.com             !(inDesc.fFlags & kRenderTarget_GrTextureFlagBit) ||
442e4eaea2d126d58d8ce4034a1ce921404e83fe3f4robertphillips@google.com             (inDesc.fConfig != kAlpha_8_GrPixelConfig));
443e4eaea2d126d58d8ce4034a1ce921404e83fe3f4robertphillips@google.com
4442d2e5c4e2425a1cb64d31d7d10832f4a3a9137a4robertphillips@google.com    if (!fGpu->caps()->reuseScratchTextures() &&
4452d2e5c4e2425a1cb64d31d7d10832f4a3a9137a4robertphillips@google.com        !(inDesc.fFlags & kRenderTarget_GrTextureFlagBit)) {
4462d2e5c4e2425a1cb64d31d7d10832f4a3a9137a4robertphillips@google.com        // If we're never recycling this texture we can always make it the right size
44795c2003740c4cd01fd1b02ed93b9de7227b1d0f5commit-bot@chromium.org        return create_scratch_texture(fGpu, fResourceCache, inDesc);
448e4eaea2d126d58d8ce4034a1ce921404e83fe3f4robertphillips@google.com    }
449e4eaea2d126d58d8ce4034a1ce921404e83fe3f4robertphillips@google.com
450e4eaea2d126d58d8ce4034a1ce921404e83fe3f4robertphillips@google.com    GrTextureDesc desc = inDesc;
4512afb8ec738fc50ea6e4500545c3cacbf346ed187rileya@google.com
4520797c2cceadd7dfc2e7f9efa30b611d18efcdcddbsalomon@google.com    if (kApprox_ScratchTexMatch == match) {
45350398bf7f1953e640e5529616e710cf540799731bsalomon@google.com        // bin by pow2 with a reasonable min
45440db6dc98d13e4632cdeaab1577a5e09fd2ad18fbsalomon@google.com        static const int MIN_SIZE = 16;
455972f9cd7a063d0544f8c919fd12b9a3adbd12b24commit-bot@chromium.org        desc.fWidth  = SkTMax(MIN_SIZE, GrNextPow2(desc.fWidth));
456972f9cd7a063d0544f8c919fd12b9a3adbd12b24commit-bot@chromium.org        desc.fHeight = SkTMax(MIN_SIZE, GrNextPow2(desc.fHeight));
45750398bf7f1953e640e5529616e710cf540799731bsalomon@google.com    }
458b5b3168a645802f66233234a06dd5a3764f18018bsalomon@google.com
459089a780c3355129eefc942246534bc1f126b8ccbcommit-bot@chromium.org    GrCacheable* resource = NULL;
460b5b3168a645802f66233234a06dd5a3764f18018bsalomon@google.com    int origWidth = desc.fWidth;
461b5b3168a645802f66233234a06dd5a3764f18018bsalomon@google.com    int origHeight = desc.fHeight;
462b5b3168a645802f66233234a06dd5a3764f18018bsalomon@google.com
463b5b3168a645802f66233234a06dd5a3764f18018bsalomon@google.com    do {
464e49157f0838c615b10da0ef2b297c742da662e34commit-bot@chromium.org        GrResourceKey key = GrTextureImpl::ComputeScratchKey(desc);
465209a1143a1a26935578d45c7f86dc6f9aa2eb1a6robertphillips@google.com        // Ensure we have exclusive access to the texture so future 'find' calls don't return it
46695c2003740c4cd01fd1b02ed93b9de7227b1d0f5commit-bot@chromium.org        resource = fResourceCache->find(key, GrResourceCache::kHide_OwnershipFlag);
46795ed55adc6b8f0cee063c2cf2e14782773b0087fbsalomon@google.com        if (NULL != resource) {
46895ed55adc6b8f0cee063c2cf2e14782773b0087fbsalomon@google.com            resource->ref();
46995ed55adc6b8f0cee063c2cf2e14782773b0087fbsalomon@google.com            break;
47095ed55adc6b8f0cee063c2cf2e14782773b0087fbsalomon@google.com        }
47195ed55adc6b8f0cee063c2cf2e14782773b0087fbsalomon@google.com        if (kExact_ScratchTexMatch == match) {
472b5b3168a645802f66233234a06dd5a3764f18018bsalomon@google.com            break;
473b5b3168a645802f66233234a06dd5a3764f18018bsalomon@google.com        }
47440db6dc98d13e4632cdeaab1577a5e09fd2ad18fbsalomon@google.com        // We had a cache miss and we are in approx mode, relax the fit of the flags.
47595ed55adc6b8f0cee063c2cf2e14782773b0087fbsalomon@google.com
476fbfcd5602128ec010c82cb733c9cdc0a3254f9f3rmistry@google.com        // We no longer try to reuse textures that were previously used as render targets in
4772afb8ec738fc50ea6e4500545c3cacbf346ed187rileya@google.com        // situations where no RT is needed; doing otherwise can confuse the video driver and
4782afb8ec738fc50ea6e4500545c3cacbf346ed187rileya@google.com        // cause significant performance problems in some cases.
4792afb8ec738fc50ea6e4500545c3cacbf346ed187rileya@google.com        if (desc.fFlags & kNoStencil_GrTextureFlagBit) {
480b5b3168a645802f66233234a06dd5a3764f18018bsalomon@google.com            desc.fFlags = desc.fFlags & ~kNoStencil_GrTextureFlagBit;
481b5b3168a645802f66233234a06dd5a3764f18018bsalomon@google.com        } else {
482b5b3168a645802f66233234a06dd5a3764f18018bsalomon@google.com            break;
483b5b3168a645802f66233234a06dd5a3764f18018bsalomon@google.com        }
484fbfcd5602128ec010c82cb733c9cdc0a3254f9f3rmistry@google.com
485b5b3168a645802f66233234a06dd5a3764f18018bsalomon@google.com    } while (true);
486b5b3168a645802f66233234a06dd5a3764f18018bsalomon@google.com
4871f47f4f7325971dd53991e2bb02da94fa7c6d962robertphillips@google.com    if (NULL == resource) {
488b5b3168a645802f66233234a06dd5a3764f18018bsalomon@google.com        desc.fFlags = inDesc.fFlags;
489b5b3168a645802f66233234a06dd5a3764f18018bsalomon@google.com        desc.fWidth = origWidth;
490b5b3168a645802f66233234a06dd5a3764f18018bsalomon@google.com        desc.fHeight = origHeight;
49195c2003740c4cd01fd1b02ed93b9de7227b1d0f5commit-bot@chromium.org        resource = create_scratch_texture(fGpu, fResourceCache, desc);
492b5b3168a645802f66233234a06dd5a3764f18018bsalomon@google.com    }
493b5b3168a645802f66233234a06dd5a3764f18018bsalomon@google.com
4941f47f4f7325971dd53991e2bb02da94fa7c6d962robertphillips@google.com    return static_cast<GrTexture*>(resource);
495b5b3168a645802f66233234a06dd5a3764f18018bsalomon@google.com}
496b5b3168a645802f66233234a06dd5a3764f18018bsalomon@google.com
49715c0fea699b25343fe6f49668a5632866e1a0306robertphillips@google.comvoid GrContext::addExistingTextureToCache(GrTexture* texture) {
49815c0fea699b25343fe6f49668a5632866e1a0306robertphillips@google.com
49915c0fea699b25343fe6f49668a5632866e1a0306robertphillips@google.com    if (NULL == texture) {
50015c0fea699b25343fe6f49668a5632866e1a0306robertphillips@google.com        return;
50115c0fea699b25343fe6f49668a5632866e1a0306robertphillips@google.com    }
50215c0fea699b25343fe6f49668a5632866e1a0306robertphillips@google.com
503521eaf8cc73cebebeaf54338c51c22922ac70951robertphillips@google.com    // This texture should already have a cache entry since it was once
504521eaf8cc73cebebeaf54338c51c22922ac70951robertphillips@google.com    // attached
505f6de475e5cbd143f348ff7738919e397b7fe7f57tfarina@chromium.org    SkASSERT(NULL != texture->getCacheEntry());
506521eaf8cc73cebebeaf54338c51c22922ac70951robertphillips@google.com
507521eaf8cc73cebebeaf54338c51c22922ac70951robertphillips@google.com    // Conceptually, the cache entry is going to assume responsibility
5089ef0426e7c126f6ad6ba833d4543b92a197c95afrobertphillips@google.com    // for the creation ref. Assert refcnt == 1.
509f6de475e5cbd143f348ff7738919e397b7fe7f57tfarina@chromium.org    SkASSERT(texture->unique());
510521eaf8cc73cebebeaf54338c51c22922ac70951robertphillips@google.com
5112d2e5c4e2425a1cb64d31d7d10832f4a3a9137a4robertphillips@google.com    if (fGpu->caps()->reuseScratchTextures() || NULL != texture->asRenderTarget()) {
5129ef0426e7c126f6ad6ba833d4543b92a197c95afrobertphillips@google.com        // Since this texture came from an AutoScratchTexture it should
5139ef0426e7c126f6ad6ba833d4543b92a197c95afrobertphillips@google.com        // still be in the exclusive pile. Recycle it.
51495c2003740c4cd01fd1b02ed93b9de7227b1d0f5commit-bot@chromium.org        fResourceCache->makeNonExclusive(texture->getCacheEntry());
515e4eaea2d126d58d8ce4034a1ce921404e83fe3f4robertphillips@google.com        this->purgeCache();
5169ef0426e7c126f6ad6ba833d4543b92a197c95afrobertphillips@google.com    } else if (texture->getDeferredRefCount() <= 0) {
517e4eaea2d126d58d8ce4034a1ce921404e83fe3f4robertphillips@google.com        // When we aren't reusing textures we know this scratch texture
518e4eaea2d126d58d8ce4034a1ce921404e83fe3f4robertphillips@google.com        // will never be reused and would be just wasting time in the cache
51995c2003740c4cd01fd1b02ed93b9de7227b1d0f5commit-bot@chromium.org        fResourceCache->makeNonExclusive(texture->getCacheEntry());
52095c2003740c4cd01fd1b02ed93b9de7227b1d0f5commit-bot@chromium.org        fResourceCache->deleteResource(texture->getCacheEntry());
5219ef0426e7c126f6ad6ba833d4543b92a197c95afrobertphillips@google.com    } else {
5229ef0426e7c126f6ad6ba833d4543b92a197c95afrobertphillips@google.com        // In this case (fDeferredRefCount > 0) but the cache is the only
5239ef0426e7c126f6ad6ba833d4543b92a197c95afrobertphillips@google.com        // one holding a real ref. Mark the object so when the deferred
5249ef0426e7c126f6ad6ba833d4543b92a197c95afrobertphillips@google.com        // ref count goes to 0 the texture will be deleted (remember
5259ef0426e7c126f6ad6ba833d4543b92a197c95afrobertphillips@google.com        // in this code path scratch textures aren't getting reused).
5269ef0426e7c126f6ad6ba833d4543b92a197c95afrobertphillips@google.com        texture->setNeedsDeferredUnref();
527e4eaea2d126d58d8ce4034a1ce921404e83fe3f4robertphillips@google.com    }
52815c0fea699b25343fe6f49668a5632866e1a0306robertphillips@google.com}
52915c0fea699b25343fe6f49668a5632866e1a0306robertphillips@google.com
530a9b0623eac4a473517c15418dbdc1e331ee752d2robertphillips@google.com
5319fbcad0f00d7098574cf3394a812c9d845c9cc5brobertphillips@google.comvoid GrContext::unlockScratchTexture(GrTexture* texture) {
5321f47f4f7325971dd53991e2bb02da94fa7c6d962robertphillips@google.com    ASSERT_OWNED_RESOURCE(texture);
533f6de475e5cbd143f348ff7738919e397b7fe7f57tfarina@chromium.org    SkASSERT(NULL != texture->getCacheEntry());
5341f47f4f7325971dd53991e2bb02da94fa7c6d962robertphillips@google.com
53550398bf7f1953e640e5529616e710cf540799731bsalomon@google.com    // If this is a scratch texture we detached it from the cache
53650398bf7f1953e640e5529616e710cf540799731bsalomon@google.com    // while it was locked (to avoid two callers simultaneously getting
53750398bf7f1953e640e5529616e710cf540799731bsalomon@google.com    // the same texture).
5380797c2cceadd7dfc2e7f9efa30b611d18efcdcddbsalomon@google.com    if (texture->getCacheEntry()->key().isScratch()) {
5392d2e5c4e2425a1cb64d31d7d10832f4a3a9137a4robertphillips@google.com        if (fGpu->caps()->reuseScratchTextures() || NULL != texture->asRenderTarget()) {
54095c2003740c4cd01fd1b02ed93b9de7227b1d0f5commit-bot@chromium.org            fResourceCache->makeNonExclusive(texture->getCacheEntry());
5419ef0426e7c126f6ad6ba833d4543b92a197c95afrobertphillips@google.com            this->purgeCache();
5429ef0426e7c126f6ad6ba833d4543b92a197c95afrobertphillips@google.com        } else if (texture->unique() && texture->getDeferredRefCount() <= 0) {
543b77f0f4ae560e97cc4cd2758752d955549017c3cskia.committer@gmail.com            // Only the cache now knows about this texture. Since we're never
544b77f0f4ae560e97cc4cd2758752d955549017c3cskia.committer@gmail.com            // reusing scratch textures (in this code path) it would just be
5459ef0426e7c126f6ad6ba833d4543b92a197c95afrobertphillips@google.com            // wasting time sitting in the cache.
54695c2003740c4cd01fd1b02ed93b9de7227b1d0f5commit-bot@chromium.org            fResourceCache->makeNonExclusive(texture->getCacheEntry());
54795c2003740c4cd01fd1b02ed93b9de7227b1d0f5commit-bot@chromium.org            fResourceCache->deleteResource(texture->getCacheEntry());
5489ef0426e7c126f6ad6ba833d4543b92a197c95afrobertphillips@google.com        } else {
5499ef0426e7c126f6ad6ba833d4543b92a197c95afrobertphillips@google.com            // In this case (fRefCnt > 1 || defRefCnt > 0) but we don't really
550b77f0f4ae560e97cc4cd2758752d955549017c3cskia.committer@gmail.com            // want to readd it to the cache (since it will never be reused).
5519ef0426e7c126f6ad6ba833d4543b92a197c95afrobertphillips@google.com            // Instead, give up the cache's ref and leave the decision up to
5529ef0426e7c126f6ad6ba833d4543b92a197c95afrobertphillips@google.com            // addExistingTextureToCache once its ref count reaches 0. For
5539ef0426e7c126f6ad6ba833d4543b92a197c95afrobertphillips@google.com            // this to work we need to leave it in the exclusive list.
554e49157f0838c615b10da0ef2b297c742da662e34commit-bot@chromium.org            texture->impl()->setFlag((GrTextureFlags) GrTextureImpl::kReturnToCache_FlagBit);
5559ef0426e7c126f6ad6ba833d4543b92a197c95afrobertphillips@google.com            // Give up the cache's ref to the texture
5569ef0426e7c126f6ad6ba833d4543b92a197c95afrobertphillips@google.com            texture->unref();
5579ef0426e7c126f6ad6ba833d4543b92a197c95afrobertphillips@google.com        }
558fea37b5e532dfe776269253afb9951e763c3b205bsalomon@google.com    }
55950a035ddbb068446645b0978f4c092dec87a1a02robertphillips@google.com}
56050a035ddbb068446645b0978f4c092dec87a1a02robertphillips@google.com
56150a035ddbb068446645b0978f4c092dec87a1a02robertphillips@google.comvoid GrContext::purgeCache() {
56295c2003740c4cd01fd1b02ed93b9de7227b1d0f5commit-bot@chromium.org    if (NULL != fResourceCache) {
56395c2003740c4cd01fd1b02ed93b9de7227b1d0f5commit-bot@chromium.org        fResourceCache->purgeAsNeeded();
564eb9b3e164e55b8d15e1c25bfb1332917453cbc3arobertphillips@google.com    }
56515c0fea699b25343fe6f49668a5632866e1a0306robertphillips@google.com}
56615c0fea699b25343fe6f49668a5632866e1a0306robertphillips@google.com
567cae27fed5e45e8899e56ece22b27e8958ffc0162commit-bot@chromium.orgbool GrContext::OverbudgetCB(void* data) {
568f6de475e5cbd143f348ff7738919e397b7fe7f57tfarina@chromium.org    SkASSERT(NULL != data);
569cae27fed5e45e8899e56ece22b27e8958ffc0162commit-bot@chromium.org
570cae27fed5e45e8899e56ece22b27e8958ffc0162commit-bot@chromium.org    GrContext* context = reinterpret_cast<GrContext*>(data);
571cae27fed5e45e8899e56ece22b27e8958ffc0162commit-bot@chromium.org
572cae27fed5e45e8899e56ece22b27e8958ffc0162commit-bot@chromium.org    // Flush the InOrderDrawBuffer to possibly free up some textures
5735dbb149fda134941e5d168790127caf294d322e2commit-bot@chromium.org    context->fFlushToReduceCacheSize = true;
574cae27fed5e45e8899e56ece22b27e8958ffc0162commit-bot@chromium.org
575cae27fed5e45e8899e56ece22b27e8958ffc0162commit-bot@chromium.org    return true;
576cae27fed5e45e8899e56ece22b27e8958ffc0162commit-bot@chromium.org}
577cae27fed5e45e8899e56ece22b27e8958ffc0162commit-bot@chromium.org
578cae27fed5e45e8899e56ece22b27e8958ffc0162commit-bot@chromium.org
57975b3c9633cb9a594dab0ccf51dab1e694c149a18robertphillips@google.comGrTexture* GrContext::createUncachedTexture(const GrTextureDesc& descIn,
58027847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com                                            void* srcData,
58127847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com                                            size_t rowBytes) {
58275b3c9633cb9a594dab0ccf51dab1e694c149a18robertphillips@google.com    GrTextureDesc descCopy = descIn;
58375b3c9633cb9a594dab0ccf51dab1e694c149a18robertphillips@google.com    return fGpu->createTexture(descCopy, srcData, rowBytes);
58427847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com}
58527847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com
58695c2003740c4cd01fd1b02ed93b9de7227b1d0f5commit-bot@chromium.orgvoid GrContext::getResourceCacheLimits(int* maxTextures, size_t* maxTextureBytes) const {
58795c2003740c4cd01fd1b02ed93b9de7227b1d0f5commit-bot@chromium.org    fResourceCache->getLimits(maxTextures, maxTextureBytes);
58827847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com}
58927847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com
59095c2003740c4cd01fd1b02ed93b9de7227b1d0f5commit-bot@chromium.orgvoid GrContext::setResourceCacheLimits(int maxTextures, size_t maxTextureBytes) {
59195c2003740c4cd01fd1b02ed93b9de7227b1d0f5commit-bot@chromium.org    fResourceCache->setLimits(maxTextures, maxTextureBytes);
59227847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com}
59327847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com
594919583674bd5daeb60327c0bc1ce8aaa80d54e13bsalomon@google.comint GrContext::getMaxTextureSize() const {
595972f9cd7a063d0544f8c919fd12b9a3adbd12b24commit-bot@chromium.org    return SkTMin(fGpu->caps()->maxTextureSize(), fMaxTextureSizeOverride);
596919583674bd5daeb60327c0bc1ce8aaa80d54e13bsalomon@google.com}
597919583674bd5daeb60327c0bc1ce8aaa80d54e13bsalomon@google.com
598919583674bd5daeb60327c0bc1ce8aaa80d54e13bsalomon@google.comint GrContext::getMaxRenderTargetSize() const {
599bcce8926524827775539874346dd424a9510dbc9bsalomon@google.com    return fGpu->caps()->maxRenderTargetSize();
60027847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com}
60127847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com
6028a70eef71cf369803e97ffea786f43f944de758ebsalomon@google.comint GrContext::getMaxSampleCount() const {
603bcce8926524827775539874346dd424a9510dbc9bsalomon@google.com    return fGpu->caps()->maxSampleCount();
6048a70eef71cf369803e97ffea786f43f944de758ebsalomon@google.com}
6058a70eef71cf369803e97ffea786f43f944de758ebsalomon@google.com
60627847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com///////////////////////////////////////////////////////////////////////////////
60727847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com
60816e3ddea6a80972aced04b21b1d66377fa95e7c7bsalomon@google.comGrTexture* GrContext::wrapBackendTexture(const GrBackendTextureDesc& desc) {
60916e3ddea6a80972aced04b21b1d66377fa95e7c7bsalomon@google.com    return fGpu->wrapBackendTexture(desc);
610e269f210bdae0288643afaf8a579b22d3f6d5bebbsalomon@google.com}
611e269f210bdae0288643afaf8a579b22d3f6d5bebbsalomon@google.com
61216e3ddea6a80972aced04b21b1d66377fa95e7c7bsalomon@google.comGrRenderTarget* GrContext::wrapBackendRenderTarget(const GrBackendRenderTargetDesc& desc) {
61316e3ddea6a80972aced04b21b1d66377fa95e7c7bsalomon@google.com    return fGpu->wrapBackendRenderTarget(desc);
614e269f210bdae0288643afaf8a579b22d3f6d5bebbsalomon@google.com}
615e269f210bdae0288643afaf8a579b22d3f6d5bebbsalomon@google.com
6165877ffd5ea71a3ea70096d5c11c843798defa690bsalomon@google.com///////////////////////////////////////////////////////////////////////////////
6175877ffd5ea71a3ea70096d5c11c843798defa690bsalomon@google.com
618b8670998a59d305cd22a3c0cbdc6e075b0a37a6ebsalomon@google.combool GrContext::supportsIndex8PixelConfig(const GrTextureParams* params,
6191f221a70214fa1ab87b8a32dd66facf485f318eebsalomon@google.com                                          int width, int height) const {
620c26d94fd7dc0b00cd6d0e42d28285f4a38aff021bsalomon@google.com    const GrDrawTargetCaps* caps = fGpu->caps();
6216e7ddaae0a077a777b8b8872ec27f8faab275536commit-bot@chromium.org    if (!caps->isConfigTexturable(kIndex_8_GrPixelConfig)) {
62227847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com        return false;
62327847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com    }
62427847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com
625f9dae780c2c46a1f08adbbe8de2faaba091254d4tfarina    bool isPow2 = SkIsPow2(width) && SkIsPow2(height);
62627847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com
62727847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com    if (!isPow2) {
628b8670998a59d305cd22a3c0cbdc6e075b0a37a6ebsalomon@google.com        bool tiled = NULL != params && params->isTiled();
629bcce8926524827775539874346dd424a9510dbc9bsalomon@google.com        if (tiled && !caps->npotTextureTileSupport()) {
63027847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com            return false;
63127847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com        }
63227847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com    }
63327847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com    return true;
63427847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com}
63527847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com
63627847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com
63727847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com////////////////////////////////////////////////////////////////////////////////
63827847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com
639fd03d4a829efe2d77a712fd991927c55f59a2ffecommit-bot@chromium.orgvoid GrContext::clear(const SkIRect* rect,
64007ea2db0260d8e6cd2bf605571b68b1c574b5a77bsalomon@google.com                      const GrColor color,
64156ce48ade325f6f49acb0da31d6252806e4ed7efrobertphillips@google.com                      bool canIgnoreRect,
642c82a8b7aa4ec19fba508c394920a9e88d3e5bd12robertphillips@google.com                      GrRenderTarget* target) {
643eb6879f50a5564eeb981ec5616b55bf685eb76fcbsalomon@google.com    AutoRestoreEffects are;
6445dbb149fda134941e5d168790127caf294d322e2commit-bot@chromium.org    AutoCheckFlush acf(this);
64518bb41e9563748fbde07c1540da9314cbb7d1dc8skia.committer@gmail.com    this->prepareToDraw(NULL, BUFFERED_DRAW, &are, &acf)->clear(rect, color,
64656ce48ade325f6f49acb0da31d6252806e4ed7efrobertphillips@google.com                                                                canIgnoreRect, target);
64727847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com}
64827847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com
6495dc26b97366934ba0f896cea02a3fec027d5d5c1bsalomon@google.comvoid GrContext::drawPaint(const GrPaint& origPaint) {
65027847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com    // set rect to be big enough to fill the space, but not super-huge, so we
65127847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com    // don't overflow fixed-point implementations
652fd03d4a829efe2d77a712fd991927c55f59a2ffecommit-bot@chromium.org    SkRect r;
653d302f1401b3c9aea094804bad4e76de98782cfe8bsalomon@google.com    r.setLTRB(0, 0,
65481712883419f76e25d2ffec38a9438284a45a48dbsalomon@google.com              SkIntToScalar(getRenderTarget()->width()),
65581712883419f76e25d2ffec38a9438284a45a48dbsalomon@google.com              SkIntToScalar(getRenderTarget()->height()));
656b9086a026844e4cfd08b219e49ce3f12294cba98bsalomon@google.com    SkMatrix inverse;
6575dc26b97366934ba0f896cea02a3fec027d5d5c1bsalomon@google.com    SkTCopyOnFirstWrite<GrPaint> paint(origPaint);
658fea85ac3e31842f80493e2df8a93a28f21cd815frobertphillips@google.com    AutoMatrix am;
6598f9cbd62ec108d410b91155dcf6a4789c641246fbsalomon@google.com
6604f83be8f865921b60e3326b3fed6d5bc8281b541bsalomon@google.com    // We attempt to map r by the inverse matrix and draw that. mapRect will
6614f83be8f865921b60e3326b3fed6d5bc8281b541bsalomon@google.com    // map the four corners and bound them with a new rect. This will not
6624f83be8f865921b60e3326b3fed6d5bc8281b541bsalomon@google.com    // produce a correct result for some perspective matrices.
6638c2fe99ed2c210317786683e8c1f1e86cff0be49bsalomon@google.com    if (!this->getMatrix().hasPerspective()) {
664bb6a3178c3e79c8549b332e4ce84c64b59964f1ecommit-bot@chromium.org        if (!fViewMatrix.invert(&inverse)) {
665e3d3216fe17b6afb2e613271b5246a2766e12df6bsalomon@google.com            GrPrintf("Could not invert matrix\n");
6668c2fe99ed2c210317786683e8c1f1e86cff0be49bsalomon@google.com            return;
6678c2fe99ed2c210317786683e8c1f1e86cff0be49bsalomon@google.com        }
66827847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com        inverse.mapRect(&r);
66927847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com    } else {
6703cbaa2d4da8bc39a99bf3afaaab43cc6dc481723bsalomon@google.com        if (!am.setIdentity(this, paint.writable())) {
6713cbaa2d4da8bc39a99bf3afaaab43cc6dc481723bsalomon@google.com            GrPrintf("Could not invert matrix\n");
6723cbaa2d4da8bc39a99bf3afaaab43cc6dc481723bsalomon@google.com            return;
6738c2fe99ed2c210317786683e8c1f1e86cff0be49bsalomon@google.com        }
67427847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com    }
6754f83be8f865921b60e3326b3fed6d5bc8281b541bsalomon@google.com    // by definition this fills the entire clip, no need for AA
6765dc26b97366934ba0f896cea02a3fec027d5d5c1bsalomon@google.com    if (paint->isAntiAlias()) {
6775dc26b97366934ba0f896cea02a3fec027d5d5c1bsalomon@google.com        paint.writable()->setAntiAlias(false);
6784f83be8f865921b60e3326b3fed6d5bc8281b541bsalomon@google.com    }
6795dc26b97366934ba0f896cea02a3fec027d5d5c1bsalomon@google.com    this->drawRect(*paint, r);
68027847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com}
68127847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com
68203e3e89641c93df603dfb705d518848dfe81427ecommit-bot@chromium.org#ifdef SK_DEVELOPER
68303e3e89641c93df603dfb705d518848dfe81427ecommit-bot@chromium.orgvoid GrContext::dumpFontCache() const {
68403e3e89641c93df603dfb705d518848dfe81427ecommit-bot@chromium.org    fFontCache->dump();
68503e3e89641c93df603dfb705d518848dfe81427ecommit-bot@chromium.org}
68603e3e89641c93df603dfb705d518848dfe81427ecommit-bot@chromium.org#endif
68703e3e89641c93df603dfb705d518848dfe81427ecommit-bot@chromium.org
688205d46067ace24bd4b111cf44efc96caff6c4d30bsalomon@google.com////////////////////////////////////////////////////////////////////////////////
689205d46067ace24bd4b111cf44efc96caff6c4d30bsalomon@google.com
69027847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com/*  create a triangle strip that strokes the specified triangle. There are 8
69127847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com unique vertices, but we repreat the last 2 to close up. Alternatively we
69227847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com could use an indices array, and then only send 8 verts, but not sure that
69327847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com would be faster.
69427847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com */
695972f9cd7a063d0544f8c919fd12b9a3adbd12b24commit-bot@chromium.orgstatic void setStrokeRectStrip(SkPoint verts[10], SkRect rect,
69681712883419f76e25d2ffec38a9438284a45a48dbsalomon@google.com                               SkScalar width) {
69781712883419f76e25d2ffec38a9438284a45a48dbsalomon@google.com    const SkScalar rad = SkScalarHalf(width);
698205d46067ace24bd4b111cf44efc96caff6c4d30bsalomon@google.com    rect.sort();
69927847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com
70027847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com    verts[0].set(rect.fLeft + rad, rect.fTop + rad);
70127847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com    verts[1].set(rect.fLeft - rad, rect.fTop - rad);
70227847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com    verts[2].set(rect.fRight - rad, rect.fTop + rad);
70327847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com    verts[3].set(rect.fRight + rad, rect.fTop - rad);
70427847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com    verts[4].set(rect.fRight - rad, rect.fBottom - rad);
70527847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com    verts[5].set(rect.fRight + rad, rect.fBottom + rad);
70627847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com    verts[6].set(rect.fLeft + rad, rect.fBottom - rad);
70727847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com    verts[7].set(rect.fLeft - rad, rect.fBottom + rad);
70827847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com    verts[8] = verts[0];
70927847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com    verts[9] = verts[1];
71027847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com}
71127847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com
712fd03d4a829efe2d77a712fd991927c55f59a2ffecommit-bot@chromium.orgstatic bool isIRect(const SkRect& r) {
713eafdf126d44abadf01e7d2910739e228f557df51skia.committer@gmail.com    return SkScalarIsInt(r.fLeft)  && SkScalarIsInt(r.fTop) &&
714eafdf126d44abadf01e7d2910739e228f557df51skia.committer@gmail.com           SkScalarIsInt(r.fRight) && SkScalarIsInt(r.fBottom);
715afd1cba5237eba5394ee011106eede9f6c8074c8robertphillips@google.com}
716afd1cba5237eba5394ee011106eede9f6c8074c8robertphillips@google.com
717205d46067ace24bd4b111cf44efc96caff6c4d30bsalomon@google.comstatic bool apply_aa_to_rect(GrDrawTarget* target,
718fd03d4a829efe2d77a712fd991927c55f59a2ffecommit-bot@chromium.org                             const SkRect& rect,
719df3695e5c72b3b4401e71ff259827d87bfe8a06frobertphillips@google.com                             SkScalar strokeWidth,
72024ab3b0ce50b3428f063849b6160e468f047487ccommit-bot@chromium.org                             const SkMatrix& combinedMatrix,
72124ab3b0ce50b3428f063849b6160e468f047487ccommit-bot@chromium.org                             SkRect* devBoundRect,
722a31082685544d0ae4c0b203d7f5ff960640ed8dfbsalomon@google.com                             bool* useVertexCoverage) {
7232eba795bcda66813fdc7a7c4388a99ae9cb2c864bsalomon@google.com    // we use a simple coverage ramp to do aa on axis-aligned rects
724fbfcd5602128ec010c82cb733c9cdc0a3254f9f3rmistry@google.com    // we check if the rect will be axis-aligned, and the rect won't land on
7252eba795bcda66813fdc7a7c4388a99ae9cb2c864bsalomon@google.com    // integer coords.
726d46e2423a71d38b8a057cec2356741e35b03334dbsalomon@google.com
727a31082685544d0ae4c0b203d7f5ff960640ed8dfbsalomon@google.com    // we are keeping around the "tweak the alpha" trick because
728a31082685544d0ae4c0b203d7f5ff960640ed8dfbsalomon@google.com    // it is our only hope for the fixed-pipe implementation.
729a31082685544d0ae4c0b203d7f5ff960640ed8dfbsalomon@google.com    // In a shader implementation we can give a separate coverage input
730289533ada623f2238a83771eec977f204f75994fbsalomon@google.com    // TODO: remove this ugliness when we drop the fixed-pipe impl
731a31082685544d0ae4c0b203d7f5ff960640ed8dfbsalomon@google.com    *useVertexCoverage = false;
7322b446734cfa8201e5478648988de86b646cb9544bsalomon@google.com    if (!target->getDrawState().canTweakAlphaForCoverage()) {
733e0a868c84ebc34c5a16b5faa1546016abb9ca0accommit-bot@chromium.org        if (target->shouldDisableCoverageAAForBlend()) {
734515dcd36032997ce335daa0163c6d67e851bcad1commit-bot@chromium.org#ifdef SK_DEBUG
7352eba795bcda66813fdc7a7c4388a99ae9cb2c864bsalomon@google.com            //GrPrintf("Turning off AA to correctly apply blend.\n");
7361983f39f1bf6295c96c0f1f7ead9f568923390bcbsalomon@google.com#endif
737a31082685544d0ae4c0b203d7f5ff960640ed8dfbsalomon@google.com            return false;
7382eba795bcda66813fdc7a7c4388a99ae9cb2c864bsalomon@google.com        } else {
7392eba795bcda66813fdc7a7c4388a99ae9cb2c864bsalomon@google.com            *useVertexCoverage = true;
740a31082685544d0ae4c0b203d7f5ff960640ed8dfbsalomon@google.com        }
741205d46067ace24bd4b111cf44efc96caff6c4d30bsalomon@google.com    }
7428f9cbd62ec108d410b91155dcf6a4789c641246fbsalomon@google.com    const GrDrawState& drawState = target->getDrawState();
7438f9cbd62ec108d410b91155dcf6a4789c641246fbsalomon@google.com    if (drawState.getRenderTarget()->isMultisampled()) {
744205d46067ace24bd4b111cf44efc96caff6c4d30bsalomon@google.com        return false;
745205d46067ace24bd4b111cf44efc96caff6c4d30bsalomon@google.com    }
746205d46067ace24bd4b111cf44efc96caff6c4d30bsalomon@google.com
747df3695e5c72b3b4401e71ff259827d87bfe8a06frobertphillips@google.com    if (0 == strokeWidth && target->willUseHWAALines()) {
748205d46067ace24bd4b111cf44efc96caff6c4d30bsalomon@google.com        return false;
749205d46067ace24bd4b111cf44efc96caff6c4d30bsalomon@google.com    }
750205d46067ace24bd4b111cf44efc96caff6c4d30bsalomon@google.com
7514b140b5fbedcb75d0b9587fa9d232ce54d9c7eb5robertphillips@google.com#if defined(SHADER_AA_FILL_RECT) || !defined(IGNORE_ROT_AA_RECT_OPT)
752df3695e5c72b3b4401e71ff259827d87bfe8a06frobertphillips@google.com    if (strokeWidth >= 0) {
753df3695e5c72b3b4401e71ff259827d87bfe8a06frobertphillips@google.com#endif
75424ab3b0ce50b3428f063849b6160e468f047487ccommit-bot@chromium.org        if (!combinedMatrix.preservesAxisAlignment()) {
755df3695e5c72b3b4401e71ff259827d87bfe8a06frobertphillips@google.com            return false;
756df3695e5c72b3b4401e71ff259827d87bfe8a06frobertphillips@google.com        }
757205d46067ace24bd4b111cf44efc96caff6c4d30bsalomon@google.com
7584b140b5fbedcb75d0b9587fa9d232ce54d9c7eb5robertphillips@google.com#if defined(SHADER_AA_FILL_RECT) || !defined(IGNORE_ROT_AA_RECT_OPT)
759df3695e5c72b3b4401e71ff259827d87bfe8a06frobertphillips@google.com    } else {
76024ab3b0ce50b3428f063849b6160e468f047487ccommit-bot@chromium.org        if (!combinedMatrix.preservesRightAngles()) {
761df3695e5c72b3b4401e71ff259827d87bfe8a06frobertphillips@google.com            return false;
762df3695e5c72b3b4401e71ff259827d87bfe8a06frobertphillips@google.com        }
763205d46067ace24bd4b111cf44efc96caff6c4d30bsalomon@google.com    }
764df3695e5c72b3b4401e71ff259827d87bfe8a06frobertphillips@google.com#endif
765205d46067ace24bd4b111cf44efc96caff6c4d30bsalomon@google.com
76624ab3b0ce50b3428f063849b6160e468f047487ccommit-bot@chromium.org    combinedMatrix.mapRect(devBoundRect, rect);
76728ac96e40d705f7fb08a61ac027e15de8d91823crobertphillips@google.com
768afd1cba5237eba5394ee011106eede9f6c8074c8robertphillips@google.com    if (strokeWidth < 0) {
76924ab3b0ce50b3428f063849b6160e468f047487ccommit-bot@chromium.org        return !isIRect(*devBoundRect);
770afd1cba5237eba5394ee011106eede9f6c8074c8robertphillips@google.com    } else {
771afd1cba5237eba5394ee011106eede9f6c8074c8robertphillips@google.com        return true;
772afd1cba5237eba5394ee011106eede9f6c8074c8robertphillips@google.com    }
773205d46067ace24bd4b111cf44efc96caff6c4d30bsalomon@google.com}
774205d46067ace24bd4b111cf44efc96caff6c4d30bsalomon@google.com
77524ab3b0ce50b3428f063849b6160e468f047487ccommit-bot@chromium.orgstatic inline bool rect_contains_inclusive(const SkRect& rect, const SkPoint& point) {
77624ab3b0ce50b3428f063849b6160e468f047487ccommit-bot@chromium.org    return point.fX >= rect.fLeft && point.fX <= rect.fRight &&
77724ab3b0ce50b3428f063849b6160e468f047487ccommit-bot@chromium.org           point.fY >= rect.fTop && point.fY <= rect.fBottom;
77824ab3b0ce50b3428f063849b6160e468f047487ccommit-bot@chromium.org}
77924ab3b0ce50b3428f063849b6160e468f047487ccommit-bot@chromium.org
78027847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.comvoid GrContext::drawRect(const GrPaint& paint,
781fd03d4a829efe2d77a712fd991927c55f59a2ffecommit-bot@chromium.org                         const SkRect& rect,
782d58a0ba9cff9fcefe5047e88ccb4a6e76c591c40egdaniel                         const GrStrokeInfo* strokeInfo,
783b9086a026844e4cfd08b219e49ce3f12294cba98bsalomon@google.com                         const SkMatrix* matrix) {
784d58a0ba9cff9fcefe5047e88ccb4a6e76c591c40egdaniel    if (NULL != strokeInfo && strokeInfo->isDashed()) {
785d58a0ba9cff9fcefe5047e88ccb4a6e76c591c40egdaniel        SkPath path;
786d58a0ba9cff9fcefe5047e88ccb4a6e76c591c40egdaniel        path.addRect(rect);
787d58a0ba9cff9fcefe5047e88ccb4a6e76c591c40egdaniel        this->drawPath(paint, path, *strokeInfo);
788d58a0ba9cff9fcefe5047e88ccb4a6e76c591c40egdaniel        return;
789d58a0ba9cff9fcefe5047e88ccb4a6e76c591c40egdaniel    }
790d58a0ba9cff9fcefe5047e88ccb4a6e76c591c40egdaniel
791eb6879f50a5564eeb981ec5616b55bf685eb76fcbsalomon@google.com    AutoRestoreEffects are;
7925dbb149fda134941e5d168790127caf294d322e2commit-bot@chromium.org    AutoCheckFlush acf(this);
7935dbb149fda134941e5d168790127caf294d322e2commit-bot@chromium.org    GrDrawTarget* target = this->prepareToDraw(&paint, BUFFERED_DRAW, &are, &acf);
79427847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com
7952a05de0c049a8648942a55016126a1f92e1c14d6commit-bot@chromium.org    GR_CREATE_TRACE_MARKER("GrContext::drawRect", target);
7962a05de0c049a8648942a55016126a1f92e1c14d6commit-bot@chromium.org
797d58a0ba9cff9fcefe5047e88ccb4a6e76c591c40egdaniel    SkScalar width = NULL == strokeInfo ? -1 : strokeInfo->getStrokeRec().getWidth();
79824ab3b0ce50b3428f063849b6160e468f047487ccommit-bot@chromium.org    SkMatrix combinedMatrix = target->drawState()->getViewMatrix();
79924ab3b0ce50b3428f063849b6160e468f047487ccommit-bot@chromium.org    if (NULL != matrix) {
80024ab3b0ce50b3428f063849b6160e468f047487ccommit-bot@chromium.org        combinedMatrix.preConcat(*matrix);
80124ab3b0ce50b3428f063849b6160e468f047487ccommit-bot@chromium.org    }
80224ab3b0ce50b3428f063849b6160e468f047487ccommit-bot@chromium.org
80324ab3b0ce50b3428f063849b6160e468f047487ccommit-bot@chromium.org    // Check if this is a full RT draw and can be replaced with a clear. We don't bother checking
80424ab3b0ce50b3428f063849b6160e468f047487ccommit-bot@chromium.org    // cases where the RT is fully inside a stroke.
80524ab3b0ce50b3428f063849b6160e468f047487ccommit-bot@chromium.org    if (width < 0) {
80624ab3b0ce50b3428f063849b6160e468f047487ccommit-bot@chromium.org        SkRect rtRect;
80724ab3b0ce50b3428f063849b6160e468f047487ccommit-bot@chromium.org        target->getDrawState().getRenderTarget()->getBoundsRect(&rtRect);
80824ab3b0ce50b3428f063849b6160e468f047487ccommit-bot@chromium.org        SkRect clipSpaceRTRect = rtRect;
80924ab3b0ce50b3428f063849b6160e468f047487ccommit-bot@chromium.org        bool checkClip = false;
81024ab3b0ce50b3428f063849b6160e468f047487ccommit-bot@chromium.org        if (NULL != this->getClip()) {
81124ab3b0ce50b3428f063849b6160e468f047487ccommit-bot@chromium.org            checkClip = true;
81224ab3b0ce50b3428f063849b6160e468f047487ccommit-bot@chromium.org            clipSpaceRTRect.offset(SkIntToScalar(this->getClip()->fOrigin.fX),
81324ab3b0ce50b3428f063849b6160e468f047487ccommit-bot@chromium.org                                   SkIntToScalar(this->getClip()->fOrigin.fY));
81424ab3b0ce50b3428f063849b6160e468f047487ccommit-bot@chromium.org        }
81524ab3b0ce50b3428f063849b6160e468f047487ccommit-bot@chromium.org        // Does the clip contain the entire RT?
81624ab3b0ce50b3428f063849b6160e468f047487ccommit-bot@chromium.org        if (!checkClip || target->getClip()->fClipStack->quickContains(clipSpaceRTRect)) {
81724ab3b0ce50b3428f063849b6160e468f047487ccommit-bot@chromium.org            SkMatrix invM;
81824ab3b0ce50b3428f063849b6160e468f047487ccommit-bot@chromium.org            if (!combinedMatrix.invert(&invM)) {
81924ab3b0ce50b3428f063849b6160e468f047487ccommit-bot@chromium.org                return;
82024ab3b0ce50b3428f063849b6160e468f047487ccommit-bot@chromium.org            }
82124ab3b0ce50b3428f063849b6160e468f047487ccommit-bot@chromium.org            // Does the rect bound the RT?
82224ab3b0ce50b3428f063849b6160e468f047487ccommit-bot@chromium.org            SkPoint srcSpaceRTQuad[4];
82324ab3b0ce50b3428f063849b6160e468f047487ccommit-bot@chromium.org            invM.mapRectToQuad(srcSpaceRTQuad, rtRect);
82424ab3b0ce50b3428f063849b6160e468f047487ccommit-bot@chromium.org            if (rect_contains_inclusive(rect, srcSpaceRTQuad[0]) &&
82524ab3b0ce50b3428f063849b6160e468f047487ccommit-bot@chromium.org                rect_contains_inclusive(rect, srcSpaceRTQuad[1]) &&
82624ab3b0ce50b3428f063849b6160e468f047487ccommit-bot@chromium.org                rect_contains_inclusive(rect, srcSpaceRTQuad[2]) &&
82724ab3b0ce50b3428f063849b6160e468f047487ccommit-bot@chromium.org                rect_contains_inclusive(rect, srcSpaceRTQuad[3])) {
82824ab3b0ce50b3428f063849b6160e468f047487ccommit-bot@chromium.org                // Will it blend?
82924ab3b0ce50b3428f063849b6160e468f047487ccommit-bot@chromium.org                GrColor clearColor;
83024ab3b0ce50b3428f063849b6160e468f047487ccommit-bot@chromium.org                if (paint.isOpaqueAndConstantColor(&clearColor)) {
83156ce48ade325f6f49acb0da31d6252806e4ed7efrobertphillips@google.com                    target->clear(NULL, clearColor, true);
83224ab3b0ce50b3428f063849b6160e468f047487ccommit-bot@chromium.org                    return;
83324ab3b0ce50b3428f063849b6160e468f047487ccommit-bot@chromium.org                }
83424ab3b0ce50b3428f063849b6160e468f047487ccommit-bot@chromium.org            }
83524ab3b0ce50b3428f063849b6160e468f047487ccommit-bot@chromium.org        }
83624ab3b0ce50b3428f063849b6160e468f047487ccommit-bot@chromium.org    }
83724ab3b0ce50b3428f063849b6160e468f047487ccommit-bot@chromium.org
83824ab3b0ce50b3428f063849b6160e468f047487ccommit-bot@chromium.org    SkRect devBoundRect;
839a31082685544d0ae4c0b203d7f5ff960640ed8dfbsalomon@google.com    bool useVertexCoverage;
840c7448cef098b835d6f9adf8a365fde9de076f178bsalomon@google.com    bool needAA = paint.isAntiAlias() &&
841bb6a3178c3e79c8549b332e4ce84c64b59964f1ecommit-bot@chromium.org                  !target->getDrawState().getRenderTarget()->isMultisampled();
84224ab3b0ce50b3428f063849b6160e468f047487ccommit-bot@chromium.org    bool doAA = needAA && apply_aa_to_rect(target, rect, width, combinedMatrix, &devBoundRect,
843289533ada623f2238a83771eec977f204f75994fbsalomon@google.com                                           &useVertexCoverage);
844d58a0ba9cff9fcefe5047e88ccb4a6e76c591c40egdaniel
845d58a0ba9cff9fcefe5047e88ccb4a6e76c591c40egdaniel    const SkStrokeRec& strokeRec = strokeInfo->getStrokeRec();
846d58a0ba9cff9fcefe5047e88ccb4a6e76c591c40egdaniel
847205d46067ace24bd4b111cf44efc96caff6c4d30bsalomon@google.com    if (doAA) {
848137f1347abaf0bb6a945e91c2f6cb49f0ee69bc3bsalomon@google.com        GrDrawState::AutoViewMatrixRestore avmr;
849137f1347abaf0bb6a945e91c2f6cb49f0ee69bc3bsalomon@google.com        if (!avmr.setIdentity(target->drawState())) {
850e3d3216fe17b6afb2e613271b5246a2766e12df6bsalomon@google.com            return;
851e3d3216fe17b6afb2e613271b5246a2766e12df6bsalomon@google.com        }
852205d46067ace24bd4b111cf44efc96caff6c4d30bsalomon@google.com        if (width >= 0) {
8536006d0f8c4f19d19a12de20826f731f52ac822a7commit-bot@chromium.org            fAARectRenderer->strokeAARect(this->getGpu(), target, rect,
8546006d0f8c4f19d19a12de20826f731f52ac822a7commit-bot@chromium.org                                          combinedMatrix, devBoundRect,
855d58a0ba9cff9fcefe5047e88ccb4a6e76c591c40egdaniel                                          strokeRec, useVertexCoverage);
856205d46067ace24bd4b111cf44efc96caff6c4d30bsalomon@google.com        } else {
857df3695e5c72b3b4401e71ff259827d87bfe8a06frobertphillips@google.com            // filled AA rect
858fbfcd5602128ec010c82cb733c9cdc0a3254f9f3rmistry@google.com            fAARectRenderer->fillAARect(this->getGpu(), target,
85924ab3b0ce50b3428f063849b6160e468f047487ccommit-bot@chromium.org                                        rect, combinedMatrix, devBoundRect,
860b19cb7f36785f3ad3b1512c342fc662ab79e3fcarobertphillips@google.com                                        useVertexCoverage);
861205d46067ace24bd4b111cf44efc96caff6c4d30bsalomon@google.com        }
862205d46067ace24bd4b111cf44efc96caff6c4d30bsalomon@google.com        return;
863205d46067ace24bd4b111cf44efc96caff6c4d30bsalomon@google.com    }
864205d46067ace24bd4b111cf44efc96caff6c4d30bsalomon@google.com
86527847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com    if (width >= 0) {
86627847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com        // TODO: consider making static vertex buffers for these cases.
8676438695222333981fafee9c8c09f3bf51dce3816bsalomon@google.com        // Hairline could be done by just adding closing vertex to
8686438695222333981fafee9c8c09f3bf51dce3816bsalomon@google.com        // unitSquareVertexBuffer()
86926c2d0a69e66f1656d2dc23953a6f153e5d5009fbsalomon@google.com
87027847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com        static const int worstCaseVertCount = 10;
8719b855c7c95ce9fff7a447e4a6bdf8a469c1f3097jvanverth@google.com        target->drawState()->setDefaultVertexAttribs();
872b75b0a0b8492e14c7728e0a0881f87dc64ce60f9jvanverth@google.com        GrDrawTarget::AutoReleaseGeometry geo(target, worstCaseVertCount, 0);
87327847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com
87427847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com        if (!geo.succeeded()) {
8756513cd06ae34f5d777b3aaea0b4533014d0a10f2bsalomon@google.com            GrPrintf("Failed to get space for vertices!\n");
87627847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com            return;
87727847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com        }
87827847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com
87927847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com        GrPrimitiveType primType;
88027847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com        int vertCount;
881972f9cd7a063d0544f8c919fd12b9a3adbd12b24commit-bot@chromium.org        SkPoint* vertex = geo.positions();
88227847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com
88327847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com        if (width > 0) {
88427847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com            vertCount = 10;
88547059542e7aa153926377456a6c611e55c8e428cbsalomon@google.com            primType = kTriangleStrip_GrPrimitiveType;
88627847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com            setStrokeRectStrip(vertex, rect, width);
88727847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com        } else {
88827847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com            // hairline
88927847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com            vertCount = 5;
89047059542e7aa153926377456a6c611e55c8e428cbsalomon@google.com            primType = kLineStrip_GrPrimitiveType;
89127847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com            vertex[0].set(rect.fLeft, rect.fTop);
89227847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com            vertex[1].set(rect.fRight, rect.fTop);
89327847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com            vertex[2].set(rect.fRight, rect.fBottom);
89427847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com            vertex[3].set(rect.fLeft, rect.fBottom);
89527847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com            vertex[4].set(rect.fLeft, rect.fTop);
89627847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com        }
89727847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com
8988f9cbd62ec108d410b91155dcf6a4789c641246fbsalomon@google.com        GrDrawState::AutoViewMatrixRestore avmr;
89927847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com        if (NULL != matrix) {
9008f9cbd62ec108d410b91155dcf6a4789c641246fbsalomon@google.com            GrDrawState* drawState = target->drawState();
9012fdcdeb86788206c23410109b3e2b7976747fd11bsalomon@google.com            avmr.set(drawState, *matrix);
90227847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com        }
90327847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com
90427847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com        target->drawNonIndexed(primType, 0, vertCount);
90527847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com    } else {
906df3695e5c72b3b4401e71ff259827d87bfe8a06frobertphillips@google.com        // filled BW rect
907235ef3d0e253200af43bb69139df09744f5ddbefrobertphillips@google.com        target->drawSimpleRect(rect, matrix);
90827847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com    }
90927847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com}
91027847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com
91127847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.comvoid GrContext::drawRectToRect(const GrPaint& paint,
912fd03d4a829efe2d77a712fd991927c55f59a2ffecommit-bot@chromium.org                               const SkRect& dstRect,
913fd03d4a829efe2d77a712fd991927c55f59a2ffecommit-bot@chromium.org                               const SkRect& localRect,
914b9086a026844e4cfd08b219e49ce3f12294cba98bsalomon@google.com                               const SkMatrix* dstMatrix,
915c78188896e28a4ae49e406a7422b345ae177dafebsalomon@google.com                               const SkMatrix* localMatrix) {
916eb6879f50a5564eeb981ec5616b55bf685eb76fcbsalomon@google.com    AutoRestoreEffects are;
9175dbb149fda134941e5d168790127caf294d322e2commit-bot@chromium.org    AutoCheckFlush acf(this);
9185dbb149fda134941e5d168790127caf294d322e2commit-bot@chromium.org    GrDrawTarget* target = this->prepareToDraw(&paint, BUFFERED_DRAW, &are, &acf);
9196438695222333981fafee9c8c09f3bf51dce3816bsalomon@google.com
9202a05de0c049a8648942a55016126a1f92e1c14d6commit-bot@chromium.org    GR_CREATE_TRACE_MARKER("GrContext::drawRectToRect", target);
9212a05de0c049a8648942a55016126a1f92e1c14d6commit-bot@chromium.org
922c78188896e28a4ae49e406a7422b345ae177dafebsalomon@google.com    target->drawRect(dstRect, dstMatrix, &localRect, localMatrix);
92327847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com}
92427847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com
925429033038271147ed66b4bc2675ac98a5ccfa75crobertphillips@google.comnamespace {
926429033038271147ed66b4bc2675ac98a5ccfa75crobertphillips@google.com
927429033038271147ed66b4bc2675ac98a5ccfa75crobertphillips@google.comextern const GrVertexAttrib gPosUVColorAttribs[] = {
928429033038271147ed66b4bc2675ac98a5ccfa75crobertphillips@google.com    {kVec2f_GrVertexAttribType,  0, kPosition_GrVertexAttribBinding },
929972f9cd7a063d0544f8c919fd12b9a3adbd12b24commit-bot@chromium.org    {kVec2f_GrVertexAttribType,  sizeof(SkPoint), kLocalCoord_GrVertexAttribBinding },
930972f9cd7a063d0544f8c919fd12b9a3adbd12b24commit-bot@chromium.org    {kVec4ub_GrVertexAttribType, 2*sizeof(SkPoint), kColor_GrVertexAttribBinding}
931429033038271147ed66b4bc2675ac98a5ccfa75crobertphillips@google.com};
932429033038271147ed66b4bc2675ac98a5ccfa75crobertphillips@google.com
933429033038271147ed66b4bc2675ac98a5ccfa75crobertphillips@google.comextern const GrVertexAttrib gPosColorAttribs[] = {
934429033038271147ed66b4bc2675ac98a5ccfa75crobertphillips@google.com    {kVec2f_GrVertexAttribType,  0, kPosition_GrVertexAttribBinding},
935972f9cd7a063d0544f8c919fd12b9a3adbd12b24commit-bot@chromium.org    {kVec4ub_GrVertexAttribType, sizeof(SkPoint), kColor_GrVertexAttribBinding},
936429033038271147ed66b4bc2675ac98a5ccfa75crobertphillips@google.com};
937429033038271147ed66b4bc2675ac98a5ccfa75crobertphillips@google.com
938429033038271147ed66b4bc2675ac98a5ccfa75crobertphillips@google.comstatic void set_vertex_attributes(GrDrawState* drawState,
939972f9cd7a063d0544f8c919fd12b9a3adbd12b24commit-bot@chromium.org                                  const SkPoint* texCoords,
940429033038271147ed66b4bc2675ac98a5ccfa75crobertphillips@google.com                                  const GrColor* colors,
941429033038271147ed66b4bc2675ac98a5ccfa75crobertphillips@google.com                                  int* colorOffset,
942429033038271147ed66b4bc2675ac98a5ccfa75crobertphillips@google.com                                  int* texOffset) {
943429033038271147ed66b4bc2675ac98a5ccfa75crobertphillips@google.com    *texOffset = -1;
944429033038271147ed66b4bc2675ac98a5ccfa75crobertphillips@google.com    *colorOffset = -1;
945429033038271147ed66b4bc2675ac98a5ccfa75crobertphillips@google.com
946429033038271147ed66b4bc2675ac98a5ccfa75crobertphillips@google.com    if (NULL != texCoords && NULL != colors) {
947972f9cd7a063d0544f8c919fd12b9a3adbd12b24commit-bot@chromium.org        *texOffset = sizeof(SkPoint);
948972f9cd7a063d0544f8c919fd12b9a3adbd12b24commit-bot@chromium.org        *colorOffset = 2*sizeof(SkPoint);
949429033038271147ed66b4bc2675ac98a5ccfa75crobertphillips@google.com        drawState->setVertexAttribs<gPosUVColorAttribs>(3);
950429033038271147ed66b4bc2675ac98a5ccfa75crobertphillips@google.com    } else if (NULL != texCoords) {
951972f9cd7a063d0544f8c919fd12b9a3adbd12b24commit-bot@chromium.org        *texOffset = sizeof(SkPoint);
952429033038271147ed66b4bc2675ac98a5ccfa75crobertphillips@google.com        drawState->setVertexAttribs<gPosUVColorAttribs>(2);
953429033038271147ed66b4bc2675ac98a5ccfa75crobertphillips@google.com    } else if (NULL != colors) {
954972f9cd7a063d0544f8c919fd12b9a3adbd12b24commit-bot@chromium.org        *colorOffset = sizeof(SkPoint);
955429033038271147ed66b4bc2675ac98a5ccfa75crobertphillips@google.com        drawState->setVertexAttribs<gPosColorAttribs>(2);
956429033038271147ed66b4bc2675ac98a5ccfa75crobertphillips@google.com    } else {
957429033038271147ed66b4bc2675ac98a5ccfa75crobertphillips@google.com        drawState->setVertexAttribs<gPosColorAttribs>(1);
958429033038271147ed66b4bc2675ac98a5ccfa75crobertphillips@google.com    }
959429033038271147ed66b4bc2675ac98a5ccfa75crobertphillips@google.com}
960429033038271147ed66b4bc2675ac98a5ccfa75crobertphillips@google.com
961429033038271147ed66b4bc2675ac98a5ccfa75crobertphillips@google.com};
962429033038271147ed66b4bc2675ac98a5ccfa75crobertphillips@google.com
96327847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.comvoid GrContext::drawVertices(const GrPaint& paint,
96427847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com                             GrPrimitiveType primitiveType,
96527847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com                             int vertexCount,
966972f9cd7a063d0544f8c919fd12b9a3adbd12b24commit-bot@chromium.org                             const SkPoint positions[],
967972f9cd7a063d0544f8c919fd12b9a3adbd12b24commit-bot@chromium.org                             const SkPoint texCoords[],
96827847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com                             const GrColor colors[],
96927847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com                             const uint16_t indices[],
97027847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com                             int indexCount) {
971eb6879f50a5564eeb981ec5616b55bf685eb76fcbsalomon@google.com    AutoRestoreEffects are;
9725dbb149fda134941e5d168790127caf294d322e2commit-bot@chromium.org    AutoCheckFlush acf(this);
9735a56793b2a19eaf90b67d6f24441cc475d74ef17commit-bot@chromium.org    GrDrawTarget::AutoReleaseGeometry geo; // must be inside AutoCheckFlush scope
9745a56793b2a19eaf90b67d6f24441cc475d74ef17commit-bot@chromium.org
9755dbb149fda134941e5d168790127caf294d322e2commit-bot@chromium.org    GrDrawTarget* target = this->prepareToDraw(&paint, BUFFERED_DRAW, &are, &acf);
976e61c411c1258a323a010558c08de3d9f8d170dcaegdaniel    GrDrawState* drawState = target->drawState();
97727847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com
9782a05de0c049a8648942a55016126a1f92e1c14d6commit-bot@chromium.org    GR_CREATE_TRACE_MARKER("GrContext::drawVertices", target);
9792a05de0c049a8648942a55016126a1f92e1c14d6commit-bot@chromium.org
9809b855c7c95ce9fff7a447e4a6bdf8a469c1f3097jvanverth@google.com    int colorOffset = -1, texOffset = -1;
981429033038271147ed66b4bc2675ac98a5ccfa75crobertphillips@google.com    set_vertex_attributes(drawState, texCoords, colors, &colorOffset, &texOffset);
9829b855c7c95ce9fff7a447e4a6bdf8a469c1f3097jvanverth@google.com
9839b855c7c95ce9fff7a447e4a6bdf8a469c1f3097jvanverth@google.com    size_t vertexSize = drawState->getVertexSize();
984972f9cd7a063d0544f8c919fd12b9a3adbd12b24commit-bot@chromium.org    if (sizeof(SkPoint) != vertexSize) {
985b75b0a0b8492e14c7728e0a0881f87dc64ce60f9jvanverth@google.com        if (!geo.set(target, vertexCount, 0)) {
9866513cd06ae34f5d777b3aaea0b4533014d0a10f2bsalomon@google.com            GrPrintf("Failed to get space for vertices!\n");
98727847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com            return;
98827847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com        }
98927847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com        void* curVertex = geo.vertices();
99027847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com
99127847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com        for (int i = 0; i < vertexCount; ++i) {
992972f9cd7a063d0544f8c919fd12b9a3adbd12b24commit-bot@chromium.org            *((SkPoint*)curVertex) = positions[i];
99327847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com
9949b855c7c95ce9fff7a447e4a6bdf8a469c1f3097jvanverth@google.com            if (texOffset >= 0) {
995972f9cd7a063d0544f8c919fd12b9a3adbd12b24commit-bot@chromium.org                *(SkPoint*)((intptr_t)curVertex + texOffset) = texCoords[i];
99627847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com            }
9979b855c7c95ce9fff7a447e4a6bdf8a469c1f3097jvanverth@google.com            if (colorOffset >= 0) {
99827847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com                *(GrColor*)((intptr_t)curVertex + colorOffset) = colors[i];
99927847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com            }
100026c2d0a69e66f1656d2dc23953a6f153e5d5009fbsalomon@google.com            curVertex = (void*)((intptr_t)curVertex + vertexSize);
100127847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com        }
100227847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com    } else {
1003b75b0a0b8492e14c7728e0a0881f87dc64ce60f9jvanverth@google.com        target->setVertexSourceToArray(positions, vertexCount);
100427847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com    }
100527847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com
1006fbfcd5602128ec010c82cb733c9cdc0a3254f9f3rmistry@google.com    // we don't currently apply offscreen AA to this path. Need improved
1007919583674bd5daeb60327c0bc1ce8aaa80d54e13bsalomon@google.com    // management of GrDrawTarget's geometry to avoid copying points per-tile.
1008a47a48dca5045d71cbc5de343404045209a13e15bsalomon@google.com
10098295dc1474db279df08d816b2115e807c681fad5bsalomon@google.com    if (NULL != indices) {
1010919583674bd5daeb60327c0bc1ce8aaa80d54e13bsalomon@google.com        target->setIndexSourceToArray(indices, indexCount);
10118295dc1474db279df08d816b2115e807c681fad5bsalomon@google.com        target->drawIndexed(primitiveType, 0, 0, vertexCount, indexCount);
10120406b9e1faee06c6ecb2732a1bcf3b0e53104e07bsalomon@google.com        target->resetIndexSource();
101327847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com    } else {
10148295dc1474db279df08d816b2115e807c681fad5bsalomon@google.com        target->drawNonIndexed(primitiveType, 0, vertexCount);
10158295dc1474db279df08d816b2115e807c681fad5bsalomon@google.com    }
101627847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com}
101727847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com
101806afe7b5a1ef03bfc6494c51ab2a1f7a386de5c2bsalomon@google.com///////////////////////////////////////////////////////////////////////////////
101993c9660cd158c5d0cab0ba4223e4257f699d5bb8bsalomon@google.com
1020f2bfd54de32ffbcf90ddcd0e249aaebb1559d9c2commit-bot@chromium.orgvoid GrContext::drawRRect(const GrPaint& paint,
10210a09d7195b8d9945e5c9c76cc4cfe6ef65d6d390commit-bot@chromium.org                          const SkRRect& rrect,
1022d58a0ba9cff9fcefe5047e88ccb4a6e76c591c40egdaniel                          const GrStrokeInfo& strokeInfo) {
10230a09d7195b8d9945e5c9c76cc4cfe6ef65d6d390commit-bot@chromium.org    if (rrect.isEmpty()) {
102419dd017a6256be636ccb550752bb563c4e7caeb5commit-bot@chromium.org       return;
102519dd017a6256be636ccb550752bb563c4e7caeb5commit-bot@chromium.org    }
1026f2bfd54de32ffbcf90ddcd0e249aaebb1559d9c2commit-bot@chromium.org
1027d58a0ba9cff9fcefe5047e88ccb4a6e76c591c40egdaniel    if (strokeInfo.isDashed()) {
1028d58a0ba9cff9fcefe5047e88ccb4a6e76c591c40egdaniel        SkPath path;
1029d58a0ba9cff9fcefe5047e88ccb4a6e76c591c40egdaniel        path.addRRect(rrect);
1030d58a0ba9cff9fcefe5047e88ccb4a6e76c591c40egdaniel        this->drawPath(paint, path, strokeInfo);
1031d58a0ba9cff9fcefe5047e88ccb4a6e76c591c40egdaniel        return;
1032d58a0ba9cff9fcefe5047e88ccb4a6e76c591c40egdaniel    }
1033d58a0ba9cff9fcefe5047e88ccb4a6e76c591c40egdaniel
1034eb6879f50a5564eeb981ec5616b55bf685eb76fcbsalomon@google.com    AutoRestoreEffects are;
10355dbb149fda134941e5d168790127caf294d322e2commit-bot@chromium.org    AutoCheckFlush acf(this);
10365dbb149fda134941e5d168790127caf294d322e2commit-bot@chromium.org    GrDrawTarget* target = this->prepareToDraw(&paint, BUFFERED_DRAW, &are, &acf);
1037f2bfd54de32ffbcf90ddcd0e249aaebb1559d9c2commit-bot@chromium.org
10382a05de0c049a8648942a55016126a1f92e1c14d6commit-bot@chromium.org    GR_CREATE_TRACE_MARKER("GrContext::drawRRect", target);
10392a05de0c049a8648942a55016126a1f92e1c14d6commit-bot@chromium.org
1040d58a0ba9cff9fcefe5047e88ccb4a6e76c591c40egdaniel    const SkStrokeRec& strokeRec = strokeInfo.getStrokeRec();
1041d58a0ba9cff9fcefe5047e88ccb4a6e76c591c40egdaniel
1042d58a0ba9cff9fcefe5047e88ccb4a6e76c591c40egdaniel    if (!fOvalRenderer->drawRRect(target, this, paint.isAntiAlias(), rrect, strokeRec)) {
1043f2bfd54de32ffbcf90ddcd0e249aaebb1559d9c2commit-bot@chromium.org        SkPath path;
10440a09d7195b8d9945e5c9c76cc4cfe6ef65d6d390commit-bot@chromium.org        path.addRRect(rrect);
1045d58a0ba9cff9fcefe5047e88ccb4a6e76c591c40egdaniel        this->internalDrawPath(target, paint.isAntiAlias(), path, strokeInfo);
1046f2bfd54de32ffbcf90ddcd0e249aaebb1559d9c2commit-bot@chromium.org    }
1047f2bfd54de32ffbcf90ddcd0e249aaebb1559d9c2commit-bot@chromium.org}
1048f2bfd54de32ffbcf90ddcd0e249aaebb1559d9c2commit-bot@chromium.org
1049f2bfd54de32ffbcf90ddcd0e249aaebb1559d9c2commit-bot@chromium.org///////////////////////////////////////////////////////////////////////////////
1050f2bfd54de32ffbcf90ddcd0e249aaebb1559d9c2commit-bot@chromium.org
10510a09d7195b8d9945e5c9c76cc4cfe6ef65d6d390commit-bot@chromium.orgvoid GrContext::drawDRRect(const GrPaint& paint,
10520a09d7195b8d9945e5c9c76cc4cfe6ef65d6d390commit-bot@chromium.org                           const SkRRect& outer,
10530a09d7195b8d9945e5c9c76cc4cfe6ef65d6d390commit-bot@chromium.org                           const SkRRect& inner) {
10540a09d7195b8d9945e5c9c76cc4cfe6ef65d6d390commit-bot@chromium.org    if (outer.isEmpty()) {
10550a09d7195b8d9945e5c9c76cc4cfe6ef65d6d390commit-bot@chromium.org       return;
10560a09d7195b8d9945e5c9c76cc4cfe6ef65d6d390commit-bot@chromium.org    }
10570a09d7195b8d9945e5c9c76cc4cfe6ef65d6d390commit-bot@chromium.org
10580a09d7195b8d9945e5c9c76cc4cfe6ef65d6d390commit-bot@chromium.org    AutoRestoreEffects are;
10590a09d7195b8d9945e5c9c76cc4cfe6ef65d6d390commit-bot@chromium.org    AutoCheckFlush acf(this);
10600a09d7195b8d9945e5c9c76cc4cfe6ef65d6d390commit-bot@chromium.org    GrDrawTarget* target = this->prepareToDraw(&paint, BUFFERED_DRAW, &are, &acf);
10610a09d7195b8d9945e5c9c76cc4cfe6ef65d6d390commit-bot@chromium.org
10620a09d7195b8d9945e5c9c76cc4cfe6ef65d6d390commit-bot@chromium.org    GR_CREATE_TRACE_MARKER("GrContext::drawDRRect", target);
10630a09d7195b8d9945e5c9c76cc4cfe6ef65d6d390commit-bot@chromium.org
10640a09d7195b8d9945e5c9c76cc4cfe6ef65d6d390commit-bot@chromium.org    if (!fOvalRenderer->drawDRRect(target, this, paint.isAntiAlias(), outer, inner)) {
10650a09d7195b8d9945e5c9c76cc4cfe6ef65d6d390commit-bot@chromium.org        SkPath path;
10660a09d7195b8d9945e5c9c76cc4cfe6ef65d6d390commit-bot@chromium.org        path.addRRect(inner);
10670a09d7195b8d9945e5c9c76cc4cfe6ef65d6d390commit-bot@chromium.org        path.addRRect(outer);
10680a09d7195b8d9945e5c9c76cc4cfe6ef65d6d390commit-bot@chromium.org        path.setFillType(SkPath::kEvenOdd_FillType);
10690a09d7195b8d9945e5c9c76cc4cfe6ef65d6d390commit-bot@chromium.org
1070d58a0ba9cff9fcefe5047e88ccb4a6e76c591c40egdaniel        GrStrokeInfo fillRec(SkStrokeRec::kFill_InitStyle);
10710a09d7195b8d9945e5c9c76cc4cfe6ef65d6d390commit-bot@chromium.org        this->internalDrawPath(target, paint.isAntiAlias(), path, fillRec);
10720a09d7195b8d9945e5c9c76cc4cfe6ef65d6d390commit-bot@chromium.org    }
10730a09d7195b8d9945e5c9c76cc4cfe6ef65d6d390commit-bot@chromium.org}
10740a09d7195b8d9945e5c9c76cc4cfe6ef65d6d390commit-bot@chromium.org
10750a09d7195b8d9945e5c9c76cc4cfe6ef65d6d390commit-bot@chromium.org///////////////////////////////////////////////////////////////////////////////
10760a09d7195b8d9945e5c9c76cc4cfe6ef65d6d390commit-bot@chromium.org
107746d3d39e65e0b3ea2ad7c91c176ccafb4df0fa24jvanverth@google.comvoid GrContext::drawOval(const GrPaint& paint,
1078fd03d4a829efe2d77a712fd991927c55f59a2ffecommit-bot@chromium.org                         const SkRect& oval,
1079d58a0ba9cff9fcefe5047e88ccb4a6e76c591c40egdaniel                         const GrStrokeInfo& strokeInfo) {
108019dd017a6256be636ccb550752bb563c4e7caeb5commit-bot@chromium.org    if (oval.isEmpty()) {
108119dd017a6256be636ccb550752bb563c4e7caeb5commit-bot@chromium.org       return;
108219dd017a6256be636ccb550752bb563c4e7caeb5commit-bot@chromium.org    }
108393c9660cd158c5d0cab0ba4223e4257f699d5bb8bsalomon@google.com
1084d58a0ba9cff9fcefe5047e88ccb4a6e76c591c40egdaniel    if (strokeInfo.isDashed()) {
1085d58a0ba9cff9fcefe5047e88ccb4a6e76c591c40egdaniel        SkPath path;
1086d58a0ba9cff9fcefe5047e88ccb4a6e76c591c40egdaniel        path.addOval(oval);
1087d58a0ba9cff9fcefe5047e88ccb4a6e76c591c40egdaniel        this->drawPath(paint, path, strokeInfo);
1088d58a0ba9cff9fcefe5047e88ccb4a6e76c591c40egdaniel        return;
1089d58a0ba9cff9fcefe5047e88ccb4a6e76c591c40egdaniel    }
1090d58a0ba9cff9fcefe5047e88ccb4a6e76c591c40egdaniel
1091eb6879f50a5564eeb981ec5616b55bf685eb76fcbsalomon@google.com    AutoRestoreEffects are;
10925dbb149fda134941e5d168790127caf294d322e2commit-bot@chromium.org    AutoCheckFlush acf(this);
10935dbb149fda134941e5d168790127caf294d322e2commit-bot@chromium.org    GrDrawTarget* target = this->prepareToDraw(&paint, BUFFERED_DRAW, &are, &acf);
10940982d35187da7e1ed6c0eba5951bbdadca8b33e7bsalomon@google.com
10952a05de0c049a8648942a55016126a1f92e1c14d6commit-bot@chromium.org    GR_CREATE_TRACE_MARKER("GrContext::drawOval", target);
10962a05de0c049a8648942a55016126a1f92e1c14d6commit-bot@chromium.org
1097d58a0ba9cff9fcefe5047e88ccb4a6e76c591c40egdaniel    const SkStrokeRec& strokeRec = strokeInfo.getStrokeRec();
1098d58a0ba9cff9fcefe5047e88ccb4a6e76c591c40egdaniel
1099d58a0ba9cff9fcefe5047e88ccb4a6e76c591c40egdaniel
1100d58a0ba9cff9fcefe5047e88ccb4a6e76c591c40egdaniel    if (!fOvalRenderer->drawOval(target, this, paint.isAntiAlias(), oval, strokeRec)) {
110181312830ef73420efdc4821feb7c2d6fd9152af8commit-bot@chromium.org        SkPath path;
110281312830ef73420efdc4821feb7c2d6fd9152af8commit-bot@chromium.org        path.addOval(oval);
1103d58a0ba9cff9fcefe5047e88ccb4a6e76c591c40egdaniel        this->internalDrawPath(target, paint.isAntiAlias(), path, strokeInfo);
110446d3d39e65e0b3ea2ad7c91c176ccafb4df0fa24jvanverth@google.com    }
1105150d28465d340e3c6da6a3e1fd5adfdb128e61d0bsalomon@google.com}
110627847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com
110783d1a68141830cbfa0d5fca6f9c9bccf9c978ad2robertphillips@google.com// Can 'path' be drawn as a pair of filled nested rectangles?
110883d1a68141830cbfa0d5fca6f9c9bccf9c978ad2robertphillips@google.comstatic bool is_nested_rects(GrDrawTarget* target,
110983d1a68141830cbfa0d5fca6f9c9bccf9c978ad2robertphillips@google.com                            const SkPath& path,
111083d1a68141830cbfa0d5fca6f9c9bccf9c978ad2robertphillips@google.com                            const SkStrokeRec& stroke,
111183d1a68141830cbfa0d5fca6f9c9bccf9c978ad2robertphillips@google.com                            SkRect rects[2],
111283d1a68141830cbfa0d5fca6f9c9bccf9c978ad2robertphillips@google.com                            bool* useVertexCoverage) {
111383d1a68141830cbfa0d5fca6f9c9bccf9c978ad2robertphillips@google.com    SkASSERT(stroke.isFillStyle());
111483d1a68141830cbfa0d5fca6f9c9bccf9c978ad2robertphillips@google.com
111583d1a68141830cbfa0d5fca6f9c9bccf9c978ad2robertphillips@google.com    if (path.isInverseFillType()) {
111683d1a68141830cbfa0d5fca6f9c9bccf9c978ad2robertphillips@google.com        return false;
111783d1a68141830cbfa0d5fca6f9c9bccf9c978ad2robertphillips@google.com    }
111883d1a68141830cbfa0d5fca6f9c9bccf9c978ad2robertphillips@google.com
111983d1a68141830cbfa0d5fca6f9c9bccf9c978ad2robertphillips@google.com    const GrDrawState& drawState = target->getDrawState();
112083d1a68141830cbfa0d5fca6f9c9bccf9c978ad2robertphillips@google.com
112183d1a68141830cbfa0d5fca6f9c9bccf9c978ad2robertphillips@google.com    // TODO: this restriction could be lifted if we were willing to apply
112283d1a68141830cbfa0d5fca6f9c9bccf9c978ad2robertphillips@google.com    // the matrix to all the points individually rather than just to the rect
112383d1a68141830cbfa0d5fca6f9c9bccf9c978ad2robertphillips@google.com    if (!drawState.getViewMatrix().preservesAxisAlignment()) {
112483d1a68141830cbfa0d5fca6f9c9bccf9c978ad2robertphillips@google.com        return false;
112583d1a68141830cbfa0d5fca6f9c9bccf9c978ad2robertphillips@google.com    }
112683d1a68141830cbfa0d5fca6f9c9bccf9c978ad2robertphillips@google.com
112783d1a68141830cbfa0d5fca6f9c9bccf9c978ad2robertphillips@google.com    *useVertexCoverage = false;
112883d1a68141830cbfa0d5fca6f9c9bccf9c978ad2robertphillips@google.com    if (!target->getDrawState().canTweakAlphaForCoverage()) {
1129e0a868c84ebc34c5a16b5faa1546016abb9ca0accommit-bot@chromium.org        if (target->shouldDisableCoverageAAForBlend()) {
113083d1a68141830cbfa0d5fca6f9c9bccf9c978ad2robertphillips@google.com            return false;
113183d1a68141830cbfa0d5fca6f9c9bccf9c978ad2robertphillips@google.com        } else {
113283d1a68141830cbfa0d5fca6f9c9bccf9c978ad2robertphillips@google.com            *useVertexCoverage = true;
113383d1a68141830cbfa0d5fca6f9c9bccf9c978ad2robertphillips@google.com        }
113483d1a68141830cbfa0d5fca6f9c9bccf9c978ad2robertphillips@google.com    }
113583d1a68141830cbfa0d5fca6f9c9bccf9c978ad2robertphillips@google.com
113683d1a68141830cbfa0d5fca6f9c9bccf9c978ad2robertphillips@google.com    SkPath::Direction dirs[2];
113783d1a68141830cbfa0d5fca6f9c9bccf9c978ad2robertphillips@google.com    if (!path.isNestedRects(rects, dirs)) {
113883d1a68141830cbfa0d5fca6f9c9bccf9c978ad2robertphillips@google.com        return false;
113983d1a68141830cbfa0d5fca6f9c9bccf9c978ad2robertphillips@google.com    }
114083d1a68141830cbfa0d5fca6f9c9bccf9c978ad2robertphillips@google.com
11418d3c640b5aa96d6316a3e52975602b35e1a66ac7robertphillips@google.com    if (SkPath::kWinding_FillType == path.getFillType() && dirs[0] == dirs[1]) {
114283d1a68141830cbfa0d5fca6f9c9bccf9c978ad2robertphillips@google.com        // The two rects need to be wound opposite to each other
11438d3c640b5aa96d6316a3e52975602b35e1a66ac7robertphillips@google.com        return false;
114483d1a68141830cbfa0d5fca6f9c9bccf9c978ad2robertphillips@google.com    }
114583d1a68141830cbfa0d5fca6f9c9bccf9c978ad2robertphillips@google.com
11468d3c640b5aa96d6316a3e52975602b35e1a66ac7robertphillips@google.com    // Right now, nested rects where the margin is not the same width
11478d3c640b5aa96d6316a3e52975602b35e1a66ac7robertphillips@google.com    // all around do not render correctly
11488d3c640b5aa96d6316a3e52975602b35e1a66ac7robertphillips@google.com    const SkScalar* outer = rects[0].asScalars();
11498d3c640b5aa96d6316a3e52975602b35e1a66ac7robertphillips@google.com    const SkScalar* inner = rects[1].asScalars();
11508d3c640b5aa96d6316a3e52975602b35e1a66ac7robertphillips@google.com
11518d3c640b5aa96d6316a3e52975602b35e1a66ac7robertphillips@google.com    SkScalar margin = SkScalarAbs(outer[0] - inner[0]);
11528d3c640b5aa96d6316a3e52975602b35e1a66ac7robertphillips@google.com    for (int i = 1; i < 4; ++i) {
11538d3c640b5aa96d6316a3e52975602b35e1a66ac7robertphillips@google.com        SkScalar temp = SkScalarAbs(outer[i] - inner[i]);
11548d3c640b5aa96d6316a3e52975602b35e1a66ac7robertphillips@google.com        if (!SkScalarNearlyEqual(margin, temp)) {
11558d3c640b5aa96d6316a3e52975602b35e1a66ac7robertphillips@google.com            return false;
11568d3c640b5aa96d6316a3e52975602b35e1a66ac7robertphillips@google.com        }
11578d3c640b5aa96d6316a3e52975602b35e1a66ac7robertphillips@google.com    }
11588d3c640b5aa96d6316a3e52975602b35e1a66ac7robertphillips@google.com
11598d3c640b5aa96d6316a3e52975602b35e1a66ac7robertphillips@google.com    return true;
11608d3c640b5aa96d6316a3e52975602b35e1a66ac7robertphillips@google.com}
116183d1a68141830cbfa0d5fca6f9c9bccf9c978ad2robertphillips@google.com
1162d58a0ba9cff9fcefe5047e88ccb4a6e76c591c40egdanielvoid GrContext::drawPath(const GrPaint& paint, const SkPath& path, const GrStrokeInfo& strokeInfo) {
116327847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com
1164fa6ac938e64fe11b442d05fe8a90ddac2d1951f9bsalomon@google.com    if (path.isEmpty()) {
116512b4e27ae1a29460e91a59f38122483e1faec697sugoi@google.com       if (path.isInverseFillType()) {
1166fa6ac938e64fe11b442d05fe8a90ddac2d1951f9bsalomon@google.com           this->drawPaint(paint);
1167fa6ac938e64fe11b442d05fe8a90ddac2d1951f9bsalomon@google.com       }
1168fa6ac938e64fe11b442d05fe8a90ddac2d1951f9bsalomon@google.com       return;
1169fa6ac938e64fe11b442d05fe8a90ddac2d1951f9bsalomon@google.com    }
1170fa6ac938e64fe11b442d05fe8a90ddac2d1951f9bsalomon@google.com
1171d58a0ba9cff9fcefe5047e88ccb4a6e76c591c40egdaniel    if (strokeInfo.isDashed()) {
1172e61c411c1258a323a010558c08de3d9f8d170dcaegdaniel        SkPoint pts[2];
1173e61c411c1258a323a010558c08de3d9f8d170dcaegdaniel        if (path.isLine(pts)) {
1174e61c411c1258a323a010558c08de3d9f8d170dcaegdaniel            AutoRestoreEffects are;
1175e61c411c1258a323a010558c08de3d9f8d170dcaegdaniel            AutoCheckFlush acf(this);
1176e61c411c1258a323a010558c08de3d9f8d170dcaegdaniel            GrDrawTarget* target = this->prepareToDraw(&paint, BUFFERED_DRAW, &are, &acf);
1177e61c411c1258a323a010558c08de3d9f8d170dcaegdaniel            GrDrawState* drawState = target->drawState();
1178e61c411c1258a323a010558c08de3d9f8d170dcaegdaniel
1179e61c411c1258a323a010558c08de3d9f8d170dcaegdaniel            SkMatrix origViewMatrix = drawState->getViewMatrix();
1180e61c411c1258a323a010558c08de3d9f8d170dcaegdaniel            GrDrawState::AutoViewMatrixRestore avmr;
1181e61c411c1258a323a010558c08de3d9f8d170dcaegdaniel            if (avmr.setIdentity(target->drawState())) {
1182e61c411c1258a323a010558c08de3d9f8d170dcaegdaniel                if (GrDashingEffect::DrawDashLine(pts, paint, strokeInfo, fGpu, target,
1183e61c411c1258a323a010558c08de3d9f8d170dcaegdaniel                                                  origViewMatrix)) {
1184e61c411c1258a323a010558c08de3d9f8d170dcaegdaniel                    return;
1185e61c411c1258a323a010558c08de3d9f8d170dcaegdaniel                }
1186e61c411c1258a323a010558c08de3d9f8d170dcaegdaniel            }
1187e61c411c1258a323a010558c08de3d9f8d170dcaegdaniel        }
1188e61c411c1258a323a010558c08de3d9f8d170dcaegdaniel
1189e61c411c1258a323a010558c08de3d9f8d170dcaegdaniel        // Filter dashed path into new path with the dashing applied
1190d58a0ba9cff9fcefe5047e88ccb4a6e76c591c40egdaniel        const SkPathEffect::DashInfo& info = strokeInfo.getDashInfo();
1191d58a0ba9cff9fcefe5047e88ccb4a6e76c591c40egdaniel        SkTLazy<SkPath> effectPath;
1192d58a0ba9cff9fcefe5047e88ccb4a6e76c591c40egdaniel        GrStrokeInfo newStrokeInfo(strokeInfo, false);
1193d58a0ba9cff9fcefe5047e88ccb4a6e76c591c40egdaniel        SkStrokeRec* stroke = newStrokeInfo.getStrokeRecPtr();
1194d58a0ba9cff9fcefe5047e88ccb4a6e76c591c40egdaniel        if (SkDashPath::FilterDashPath(effectPath.init(), path, stroke, NULL, info)) {
1195d58a0ba9cff9fcefe5047e88ccb4a6e76c591c40egdaniel            this->drawPath(paint, *effectPath.get(), newStrokeInfo);
1196d58a0ba9cff9fcefe5047e88ccb4a6e76c591c40egdaniel            return;
1197d58a0ba9cff9fcefe5047e88ccb4a6e76c591c40egdaniel        }
1198d58a0ba9cff9fcefe5047e88ccb4a6e76c591c40egdaniel
1199d58a0ba9cff9fcefe5047e88ccb4a6e76c591c40egdaniel        this->drawPath(paint, path, newStrokeInfo);
1200d58a0ba9cff9fcefe5047e88ccb4a6e76c591c40egdaniel        return;
1201d58a0ba9cff9fcefe5047e88ccb4a6e76c591c40egdaniel    }
1202d58a0ba9cff9fcefe5047e88ccb4a6e76c591c40egdaniel
120381312830ef73420efdc4821feb7c2d6fd9152af8commit-bot@chromium.org    // Note that internalDrawPath may sw-rasterize the path into a scratch texture.
120481312830ef73420efdc4821feb7c2d6fd9152af8commit-bot@chromium.org    // Scratch textures can be recycled after they are returned to the texture
120581312830ef73420efdc4821feb7c2d6fd9152af8commit-bot@chromium.org    // cache. This presents a potential hazard for buffered drawing. However,
120681312830ef73420efdc4821feb7c2d6fd9152af8commit-bot@chromium.org    // the writePixels that uploads to the scratch will perform a flush so we're
120781312830ef73420efdc4821feb7c2d6fd9152af8commit-bot@chromium.org    // OK.
1208eb6879f50a5564eeb981ec5616b55bf685eb76fcbsalomon@google.com    AutoRestoreEffects are;
12095dbb149fda134941e5d168790127caf294d322e2commit-bot@chromium.org    AutoCheckFlush acf(this);
12105dbb149fda134941e5d168790127caf294d322e2commit-bot@chromium.org    GrDrawTarget* target = this->prepareToDraw(&paint, BUFFERED_DRAW, &are, &acf);
1211e0a868c84ebc34c5a16b5faa1546016abb9ca0accommit-bot@chromium.org    GrDrawState* drawState = target->drawState();
121281312830ef73420efdc4821feb7c2d6fd9152af8commit-bot@chromium.org
12132a05de0c049a8648942a55016126a1f92e1c14d6commit-bot@chromium.org    GR_CREATE_TRACE_MARKER("GrContext::drawPath", target);
12142a05de0c049a8648942a55016126a1f92e1c14d6commit-bot@chromium.org
1215d58a0ba9cff9fcefe5047e88ccb4a6e76c591c40egdaniel    const SkStrokeRec& strokeRec = strokeInfo.getStrokeRec();
1216d58a0ba9cff9fcefe5047e88ccb4a6e76c591c40egdaniel
1217e0a868c84ebc34c5a16b5faa1546016abb9ca0accommit-bot@chromium.org    bool useCoverageAA = paint.isAntiAlias() && !drawState->getRenderTarget()->isMultisampled();
1218e0a868c84ebc34c5a16b5faa1546016abb9ca0accommit-bot@chromium.org
1219d58a0ba9cff9fcefe5047e88ccb4a6e76c591c40egdaniel    if (useCoverageAA && strokeRec.getWidth() < 0 && !path.isConvex()) {
122083d1a68141830cbfa0d5fca6f9c9bccf9c978ad2robertphillips@google.com        // Concave AA paths are expensive - try to avoid them for special cases
122183d1a68141830cbfa0d5fca6f9c9bccf9c978ad2robertphillips@google.com        bool useVertexCoverage;
122283d1a68141830cbfa0d5fca6f9c9bccf9c978ad2robertphillips@google.com        SkRect rects[2];
122383d1a68141830cbfa0d5fca6f9c9bccf9c978ad2robertphillips@google.com
1224d58a0ba9cff9fcefe5047e88ccb4a6e76c591c40egdaniel        if (is_nested_rects(target, path, strokeRec, rects, &useVertexCoverage)) {
1225e0a868c84ebc34c5a16b5faa1546016abb9ca0accommit-bot@chromium.org            SkMatrix origViewMatrix = drawState->getViewMatrix();
1226137f1347abaf0bb6a945e91c2f6cb49f0ee69bc3bsalomon@google.com            GrDrawState::AutoViewMatrixRestore avmr;
1227137f1347abaf0bb6a945e91c2f6cb49f0ee69bc3bsalomon@google.com            if (!avmr.setIdentity(target->drawState())) {
122883d1a68141830cbfa0d5fca6f9c9bccf9c978ad2robertphillips@google.com                return;
122983d1a68141830cbfa0d5fca6f9c9bccf9c978ad2robertphillips@google.com            }
123083d1a68141830cbfa0d5fca6f9c9bccf9c978ad2robertphillips@google.com
123183d1a68141830cbfa0d5fca6f9c9bccf9c978ad2robertphillips@google.com            fAARectRenderer->fillAANestedRects(this->getGpu(), target,
123283d1a68141830cbfa0d5fca6f9c9bccf9c978ad2robertphillips@google.com                                               rects,
1233137f1347abaf0bb6a945e91c2f6cb49f0ee69bc3bsalomon@google.com                                               origViewMatrix,
123483d1a68141830cbfa0d5fca6f9c9bccf9c978ad2robertphillips@google.com                                               useVertexCoverage);
123583d1a68141830cbfa0d5fca6f9c9bccf9c978ad2robertphillips@google.com            return;
123683d1a68141830cbfa0d5fca6f9c9bccf9c978ad2robertphillips@google.com        }
123783d1a68141830cbfa0d5fca6f9c9bccf9c978ad2robertphillips@google.com    }
123883d1a68141830cbfa0d5fca6f9c9bccf9c978ad2robertphillips@google.com
123993c9660cd158c5d0cab0ba4223e4257f699d5bb8bsalomon@google.com    SkRect ovalRect;
124046d3d39e65e0b3ea2ad7c91c176ccafb4df0fa24jvanverth@google.com    bool isOval = path.isOval(&ovalRect);
124146d3d39e65e0b3ea2ad7c91c176ccafb4df0fa24jvanverth@google.com
12427e32851d5473d14db5c396f5877e3dfcb7b19f6dskia.committer@gmail.com    if (!isOval || path.isInverseFillType()
1243d58a0ba9cff9fcefe5047e88ccb4a6e76c591c40egdaniel        || !fOvalRenderer->drawOval(target, this, paint.isAntiAlias(), ovalRect, strokeRec)) {
1244d58a0ba9cff9fcefe5047e88ccb4a6e76c591c40egdaniel        this->internalDrawPath(target, paint.isAntiAlias(), path, strokeInfo);
124593c9660cd158c5d0cab0ba4223e4257f699d5bb8bsalomon@google.com    }
124693c9660cd158c5d0cab0ba4223e4257f699d5bb8bsalomon@google.com}
124793c9660cd158c5d0cab0ba4223e4257f699d5bb8bsalomon@google.com
12481b20a10f0205da2d53e0837e4ddc6b2bd3b8a462bsalomon@google.comvoid GrContext::internalDrawPath(GrDrawTarget* target, bool useAA, const SkPath& path,
1249d58a0ba9cff9fcefe5047e88ccb4a6e76c591c40egdaniel                                 const GrStrokeInfo& strokeInfo) {
125019dd017a6256be636ccb550752bb563c4e7caeb5commit-bot@chromium.org    SkASSERT(!path.isEmpty());
125193c9660cd158c5d0cab0ba4223e4257f699d5bb8bsalomon@google.com
12522a05de0c049a8648942a55016126a1f92e1c14d6commit-bot@chromium.org    GR_CREATE_TRACE_MARKER("GrContext::internalDrawPath", target);
12532a05de0c049a8648942a55016126a1f92e1c14d6commit-bot@chromium.org
12542a05de0c049a8648942a55016126a1f92e1c14d6commit-bot@chromium.org
1255d46e2423a71d38b8a057cec2356741e35b03334dbsalomon@google.com    // An Assumption here is that path renderer would use some form of tweaking
1256d46e2423a71d38b8a057cec2356741e35b03334dbsalomon@google.com    // the src color (either the input alpha or in the frag shader) to implement
1257d46e2423a71d38b8a057cec2356741e35b03334dbsalomon@google.com    // aa. If we have some future driver-mojo path AA that can do the right
1258d46e2423a71d38b8a057cec2356741e35b03334dbsalomon@google.com    // thing WRT to the blend then we'll need some query on the PR.
1259e0a868c84ebc34c5a16b5faa1546016abb9ca0accommit-bot@chromium.org    bool useCoverageAA = useAA &&
1260e0a868c84ebc34c5a16b5faa1546016abb9ca0accommit-bot@chromium.org        !target->getDrawState().getRenderTarget()->isMultisampled() &&
1261e0a868c84ebc34c5a16b5faa1546016abb9ca0accommit-bot@chromium.org        !target->shouldDisableCoverageAAForBlend();
1262e0a868c84ebc34c5a16b5faa1546016abb9ca0accommit-bot@chromium.org
1263289533ada623f2238a83771eec977f204f75994fbsalomon@google.com
1264e0a868c84ebc34c5a16b5faa1546016abb9ca0accommit-bot@chromium.org    GrPathRendererChain::DrawType type =
1265e0a868c84ebc34c5a16b5faa1546016abb9ca0accommit-bot@chromium.org        useCoverageAA ? GrPathRendererChain::kColorAntiAlias_DrawType :
1266e79f320ed6c5ec9f6164ba84be1ff586532e6517robertphillips@google.com                           GrPathRendererChain::kColor_DrawType;
126745a15f551b5b3c6c747d8eaf6466b7d3b76a8faebsalomon@google.com
1268eb928ea49a1c8a72ba3e01f64452b20713232059robertphillips@google.com    const SkPath* pathPtr = &path;
1269f0c41e24d5322022c7678b60837274c1340fc109commit-bot@chromium.org    SkTLazy<SkPath> tmpPath;
1270d58a0ba9cff9fcefe5047e88ccb4a6e76c591c40egdaniel    SkTCopyOnFirstWrite<SkStrokeRec> stroke(strokeInfo.getStrokeRec());
1271eb928ea49a1c8a72ba3e01f64452b20713232059robertphillips@google.com
1272eb928ea49a1c8a72ba3e01f64452b20713232059robertphillips@google.com    // Try a 1st time without stroking the path and without allowing the SW renderer
1273e79f320ed6c5ec9f6164ba84be1ff586532e6517robertphillips@google.com    GrPathRenderer* pr = this->getPathRenderer(*pathPtr, *stroke, target, false, type);
1274eb928ea49a1c8a72ba3e01f64452b20713232059robertphillips@google.com
1275e79f320ed6c5ec9f6164ba84be1ff586532e6517robertphillips@google.com    if (NULL == pr) {
1276f0c41e24d5322022c7678b60837274c1340fc109commit-bot@chromium.org        if (!GrPathRenderer::IsStrokeHairlineOrEquivalent(*stroke, this->getMatrix(), NULL)) {
1277eb928ea49a1c8a72ba3e01f64452b20713232059robertphillips@google.com            // It didn't work the 1st time, so try again with the stroked path
1278f0c41e24d5322022c7678b60837274c1340fc109commit-bot@chromium.org            if (stroke->applyToPath(tmpPath.init(), *pathPtr)) {
1279f0c41e24d5322022c7678b60837274c1340fc109commit-bot@chromium.org                pathPtr = tmpPath.get();
1280f0c41e24d5322022c7678b60837274c1340fc109commit-bot@chromium.org                stroke.writable()->setFillStyle();
1281e0a868c84ebc34c5a16b5faa1546016abb9ca0accommit-bot@chromium.org                if (pathPtr->isEmpty()) {
1282e0a868c84ebc34c5a16b5faa1546016abb9ca0accommit-bot@chromium.org                    return;
1283e0a868c84ebc34c5a16b5faa1546016abb9ca0accommit-bot@chromium.org                }
1284eb928ea49a1c8a72ba3e01f64452b20713232059robertphillips@google.com            }
1285eb928ea49a1c8a72ba3e01f64452b20713232059robertphillips@google.com        }
128619dd017a6256be636ccb550752bb563c4e7caeb5commit-bot@chromium.org
1287eb928ea49a1c8a72ba3e01f64452b20713232059robertphillips@google.com        // This time, allow SW renderer
1288e79f320ed6c5ec9f6164ba84be1ff586532e6517robertphillips@google.com        pr = this->getPathRenderer(*pathPtr, *stroke, target, true, type);
1289eb928ea49a1c8a72ba3e01f64452b20713232059robertphillips@google.com    }
1290eb928ea49a1c8a72ba3e01f64452b20713232059robertphillips@google.com
1291e79f320ed6c5ec9f6164ba84be1ff586532e6517robertphillips@google.com    if (NULL == pr) {
1292515dcd36032997ce335daa0163c6d67e851bcad1commit-bot@chromium.org#ifdef SK_DEBUG
12933008519e9f977cd60194841d558a4f45c28e9833bsalomon@google.com        GrPrintf("Unable to find path renderer compatible with path.\n");
12941983f39f1bf6295c96c0f1f7ead9f568923390bcbsalomon@google.com#endif
12953008519e9f977cd60194841d558a4f45c28e9833bsalomon@google.com        return;
12963008519e9f977cd60194841d558a4f45c28e9833bsalomon@google.com    }
12973008519e9f977cd60194841d558a4f45c28e9833bsalomon@google.com
1298e79f320ed6c5ec9f6164ba84be1ff586532e6517robertphillips@google.com    pr->drawPath(*pathPtr, *stroke, target, useCoverageAA);
129927847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com}
13008295dc1474db279df08d816b2115e807c681fad5bsalomon@google.com
130127847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com////////////////////////////////////////////////////////////////////////////////
130227847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com
1303a7f84e150cb9e821267a8ca9e59c1ae9a3cfa300bsalomon@google.comvoid GrContext::flush(int flagsBitfield) {
1304e7db8d6c0291371ae2766fd0b6fc0918a0ed1c03robertphillips@google.com    if (NULL == fDrawBuffer) {
1305e7db8d6c0291371ae2766fd0b6fc0918a0ed1c03robertphillips@google.com        return;
1306e7db8d6c0291371ae2766fd0b6fc0918a0ed1c03robertphillips@google.com    }
1307e7db8d6c0291371ae2766fd0b6fc0918a0ed1c03robertphillips@google.com
1308a7f84e150cb9e821267a8ca9e59c1ae9a3cfa300bsalomon@google.com    if (kDiscard_FlushBit & flagsBitfield) {
1309a7f84e150cb9e821267a8ca9e59c1ae9a3cfa300bsalomon@google.com        fDrawBuffer->reset();
1310a7f84e150cb9e821267a8ca9e59c1ae9a3cfa300bsalomon@google.com    } else {
13116e4e65066a7c0dbc9bfbfe4b8f5d49c3d8a79b59bsalomon@google.com        fDrawBuffer->flush();
131253a5584bb0094e19c39a66cec7f346aad04ecac4junov@google.com    }
13135dbb149fda134941e5d168790127caf294d322e2commit-bot@chromium.org    fFlushToReduceCacheSize = false;
131427847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com}
131527847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com
13169c68058b679aee81e6e0158e7fcbfb5d8479c91absalomon@google.combool GrContext::writeTexturePixels(GrTexture* texture,
13170342a85091fd430c90a142d155dc9642aa729d9ebsalomon@google.com                                   int left, int top, int width, int height,
13180342a85091fd430c90a142d155dc9642aa729d9ebsalomon@google.com                                   GrPixelConfig config, const void* buffer, size_t rowBytes,
13190342a85091fd430c90a142d155dc9642aa729d9ebsalomon@google.com                                   uint32_t flags) {
1320bc4b654af85fa67bdd9cc1b88747b8c394a00e27bsalomon@google.com    ASSERT_OWNED_RESOURCE(texture);
1321bc4b654af85fa67bdd9cc1b88747b8c394a00e27bsalomon@google.com
13229c68058b679aee81e6e0158e7fcbfb5d8479c91absalomon@google.com    if ((kUnpremul_PixelOpsFlag & flags) || !fGpu->canWriteTexturePixels(texture, config)) {
13239c68058b679aee81e6e0158e7fcbfb5d8479c91absalomon@google.com        if (NULL != texture->asRenderTarget()) {
13249c68058b679aee81e6e0158e7fcbfb5d8479c91absalomon@google.com            return this->writeRenderTargetPixels(texture->asRenderTarget(),
13259c68058b679aee81e6e0158e7fcbfb5d8479c91absalomon@google.com                                                 left, top, width, height,
13269c68058b679aee81e6e0158e7fcbfb5d8479c91absalomon@google.com                                                 config, buffer, rowBytes, flags);
13279c68058b679aee81e6e0158e7fcbfb5d8479c91absalomon@google.com        } else {
13289c68058b679aee81e6e0158e7fcbfb5d8479c91absalomon@google.com            return false;
13299c68058b679aee81e6e0158e7fcbfb5d8479c91absalomon@google.com        }
13306f3795105b2b458079e53a721c1735c9518f6bb5bsalomon@google.com    }
13319c68058b679aee81e6e0158e7fcbfb5d8479c91absalomon@google.com
13320342a85091fd430c90a142d155dc9642aa729d9ebsalomon@google.com    if (!(kDontFlush_PixelOpsFlag & flags)) {
13330342a85091fd430c90a142d155dc9642aa729d9ebsalomon@google.com        this->flush();
13340342a85091fd430c90a142d155dc9642aa729d9ebsalomon@google.com    }
13356f3795105b2b458079e53a721c1735c9518f6bb5bsalomon@google.com
13369c68058b679aee81e6e0158e7fcbfb5d8479c91absalomon@google.com    return fGpu->writeTexturePixels(texture, left, top, width, height,
13379c68058b679aee81e6e0158e7fcbfb5d8479c91absalomon@google.com                                    config, buffer, rowBytes);
13386f3795105b2b458079e53a721c1735c9518f6bb5bsalomon@google.com}
13396f3795105b2b458079e53a721c1735c9518f6bb5bsalomon@google.com
13400342a85091fd430c90a142d155dc9642aa729d9ebsalomon@google.combool GrContext::readTexturePixels(GrTexture* texture,
13410342a85091fd430c90a142d155dc9642aa729d9ebsalomon@google.com                                  int left, int top, int width, int height,
13420342a85091fd430c90a142d155dc9642aa729d9ebsalomon@google.com                                  GrPixelConfig config, void* buffer, size_t rowBytes,
13430342a85091fd430c90a142d155dc9642aa729d9ebsalomon@google.com                                  uint32_t flags) {
1344bc4b654af85fa67bdd9cc1b88747b8c394a00e27bsalomon@google.com    ASSERT_OWNED_RESOURCE(texture);
1345669fdc4ed8ed461a141cb97d0afdd9ef72a82be1bsalomon@google.com
1346669fdc4ed8ed461a141cb97d0afdd9ef72a82be1bsalomon@google.com    GrRenderTarget* target = texture->asRenderTarget();
1347669fdc4ed8ed461a141cb97d0afdd9ef72a82be1bsalomon@google.com    if (NULL != target) {
13480342a85091fd430c90a142d155dc9642aa729d9ebsalomon@google.com        return this->readRenderTargetPixels(target,
13490342a85091fd430c90a142d155dc9642aa729d9ebsalomon@google.com                                            left, top, width, height,
13500342a85091fd430c90a142d155dc9642aa729d9ebsalomon@google.com                                            config, buffer, rowBytes,
13510342a85091fd430c90a142d155dc9642aa729d9ebsalomon@google.com                                            flags);
1352669fdc4ed8ed461a141cb97d0afdd9ef72a82be1bsalomon@google.com    } else {
13533f80dd5f01a194d4fd9ce502734bc9f56bf3fb9fcommit-bot@chromium.org        // TODO: make this more efficient for cases where we're reading the entire
13543f80dd5f01a194d4fd9ce502734bc9f56bf3fb9fcommit-bot@chromium.org        //       texture, i.e., use GetTexImage() instead
13553f80dd5f01a194d4fd9ce502734bc9f56bf3fb9fcommit-bot@chromium.org
13563f80dd5f01a194d4fd9ce502734bc9f56bf3fb9fcommit-bot@chromium.org        // create scratch rendertarget and read from that
13573f80dd5f01a194d4fd9ce502734bc9f56bf3fb9fcommit-bot@chromium.org        GrAutoScratchTexture ast;
13583f80dd5f01a194d4fd9ce502734bc9f56bf3fb9fcommit-bot@chromium.org        GrTextureDesc desc;
13593f80dd5f01a194d4fd9ce502734bc9f56bf3fb9fcommit-bot@chromium.org        desc.fFlags = kRenderTarget_GrTextureFlagBit;
13603f80dd5f01a194d4fd9ce502734bc9f56bf3fb9fcommit-bot@chromium.org        desc.fWidth = width;
13613f80dd5f01a194d4fd9ce502734bc9f56bf3fb9fcommit-bot@chromium.org        desc.fHeight = height;
13623f80dd5f01a194d4fd9ce502734bc9f56bf3fb9fcommit-bot@chromium.org        desc.fConfig = config;
13633f80dd5f01a194d4fd9ce502734bc9f56bf3fb9fcommit-bot@chromium.org        desc.fOrigin = kTopLeft_GrSurfaceOrigin;
13643f80dd5f01a194d4fd9ce502734bc9f56bf3fb9fcommit-bot@chromium.org        ast.set(this, desc, kExact_ScratchTexMatch);
13653f80dd5f01a194d4fd9ce502734bc9f56bf3fb9fcommit-bot@chromium.org        GrTexture* dst = ast.texture();
13663f80dd5f01a194d4fd9ce502734bc9f56bf3fb9fcommit-bot@chromium.org        if (NULL != dst && NULL != (target = dst->asRenderTarget())) {
13673f80dd5f01a194d4fd9ce502734bc9f56bf3fb9fcommit-bot@chromium.org            this->copyTexture(texture, target, NULL);
13683f80dd5f01a194d4fd9ce502734bc9f56bf3fb9fcommit-bot@chromium.org            return this->readRenderTargetPixels(target,
13693f80dd5f01a194d4fd9ce502734bc9f56bf3fb9fcommit-bot@chromium.org                                                left, top, width, height,
13703f80dd5f01a194d4fd9ce502734bc9f56bf3fb9fcommit-bot@chromium.org                                                config, buffer, rowBytes,
13713f80dd5f01a194d4fd9ce502734bc9f56bf3fb9fcommit-bot@chromium.org                                                flags);
13723f80dd5f01a194d4fd9ce502734bc9f56bf3fb9fcommit-bot@chromium.org        }
1373583b18a20959c9ac360316a366f4ddd9598bdf52skia.committer@gmail.com
1374669fdc4ed8ed461a141cb97d0afdd9ef72a82be1bsalomon@google.com        return false;
1375669fdc4ed8ed461a141cb97d0afdd9ef72a82be1bsalomon@google.com    }
1376669fdc4ed8ed461a141cb97d0afdd9ef72a82be1bsalomon@google.com}
1377669fdc4ed8ed461a141cb97d0afdd9ef72a82be1bsalomon@google.com
1378a91e923874ca0565b4f4816b5697dfdcd337b889bsalomon@google.com#include "SkConfig8888.h"
1379a91e923874ca0565b4f4816b5697dfdcd337b889bsalomon@google.com
13807111d463cee893a479280c7af41757e709e33ef5reed@google.com// toggles between RGBA and BGRA
13817111d463cee893a479280c7af41757e709e33ef5reed@google.comstatic SkColorType toggle_colortype32(SkColorType ct) {
13827111d463cee893a479280c7af41757e709e33ef5reed@google.com    if (kRGBA_8888_SkColorType == ct) {
13837111d463cee893a479280c7af41757e709e33ef5reed@google.com        return kBGRA_8888_SkColorType;
13847111d463cee893a479280c7af41757e709e33ef5reed@google.com    } else {
13857111d463cee893a479280c7af41757e709e33ef5reed@google.com        SkASSERT(kBGRA_8888_SkColorType == ct);
13867111d463cee893a479280c7af41757e709e33ef5reed@google.com        return kRGBA_8888_SkColorType;
1387231f6b81c22001cac4ea87ea412c4d6fd10ffb8acommit-bot@chromium.org    }
1388231f6b81c22001cac4ea87ea412c4d6fd10ffb8acommit-bot@chromium.org}
1389231f6b81c22001cac4ea87ea412c4d6fd10ffb8acommit-bot@chromium.org
13900342a85091fd430c90a142d155dc9642aa729d9ebsalomon@google.combool GrContext::readRenderTargetPixels(GrRenderTarget* target,
13910342a85091fd430c90a142d155dc9642aa729d9ebsalomon@google.com                                       int left, int top, int width, int height,
13929c68058b679aee81e6e0158e7fcbfb5d8479c91absalomon@google.com                                       GrPixelConfig dstConfig, void* buffer, size_t rowBytes,
13930342a85091fd430c90a142d155dc9642aa729d9ebsalomon@google.com                                       uint32_t flags) {
1394bc4b654af85fa67bdd9cc1b88747b8c394a00e27bsalomon@google.com    ASSERT_OWNED_RESOURCE(target);
1395bc4b654af85fa67bdd9cc1b88747b8c394a00e27bsalomon@google.com
1396fbfcd5602128ec010c82cb733c9cdc0a3254f9f3rmistry@google.com    if (NULL == target) {
1397bb6a3178c3e79c8549b332e4ce84c64b59964f1ecommit-bot@chromium.org        target = fRenderTarget.get();
1398c43649962221c348d656d425a3fa9b29c78231d4bsalomon@google.com        if (NULL == target) {
1399c43649962221c348d656d425a3fa9b29c78231d4bsalomon@google.com            return false;
1400c43649962221c348d656d425a3fa9b29c78231d4bsalomon@google.com        }
1401c43649962221c348d656d425a3fa9b29c78231d4bsalomon@google.com    }
1402669fdc4ed8ed461a141cb97d0afdd9ef72a82be1bsalomon@google.com
14036f3795105b2b458079e53a721c1735c9518f6bb5bsalomon@google.com    if (!(kDontFlush_PixelOpsFlag & flags)) {
14046f3795105b2b458079e53a721c1735c9518f6bb5bsalomon@google.com        this->flush();
14056f3795105b2b458079e53a721c1735c9518f6bb5bsalomon@google.com    }
1406c43649962221c348d656d425a3fa9b29c78231d4bsalomon@google.com
1407a04e8e842450e606dd938ddae17857849bd504d4bsalomon@google.com    // Determine which conversions have to be applied: flipY, swapRAnd, and/or unpremul.
1408c43649962221c348d656d425a3fa9b29c78231d4bsalomon@google.com
1409a04e8e842450e606dd938ddae17857849bd504d4bsalomon@google.com    // If fGpu->readPixels would incur a y-flip cost then we will read the pixels upside down. We'll
1410a04e8e842450e606dd938ddae17857849bd504d4bsalomon@google.com    // either do the flipY by drawing into a scratch with a matrix or on the cpu after the read.
1411a04e8e842450e606dd938ddae17857849bd504d4bsalomon@google.com    bool flipY = fGpu->readPixelsWillPayForYFlip(target, left, top,
14129c68058b679aee81e6e0158e7fcbfb5d8479c91absalomon@google.com                                                 width, height, dstConfig,
1413c43649962221c348d656d425a3fa9b29c78231d4bsalomon@google.com                                                 rowBytes);
14149c68058b679aee81e6e0158e7fcbfb5d8479c91absalomon@google.com    // We ignore the preferred config if it is different than our config unless it is an R/B swap.
14159c68058b679aee81e6e0158e7fcbfb5d8479c91absalomon@google.com    // In that case we'll perform an R and B swap while drawing to a scratch texture of the swapped
14169c68058b679aee81e6e0158e7fcbfb5d8479c91absalomon@google.com    // config. Then we will call readPixels on the scratch with the swapped config. The swaps during
14179c68058b679aee81e6e0158e7fcbfb5d8479c91absalomon@google.com    // the draw cancels out the fact that we call readPixels with a config that is R/B swapped from
14189c68058b679aee81e6e0158e7fcbfb5d8479c91absalomon@google.com    // dstConfig.
14199c68058b679aee81e6e0158e7fcbfb5d8479c91absalomon@google.com    GrPixelConfig readConfig = dstConfig;
14209c68058b679aee81e6e0158e7fcbfb5d8479c91absalomon@google.com    bool swapRAndB = false;
14215d1d79a1f9d351e6f2390d844e6a7361d7d607cacommit-bot@chromium.org    if (GrPixelConfigSwapRAndB(dstConfig) ==
14225d1d79a1f9d351e6f2390d844e6a7361d7d607cacommit-bot@chromium.org        fGpu->preferredReadPixelsConfig(dstConfig, target->config())) {
14239c68058b679aee81e6e0158e7fcbfb5d8479c91absalomon@google.com        readConfig = GrPixelConfigSwapRAndB(readConfig);
14249c68058b679aee81e6e0158e7fcbfb5d8479c91absalomon@google.com        swapRAndB = true;
14259c68058b679aee81e6e0158e7fcbfb5d8479c91absalomon@google.com    }
1426a04e8e842450e606dd938ddae17857849bd504d4bsalomon@google.com
14270342a85091fd430c90a142d155dc9642aa729d9ebsalomon@google.com    bool unpremul = SkToBool(kUnpremul_PixelOpsFlag & flags);
1428c43649962221c348d656d425a3fa9b29c78231d4bsalomon@google.com
14299c68058b679aee81e6e0158e7fcbfb5d8479c91absalomon@google.com    if (unpremul && !GrPixelConfigIs8888(dstConfig)) {
1430a04e8e842450e606dd938ddae17857849bd504d4bsalomon@google.com        // The unpremul flag is only allowed for these two configs.
14310a97be216df494291fe929b79d438809af7e9c83bsalomon@google.com        return false;
14320a97be216df494291fe929b79d438809af7e9c83bsalomon@google.com    }
1433a04e8e842450e606dd938ddae17857849bd504d4bsalomon@google.com
1434a04e8e842450e606dd938ddae17857849bd504d4bsalomon@google.com    // If the src is a texture and we would have to do conversions after read pixels, we instead
1435a04e8e842450e606dd938ddae17857849bd504d4bsalomon@google.com    // do the conversions by drawing the src to a scratch texture. If we handle any of the
1436a04e8e842450e606dd938ddae17857849bd504d4bsalomon@google.com    // conversions in the draw we set the corresponding bool to false so that we don't reapply it
1437a04e8e842450e606dd938ddae17857849bd504d4bsalomon@google.com    // on the read back pixels.
1438a04e8e842450e606dd938ddae17857849bd504d4bsalomon@google.com    GrTexture* src = target->asTexture();
1439c4ff22a2965616629765b8ffe0e58f6d05f92fa3bsalomon@google.com    GrAutoScratchTexture ast;
1440a04e8e842450e606dd938ddae17857849bd504d4bsalomon@google.com    if (NULL != src && (swapRAndB || unpremul || flipY)) {
1441a04e8e842450e606dd938ddae17857849bd504d4bsalomon@google.com        // Make the scratch a render target because we don't have a robust readTexturePixels as of
1442a04e8e842450e606dd938ddae17857849bd504d4bsalomon@google.com        // yet. It calls this function.
144375b3c9633cb9a594dab0ccf51dab1e694c149a18robertphillips@google.com        GrTextureDesc desc;
144475b3c9633cb9a594dab0ccf51dab1e694c149a18robertphillips@google.com        desc.fFlags = kRenderTarget_GrTextureFlagBit;
144575b3c9633cb9a594dab0ccf51dab1e694c149a18robertphillips@google.com        desc.fWidth = width;
144675b3c9633cb9a594dab0ccf51dab1e694c149a18robertphillips@google.com        desc.fHeight = height;
1447a04e8e842450e606dd938ddae17857849bd504d4bsalomon@google.com        desc.fConfig = readConfig;
14483cb406bb88f5aa09cf9f5a9554b4b1314cf1a2eesenorblanco@chromium.org        desc.fOrigin = kTopLeft_GrSurfaceOrigin;
1449c4ff22a2965616629765b8ffe0e58f6d05f92fa3bsalomon@google.com
14509c68058b679aee81e6e0158e7fcbfb5d8479c91absalomon@google.com        // When a full read back is faster than a partial we could always make the scratch exactly
1451a04e8e842450e606dd938ddae17857849bd504d4bsalomon@google.com        // match the passed rect. However, if we see many different size rectangles we will trash
1452a04e8e842450e606dd938ddae17857849bd504d4bsalomon@google.com        // our texture cache and pay the cost of creating and destroying many textures. So, we only
1453a04e8e842450e606dd938ddae17857849bd504d4bsalomon@google.com        // request an exact match when the caller is reading an entire RT.
145456d11e097b1975371d0e0b1452ac0c4d5fc46930bsalomon@google.com        ScratchTexMatch match = kApprox_ScratchTexMatch;
145556d11e097b1975371d0e0b1452ac0c4d5fc46930bsalomon@google.com        if (0 == left &&
145656d11e097b1975371d0e0b1452ac0c4d5fc46930bsalomon@google.com            0 == top &&
145756d11e097b1975371d0e0b1452ac0c4d5fc46930bsalomon@google.com            target->width() == width &&
145856d11e097b1975371d0e0b1452ac0c4d5fc46930bsalomon@google.com            target->height() == height &&
145956d11e097b1975371d0e0b1452ac0c4d5fc46930bsalomon@google.com            fGpu->fullReadPixelsIsFasterThanPartial()) {
146056d11e097b1975371d0e0b1452ac0c4d5fc46930bsalomon@google.com            match = kExact_ScratchTexMatch;
146156d11e097b1975371d0e0b1452ac0c4d5fc46930bsalomon@google.com        }
146256d11e097b1975371d0e0b1452ac0c4d5fc46930bsalomon@google.com        ast.set(this, desc, match);
1463c43649962221c348d656d425a3fa9b29c78231d4bsalomon@google.com        GrTexture* texture = ast.texture();
1464a04e8e842450e606dd938ddae17857849bd504d4bsalomon@google.com        if (texture) {
1465d8b5faca043100d7a1e4594b4d10e462532af390bsalomon@google.com            // compute a matrix to perform the draw
1466b9086a026844e4cfd08b219e49ce3f12294cba98bsalomon@google.com            SkMatrix textureMatrix;
14673cb406bb88f5aa09cf9f5a9554b4b1314cf1a2eesenorblanco@chromium.org            textureMatrix.setTranslate(SK_Scalar1 *left, SK_Scalar1 *top);
1468d8b5faca043100d7a1e4594b4d10e462532af390bsalomon@google.com            textureMatrix.postIDiv(src->width(), src->height());
1469d8b5faca043100d7a1e4594b4d10e462532af390bsalomon@google.com
1470adc6536fe5baff2216fb76ecda6cc81c61109d5cbsalomon@google.com            SkAutoTUnref<const GrEffectRef> effect;
1471a04e8e842450e606dd938ddae17857849bd504d4bsalomon@google.com            if (unpremul) {
1472adc6536fe5baff2216fb76ecda6cc81c61109d5cbsalomon@google.com                effect.reset(this->createPMToUPMEffect(src, swapRAndB, textureMatrix));
1473adc6536fe5baff2216fb76ecda6cc81c61109d5cbsalomon@google.com                if (NULL != effect) {
14749c68058b679aee81e6e0158e7fcbfb5d8479c91absalomon@google.com                    unpremul = false; // we no longer need to do this on CPU after the read back.
1475d8b5faca043100d7a1e4594b4d10e462532af390bsalomon@google.com                }
1476a04e8e842450e606dd938ddae17857849bd504d4bsalomon@google.com            }
1477a04e8e842450e606dd938ddae17857849bd504d4bsalomon@google.com            // If we failed to create a PM->UPM effect and have no other conversions to perform then
1478a04e8e842450e606dd938ddae17857849bd504d4bsalomon@google.com            // there is no longer any point to using the scratch.
1479adc6536fe5baff2216fb76ecda6cc81c61109d5cbsalomon@google.com            if (NULL != effect || flipY || swapRAndB) {
1480adc6536fe5baff2216fb76ecda6cc81c61109d5cbsalomon@google.com                if (!effect) {
1481adc6536fe5baff2216fb76ecda6cc81c61109d5cbsalomon@google.com                    effect.reset(GrConfigConversionEffect::Create(
1482adc6536fe5baff2216fb76ecda6cc81c61109d5cbsalomon@google.com                                                    src,
1483adc6536fe5baff2216fb76ecda6cc81c61109d5cbsalomon@google.com                                                    swapRAndB,
1484adc6536fe5baff2216fb76ecda6cc81c61109d5cbsalomon@google.com                                                    GrConfigConversionEffect::kNone_PMConversion,
1485adc6536fe5baff2216fb76ecda6cc81c61109d5cbsalomon@google.com                                                    textureMatrix));
1486a04e8e842450e606dd938ddae17857849bd504d4bsalomon@google.com                }
1487a04e8e842450e606dd938ddae17857849bd504d4bsalomon@google.com                swapRAndB = false; // we will handle the swap in the draw.
1488a04e8e842450e606dd938ddae17857849bd504d4bsalomon@google.com
148913f181f28f4336adcc93b7297b6d16503f4c323crobertphillips@google.com                // We protect the existing geometry here since it may not be
149013f181f28f4336adcc93b7297b6d16503f4c323crobertphillips@google.com                // clear to the caller that a draw operation (i.e., drawSimpleRect)
149113f181f28f4336adcc93b7297b6d16503f4c323crobertphillips@google.com                // can be invoked in this method
149213f181f28f4336adcc93b7297b6d16503f4c323crobertphillips@google.com                GrDrawTarget::AutoGeometryAndStatePush agasp(fGpu, GrDrawTarget::kReset_ASRInit);
1493a04e8e842450e606dd938ddae17857849bd504d4bsalomon@google.com                GrDrawState* drawState = fGpu->drawState();
1494f6de475e5cbd143f348ff7738919e397b7fe7f57tfarina@chromium.org                SkASSERT(effect);
1495eb6879f50a5564eeb981ec5616b55bf685eb76fcbsalomon@google.com                drawState->addColorEffect(effect);
1496d8b5faca043100d7a1e4594b4d10e462532af390bsalomon@google.com
1497a04e8e842450e606dd938ddae17857849bd504d4bsalomon@google.com                drawState->setRenderTarget(texture->asRenderTarget());
1498fd03d4a829efe2d77a712fd991927c55f59a2ffecommit-bot@chromium.org                SkRect rect = SkRect::MakeWH(SkIntToScalar(width), SkIntToScalar(height));
1499a04e8e842450e606dd938ddae17857849bd504d4bsalomon@google.com                fGpu->drawSimpleRect(rect, NULL);
1500a04e8e842450e606dd938ddae17857849bd504d4bsalomon@google.com                // we want to read back from the scratch's origin
1501a04e8e842450e606dd938ddae17857849bd504d4bsalomon@google.com                left = 0;
1502a04e8e842450e606dd938ddae17857849bd504d4bsalomon@google.com                top = 0;
1503a04e8e842450e606dd938ddae17857849bd504d4bsalomon@google.com                target = texture->asRenderTarget();
1504a04e8e842450e606dd938ddae17857849bd504d4bsalomon@google.com            }
1505c43649962221c348d656d425a3fa9b29c78231d4bsalomon@google.com        }
1506a04e8e842450e606dd938ddae17857849bd504d4bsalomon@google.com    }
1507a04e8e842450e606dd938ddae17857849bd504d4bsalomon@google.com    if (!fGpu->readPixels(target,
1508a04e8e842450e606dd938ddae17857849bd504d4bsalomon@google.com                          left, top, width, height,
15093cb406bb88f5aa09cf9f5a9554b4b1314cf1a2eesenorblanco@chromium.org                          readConfig, buffer, rowBytes)) {
1510a04e8e842450e606dd938ddae17857849bd504d4bsalomon@google.com        return false;
1511a04e8e842450e606dd938ddae17857849bd504d4bsalomon@google.com    }
1512d8b5faca043100d7a1e4594b4d10e462532af390bsalomon@google.com    // Perform any conversions we weren't able to perform using a scratch texture.
15133cb406bb88f5aa09cf9f5a9554b4b1314cf1a2eesenorblanco@chromium.org    if (unpremul || swapRAndB) {
15147111d463cee893a479280c7af41757e709e33ef5reed@google.com        SkDstPixelInfo dstPI;
15157111d463cee893a479280c7af41757e709e33ef5reed@google.com        if (!GrPixelConfig2ColorType(dstConfig, &dstPI.fColorType)) {
15167111d463cee893a479280c7af41757e709e33ef5reed@google.com            return false;
15177111d463cee893a479280c7af41757e709e33ef5reed@google.com        }
15187111d463cee893a479280c7af41757e709e33ef5reed@google.com        dstPI.fAlphaType = kUnpremul_SkAlphaType;
15197111d463cee893a479280c7af41757e709e33ef5reed@google.com        dstPI.fPixels = buffer;
15207111d463cee893a479280c7af41757e709e33ef5reed@google.com        dstPI.fRowBytes = rowBytes;
1521be41d38f1c076c9e4dc595a6e1a4eb5ccdbd307bskia.committer@gmail.com
15227111d463cee893a479280c7af41757e709e33ef5reed@google.com        SkSrcPixelInfo srcPI;
15237111d463cee893a479280c7af41757e709e33ef5reed@google.com        srcPI.fColorType = swapRAndB ? toggle_colortype32(dstPI.fColorType) : dstPI.fColorType;
15247111d463cee893a479280c7af41757e709e33ef5reed@google.com        srcPI.fAlphaType = kPremul_SkAlphaType;
15257111d463cee893a479280c7af41757e709e33ef5reed@google.com        srcPI.fPixels = buffer;
15267111d463cee893a479280c7af41757e709e33ef5reed@google.com        srcPI.fRowBytes = rowBytes;
1527be41d38f1c076c9e4dc595a6e1a4eb5ccdbd307bskia.committer@gmail.com
15287111d463cee893a479280c7af41757e709e33ef5reed@google.com        return srcPI.convertPixelsTo(&dstPI, width, height);
1529c43649962221c348d656d425a3fa9b29c78231d4bsalomon@google.com    }
1530a04e8e842450e606dd938ddae17857849bd504d4bsalomon@google.com    return true;
153127847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com}
153227847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com
153375f9f25d8bf2adc0494f9afbbd5965809ee13acabsalomon@google.comvoid GrContext::resolveRenderTarget(GrRenderTarget* target) {
1534f6de475e5cbd143f348ff7738919e397b7fe7f57tfarina@chromium.org    SkASSERT(target);
153575f9f25d8bf2adc0494f9afbbd5965809ee13acabsalomon@google.com    ASSERT_OWNED_RESOURCE(target);
153675f9f25d8bf2adc0494f9afbbd5965809ee13acabsalomon@google.com    // In the future we may track whether there are any pending draws to this
153775f9f25d8bf2adc0494f9afbbd5965809ee13acabsalomon@google.com    // target. We don't today so we always perform a flush. We don't promise
153875f9f25d8bf2adc0494f9afbbd5965809ee13acabsalomon@google.com    // this to our clients, though.
153975f9f25d8bf2adc0494f9afbbd5965809ee13acabsalomon@google.com    this->flush();
154075f9f25d8bf2adc0494f9afbbd5965809ee13acabsalomon@google.com    fGpu->resolveRenderTarget(target);
154175f9f25d8bf2adc0494f9afbbd5965809ee13acabsalomon@google.com}
154275f9f25d8bf2adc0494f9afbbd5965809ee13acabsalomon@google.com
154328361fad1054d59ed4e6a320c7a8b8782a1487c7commit-bot@chromium.orgvoid GrContext::discardRenderTarget(GrRenderTarget* target) {
154428361fad1054d59ed4e6a320c7a8b8782a1487c7commit-bot@chromium.org    SkASSERT(target);
154528361fad1054d59ed4e6a320c7a8b8782a1487c7commit-bot@chromium.org    ASSERT_OWNED_RESOURCE(target);
154628361fad1054d59ed4e6a320c7a8b8782a1487c7commit-bot@chromium.org    AutoRestoreEffects are;
154728361fad1054d59ed4e6a320c7a8b8782a1487c7commit-bot@chromium.org    AutoCheckFlush acf(this);
154828361fad1054d59ed4e6a320c7a8b8782a1487c7commit-bot@chromium.org    this->prepareToDraw(NULL, BUFFERED_DRAW, &are, &acf)->discard(target);
154928361fad1054d59ed4e6a320c7a8b8782a1487c7commit-bot@chromium.org}
155028361fad1054d59ed4e6a320c7a8b8782a1487c7commit-bot@chromium.org
1551a2a31928470dfb642880f6ab2e4d34b1c7f5d476scroggo@google.comvoid GrContext::copyTexture(GrTexture* src, GrRenderTarget* dst, const SkIPoint* topLeft) {
1552ef843cdcd1be858fe55cc99ff134ffbd080c9a51senorblanco@chromium.org    if (NULL == src || NULL == dst) {
1553ef843cdcd1be858fe55cc99ff134ffbd080c9a51senorblanco@chromium.org        return;
1554ef843cdcd1be858fe55cc99ff134ffbd080c9a51senorblanco@chromium.org    }
1555ef843cdcd1be858fe55cc99ff134ffbd080c9a51senorblanco@chromium.org    ASSERT_OWNED_RESOURCE(src);
1556ef843cdcd1be858fe55cc99ff134ffbd080c9a51senorblanco@chromium.org
15571ac87ff5aaff284b337652cf3ac0b41bd56fb781twiz@google.com    // Writes pending to the source texture are not tracked, so a flush
15581ac87ff5aaff284b337652cf3ac0b41bd56fb781twiz@google.com    // is required to ensure that the copy captures the most recent contents
1559adc6536fe5baff2216fb76ecda6cc81c61109d5cbsalomon@google.com    // of the source texture. See similar behavior in
15601ac87ff5aaff284b337652cf3ac0b41bd56fb781twiz@google.com    // GrContext::resolveRenderTarget.
15611ac87ff5aaff284b337652cf3ac0b41bd56fb781twiz@google.com    this->flush();
15621ac87ff5aaff284b337652cf3ac0b41bd56fb781twiz@google.com
1563873ea0c93f202600ec2591bc1e2e5d7a1e05f59dbsalomon@google.com    GrDrawTarget::AutoStateRestore asr(fGpu, GrDrawTarget::kReset_ASRInit);
15648f9cbd62ec108d410b91155dcf6a4789c641246fbsalomon@google.com    GrDrawState* drawState = fGpu->drawState();
15658f9cbd62ec108d410b91155dcf6a4789c641246fbsalomon@google.com    drawState->setRenderTarget(dst);
1566b9086a026844e4cfd08b219e49ce3f12294cba98bsalomon@google.com    SkMatrix sampleM;
1567ef843cdcd1be858fe55cc99ff134ffbd080c9a51senorblanco@chromium.org    sampleM.setIDiv(src->width(), src->height());
1568a2a31928470dfb642880f6ab2e4d34b1c7f5d476scroggo@google.com    SkIRect srcRect = SkIRect::MakeWH(dst->width(), dst->height());
1569a2a31928470dfb642880f6ab2e4d34b1c7f5d476scroggo@google.com    if (NULL != topLeft) {
1570a2a31928470dfb642880f6ab2e4d34b1c7f5d476scroggo@google.com        srcRect.offset(*topLeft);
1571a2a31928470dfb642880f6ab2e4d34b1c7f5d476scroggo@google.com    }
1572a2a31928470dfb642880f6ab2e4d34b1c7f5d476scroggo@google.com    SkIRect srcBounds = SkIRect::MakeWH(src->width(), src->height());
1573a2a31928470dfb642880f6ab2e4d34b1c7f5d476scroggo@google.com    if (!srcRect.intersect(srcBounds)) {
1574a2a31928470dfb642880f6ab2e4d34b1c7f5d476scroggo@google.com        return;
1575a2a31928470dfb642880f6ab2e4d34b1c7f5d476scroggo@google.com    }
1576a2a31928470dfb642880f6ab2e4d34b1c7f5d476scroggo@google.com    sampleM.preTranslate(SkIntToScalar(srcRect.fLeft), SkIntToScalar(srcRect.fTop));
1577eb6879f50a5564eeb981ec5616b55bf685eb76fcbsalomon@google.com    drawState->addColorTextureEffect(src, sampleM);
1578a2a31928470dfb642880f6ab2e4d34b1c7f5d476scroggo@google.com    SkRect dstR = SkRect::MakeWH(SkIntToScalar(srcRect.width()), SkIntToScalar(srcRect.height()));
1579a2a31928470dfb642880f6ab2e4d34b1c7f5d476scroggo@google.com    fGpu->drawSimpleRect(dstR, NULL);
1580ef843cdcd1be858fe55cc99ff134ffbd080c9a51senorblanco@chromium.org}
1581ef843cdcd1be858fe55cc99ff134ffbd080c9a51senorblanco@chromium.org
15829c68058b679aee81e6e0158e7fcbfb5d8479c91absalomon@google.combool GrContext::writeRenderTargetPixels(GrRenderTarget* target,
15830342a85091fd430c90a142d155dc9642aa729d9ebsalomon@google.com                                        int left, int top, int width, int height,
15849c68058b679aee81e6e0158e7fcbfb5d8479c91absalomon@google.com                                        GrPixelConfig srcConfig,
15850342a85091fd430c90a142d155dc9642aa729d9ebsalomon@google.com                                        const void* buffer,
15860342a85091fd430c90a142d155dc9642aa729d9ebsalomon@google.com                                        size_t rowBytes,
15870342a85091fd430c90a142d155dc9642aa729d9ebsalomon@google.com                                        uint32_t flags) {
1588bc4b654af85fa67bdd9cc1b88747b8c394a00e27bsalomon@google.com    ASSERT_OWNED_RESOURCE(target);
15896f3795105b2b458079e53a721c1735c9518f6bb5bsalomon@google.com
1590fbfcd5602128ec010c82cb733c9cdc0a3254f9f3rmistry@google.com    if (NULL == target) {
1591bb6a3178c3e79c8549b332e4ce84c64b59964f1ecommit-bot@chromium.org        target = fRenderTarget.get();
15926f3795105b2b458079e53a721c1735c9518f6bb5bsalomon@google.com        if (NULL == target) {
15939c68058b679aee81e6e0158e7fcbfb5d8479c91absalomon@google.com            return false;
15946f3795105b2b458079e53a721c1735c9518f6bb5bsalomon@google.com        }
15956f3795105b2b458079e53a721c1735c9518f6bb5bsalomon@google.com    }
159627847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com
1597a04e8e842450e606dd938ddae17857849bd504d4bsalomon@google.com    // TODO: when underlying api has a direct way to do this we should use it (e.g. glDrawPixels on
1598a04e8e842450e606dd938ddae17857849bd504d4bsalomon@google.com    // desktop GL).
1599a04e8e842450e606dd938ddae17857849bd504d4bsalomon@google.com
1600a04e8e842450e606dd938ddae17857849bd504d4bsalomon@google.com    // We will always call some form of writeTexturePixels and we will pass our flags on to it.
1601a04e8e842450e606dd938ddae17857849bd504d4bsalomon@google.com    // Thus, we don't perform a flush here since that call will do it (if the kNoFlush flag isn't
1602a04e8e842450e606dd938ddae17857849bd504d4bsalomon@google.com    // set.)
160327847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com
16040342a85091fd430c90a142d155dc9642aa729d9ebsalomon@google.com    // If the RT is also a texture and we don't have to premultiply then take the texture path.
16050342a85091fd430c90a142d155dc9642aa729d9ebsalomon@google.com    // We expect to be at least as fast or faster since it doesn't use an intermediate texture as
16060342a85091fd430c90a142d155dc9642aa729d9ebsalomon@google.com    // we do below.
1607fbfcd5602128ec010c82cb733c9cdc0a3254f9f3rmistry@google.com
16084382330a15e13b9ef54010606eb758c0c66e1868commit-bot@chromium.org#if !defined(SK_BUILD_FOR_MAC)
1609a04e8e842450e606dd938ddae17857849bd504d4bsalomon@google.com    // At least some drivers on the Mac get confused when glTexImage2D is called on a texture
1610a04e8e842450e606dd938ddae17857849bd504d4bsalomon@google.com    // attached to an FBO. The FBO still sees the old image. TODO: determine what OS versions and/or
1611a04e8e842450e606dd938ddae17857849bd504d4bsalomon@google.com    // HW is affected.
16129c68058b679aee81e6e0158e7fcbfb5d8479c91absalomon@google.com    if (NULL != target->asTexture() && !(kUnpremul_PixelOpsFlag & flags) &&
16139c68058b679aee81e6e0158e7fcbfb5d8479c91absalomon@google.com        fGpu->canWriteTexturePixels(target->asTexture(), srcConfig)) {
16149c68058b679aee81e6e0158e7fcbfb5d8479c91absalomon@google.com        return this->writeTexturePixels(target->asTexture(),
16159c68058b679aee81e6e0158e7fcbfb5d8479c91absalomon@google.com                                        left, top, width, height,
16169c68058b679aee81e6e0158e7fcbfb5d8479c91absalomon@google.com                                        srcConfig, buffer, rowBytes, flags);
1617a85449dac125b8985010df7c057e9e6201d55112bsalomon@google.com    }
1618a85449dac125b8985010df7c057e9e6201d55112bsalomon@google.com#endif
1619d8b5faca043100d7a1e4594b4d10e462532af390bsalomon@google.com
16209c68058b679aee81e6e0158e7fcbfb5d8479c91absalomon@google.com    // We ignore the preferred config unless it is a R/B swap of the src config. In that case
16219c68058b679aee81e6e0158e7fcbfb5d8479c91absalomon@google.com    // we will upload the original src data to a scratch texture but we will spoof it as the swapped
16229c68058b679aee81e6e0158e7fcbfb5d8479c91absalomon@google.com    // config. This scratch will then have R and B swapped. We correct for this by swapping again
16239c68058b679aee81e6e0158e7fcbfb5d8479c91absalomon@google.com    // when drawing the scratch to the dst using a conversion effect.
16249c68058b679aee81e6e0158e7fcbfb5d8479c91absalomon@google.com    bool swapRAndB = false;
16259c68058b679aee81e6e0158e7fcbfb5d8479c91absalomon@google.com    GrPixelConfig writeConfig = srcConfig;
16265d1d79a1f9d351e6f2390d844e6a7361d7d607cacommit-bot@chromium.org    if (GrPixelConfigSwapRAndB(srcConfig) ==
16275d1d79a1f9d351e6f2390d844e6a7361d7d607cacommit-bot@chromium.org        fGpu->preferredWritePixelsConfig(srcConfig, target->config())) {
16289c68058b679aee81e6e0158e7fcbfb5d8479c91absalomon@google.com        writeConfig = GrPixelConfigSwapRAndB(srcConfig);
16299c68058b679aee81e6e0158e7fcbfb5d8479c91absalomon@google.com        swapRAndB = true;
1630a85449dac125b8985010df7c057e9e6201d55112bsalomon@google.com    }
1631a85449dac125b8985010df7c057e9e6201d55112bsalomon@google.com
163275b3c9633cb9a594dab0ccf51dab1e694c149a18robertphillips@google.com    GrTextureDesc desc;
163375b3c9633cb9a594dab0ccf51dab1e694c149a18robertphillips@google.com    desc.fWidth = width;
163475b3c9633cb9a594dab0ccf51dab1e694c149a18robertphillips@google.com    desc.fHeight = height;
16359c68058b679aee81e6e0158e7fcbfb5d8479c91absalomon@google.com    desc.fConfig = writeConfig;
163650398bf7f1953e640e5529616e710cf540799731bsalomon@google.com    GrAutoScratchTexture ast(this, desc);
163750398bf7f1953e640e5529616e710cf540799731bsalomon@google.com    GrTexture* texture = ast.texture();
163827847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com    if (NULL == texture) {
16399c68058b679aee81e6e0158e7fcbfb5d8479c91absalomon@google.com        return false;
164027847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com    }
1641d8b5faca043100d7a1e4594b4d10e462532af390bsalomon@google.com
1642adc6536fe5baff2216fb76ecda6cc81c61109d5cbsalomon@google.com    SkAutoTUnref<const GrEffectRef> effect;
1643b9086a026844e4cfd08b219e49ce3f12294cba98bsalomon@google.com    SkMatrix textureMatrix;
1644d8b5faca043100d7a1e4594b4d10e462532af390bsalomon@google.com    textureMatrix.setIDiv(texture->width(), texture->height());
1645d8b5faca043100d7a1e4594b4d10e462532af390bsalomon@google.com
1646a04e8e842450e606dd938ddae17857849bd504d4bsalomon@google.com    // allocate a tmp buffer and sw convert the pixels to premul
1647a04e8e842450e606dd938ddae17857849bd504d4bsalomon@google.com    SkAutoSTMalloc<128 * 128, uint32_t> tmpPixels(0);
1648a04e8e842450e606dd938ddae17857849bd504d4bsalomon@google.com
1649a04e8e842450e606dd938ddae17857849bd504d4bsalomon@google.com    if (kUnpremul_PixelOpsFlag & flags) {
16509c68058b679aee81e6e0158e7fcbfb5d8479c91absalomon@google.com        if (!GrPixelConfigIs8888(srcConfig)) {
16519c68058b679aee81e6e0158e7fcbfb5d8479c91absalomon@google.com            return false;
1652a04e8e842450e606dd938ddae17857849bd504d4bsalomon@google.com        }
1653adc6536fe5baff2216fb76ecda6cc81c61109d5cbsalomon@google.com        effect.reset(this->createUPMToPMEffect(texture, swapRAndB, textureMatrix));
16549c68058b679aee81e6e0158e7fcbfb5d8479c91absalomon@google.com        // handle the unpremul step on the CPU if we couldn't create an effect to do it.
1655adc6536fe5baff2216fb76ecda6cc81c61109d5cbsalomon@google.com        if (NULL == effect) {
16567111d463cee893a479280c7af41757e709e33ef5reed@google.com            SkSrcPixelInfo srcPI;
16577111d463cee893a479280c7af41757e709e33ef5reed@google.com            if (!GrPixelConfig2ColorType(srcConfig, &srcPI.fColorType)) {
16587111d463cee893a479280c7af41757e709e33ef5reed@google.com                return false;
16597111d463cee893a479280c7af41757e709e33ef5reed@google.com            }
16607111d463cee893a479280c7af41757e709e33ef5reed@google.com            srcPI.fAlphaType = kUnpremul_SkAlphaType;
16617111d463cee893a479280c7af41757e709e33ef5reed@google.com            srcPI.fPixels = buffer;
16627111d463cee893a479280c7af41757e709e33ef5reed@google.com            srcPI.fRowBytes = rowBytes;
16637111d463cee893a479280c7af41757e709e33ef5reed@google.com
1664231f6b81c22001cac4ea87ea412c4d6fd10ffb8acommit-bot@chromium.org            tmpPixels.reset(width * height);
16657111d463cee893a479280c7af41757e709e33ef5reed@google.com
16667111d463cee893a479280c7af41757e709e33ef5reed@google.com            SkDstPixelInfo dstPI;
16677111d463cee893a479280c7af41757e709e33ef5reed@google.com            dstPI.fColorType = srcPI.fColorType;
16687111d463cee893a479280c7af41757e709e33ef5reed@google.com            dstPI.fAlphaType = kPremul_SkAlphaType;
16697111d463cee893a479280c7af41757e709e33ef5reed@google.com            dstPI.fPixels = tmpPixels.get();
16707111d463cee893a479280c7af41757e709e33ef5reed@google.com            dstPI.fRowBytes = 4 * width;
16717111d463cee893a479280c7af41757e709e33ef5reed@google.com
16727111d463cee893a479280c7af41757e709e33ef5reed@google.com            if (!srcPI.convertPixelsTo(&dstPI, width, height)) {
16737111d463cee893a479280c7af41757e709e33ef5reed@google.com                return false;
16747111d463cee893a479280c7af41757e709e33ef5reed@google.com            }
16757111d463cee893a479280c7af41757e709e33ef5reed@google.com
1676a04e8e842450e606dd938ddae17857849bd504d4bsalomon@google.com            buffer = tmpPixels.get();
1677a04e8e842450e606dd938ddae17857849bd504d4bsalomon@google.com            rowBytes = 4 * width;
1678a04e8e842450e606dd938ddae17857849bd504d4bsalomon@google.com        }
1679a04e8e842450e606dd938ddae17857849bd504d4bsalomon@google.com    }
1680adc6536fe5baff2216fb76ecda6cc81c61109d5cbsalomon@google.com    if (NULL == effect) {
1681adc6536fe5baff2216fb76ecda6cc81c61109d5cbsalomon@google.com        effect.reset(GrConfigConversionEffect::Create(texture,
1682adc6536fe5baff2216fb76ecda6cc81c61109d5cbsalomon@google.com                                                      swapRAndB,
1683adc6536fe5baff2216fb76ecda6cc81c61109d5cbsalomon@google.com                                                      GrConfigConversionEffect::kNone_PMConversion,
1684adc6536fe5baff2216fb76ecda6cc81c61109d5cbsalomon@google.com                                                      textureMatrix));
1685a04e8e842450e606dd938ddae17857849bd504d4bsalomon@google.com    }
1686a04e8e842450e606dd938ddae17857849bd504d4bsalomon@google.com
16879c68058b679aee81e6e0158e7fcbfb5d8479c91absalomon@google.com    if (!this->writeTexturePixels(texture,
16889c68058b679aee81e6e0158e7fcbfb5d8479c91absalomon@google.com                                  0, 0, width, height,
16899c68058b679aee81e6e0158e7fcbfb5d8479c91absalomon@google.com                                  writeConfig, buffer, rowBytes,
16909c68058b679aee81e6e0158e7fcbfb5d8479c91absalomon@google.com                                  flags & ~kUnpremul_PixelOpsFlag)) {
16919c68058b679aee81e6e0158e7fcbfb5d8479c91absalomon@google.com        return false;
16929c68058b679aee81e6e0158e7fcbfb5d8479c91absalomon@google.com    }
169327847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com
169413f181f28f4336adcc93b7297b6d16503f4c323crobertphillips@google.com    // writeRenderTargetPixels can be called in the midst of drawing another
16950c23faf222c24529781139495a5f4f4ab61f7cb2skia.committer@gmail.com    // object (e.g., when uploading a SW path rendering to the gpu while
169613f181f28f4336adcc93b7297b6d16503f4c323crobertphillips@google.com    // drawing a rect) so preserve the current geometry.
1697137f1347abaf0bb6a945e91c2f6cb49f0ee69bc3bsalomon@google.com    SkMatrix matrix;
1698137f1347abaf0bb6a945e91c2f6cb49f0ee69bc3bsalomon@google.com    matrix.setTranslate(SkIntToScalar(left), SkIntToScalar(top));
1699137f1347abaf0bb6a945e91c2f6cb49f0ee69bc3bsalomon@google.com    GrDrawTarget::AutoGeometryAndStatePush agasp(fGpu, GrDrawTarget::kReset_ASRInit, &matrix);
17008f9cbd62ec108d410b91155dcf6a4789c641246fbsalomon@google.com    GrDrawState* drawState = fGpu->drawState();
1701f6de475e5cbd143f348ff7738919e397b7fe7f57tfarina@chromium.org    SkASSERT(effect);
1702eb6879f50a5564eeb981ec5616b55bf685eb76fcbsalomon@google.com    drawState->addColorEffect(effect);
170327847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com
17048f9cbd62ec108d410b91155dcf6a4789c641246fbsalomon@google.com    drawState->setRenderTarget(target);
170527847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com
1706fd03d4a829efe2d77a712fd991927c55f59a2ffecommit-bot@chromium.org    fGpu->drawSimpleRect(SkRect::MakeWH(SkIntToScalar(width), SkIntToScalar(height)), NULL);
17079c68058b679aee81e6e0158e7fcbfb5d8479c91absalomon@google.com    return true;
170827847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com}
170927847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com////////////////////////////////////////////////////////////////////////////////
171027847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com
1711eb6879f50a5564eeb981ec5616b55bf685eb76fcbsalomon@google.comGrDrawTarget* GrContext::prepareToDraw(const GrPaint* paint,
1712eb6879f50a5564eeb981ec5616b55bf685eb76fcbsalomon@google.com                                       BufferedDraw buffered,
17135dbb149fda134941e5d168790127caf294d322e2commit-bot@chromium.org                                       AutoRestoreEffects* are,
17145dbb149fda134941e5d168790127caf294d322e2commit-bot@chromium.org                                       AutoCheckFlush* acf) {
1715eb6879f50a5564eeb981ec5616b55bf685eb76fcbsalomon@google.com    // All users of this draw state should be freeing up all effects when they're done.
1716eb6879f50a5564eeb981ec5616b55bf685eb76fcbsalomon@google.com    // Otherwise effects that own resources may keep those resources alive indefinitely.
1717f6de475e5cbd143f348ff7738919e397b7fe7f57tfarina@chromium.org    SkASSERT(0 == fDrawState->numColorStages() && 0 == fDrawState->numCoverageStages());
1718eb6879f50a5564eeb981ec5616b55bf685eb76fcbsalomon@google.com
17191d4edd38f6b62d1cc54cb7bc6f3c6ce10ccb1471bsalomon@google.com    if (kNo_BufferedDraw == buffered && kYes_BufferedDraw == fLastDrawWasBuffered) {
17201267fbd95290f58443652ca8d947bde50b212618robertphillips@google.com        fDrawBuffer->flush();
17211d4edd38f6b62d1cc54cb7bc6f3c6ce10ccb1471bsalomon@google.com        fLastDrawWasBuffered = kNo_BufferedDraw;
172227847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com    }
1723bb6a3178c3e79c8549b332e4ce84c64b59964f1ecommit-bot@chromium.org    ASSERT_OWNED_RESOURCE(fRenderTarget.get());
172407ea2db0260d8e6cd2bf605571b68b1c574b5a77bsalomon@google.com    if (NULL != paint) {
1725f6de475e5cbd143f348ff7738919e397b7fe7f57tfarina@chromium.org        SkASSERT(NULL != are);
17265dbb149fda134941e5d168790127caf294d322e2commit-bot@chromium.org        SkASSERT(NULL != acf);
1727eb6879f50a5564eeb981ec5616b55bf685eb76fcbsalomon@google.com        are->set(fDrawState);
1728bb6a3178c3e79c8549b332e4ce84c64b59964f1ecommit-bot@chromium.org        fDrawState->setFromPaint(*paint, fViewMatrix, fRenderTarget.get());
1729af84e748cedbf43e2d0e8d2eac9b7800c8d8ca19bsalomon@google.com#if GR_DEBUG_PARTIAL_COVERAGE_CHECK
1730af84e748cedbf43e2d0e8d2eac9b7800c8d8ca19bsalomon@google.com        if ((paint->hasMask() || 0xff != paint->fCoverage) &&
1731af84e748cedbf43e2d0e8d2eac9b7800c8d8ca19bsalomon@google.com            !fGpu->canApplyCoverage()) {
1732af84e748cedbf43e2d0e8d2eac9b7800c8d8ca19bsalomon@google.com            GrPrintf("Partial pixel coverage will be incorrectly blended.\n");
1733af84e748cedbf43e2d0e8d2eac9b7800c8d8ca19bsalomon@google.com        }
1734af84e748cedbf43e2d0e8d2eac9b7800c8d8ca19bsalomon@google.com#endif
1735bb6a3178c3e79c8549b332e4ce84c64b59964f1ecommit-bot@chromium.org    } else {
1736137f1347abaf0bb6a945e91c2f6cb49f0ee69bc3bsalomon@google.com        fDrawState->reset(fViewMatrix);
1737bb6a3178c3e79c8549b332e4ce84c64b59964f1ecommit-bot@chromium.org        fDrawState->setRenderTarget(fRenderTarget.get());
173807ea2db0260d8e6cd2bf605571b68b1c574b5a77bsalomon@google.com    }
1739bb6a3178c3e79c8549b332e4ce84c64b59964f1ecommit-bot@chromium.org    GrDrawTarget* target;
17401d4edd38f6b62d1cc54cb7bc6f3c6ce10ccb1471bsalomon@google.com    if (kYes_BufferedDraw == buffered) {
17411d4edd38f6b62d1cc54cb7bc6f3c6ce10ccb1471bsalomon@google.com        fLastDrawWasBuffered = kYes_BufferedDraw;
1742bb6a3178c3e79c8549b332e4ce84c64b59964f1ecommit-bot@chromium.org        target = fDrawBuffer;
17431d4edd38f6b62d1cc54cb7bc6f3c6ce10ccb1471bsalomon@google.com    } else {
1744f6de475e5cbd143f348ff7738919e397b7fe7f57tfarina@chromium.org        SkASSERT(kNo_BufferedDraw == buffered);
1745bb6a3178c3e79c8549b332e4ce84c64b59964f1ecommit-bot@chromium.org        fLastDrawWasBuffered = kNo_BufferedDraw;
1746bb6a3178c3e79c8549b332e4ce84c64b59964f1ecommit-bot@chromium.org        target = fGpu;
174727847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com    }
1748bb6a3178c3e79c8549b332e4ce84c64b59964f1ecommit-bot@chromium.org    fDrawState->setState(GrDrawState::kClip_StateBit, NULL != fClip &&
1749bb6a3178c3e79c8549b332e4ce84c64b59964f1ecommit-bot@chromium.org                                                     !fClip->fClipStack->isWideOpen());
1750bb6a3178c3e79c8549b332e4ce84c64b59964f1ecommit-bot@chromium.org    target->setClip(fClip);
1751f6de475e5cbd143f348ff7738919e397b7fe7f57tfarina@chromium.org    SkASSERT(fDrawState == target->drawState());
1752bb6a3178c3e79c8549b332e4ce84c64b59964f1ecommit-bot@chromium.org    return target;
175327847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com}
175427847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com
175572176b2d38db005863a54e3dd6657bbabd068bb6robertphillips@google.com/*
175672176b2d38db005863a54e3dd6657bbabd068bb6robertphillips@google.com * This method finds a path renderer that can draw the specified path on
175772176b2d38db005863a54e3dd6657bbabd068bb6robertphillips@google.com * the provided target.
1758fbfcd5602128ec010c82cb733c9cdc0a3254f9f3rmistry@google.com * Due to its expense, the software path renderer has split out so it can
175972176b2d38db005863a54e3dd6657bbabd068bb6robertphillips@google.com * can be individually allowed/disallowed via the "allowSW" boolean.
176072176b2d38db005863a54e3dd6657bbabd068bb6robertphillips@google.com */
17618d033a1b125886c62906d975b5cc28a382064526bsalomon@google.comGrPathRenderer* GrContext::getPathRenderer(const SkPath& path,
17625f74cf8c49701f514b69dc6f1a8b5c0ffd78af0asugoi@google.com                                           const SkStrokeRec& stroke,
1763c2099d2707abcc94e139627399aed4b8894b69bbbsalomon@google.com                                           const GrDrawTarget* target,
176445a15f551b5b3c6c747d8eaf6466b7d3b76a8faebsalomon@google.com                                           bool allowSW,
176545a15f551b5b3c6c747d8eaf6466b7d3b76a8faebsalomon@google.com                                           GrPathRendererChain::DrawType drawType,
176645a15f551b5b3c6c747d8eaf6466b7d3b76a8faebsalomon@google.com                                           GrPathRendererChain::StencilSupport* stencilSupport) {
176745a15f551b5b3c6c747d8eaf6466b7d3b76a8faebsalomon@google.com
17683008519e9f977cd60194841d558a4f45c28e9833bsalomon@google.com    if (NULL == fPathRendererChain) {
176945a15f551b5b3c6c747d8eaf6466b7d3b76a8faebsalomon@google.com        fPathRendererChain = SkNEW_ARGS(GrPathRendererChain, (this));
17703008519e9f977cd60194841d558a4f45c28e9833bsalomon@google.com    }
177172176b2d38db005863a54e3dd6657bbabd068bb6robertphillips@google.com
177212b4e27ae1a29460e91a59f38122483e1faec697sugoi@google.com    GrPathRenderer* pr = fPathRendererChain->getPathRenderer(path,
177312b4e27ae1a29460e91a59f38122483e1faec697sugoi@google.com                                                             stroke,
177472176b2d38db005863a54e3dd6657bbabd068bb6robertphillips@google.com                                                             target,
177545a15f551b5b3c6c747d8eaf6466b7d3b76a8faebsalomon@google.com                                                             drawType,
177645a15f551b5b3c6c747d8eaf6466b7d3b76a8faebsalomon@google.com                                                             stencilSupport);
177772176b2d38db005863a54e3dd6657bbabd068bb6robertphillips@google.com
177872176b2d38db005863a54e3dd6657bbabd068bb6robertphillips@google.com    if (NULL == pr && allowSW) {
177972176b2d38db005863a54e3dd6657bbabd068bb6robertphillips@google.com        if (NULL == fSoftwarePathRenderer) {
1780c377baf406996aed18d82d328029c82dbc3b8ddatomhudson@google.com            fSoftwarePathRenderer = SkNEW_ARGS(GrSoftwarePathRenderer, (this));
178172176b2d38db005863a54e3dd6657bbabd068bb6robertphillips@google.com        }
178272176b2d38db005863a54e3dd6657bbabd068bb6robertphillips@google.com        pr = fSoftwarePathRenderer;
178372176b2d38db005863a54e3dd6657bbabd068bb6robertphillips@google.com    }
178472176b2d38db005863a54e3dd6657bbabd068bb6robertphillips@google.com
178572176b2d38db005863a54e3dd6657bbabd068bb6robertphillips@google.com    return pr;
17863008519e9f977cd60194841d558a4f45c28e9833bsalomon@google.com}
17873008519e9f977cd60194841d558a4f45c28e9833bsalomon@google.com
178827847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com////////////////////////////////////////////////////////////////////////////////
17896b7938f9cb250086a7c6325cf31576f894ca4a1bcommit-bot@chromium.orgbool GrContext::isConfigRenderable(GrPixelConfig config, bool withMSAA) const {
17906b7938f9cb250086a7c6325cf31576f894ca4a1bcommit-bot@chromium.org    return fGpu->caps()->isConfigRenderable(config, withMSAA);
179199a5ac0b67a14048a1db3f429878775854d29397robertphillips@google.com}
179299a5ac0b67a14048a1db3f429878775854d29397robertphillips@google.com
1793b471a32460a44043e1f00d28cbefc87579dc30c5commit-bot@chromium.orgint GrContext::getRecommendedSampleCount(GrPixelConfig config,
1794b471a32460a44043e1f00d28cbefc87579dc30c5commit-bot@chromium.org                                         SkScalar dpi) const {
1795b471a32460a44043e1f00d28cbefc87579dc30c5commit-bot@chromium.org    if (!this->isConfigRenderable(config, true)) {
1796b471a32460a44043e1f00d28cbefc87579dc30c5commit-bot@chromium.org        return 0;
1797b471a32460a44043e1f00d28cbefc87579dc30c5commit-bot@chromium.org    }
1798b471a32460a44043e1f00d28cbefc87579dc30c5commit-bot@chromium.org    int chosenSampleCount = 0;
1799b471a32460a44043e1f00d28cbefc87579dc30c5commit-bot@chromium.org    if (fGpu->caps()->pathRenderingSupport()) {
1800b471a32460a44043e1f00d28cbefc87579dc30c5commit-bot@chromium.org        if (dpi >= 250.0f) {
1801b471a32460a44043e1f00d28cbefc87579dc30c5commit-bot@chromium.org            chosenSampleCount = 4;
1802b471a32460a44043e1f00d28cbefc87579dc30c5commit-bot@chromium.org        } else {
1803b471a32460a44043e1f00d28cbefc87579dc30c5commit-bot@chromium.org            chosenSampleCount = 16;
1804b471a32460a44043e1f00d28cbefc87579dc30c5commit-bot@chromium.org        }
1805b471a32460a44043e1f00d28cbefc87579dc30c5commit-bot@chromium.org    }
1806b471a32460a44043e1f00d28cbefc87579dc30c5commit-bot@chromium.org    return chosenSampleCount <= fGpu->caps()->maxSampleCount() ?
1807b471a32460a44043e1f00d28cbefc87579dc30c5commit-bot@chromium.org        chosenSampleCount : 0;
1808b471a32460a44043e1f00d28cbefc87579dc30c5commit-bot@chromium.org}
1809b471a32460a44043e1f00d28cbefc87579dc30c5commit-bot@chromium.org
18108fe72477f204b1a45393e6a64caa84fd287b805bbsalomon@google.comvoid GrContext::setupDrawBuffer() {
1811f6de475e5cbd143f348ff7738919e397b7fe7f57tfarina@chromium.org    SkASSERT(NULL == fDrawBuffer);
1812f6de475e5cbd143f348ff7738919e397b7fe7f57tfarina@chromium.org    SkASSERT(NULL == fDrawBufferVBAllocPool);
1813f6de475e5cbd143f348ff7738919e397b7fe7f57tfarina@chromium.org    SkASSERT(NULL == fDrawBufferIBAllocPool);
18148fe72477f204b1a45393e6a64caa84fd287b805bbsalomon@google.com
1815de6ac2dec54a34545dae1986cd743d24c8d655e8bsalomon@google.com    fDrawBufferVBAllocPool =
1816c377baf406996aed18d82d328029c82dbc3b8ddatomhudson@google.com        SkNEW_ARGS(GrVertexBufferAllocPool, (fGpu, false,
181727847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com                                    DRAW_BUFFER_VBPOOL_BUFFER_SIZE,
1818c377baf406996aed18d82d328029c82dbc3b8ddatomhudson@google.com                                    DRAW_BUFFER_VBPOOL_PREALLOC_BUFFERS));
1819de6ac2dec54a34545dae1986cd743d24c8d655e8bsalomon@google.com    fDrawBufferIBAllocPool =
1820c377baf406996aed18d82d328029c82dbc3b8ddatomhudson@google.com        SkNEW_ARGS(GrIndexBufferAllocPool, (fGpu, false,
1821de6ac2dec54a34545dae1986cd743d24c8d655e8bsalomon@google.com                                   DRAW_BUFFER_IBPOOL_BUFFER_SIZE,
1822c377baf406996aed18d82d328029c82dbc3b8ddatomhudson@google.com                                   DRAW_BUFFER_IBPOOL_PREALLOC_BUFFERS));
182327847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com
1824c377baf406996aed18d82d328029c82dbc3b8ddatomhudson@google.com    fDrawBuffer = SkNEW_ARGS(GrInOrderDrawBuffer, (fGpu,
18256e4e65066a7c0dbc9bfbfe4b8f5d49c3d8a79b59bsalomon@google.com                                                   fDrawBufferVBAllocPool,
18266e4e65066a7c0dbc9bfbfe4b8f5d49c3d8a79b59bsalomon@google.com                                                   fDrawBufferIBAllocPool));
18273c4d032aeb2831a64fd6eff570667d590e3ed209bsalomon@google.com
18286e4e65066a7c0dbc9bfbfe4b8f5d49c3d8a79b59bsalomon@google.com    fDrawBuffer->setDrawState(fDrawState);
182927847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com}
183027847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com
183121c10c5ff50cb8f2fd995fc9396d435d3396258bbsalomon@google.comGrDrawTarget* GrContext::getTextTarget() {
18325dbb149fda134941e5d168790127caf294d322e2commit-bot@chromium.org    return this->prepareToDraw(NULL, BUFFERED_DRAW, NULL, NULL);
183327847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com}
183427847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com
183527847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.comconst GrIndexBuffer* GrContext::getQuadIndexBuffer() const {
183627847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com    return fGpu->getQuadIndexBuffer();
183727847dedd9b5c1f48998c40842f3494c0746257fbsalomon@google.com}
1838dfe75bcf98b0c04535efbf7fe36492a7fb53c90dbsalomon@google.com
1839a04e8e842450e606dd938ddae17857849bd504d4bsalomon@google.comnamespace {
1840a04e8e842450e606dd938ddae17857849bd504d4bsalomon@google.comvoid test_pm_conversions(GrContext* ctx, int* pmToUPMValue, int* upmToPMValue) {
1841a04e8e842450e606dd938ddae17857849bd504d4bsalomon@google.com    GrConfigConversionEffect::PMConversion pmToUPM;
1842a04e8e842450e606dd938ddae17857849bd504d4bsalomon@google.com    GrConfigConversionEffect::PMConversion upmToPM;
1843a04e8e842450e606dd938ddae17857849bd504d4bsalomon@google.com    GrConfigConversionEffect::TestForPreservingPMConversions(ctx, &pmToUPM, &upmToPM);
1844a04e8e842450e606dd938ddae17857849bd504d4bsalomon@google.com    *pmToUPMValue = pmToUPM;
1845a04e8e842450e606dd938ddae17857849bd504d4bsalomon@google.com    *upmToPMValue = upmToPM;
1846a04e8e842450e606dd938ddae17857849bd504d4bsalomon@google.com}
1847a04e8e842450e606dd938ddae17857849bd504d4bsalomon@google.com}
1848a04e8e842450e606dd938ddae17857849bd504d4bsalomon@google.com
1849adc6536fe5baff2216fb76ecda6cc81c61109d5cbsalomon@google.comconst GrEffectRef* GrContext::createPMToUPMEffect(GrTexture* texture,
1850adc6536fe5baff2216fb76ecda6cc81c61109d5cbsalomon@google.com                                                  bool swapRAndB,
1851adc6536fe5baff2216fb76ecda6cc81c61109d5cbsalomon@google.com                                                  const SkMatrix& matrix) {
1852a04e8e842450e606dd938ddae17857849bd504d4bsalomon@google.com    if (!fDidTestPMConversions) {
1853a04e8e842450e606dd938ddae17857849bd504d4bsalomon@google.com        test_pm_conversions(this, &fPMToUPMConversion, &fUPMToPMConversion);
1854d0f3f6825bd5c232da52f4dc1af69b76403b797fbsalomon@google.com        fDidTestPMConversions = true;
1855a04e8e842450e606dd938ddae17857849bd504d4bsalomon@google.com    }
1856a04e8e842450e606dd938ddae17857849bd504d4bsalomon@google.com    GrConfigConversionEffect::PMConversion pmToUPM =
1857a04e8e842450e606dd938ddae17857849bd504d4bsalomon@google.com        static_cast<GrConfigConversionEffect::PMConversion>(fPMToUPMConversion);
1858a04e8e842450e606dd938ddae17857849bd504d4bsalomon@google.com    if (GrConfigConversionEffect::kNone_PMConversion != pmToUPM) {
1859adc6536fe5baff2216fb76ecda6cc81c61109d5cbsalomon@google.com        return GrConfigConversionEffect::Create(texture, swapRAndB, pmToUPM, matrix);
1860a04e8e842450e606dd938ddae17857849bd504d4bsalomon@google.com    } else {
1861adc6536fe5baff2216fb76ecda6cc81c61109d5cbsalomon@google.com        return NULL;
1862a04e8e842450e606dd938ddae17857849bd504d4bsalomon@google.com    }
1863a04e8e842450e606dd938ddae17857849bd504d4bsalomon@google.com}
1864a04e8e842450e606dd938ddae17857849bd504d4bsalomon@google.com
1865adc6536fe5baff2216fb76ecda6cc81c61109d5cbsalomon@google.comconst GrEffectRef* GrContext::createUPMToPMEffect(GrTexture* texture,
1866adc6536fe5baff2216fb76ecda6cc81c61109d5cbsalomon@google.com                                                  bool swapRAndB,
1867adc6536fe5baff2216fb76ecda6cc81c61109d5cbsalomon@google.com                                                  const SkMatrix& matrix) {
1868a04e8e842450e606dd938ddae17857849bd504d4bsalomon@google.com    if (!fDidTestPMConversions) {
1869a04e8e842450e606dd938ddae17857849bd504d4bsalomon@google.com        test_pm_conversions(this, &fPMToUPMConversion, &fUPMToPMConversion);
1870d0f3f6825bd5c232da52f4dc1af69b76403b797fbsalomon@google.com        fDidTestPMConversions = true;
1871a04e8e842450e606dd938ddae17857849bd504d4bsalomon@google.com    }
1872a04e8e842450e606dd938ddae17857849bd504d4bsalomon@google.com    GrConfigConversionEffect::PMConversion upmToPM =
1873a04e8e842450e606dd938ddae17857849bd504d4bsalomon@google.com        static_cast<GrConfigConversionEffect::PMConversion>(fUPMToPMConversion);
1874a04e8e842450e606dd938ddae17857849bd504d4bsalomon@google.com    if (GrConfigConversionEffect::kNone_PMConversion != upmToPM) {
1875adc6536fe5baff2216fb76ecda6cc81c61109d5cbsalomon@google.com        return GrConfigConversionEffect::Create(texture, swapRAndB, upmToPM, matrix);
1876a04e8e842450e606dd938ddae17857849bd504d4bsalomon@google.com    } else {
1877adc6536fe5baff2216fb76ecda6cc81c61109d5cbsalomon@google.com        return NULL;
1878a04e8e842450e606dd938ddae17857849bd504d4bsalomon@google.com    }
1879a04e8e842450e606dd938ddae17857849bd504d4bsalomon@google.com}
1880a04e8e842450e606dd938ddae17857849bd504d4bsalomon@google.com
18815c8ee2539b9316b22416a991a1f560ef5cec7957commit-bot@chromium.orgGrPath* GrContext::createPath(const SkPath& inPath, const SkStrokeRec& stroke) {
18825c8ee2539b9316b22416a991a1f560ef5cec7957commit-bot@chromium.org    SkASSERT(fGpu->caps()->pathRenderingSupport());
18835c8ee2539b9316b22416a991a1f560ef5cec7957commit-bot@chromium.org
188495c2003740c4cd01fd1b02ed93b9de7227b1d0f5commit-bot@chromium.org    // TODO: now we add to fResourceCache. This should change to fResourceCache.
18855c8ee2539b9316b22416a991a1f560ef5cec7957commit-bot@chromium.org    GrResourceKey resourceKey = GrPath::ComputeKey(inPath, stroke);
188695c2003740c4cd01fd1b02ed93b9de7227b1d0f5commit-bot@chromium.org    GrPath* path = static_cast<GrPath*>(fResourceCache->find(resourceKey));
18875c8ee2539b9316b22416a991a1f560ef5cec7957commit-bot@chromium.org    if (NULL != path && path->isEqualTo(inPath, stroke)) {
18885c8ee2539b9316b22416a991a1f560ef5cec7957commit-bot@chromium.org        path->ref();
18895c8ee2539b9316b22416a991a1f560ef5cec7957commit-bot@chromium.org    } else {
18905c8ee2539b9316b22416a991a1f560ef5cec7957commit-bot@chromium.org        path = fGpu->createPath(inPath, stroke);
189195c2003740c4cd01fd1b02ed93b9de7227b1d0f5commit-bot@chromium.org        fResourceCache->purgeAsNeeded(1, path->gpuMemorySize());
189295c2003740c4cd01fd1b02ed93b9de7227b1d0f5commit-bot@chromium.org        fResourceCache->addResource(resourceKey, path);
18935c8ee2539b9316b22416a991a1f560ef5cec7957commit-bot@chromium.org    }
18945c8ee2539b9316b22416a991a1f560ef5cec7957commit-bot@chromium.org    return path;
18955c8ee2539b9316b22416a991a1f560ef5cec7957commit-bot@chromium.org}
18965c8ee2539b9316b22416a991a1f560ef5cec7957commit-bot@chromium.org
189795a2b0e86d361c06716874f8a56782e1551c308ecommit-bot@chromium.orgvoid GrContext::addResourceToCache(const GrResourceKey& resourceKey, GrCacheable* resource) {
189895c2003740c4cd01fd1b02ed93b9de7227b1d0f5commit-bot@chromium.org    fResourceCache->purgeAsNeeded(1, resource->gpuMemorySize());
189995c2003740c4cd01fd1b02ed93b9de7227b1d0f5commit-bot@chromium.org    fResourceCache->addResource(resourceKey, resource);
190095a2b0e86d361c06716874f8a56782e1551c308ecommit-bot@chromium.org}
190195a2b0e86d361c06716874f8a56782e1551c308ecommit-bot@chromium.org
190295a2b0e86d361c06716874f8a56782e1551c308ecommit-bot@chromium.orgGrCacheable* GrContext::findAndRefCachedResource(const GrResourceKey& resourceKey) {
190395c2003740c4cd01fd1b02ed93b9de7227b1d0f5commit-bot@chromium.org    GrCacheable* resource = fResourceCache->find(resourceKey);
190495a2b0e86d361c06716874f8a56782e1551c308ecommit-bot@chromium.org    SkSafeRef(resource);
190595a2b0e86d361c06716874f8a56782e1551c308ecommit-bot@chromium.org    return resource;
190695a2b0e86d361c06716874f8a56782e1551c308ecommit-bot@chromium.org}
190795a2b0e86d361c06716874f8a56782e1551c308ecommit-bot@chromium.org
1908bbcb38df4f7477aa0a38da00a0757586a0125954egdanielvoid GrContext::addGpuTraceMarker(const GrGpuTraceMarker* marker) {
1909bbcb38df4f7477aa0a38da00a0757586a0125954egdaniel    fGpu->addGpuTraceMarker(marker);
1910bbcb38df4f7477aa0a38da00a0757586a0125954egdaniel    if (NULL != fDrawBuffer) {
1911bbcb38df4f7477aa0a38da00a0757586a0125954egdaniel        fDrawBuffer->addGpuTraceMarker(marker);
1912bbcb38df4f7477aa0a38da00a0757586a0125954egdaniel    }
1913bbcb38df4f7477aa0a38da00a0757586a0125954egdaniel}
1914bbcb38df4f7477aa0a38da00a0757586a0125954egdaniel
1915bbcb38df4f7477aa0a38da00a0757586a0125954egdanielvoid GrContext::removeGpuTraceMarker(const GrGpuTraceMarker* marker) {
1916bbcb38df4f7477aa0a38da00a0757586a0125954egdaniel    fGpu->removeGpuTraceMarker(marker);
1917bbcb38df4f7477aa0a38da00a0757586a0125954egdaniel    if (NULL != fDrawBuffer) {
1918bbcb38df4f7477aa0a38da00a0757586a0125954egdaniel        fDrawBuffer->removeGpuTraceMarker(marker);
1919bbcb38df4f7477aa0a38da00a0757586a0125954egdaniel    }
1920bbcb38df4f7477aa0a38da00a0757586a0125954egdaniel}
1921bbcb38df4f7477aa0a38da00a0757586a0125954egdaniel
1922c43649962221c348d656d425a3fa9b29c78231d4bsalomon@google.com///////////////////////////////////////////////////////////////////////////////
19235955202c805c7ef1448103cbf666972ea9d1ded1robertphillips@google.com#if GR_CACHE_STATS
19245f9f2f574fe9b195f5f3e40edeb2e28b673511fdrobertphillips@google.comvoid GrContext::printCacheStats() const {
192595c2003740c4cd01fd1b02ed93b9de7227b1d0f5commit-bot@chromium.org    fResourceCache->printStats();
19265f9f2f574fe9b195f5f3e40edeb2e28b673511fdrobertphillips@google.com}
19275f9f2f574fe9b195f5f3e40edeb2e28b673511fdrobertphillips@google.com#endif
1928